From b7edffe244581b428a4b4da4ff6a08ab461b018f Mon Sep 17 00:00:00 2001 From: Christophe MASSOLIN Date: Mon, 27 Apr 2020 00:11:04 +0200 Subject: Started rust-analyzer.cargo.defaultTarget implementation --- crates/ra_project_model/src/cargo_workspace.rs | 12 ++++++++++++ crates/rust-analyzer/src/config.rs | 1 + 2 files changed, 13 insertions(+) (limited to 'crates') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 362ee30fe..810833b64 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -42,6 +42,11 @@ impl ops::Index for CargoWorkspace { } } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct RustcConfig { + pub default_target: Option, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct CargoConfig { /// Do not activate the `default` feature. @@ -56,6 +61,9 @@ pub struct CargoConfig { /// Runs cargo check on launch to figure out the correct values of OUT_DIR pub load_out_dirs_from_check: bool, + + /// rustc config + pub rustc: RustcConfig, } impl Default for CargoConfig { @@ -65,6 +73,7 @@ impl Default for CargoConfig { all_features: true, features: Vec::new(), load_out_dirs_from_check: false, + rustc: RustcConfig { default_target: None }, } } } @@ -160,6 +169,9 @@ impl CargoWorkspace { if let Some(parent) = cargo_toml.parent() { meta.current_dir(parent); } + if let Some(target) = cargo_features.rustc.default_target.as_ref() { + meta.other_options(&[String::from("--filter-platform"), target.clone()]); + } let meta = meta.exec().with_context(|| { format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) })?; diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 715eddadb..908208ece 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -134,6 +134,7 @@ impl Config { set(value, "/cargo/allFeatures", &mut self.cargo.all_features); set(value, "/cargo/features", &mut self.cargo.features); set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); + set(value, "/cargo/rustc/defaultTarget", &mut self.cargo.rustc.default_target); match get(value, "/procMacro/enable") { Some(true) => { -- cgit v1.2.3 From ed5af989f431b9bfabf6f67350587add05a1942c Mon Sep 17 00:00:00 2001 From: Christophe MASSOLIN Date: Tue, 28 Apr 2020 00:15:54 +0200 Subject: [config] rename cargo.defaultTarget --- crates/ra_project_model/src/cargo_workspace.rs | 8 ++++---- crates/rust-analyzer/src/config.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'crates') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 810833b64..1dfee6b47 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -62,8 +62,8 @@ pub struct CargoConfig { /// Runs cargo check on launch to figure out the correct values of OUT_DIR pub load_out_dirs_from_check: bool, - /// rustc config - pub rustc: RustcConfig, + /// rustc target + pub default_target: Option, } impl Default for CargoConfig { @@ -73,7 +73,7 @@ impl Default for CargoConfig { all_features: true, features: Vec::new(), load_out_dirs_from_check: false, - rustc: RustcConfig { default_target: None }, + default_target: None, } } } @@ -169,7 +169,7 @@ impl CargoWorkspace { if let Some(parent) = cargo_toml.parent() { meta.current_dir(parent); } - if let Some(target) = cargo_features.rustc.default_target.as_ref() { + if let Some(target) = cargo_features.default_target.as_ref() { meta.other_options(&[String::from("--filter-platform"), target.clone()]); } let meta = meta.exec().with_context(|| { diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 908208ece..25404ef90 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -134,7 +134,7 @@ impl Config { set(value, "/cargo/allFeatures", &mut self.cargo.all_features); set(value, "/cargo/features", &mut self.cargo.features); set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); - set(value, "/cargo/rustc/defaultTarget", &mut self.cargo.rustc.default_target); + set(value, "/cargo/defaultTarget", &mut self.cargo.default_target); match get(value, "/procMacro/enable") { Some(true) => { -- cgit v1.2.3 From e7523511ce201763e093d5f5563c20d0e0fc5d54 Mon Sep 17 00:00:00 2001 From: Christophe MASSOLIN Date: Tue, 28 Apr 2020 00:17:23 +0200 Subject: [config] remove RustcConfig --- crates/ra_project_model/src/cargo_workspace.rs | 5 ----- 1 file changed, 5 deletions(-) (limited to 'crates') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 1dfee6b47..31499b468 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -42,11 +42,6 @@ impl ops::Index for CargoWorkspace { } } -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct RustcConfig { - pub default_target: Option, -} - #[derive(Clone, Debug, PartialEq, Eq)] pub struct CargoConfig { /// Do not activate the `default` feature. -- cgit v1.2.3 From b5c330bf5a1884ff8ad196a23fa6e356c460e130 Mon Sep 17 00:00:00 2001 From: Jesse Bakker Date: Sat, 2 May 2020 18:10:23 +0200 Subject: Make `change_visibility` assist work for tuple struct field visibility --- crates/ra_assists/src/handlers/change_visibility.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs index 44f6a1dae..1cd532e80 100644 --- a/crates/ra_assists/src/handlers/change_visibility.rs +++ b/crates/ra_assists/src/handlers/change_visibility.rs @@ -47,8 +47,7 @@ fn add_vis(ctx: AssistCtx) -> Option { return None; } (vis_offset(&parent), keyword.text_range()) - } else { - let field_name: ast::Name = ctx.find_node_at_offset()?; + } else if let Some(field_name) = ctx.find_node_at_offset::() { let field = field_name.syntax().ancestors().find_map(ast::RecordFieldDef::cast)?; if field.name()? != field_name { tested_by!(change_visibility_field_false_positive); @@ -58,6 +57,13 @@ fn add_vis(ctx: AssistCtx) -> Option { return None; } (vis_offset(field.syntax()), field_name.syntax().text_range()) + } else if let Some(field) = ctx.find_node_at_offset::() { + if field.visibility().is_some() { + return None; + } + (vis_offset(field.syntax()), field.syntax().text_range()) + } else { + return None; }; ctx.add_assist(AssistId("change_visibility"), "Change visibility to pub(crate)", |edit| { @@ -129,7 +135,8 @@ mod tests { change_visibility, r"struct S { <|>field: u32 }", r"struct S { <|>pub(crate) field: u32 }", - ) + ); + check_assist(change_visibility, r"struct S ( <|>u32 )", r"struct S ( <|>pub(crate) u32 )"); } #[test] -- cgit v1.2.3 From 8d96db3417fdabb1bad7a9919ea8ae1db25296f1 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 5 May 2020 00:17:22 +0800 Subject: Favor types for Record in name resolution --- crates/ra_hir_def/src/body/lower.rs | 15 +++++++++++---- crates/ra_hir_def/src/item_scope.rs | 11 +++++++++-- crates/ra_hir_def/src/nameres/collector.rs | 13 ++++++++++--- crates/ra_hir_def/src/nameres/raw.rs | 18 +++++++++++++++--- 4 files changed, 45 insertions(+), 12 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 687216dc3..49f5420d1 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -18,7 +18,7 @@ use ra_syntax::{ use test_utils::tested_by; use crate::{ - adt::StructKind, + adt::{self, StructKind}, body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, builtin_type::{BuiltinFloat, BuiltinInt}, db::DefDatabase, @@ -575,9 +575,16 @@ impl ExprCollector<'_> { self.body.item_scope.define_def(def); if let Some(name) = name { let vis = crate::visibility::Visibility::Public; // FIXME determine correctly - self.body - .item_scope - .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); + let favor_types = match def { + ModuleDefId::AdtId(AdtId::StructId(s)) => { + self.db.struct_data(s).variant_data.kind() == adt::StructKind::Record + } + _ => false, + }; + self.body.item_scope.push_res( + name.as_name(), + crate::per_ns::PerNs::from_def(def, vis, favor_types), + ); } } } diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 259b9ff03..6d8d1f8a3 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -151,13 +151,20 @@ impl ItemScope { } impl PerNs { - pub(crate) fn from_def(def: ModuleDefId, v: Visibility) -> PerNs { + pub(crate) fn from_def(def: ModuleDefId, v: Visibility, favor_types: bool) -> PerNs { match def { ModuleDefId::ModuleId(_) => PerNs::types(def, v), ModuleDefId::FunctionId(_) => PerNs::values(def, v), ModuleDefId::AdtId(adt) => match adt { - AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def, v), + AdtId::UnionId(_) => PerNs::both(def, def, v), AdtId::EnumId(_) => PerNs::types(def, v), + AdtId::StructId(_) => { + if favor_types { + PerNs::types(def, v) + } else { + PerNs::both(def, def, v) + } + } }, ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index bf3968bd6..49b33ca94 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -830,7 +830,7 @@ impl ModCollector<'_, '_> { let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; let def: ModuleDefId = module.into(); self.def_collector.def_map.modules[self.module_id].scope.define_def(def); - self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis); + self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis, false))], vis); res } @@ -844,6 +844,8 @@ impl ModCollector<'_, '_> { let name = def.name.clone(); let container = ContainerId::ModuleId(module); let vis = &def.visibility; + let mut favor_types = false; + let def: ModuleDefId = match def.kind { raw::DefKind::Function(ast_id) => FunctionLoc { container: container.into(), @@ -851,7 +853,8 @@ impl ModCollector<'_, '_> { } .intern(self.def_collector.db) .into(), - raw::DefKind::Struct(ast_id) => { + raw::DefKind::Struct(ast_id, mode) => { + favor_types = mode == raw::StructDefKind::Record; StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db) .into() @@ -894,7 +897,11 @@ impl ModCollector<'_, '_> { .def_map .resolve_visibility(self.def_collector.db, self.module_id, vis) .unwrap_or(Visibility::Public); - self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis) + self.def_collector.update( + self.module_id, + &[(name, PerNs::from_def(def, vis, favor_types))], + vis, + ) } fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index a71503c76..f2716a295 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -155,10 +155,17 @@ pub(super) struct DefData { pub(super) visibility: RawVisibility, } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub(super) enum StructDefKind { + Record, + Tuple, + Unit, +} + #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub(super) enum DefKind { Function(FileAstId), - Struct(FileAstId), + Struct(FileAstId, StructDefKind), Union(FileAstId), Enum(FileAstId), Const(FileAstId), @@ -171,7 +178,7 @@ impl DefKind { pub fn ast_id(&self) -> FileAstId { match self { DefKind::Function(it) => it.upcast(), - DefKind::Struct(it) => it.upcast(), + DefKind::Struct(it, _) => it.upcast(), DefKind::Union(it) => it.upcast(), DefKind::Enum(it) => it.upcast(), DefKind::Const(it) => it.upcast(), @@ -236,9 +243,14 @@ impl RawItemsCollector { return; } ast::ModuleItem::StructDef(it) => { + let kind = match it.kind() { + ast::StructKind::Record(_) => StructDefKind::Record, + ast::StructKind::Tuple(_) => StructDefKind::Tuple, + ast::StructKind::Unit => StructDefKind::Unit, + }; let id = self.source_ast_id_map.ast_id(&it); let name = it.name(); - (DefKind::Struct(id), name) + (DefKind::Struct(id, kind), name) } ast::ModuleItem::UnionDef(it) => { let id = self.source_ast_id_map.ast_id(&it); -- cgit v1.2.3 From af001677d103a3e0f5cf1bfde44982171faf34b9 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 5 May 2020 00:17:30 +0800 Subject: Fix test --- crates/ra_hir_def/src/nameres/tests/macros.rs | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs index 9bc0e6287..40289e3ca 100644 --- a/crates/ra_hir_def/src/nameres/tests/macros.rs +++ b/crates/ra_hir_def/src/nameres/tests/macros.rs @@ -19,12 +19,12 @@ fn macro_rules_are_globally_visible() { ); assert_snapshot!(map, @r###" ⋮crate - ⋮Foo: t v + ⋮Foo: t ⋮nested: t ⋮ ⋮crate::nested - ⋮Bar: t v - ⋮Baz: t v + ⋮Bar: t + ⋮Baz: t "###); } @@ -91,13 +91,13 @@ fn macro_rules_from_other_crates_are_visible() { ); assert_snapshot!(map, @r###" ⋮crate - ⋮Bar: t v - ⋮Foo: t v + ⋮Bar: t + ⋮Foo: t ⋮bar: t ⋮ ⋮crate::bar - ⋮Bar: t v - ⋮Foo: t v + ⋮Bar: t + ⋮Foo: t ⋮bar: t "###); } @@ -124,13 +124,13 @@ fn macro_rules_export_with_local_inner_macros_are_visible() { ); assert_snapshot!(map, @r###" ⋮crate - ⋮Bar: t v - ⋮Foo: t v + ⋮Bar: t + ⋮Foo: t ⋮bar: t ⋮ ⋮crate::bar - ⋮Bar: t v - ⋮Foo: t v + ⋮Bar: t + ⋮Foo: t ⋮bar: t "###); } @@ -161,13 +161,13 @@ fn local_inner_macros_makes_local_macros_usable() { ); assert_snapshot!(map, @r###" ⋮crate - ⋮Bar: t v - ⋮Foo: t v + ⋮Bar: t + ⋮Foo: t ⋮bar: t ⋮ ⋮crate::bar - ⋮Bar: t v - ⋮Foo: t v + ⋮Bar: t + ⋮Foo: t ⋮bar: t "###); } @@ -204,7 +204,7 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() { ); assert_snapshot!(map, @r###" ⋮crate - ⋮Foo: t v + ⋮Foo: t ⋮bar: m ⋮foo: m "###); -- cgit v1.2.3 From 204c8de3bfc5a8c21e0104a68356bf90f7762527 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 5 May 2020 00:29:47 +0800 Subject: Add test for issue --- crates/ra_hir_ty/src/tests/regression.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'crates') diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 8a1292c7a..115ad8328 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs @@ -534,6 +534,35 @@ fn foo(b: Bar) { ); } +#[test] +fn issue_4235_name_conflicts() { + assert_snapshot!( + infer(r#" +struct FOO {} +static FOO:FOO = FOO {}; + +impl FOO { + fn foo(&self) {} +} + +fn main() { + let a = &FOO; + a.foo(); +} +"#), @r###" + 32..38 'FOO {}': FOO + 64..68 'self': &FOO + 70..72 '{}': () + 86..120 '{ ...o(); }': () + 96..97 'a': &FOO + 100..104 '&FOO': &FOO + 101..104 'FOO': FOO + 110..111 'a': &FOO + 110..117 'a.foo()': () +"### + ); +} + #[test] fn issue_4053_diesel_where_clauses() { assert_snapshot!( -- cgit v1.2.3 From 5ae18f4f814501ccd96a277c320e919159c91fac Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 5 May 2020 00:34:54 +0800 Subject: Remove unused import --- crates/ra_hir_def/src/body/lower.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 49f5420d1..ea0ddeebc 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -18,7 +18,7 @@ use ra_syntax::{ use test_utils::tested_by; use crate::{ - adt::{self, StructKind}, + adt::StructKind, body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, builtin_type::{BuiltinFloat, BuiltinInt}, db::DefDatabase, @@ -577,7 +577,7 @@ impl ExprCollector<'_> { let vis = crate::visibility::Visibility::Public; // FIXME determine correctly let favor_types = match def { ModuleDefId::AdtId(AdtId::StructId(s)) => { - self.db.struct_data(s).variant_data.kind() == adt::StructKind::Record + self.db.struct_data(s).variant_data.kind() == StructKind::Record } _ => false, }; -- cgit v1.2.3 From 191abf368563d6229c5e6025f7cde2e7d4c22ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 4 May 2020 19:54:23 +0300 Subject: Make incremental sync opt-out --- crates/rust-analyzer/src/caps.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 680415cac..110c9a442 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs @@ -17,10 +17,10 @@ pub fn server_capabilities() -> ServerCapabilities { ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { open_close: Some(true), - change: Some(if env::var("RA_PROFILE").is_ok() { - TextDocumentSyncKind::Incremental - } else { + change: Some(if env::var("RA_NO_INCREMENTAL_SYNC").is_ok() { TextDocumentSyncKind::Full + } else { + TextDocumentSyncKind::Incremental }), will_save: None, will_save_wait_until: None, -- cgit v1.2.3 From 7c1d5f286a971484fc1f1d367e762853471873e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 4 May 2020 20:04:30 +0300 Subject: Fix line index rebuild during incremental changes --- crates/rust-analyzer/src/main_loop.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'crates') diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 401fae755..b163ea848 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -676,13 +676,13 @@ fn apply_document_changes( // remember the last valid line in the index and only rebuild it if needed. enum IndexValid { All, - UpToLine(u64), + UpToLineExclusive(u64), } impl IndexValid { fn covers(&self, line: u64) -> bool { match *self { - IndexValid::UpToLine(to) => to >= line, + IndexValid::UpToLineExclusive(to) => to > line, _ => true, } } @@ -692,10 +692,10 @@ fn apply_document_changes( for change in content_changes { match change.range { Some(range) => { - if !index_valid.covers(range.start.line) { + if !index_valid.covers(range.end.line) { line_index = Cow::Owned(LineIndex::new(&old_text)); } - index_valid = IndexValid::UpToLine(range.start.line); + index_valid = IndexValid::UpToLineExclusive(range.start.line); let range = range.conv_with(&line_index); let mut text = old_text.to_owned(); match std::panic::catch_unwind(move || { @@ -713,7 +713,7 @@ fn apply_document_changes( } None => { *old_text = change.text; - index_valid = IndexValid::UpToLine(0); + index_valid = IndexValid::UpToLineExclusive(0); } } } -- cgit v1.2.3 From e921195d93c443b20a6fcb3cb1c5b8117fe2fa1b Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 5 May 2020 01:15:27 +0800 Subject: Change favor_types to has_constructor --- crates/ra_hir_def/src/body/lower.rs | 8 ++++---- crates/ra_hir_def/src/item_scope.rs | 4 ++-- crates/ra_hir_def/src/nameres/collector.rs | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index ea0ddeebc..4671b72e9 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -575,15 +575,15 @@ impl ExprCollector<'_> { self.body.item_scope.define_def(def); if let Some(name) = name { let vis = crate::visibility::Visibility::Public; // FIXME determine correctly - let favor_types = match def { + let has_constructor = match def { ModuleDefId::AdtId(AdtId::StructId(s)) => { - self.db.struct_data(s).variant_data.kind() == StructKind::Record + self.db.struct_data(s).variant_data.kind() != StructKind::Record } - _ => false, + _ => true, }; self.body.item_scope.push_res( name.as_name(), - crate::per_ns::PerNs::from_def(def, vis, favor_types), + crate::per_ns::PerNs::from_def(def, vis, has_constructor), ); } } diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 6d8d1f8a3..954f2542a 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -151,7 +151,7 @@ impl ItemScope { } impl PerNs { - pub(crate) fn from_def(def: ModuleDefId, v: Visibility, favor_types: bool) -> PerNs { + pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs { match def { ModuleDefId::ModuleId(_) => PerNs::types(def, v), ModuleDefId::FunctionId(_) => PerNs::values(def, v), @@ -159,7 +159,7 @@ impl PerNs { AdtId::UnionId(_) => PerNs::both(def, def, v), AdtId::EnumId(_) => PerNs::types(def, v), AdtId::StructId(_) => { - if favor_types { + if !has_constructor { PerNs::types(def, v) } else { PerNs::both(def, def, v) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 49b33ca94..db994122a 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -844,7 +844,7 @@ impl ModCollector<'_, '_> { let name = def.name.clone(); let container = ContainerId::ModuleId(module); let vis = &def.visibility; - let mut favor_types = false; + let mut has_constructor = false; let def: ModuleDefId = match def.kind { raw::DefKind::Function(ast_id) => FunctionLoc { @@ -854,7 +854,7 @@ impl ModCollector<'_, '_> { .intern(self.def_collector.db) .into(), raw::DefKind::Struct(ast_id, mode) => { - favor_types = mode == raw::StructDefKind::Record; + has_constructor = mode != raw::StructDefKind::Record; StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db) .into() @@ -899,7 +899,7 @@ impl ModCollector<'_, '_> { .unwrap_or(Visibility::Public); self.def_collector.update( self.module_id, - &[(name, PerNs::from_def(def, vis, favor_types))], + &[(name, PerNs::from_def(def, vis, has_constructor))], vis, ) } -- cgit v1.2.3 From cf821cc33271b3a133ea3b3775f86573aa2514cb Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 5 May 2020 01:19:54 +0800 Subject: Change union resolve types only --- crates/ra_hir_def/src/item_scope.rs | 2 +- crates/ra_hir_def/src/nameres/tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 954f2542a..7792ed709 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -156,7 +156,7 @@ impl PerNs { ModuleDefId::ModuleId(_) => PerNs::types(def, v), ModuleDefId::FunctionId(_) => PerNs::values(def, v), ModuleDefId::AdtId(adt) => match adt { - AdtId::UnionId(_) => PerNs::both(def, def, v), + AdtId::UnionId(_) => PerNs::types(def, v), AdtId::EnumId(_) => PerNs::types(def, v), AdtId::StructId(_) => { if !has_constructor { diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 83120fa36..1b66c1aac 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs @@ -67,7 +67,7 @@ fn crate_def_map_smoke_test() { ⋮Baz: t v ⋮E: t ⋮EXT: v - ⋮U: t v + ⋮U: t ⋮ext: v "###) } -- cgit v1.2.3 From 831bb1cf91d69e7e325ecbdab11e6fc80bcae4a4 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Tue, 5 May 2020 09:34:07 +0200 Subject: refactor: use attrsOwner directly in is_cfg_enabled Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_hir_def/src/adt.rs | 17 ++++++++--------- crates/ra_hir_def/src/body.rs | 11 ++++------- crates/ra_hir_def/src/body/lower.rs | 6 ++---- crates/ra_hir_def/src/data.rs | 3 +-- 4 files changed, 15 insertions(+), 22 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index d0912ddaa..2bc34d449 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -118,11 +118,12 @@ fn lower_enum( module_id: ModuleId, ) { let expander = CfgExpander::new(db, ast.file_id, module_id.krate); - let variants = - ast.value.variant_list().into_iter().flat_map(|it| it.variants()).filter(|var| { - let attrs = expander.parse_attrs(var); - expander.is_cfg_enabled(&attrs) - }); + let variants = ast + .value + .variant_list() + .into_iter() + .flat_map(|it| it.variants()) + .filter(|var| expander.is_cfg_enabled(var)); for var in variants { trace.alloc( || var.clone(), @@ -215,8 +216,7 @@ fn lower_struct( match &ast.value { ast::StructKind::Tuple(fl) => { for (i, fd) in fl.fields().enumerate() { - let attrs = expander.parse_attrs(&fd); - if !expander.is_cfg_enabled(&attrs) { + if !expander.is_cfg_enabled(&fd) { continue; } @@ -233,8 +233,7 @@ fn lower_struct( } ast::StructKind::Record(fl) => { for fd in fl.fields() { - let attrs = expander.parse_attrs(&fd); - if !expander.is_cfg_enabled(&attrs) { + if !expander.is_cfg_enabled(&fd) { continue; } diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 4edaad960..f5a7305dc 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -60,7 +60,8 @@ impl CfgExpander { Attrs::new(owner, &self.hygiene) } - pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { + pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { + let attrs = self.parse_attrs(owner); attrs.is_cfg_enabled(&self.cfg_options) } } @@ -141,12 +142,8 @@ impl Expander { InFile { file_id: self.current_file_id, value } } - pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { - self.cfg_expander.parse_attrs(owner) - } - - pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { - self.cfg_expander.is_cfg_enabled(attrs) + pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { + self.cfg_expander.is_cfg_enabled(owner) } fn parse_path(&mut self, path: ast::Path) -> Option { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 687216dc3..8f5fa1b55 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -162,8 +162,7 @@ impl ExprCollector<'_> { fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { let syntax_ptr = AstPtr::new(&expr); - let attrs = self.expander.parse_attrs(&expr); - if !self.expander.is_cfg_enabled(&attrs) { + if !self.expander.is_cfg_enabled(&expr) { return self.missing_expr(); } match expr { @@ -329,8 +328,7 @@ impl ExprCollector<'_> { .fields() .inspect(|field| field_ptrs.push(AstPtr::new(field))) .filter_map(|field| { - let attrs = self.expander.parse_attrs(&field); - if !self.expander.is_cfg_enabled(&attrs) { + if !self.expander.is_cfg_enabled(&field) { return None; } let name = field.field_name()?.as_name(); diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index d4cba4d05..2dbae04d3 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -335,8 +335,7 @@ fn collect_items( .filter_map(|item_node| match item_node { ast::ImplItem::FnDef(it) => { let name = it.name().map_or_else(Name::missing, |it| it.as_name()); - let attrs = expander.parse_attrs(&it); - if !expander.is_cfg_enabled(&attrs) { + if !expander.is_cfg_enabled(&it) { return None; } let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } -- cgit v1.2.3 From 07de8ea165deb37ca9c42e66d2d3ecac57756ec6 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 5 May 2020 23:01:07 +0800 Subject: invert if --- crates/ra_hir_def/src/item_scope.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 7792ed709..fc15948ad 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -159,10 +159,10 @@ impl PerNs { AdtId::UnionId(_) => PerNs::types(def, v), AdtId::EnumId(_) => PerNs::types(def, v), AdtId::StructId(_) => { - if !has_constructor { - PerNs::types(def, v) - } else { + if has_constructor { PerNs::both(def, def, v) + } else { + PerNs::types(def, v) } } }, -- cgit v1.2.3 From fe52f8f0281c0f56955871863a6e0c14732540f9 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Tue, 5 May 2020 17:43:28 +0200 Subject: add doctest support #4317 Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_ide/src/runnables.rs | 43 ++++++++++++++++++++++++++ crates/rust-analyzer/src/cargo_target_spec.rs | 26 ++++++++++++---- crates/rust-analyzer/src/main_loop/handlers.rs | 2 ++ 3 files changed, 65 insertions(+), 6 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 38637c19c..fa8a9d92c 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs @@ -9,6 +9,7 @@ use ra_syntax::{ }; use crate::FileId; +use ast::DocCommentsOwner; use std::fmt::Display; #[derive(Debug)] @@ -37,6 +38,7 @@ pub enum RunnableKind { Test { test_id: TestId, attr: TestAttr }, TestMod { path: String }, Bench { test_id: TestId }, + DocTest { test_id: TestId }, Bin, } @@ -81,6 +83,8 @@ fn runnable_fn(sema: &Semantics, fn_def: ast::FnDef) -> Option bool { .any(|attribute_text| attribute_text.contains("test")) } +fn has_doc_test(fn_def: &ast::FnDef) -> bool { + fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```")) +} + fn runnable_mod(sema: &Semantics, module: ast::Module) -> Option { let has_test_function = module .item_list()? @@ -194,6 +202,41 @@ mod tests { ); } + #[test] + fn test_runnables_doc_test() { + let (analysis, pos) = analysis_and_position( + r#" + //- /lib.rs + <|> //empty + fn main() {} + + /// ``` + /// let x = 5; + /// ``` + fn foo() {} + "#, + ); + let runnables = analysis.runnables(pos.file_id).unwrap(); + assert_debug_snapshot!(&runnables, + @r###" + [ + Runnable { + range: 1..21, + kind: Bin, + }, + Runnable { + range: 22..64, + kind: DocTest { + test_id: Path( + "foo", + ), + }, + }, + ] + "### + ); + } + #[test] fn test_runnables_module() { let (analysis, pos) = analysis_and_position( diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index 10c25666a..5e5a17943 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs @@ -27,7 +27,7 @@ impl CargoTargetSpec { RunnableKind::Test { test_id, attr } => { args.push("test".to_string()); if let Some(spec) = spec { - spec.push_to(&mut args); + spec.push_to(&mut args, kind); } extra_args.push(test_id.to_string()); if let TestId::Path(_) = test_id { @@ -35,13 +35,13 @@ impl CargoTargetSpec { } extra_args.push("--nocapture".to_string()); if attr.ignore { - extra_args.push("--ignored".to_string()) + extra_args.push("--ignored".to_string()); } } RunnableKind::TestMod { path } => { args.push("test".to_string()); if let Some(spec) = spec { - spec.push_to(&mut args); + spec.push_to(&mut args, kind); } extra_args.push(path.to_string()); extra_args.push("--nocapture".to_string()); @@ -49,7 +49,7 @@ impl CargoTargetSpec { RunnableKind::Bench { test_id } => { args.push("bench".to_string()); if let Some(spec) = spec { - spec.push_to(&mut args); + spec.push_to(&mut args, kind); } extra_args.push(test_id.to_string()); if let TestId::Path(_) = test_id { @@ -57,10 +57,19 @@ impl CargoTargetSpec { } extra_args.push("--nocapture".to_string()); } + RunnableKind::DocTest { test_id } => { + args.push("test".to_string()); + args.push("--doc".to_string()); + if let Some(spec) = spec { + spec.push_to(&mut args, kind); + } + extra_args.push(test_id.to_string()); + extra_args.push("--nocapture".to_string()); + } RunnableKind::Bin => { args.push("run".to_string()); if let Some(spec) = spec { - spec.push_to(&mut args); + spec.push_to(&mut args, kind); } } } @@ -91,9 +100,14 @@ impl CargoTargetSpec { Ok(res) } - pub(crate) fn push_to(self, buf: &mut Vec) { + pub(crate) fn push_to(self, buf: &mut Vec, kind: &RunnableKind) { buf.push("--package".to_string()); buf.push(self.package); + + // Can't mix --doc with other target flags + if let RunnableKind::DocTest { .. } = kind { + return; + } match self.target_kind { TargetKind::Bin => { buf.push("--bin".to_string()); diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index c7a96ba93..15e8305f8 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs @@ -835,6 +835,7 @@ pub fn handle_code_lens( for runnable in world.analysis().runnables(file_id)? { let title = match &runnable.kind { RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => "▶️\u{fe0e}Run Test", + RunnableKind::DocTest { .. } => "▶️\u{fe0e}Run Doctest", RunnableKind::Bench { .. } => "Run Bench", RunnableKind::Bin => "Run", } @@ -1018,6 +1019,7 @@ fn to_lsp_runnable( RunnableKind::Test { test_id, .. } => format!("test {}", test_id), RunnableKind::TestMod { path } => format!("test-mod {}", path), RunnableKind::Bench { test_id } => format!("bench {}", test_id), + RunnableKind::DocTest { test_id, .. } => format!("doctest {}", test_id), RunnableKind::Bin => "run binary".to_string(), }; Ok(req::Runnable { -- cgit v1.2.3 From 92665358cd98913e3fef8294e1889cc0bb919e3f Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 5 May 2020 23:56:10 +0800 Subject: Rename ImplItem to AssocItem --- .../src/handlers/add_missing_impl_members.rs | 26 ++++++------ crates/ra_assists/src/handlers/add_new.rs | 4 +- crates/ra_assists/src/utils.rs | 10 ++--- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir_def/src/data.rs | 18 ++++----- crates/ra_hir_ty/src/tests/macros.rs | 4 +- .../src/completion/complete_qualified_path.rs | 2 +- .../ra_ide/src/completion/complete_trait_impl.rs | 46 ++++++++++++---------- crates/ra_mbe/src/syntax_bridge.rs | 2 +- crates/ra_syntax/src/ast/edit.rs | 6 +-- crates/ra_syntax/src/ast/generated/nodes.rs | 36 ++++++++--------- 11 files changed, 81 insertions(+), 75 deletions(-) (limited to 'crates') diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index e466c9a86..e47feda71 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs @@ -10,7 +10,7 @@ use ra_syntax::{ use crate::{ ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, - utils::{get_missing_impl_items, resolve_target_trait}, + utils::{get_missing_assoc_items, resolve_target_trait}, Assist, AssistCtx, AssistId, }; @@ -112,25 +112,25 @@ fn add_missing_impl_members_inner( let trait_ = resolve_target_trait(&ctx.sema, &impl_node)?; - let def_name = |item: &ast::ImplItem| -> Option { + let def_name = |item: &ast::AssocItem| -> Option { match item { - ast::ImplItem::FnDef(def) => def.name(), - ast::ImplItem::TypeAliasDef(def) => def.name(), - ast::ImplItem::ConstDef(def) => def.name(), + ast::AssocItem::FnDef(def) => def.name(), + ast::AssocItem::TypeAliasDef(def) => def.name(), + ast::AssocItem::ConstDef(def) => def.name(), } .map(|it| it.text().clone()) }; - let missing_items = get_missing_impl_items(&ctx.sema, &impl_node) + let missing_items = get_missing_assoc_items(&ctx.sema, &impl_node) .iter() .map(|i| match i { - hir::AssocItem::Function(i) => ast::ImplItem::FnDef(i.source(ctx.db).value), - hir::AssocItem::TypeAlias(i) => ast::ImplItem::TypeAliasDef(i.source(ctx.db).value), - hir::AssocItem::Const(i) => ast::ImplItem::ConstDef(i.source(ctx.db).value), + hir::AssocItem::Function(i) => ast::AssocItem::FnDef(i.source(ctx.db).value), + hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAliasDef(i.source(ctx.db).value), + hir::AssocItem::Const(i) => ast::AssocItem::ConstDef(i.source(ctx.db).value), }) .filter(|t| def_name(&t).is_some()) .filter(|t| match t { - ast::ImplItem::FnDef(def) => match mode { + ast::AssocItem::FnDef(def) => match mode { AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(), AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(), }, @@ -145,7 +145,7 @@ fn add_missing_impl_members_inner( let sema = ctx.sema; ctx.add_assist(AssistId(assist_id), label, |edit| { - let n_existing_items = impl_item_list.impl_items().count(); + let n_existing_items = impl_item_list.assoc_items().count(); let source_scope = sema.scope_for_def(trait_); let target_scope = sema.scope(impl_item_list.syntax()); let ast_transform = QualifyPaths::new(&target_scope, &source_scope) @@ -154,13 +154,13 @@ fn add_missing_impl_members_inner( .into_iter() .map(|it| ast_transform::apply(&*ast_transform, it)) .map(|it| match it { - ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), + ast::AssocItem::FnDef(def) => ast::AssocItem::FnDef(add_body(def)), _ => it, }) .map(|it| edit::remove_attrs_and_docs(&it)); let new_impl_item_list = impl_item_list.append_items(items); let cursor_position = { - let first_new_item = new_impl_item_list.impl_items().nth(n_existing_items).unwrap(); + let first_new_item = new_impl_item_list.assoc_items().nth(n_existing_items).unwrap(); first_new_item.syntax().text_range().start() }; diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index 0f9174a29..e8a36c7de 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs @@ -162,8 +162,8 @@ fn find_struct_impl(ctx: &AssistCtx, strukt: &ast::StructDef) -> Option bool { if let Some(il) = imp.item_list() { - for item in il.impl_items() { - if let ast::ImplItem::FnDef(f) = item { + for item in il.assoc_items() { + if let ast::AssocItem::FnDef(f) = item { if let Some(name) = f.name() { if name.text().eq_ignore_ascii_case("new") { return true; diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 6be704ce3..2f15a3f15 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs @@ -13,7 +13,7 @@ use rustc_hash::FxHashSet; pub(crate) use insert_use::insert_use_statement; -pub fn get_missing_impl_items( +pub fn get_missing_assoc_items( sema: &Semantics, impl_def: &ast::ImplDef, ) -> Vec { @@ -23,21 +23,21 @@ pub fn get_missing_impl_items( let mut impl_type = FxHashSet::default(); if let Some(item_list) = impl_def.item_list() { - for item in item_list.impl_items() { + for item in item_list.assoc_items() { match item { - ast::ImplItem::FnDef(f) => { + ast::AssocItem::FnDef(f) => { if let Some(n) = f.name() { impl_fns_consts.insert(n.syntax().to_string()); } } - ast::ImplItem::TypeAliasDef(t) => { + ast::AssocItem::TypeAliasDef(t) => { if let Some(n) = t.name() { impl_type.insert(n.syntax().to_string()); } } - ast::ImplItem::ConstDef(c) => { + ast::AssocItem::ConstDef(c) => { if let Some(n) = c.name() { impl_fns_consts.insert(n.syntax().to_string()); } diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index a004363ee..5f480c304 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -1211,7 +1211,7 @@ impl Type { // This would be nicer if it just returned an iterator, but that runs into // lifetime problems, because we need to borrow temp `CrateImplDefs`. - pub fn iterate_impl_items( + pub fn iterate_assoc_items( self, db: &dyn HirDatabase, krate: Crate, diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 2dbae04d3..e7eb2bb11 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -9,7 +9,7 @@ use hir_expand::{ }; use ra_prof::profile; use ra_syntax::ast::{ - self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, + self, AssocItem, AstNode, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, VisibilityOwner, }; @@ -164,7 +164,7 @@ impl TraitData { items.extend(collect_items( db, &mut expander, - item_list.impl_items(), + item_list.assoc_items(), src.file_id, container, )); @@ -219,7 +219,7 @@ impl ImplData { if let Some(item_list) = src.value.item_list() { let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); items.extend( - collect_items(db, &mut expander, item_list.impl_items(), src.file_id, container) + collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container) .into_iter() .map(|(_, item)| item), ); @@ -304,7 +304,7 @@ fn collect_items_in_macro( let mut res = collect_items( db, expander, - items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), + items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())), items.file_id, container, ); @@ -325,15 +325,15 @@ fn collect_items_in_macro( fn collect_items( db: &dyn DefDatabase, expander: &mut Expander, - impl_items: impl Iterator, + assoc_items: impl Iterator, file_id: crate::HirFileId, container: AssocContainerId, ) -> Vec<(Name, AssocItemId)> { let items = db.ast_id_map(file_id); - impl_items + assoc_items .filter_map(|item_node| match item_node { - ast::ImplItem::FnDef(it) => { + ast::AssocItem::FnDef(it) => { let name = it.name().map_or_else(Name::missing, |it| it.as_name()); if !expander.is_cfg_enabled(&it) { return None; @@ -342,13 +342,13 @@ fn collect_items( .intern(db); Some((name, def.into())) } - ast::ImplItem::ConstDef(it) => { + ast::AssocItem::ConstDef(it) => { let name = it.name().map_or_else(Name::missing, |it| it.as_name()); let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } .intern(db); Some((name, def.into())) } - ast::ImplItem::TypeAliasDef(it) => { + ast::AssocItem::TypeAliasDef(it) => { let name = it.name().map_or_else(Name::missing, |it| it.as_name()); let def = TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 29e38a06c..07398ddcc 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -269,7 +269,7 @@ fn test() { S.foo()<|>; } } #[test] -fn infer_impl_items_generated_by_macros() { +fn infer_assoc_items_generated_by_macros() { let t = type_at( r#" //- /main.rs @@ -288,7 +288,7 @@ fn test() { S.foo()<|>; } } #[test] -fn infer_impl_items_generated_by_macros_chain() { +fn infer_assoc_items_generated_by_macros_chain() { let t = type_at( r#" //- /main.rs diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs index d9ea92ef8..7fcd22525 100644 --- a/crates/ra_ide/src/completion/complete_qualified_path.rs +++ b/crates/ra_ide/src/completion/complete_qualified_path.rs @@ -84,7 +84,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon }); // Iterate assoc types separately - ty.iterate_impl_items(ctx.db, krate, |item| { + ty.iterate_assoc_items(ctx.db, krate, |item| { if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { return None; } diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index ee32d1ff6..039df03e0 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs @@ -32,7 +32,7 @@ //! ``` use hir::{self, Docs, HasSource}; -use ra_assists::utils::get_missing_impl_items; +use ra_assists::utils::get_missing_assoc_items; use ra_syntax::{ ast::{self, edit, ImplDef}, AstNode, SyntaxKind, SyntaxNode, TextRange, T, @@ -50,7 +50,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext if let Some((trigger, impl_def)) = completion_match(ctx) { match trigger.kind() { SyntaxKind::NAME_REF => { - get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item { + get_missing_assoc_items(&ctx.sema, &impl_def).iter().for_each(|item| match item { hir::AssocItem::Function(fn_item) => { add_function_impl(&trigger, acc, ctx, &fn_item) } @@ -64,34 +64,40 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext } SyntaxKind::FN_DEF => { - for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( - |item| match item { - hir::AssocItem::Function(fn_item) => Some(fn_item), - _ => None, - }, - ) { + for missing_fn in + get_missing_assoc_items(&ctx.sema, &impl_def).iter().filter_map(|item| { + match item { + hir::AssocItem::Function(fn_item) => Some(fn_item), + _ => None, + } + }) + { add_function_impl(&trigger, acc, ctx, &missing_fn); } } SyntaxKind::TYPE_ALIAS_DEF => { - for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( - |item| match item { - hir::AssocItem::TypeAlias(type_item) => Some(type_item), - _ => None, - }, - ) { + for missing_fn in + get_missing_assoc_items(&ctx.sema, &impl_def).iter().filter_map(|item| { + match item { + hir::AssocItem::TypeAlias(type_item) => Some(type_item), + _ => None, + } + }) + { add_type_alias_impl(&trigger, acc, ctx, &missing_fn); } } SyntaxKind::CONST_DEF => { - for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( - |item| match item { - hir::AssocItem::Const(const_item) => Some(const_item), - _ => None, - }, - ) { + for missing_fn in + get_missing_assoc_items(&ctx.sema, &impl_def).iter().filter_map(|item| { + match item { + hir::AssocItem::Const(const_item) => Some(const_item), + _ => None, + } + }) + { add_const_impl(&trigger, acc, ctx, &missing_fn); } } diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index bb28acfd9..fc4133a67 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -63,7 +63,7 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke // * Items(SmallVec<[P; 1]>) -> token_tree_to_items // // * TraitItems(SmallVec<[ast::TraitItem; 1]>) -// * ImplItems(SmallVec<[ast::ImplItem; 1]>) +// * AssocItems(SmallVec<[ast::AssocItem; 1]>) // * ForeignItems(SmallVec<[ast::ForeignItem; 1]> pub fn token_tree_to_syntax_node( diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index c507dc683..3e6dd6061 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs @@ -79,7 +79,7 @@ where impl ast::ItemList { #[must_use] - pub fn append_items(&self, items: impl IntoIterator) -> ast::ItemList { + pub fn append_items(&self, items: impl IntoIterator) -> ast::ItemList { let mut res = self.clone(); if !self.syntax().text().contains_char('\n') { res = make_multiline(res); @@ -89,8 +89,8 @@ impl ast::ItemList { } #[must_use] - pub fn append_item(&self, item: ast::ImplItem) -> ast::ItemList { - let (indent, position) = match self.impl_items().last() { + pub fn append_item(&self, item: ast::AssocItem) -> ast::ItemList { + let (indent, position) = match self.assoc_items().last() { Some(it) => ( leading_indent(it.syntax()).unwrap_or_default().to_string(), InsertPosition::After(it.syntax().clone().into()), diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index c2cc25958..b00c15608 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs @@ -196,7 +196,7 @@ pub struct ItemList { impl ast::ModuleItemOwner for ItemList {} impl ItemList { pub fn l_curly_token(&self) -> Option { support::token(&self.syntax, T!['{']) } - pub fn impl_items(&self) -> AstChildren { support::children(&self.syntax) } + pub fn assoc_items(&self) -> AstChildren { support::children(&self.syntax) } pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } @@ -1429,13 +1429,13 @@ impl ast::AttrsOwner for ModuleItem {} impl ast::VisibilityOwner for ModuleItem {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum ImplItem { +pub enum AssocItem { FnDef(FnDef), TypeAliasDef(TypeAliasDef), ConstDef(ConstDef), } -impl ast::NameOwner for ImplItem {} -impl ast::AttrsOwner for ImplItem {} +impl ast::NameOwner for AssocItem {} +impl ast::AttrsOwner for AssocItem {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ExternItem { @@ -3167,16 +3167,16 @@ impl AstNode for ModuleItem { } } } -impl From for ImplItem { - fn from(node: FnDef) -> ImplItem { ImplItem::FnDef(node) } +impl From for AssocItem { + fn from(node: FnDef) -> AssocItem { AssocItem::FnDef(node) } } -impl From for ImplItem { - fn from(node: TypeAliasDef) -> ImplItem { ImplItem::TypeAliasDef(node) } +impl From for AssocItem { + fn from(node: TypeAliasDef) -> AssocItem { AssocItem::TypeAliasDef(node) } } -impl From for ImplItem { - fn from(node: ConstDef) -> ImplItem { ImplItem::ConstDef(node) } +impl From for AssocItem { + fn from(node: ConstDef) -> AssocItem { AssocItem::ConstDef(node) } } -impl AstNode for ImplItem { +impl AstNode for AssocItem { fn can_cast(kind: SyntaxKind) -> bool { match kind { FN_DEF | TYPE_ALIAS_DEF | CONST_DEF => true, @@ -3185,18 +3185,18 @@ impl AstNode for ImplItem { } fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { - FN_DEF => ImplItem::FnDef(FnDef { syntax }), - TYPE_ALIAS_DEF => ImplItem::TypeAliasDef(TypeAliasDef { syntax }), - CONST_DEF => ImplItem::ConstDef(ConstDef { syntax }), + FN_DEF => AssocItem::FnDef(FnDef { syntax }), + TYPE_ALIAS_DEF => AssocItem::TypeAliasDef(TypeAliasDef { syntax }), + CONST_DEF => AssocItem::ConstDef(ConstDef { syntax }), _ => return None, }; Some(res) } fn syntax(&self) -> &SyntaxNode { match self { - ImplItem::FnDef(it) => &it.syntax, - ImplItem::TypeAliasDef(it) => &it.syntax, - ImplItem::ConstDef(it) => &it.syntax, + AssocItem::FnDef(it) => &it.syntax, + AssocItem::TypeAliasDef(it) => &it.syntax, + AssocItem::ConstDef(it) => &it.syntax, } } } @@ -3641,7 +3641,7 @@ impl std::fmt::Display for ModuleItem { std::fmt::Display::fmt(self.syntax(), f) } } -impl std::fmt::Display for ImplItem { +impl std::fmt::Display for AssocItem { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } -- cgit v1.2.3 From 0ab4340cdb31ac4d50f039f0a56ebaff86710eb7 Mon Sep 17 00:00:00 2001 From: Christophe MASSOLIN Date: Tue, 5 May 2020 18:01:54 +0200 Subject: Rename `defaultTarget` to target --- crates/ra_project_model/src/cargo_workspace.rs | 6 +++--- crates/rust-analyzer/src/config.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'crates') diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 31499b468..59f46a2a0 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -58,7 +58,7 @@ pub struct CargoConfig { pub load_out_dirs_from_check: bool, /// rustc target - pub default_target: Option, + pub target: Option, } impl Default for CargoConfig { @@ -68,7 +68,7 @@ impl Default for CargoConfig { all_features: true, features: Vec::new(), load_out_dirs_from_check: false, - default_target: None, + target: None, } } } @@ -164,7 +164,7 @@ impl CargoWorkspace { if let Some(parent) = cargo_toml.parent() { meta.current_dir(parent); } - if let Some(target) = cargo_features.default_target.as_ref() { + if let Some(target) = cargo_features.target.as_ref() { meta.other_options(&[String::from("--filter-platform"), target.clone()]); } let meta = meta.exec().with_context(|| { diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 25404ef90..4b2570d4d 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -134,7 +134,7 @@ impl Config { set(value, "/cargo/allFeatures", &mut self.cargo.all_features); set(value, "/cargo/features", &mut self.cargo.features); set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); - set(value, "/cargo/defaultTarget", &mut self.cargo.default_target); + set(value, "/cargo/target", &mut self.cargo.target); match get(value, "/procMacro/enable") { Some(true) => { -- cgit v1.2.3 From 14dde99627119f76fd9970dcd07f883be5bc7101 Mon Sep 17 00:00:00 2001 From: Christophe MASSOLIN Date: Tue, 5 May 2020 18:15:13 +0200 Subject: Pass cargo.target to rustc --- crates/ra_project_model/src/lib.rs | 18 +++++++++++++----- crates/rust-analyzer/src/cli/load_cargo.rs | 2 +- crates/rust-analyzer/src/world.rs | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) (limited to 'crates') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 731cbd291..8fa895aa6 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -543,7 +543,7 @@ impl ProjectWorkspace { } } -pub fn get_rustc_cfg_options() -> CfgOptions { +pub fn get_rustc_cfg_options(target: Option<&String>) -> CfgOptions { let mut cfg_options = CfgOptions::default(); // Some nightly-only cfgs, which are required for stdlib @@ -558,10 +558,18 @@ pub fn get_rustc_cfg_options() -> CfgOptions { match (|| -> Result { // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. - let output = Command::new("rustc") - .args(&["--print", "cfg", "-O"]) - .output() - .context("Failed to get output from rustc --print cfg -O")?; + let output = if let Some(target) = target { + Command::new("rustc") + .args(&["--print", "cfg", "-O", "--target", target.as_str()]) + .output() + .context("Failed to get output from rustc --print cfg -O")? + } else { + Command::new("rustc") + .args(&["--print", "cfg", "-O"]) + .output() + .context("Failed to get output from rustc --print cfg -O")? + }; + if !output.status.success() { bail!( "rustc --print cfg -O exited with exit code ({})", diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index d0a71120a..023ced6cf 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs @@ -149,7 +149,7 @@ pub(crate) fn load( // FIXME: cfg options? let default_cfg_options = { - let mut opts = get_rustc_cfg_options(); + let mut opts = get_rustc_cfg_options(None); opts.insert_atom("test".into()); opts.insert_atom("debug_assertion".into()); opts diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index 34941931b..16020648d 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs @@ -131,7 +131,7 @@ impl WorldState { // FIXME: Read default cfgs from config let default_cfg_options = { - let mut opts = get_rustc_cfg_options(); + let mut opts = get_rustc_cfg_options(config.cargo.target.as_ref()); opts.insert_atom("test".into()); opts.insert_atom("debug_assertion".into()); opts -- cgit v1.2.3 From 04e32fbffca22e632594218e8dfafdc39281c6f7 Mon Sep 17 00:00:00 2001 From: Christophe MASSOLIN Date: Tue, 5 May 2020 18:23:47 +0200 Subject: Remove code duplicates --- crates/ra_project_model/src/lib.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'crates') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 8fa895aa6..c2b33c1dc 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -558,18 +558,12 @@ pub fn get_rustc_cfg_options(target: Option<&String>) -> CfgOptions { match (|| -> Result { // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. - let output = if let Some(target) = target { - Command::new("rustc") - .args(&["--print", "cfg", "-O", "--target", target.as_str()]) - .output() - .context("Failed to get output from rustc --print cfg -O")? - } else { - Command::new("rustc") - .args(&["--print", "cfg", "-O"]) - .output() - .context("Failed to get output from rustc --print cfg -O")? - }; - + let mut cmd = Command::new("rustc"); + cmd.args(&["--print", "cfg", "-O"]); + if let Some(target) = target { + cmd.args(&["--target", target.as_str()]); + } + let output = cmd.output().context("Failed to get output from rustc --print cfg -O")?; if !output.status.success() { bail!( "rustc --print cfg -O exited with exit code ({})", -- cgit v1.2.3 From 7ec1b63f813e45f26668c2d6d803ec72c3c75738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 5 May 2020 19:22:01 +0300 Subject: Add tests for #4306 --- crates/rust-analyzer/src/main_loop.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'crates') diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index b163ea848..b77f0c5a9 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -1083,5 +1083,17 @@ mod tests { assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n"); run(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); assert_eq!(text, "the quick \nthey have quiet dreams\n"); + + text = String::from("❤️"); + run(&mut text, c![0, 0; 0, 0 => "a"]); + assert_eq!(text, "a❤️"); + + text = String::from("a\nb"); + run(&mut text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); + assert_eq!(text, "adcb"); + + text = String::from("a\nb"); + run(&mut text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); + assert_eq!(text, "ațc\ncb"); } } -- cgit v1.2.3 From 1d794e859028a71d182daf2fa5826aeeeab2876b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 5 May 2020 20:29:04 +0300 Subject: Fix column conversion for supplementary plane characters --- crates/ra_ide_db/src/line_index.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide_db/src/line_index.rs b/crates/ra_ide_db/src/line_index.rs index 212cb7b5b..c7c744fce 100644 --- a/crates/ra_ide_db/src/line_index.rs +++ b/crates/ra_ide_db/src/line_index.rs @@ -31,9 +31,19 @@ pub(crate) struct Utf16Char { } impl Utf16Char { + /// Returns the length in 8-bit UTF-8 code units. fn len(&self) -> TextSize { self.end - self.start } + + /// Returns the length in 16-bit UTF-16 code units. + fn len_utf16(&self) -> usize { + if self.len() == TextSize::from(4) { + 2 + } else { + 1 + } + } } impl LineIndex { @@ -110,7 +120,7 @@ impl LineIndex { if let Some(utf16_chars) = self.utf16_lines.get(&line) { for c in utf16_chars { if c.end <= col { - res -= usize::from(c.len()) - 1; + res -= usize::from(c.len()) - c.len_utf16(); } else { // From here on, all utf16 characters come *after* the character we are mapping, // so we don't need to take them into account @@ -125,7 +135,7 @@ impl LineIndex { if let Some(utf16_chars) = self.utf16_lines.get(&line) { for c in utf16_chars { if col > u32::from(c.start) { - col += u32::from(c.len()) - 1; + col += u32::from(c.len()) - c.len_utf16() as u32; } else { // From here on, all utf16 characters come *after* the character we are mapping, // so we don't need to take them into account @@ -204,6 +214,9 @@ const C: char = 'メ'; // UTF-16 to UTF-8 assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21)); + + let col_index = LineIndex::new("a𐐏b"); + assert_eq!(col_index.utf16_to_utf8_col(0, 3), TextSize::from(5)); } #[test] -- cgit v1.2.3 From 13c078db9cba8bbbf48918a928cd2533571a7f5d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 May 2020 20:30:33 +0200 Subject: Flip Assist::new arguments --- crates/ra_assists/src/assist_ctx.rs | 4 ++-- crates/ra_assists/src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'crates') diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index da2880037..d6f585d0e 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -100,7 +100,7 @@ impl<'a> AssistCtx<'a> { label: impl Into, f: impl FnOnce(&mut ActionBuilder), ) -> Option { - let label = AssistLabel::new(label.into(), id); + let label = AssistLabel::new(id, label.into()); let mut info = AssistInfo::new(label); if self.should_compute_edit { @@ -157,7 +157,7 @@ impl<'a> AssistGroup<'a> { label: impl Into, f: impl FnOnce(&mut ActionBuilder), ) { - let label = AssistLabel::new(label.into(), id); + let label = AssistLabel::new(id, label.into()); let mut info = AssistInfo::new(label).with_group(GroupLabel(self.group_name.clone())); if self.ctx.should_compute_edit { diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index c5df86600..6156f4e2c 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -32,16 +32,16 @@ pub struct AssistId(pub &'static str); #[derive(Debug, Clone)] pub struct AssistLabel { + pub id: AssistId, /// Short description of the assist, as shown in the UI. pub label: String, - pub id: AssistId, } #[derive(Clone, Debug)] pub struct GroupLabel(pub String); impl AssistLabel { - pub(crate) fn new(label: String, id: AssistId) -> AssistLabel { + pub(crate) fn new(id: AssistId, label: String) -> AssistLabel { // FIXME: make fields private, so that this invariant can't be broken assert!(label.starts_with(|c: char| c.is_uppercase())); AssistLabel { label, id } -- cgit v1.2.3 From d5b9282ede9947e5743608054e09222033a4e6e4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 May 2020 20:33:10 +0200 Subject: Minor rename --- crates/ra_assists/src/assist_ctx.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index d6f585d0e..1020fed29 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -116,7 +116,7 @@ impl<'a> AssistCtx<'a> { } pub(crate) fn add_assist_group(self, group_name: impl Into) -> AssistGroup<'a> { - AssistGroup { ctx: self, group_name: group_name.into(), assists: Vec::new() } + AssistGroup { ctx: self, group: group_name.into(), assists: Vec::new() } } pub(crate) fn token_at_offset(&self) -> TokenAtOffset { @@ -146,7 +146,7 @@ impl<'a> AssistCtx<'a> { pub(crate) struct AssistGroup<'a> { ctx: AssistCtx<'a>, - group_name: String, + group: String, assists: Vec, } @@ -159,7 +159,7 @@ impl<'a> AssistGroup<'a> { ) { let label = AssistLabel::new(id, label.into()); - let mut info = AssistInfo::new(label).with_group(GroupLabel(self.group_name.clone())); + let mut info = AssistInfo::new(label).with_group(GroupLabel(self.group.clone())); if self.ctx.should_compute_edit { let action = { let mut edit = ActionBuilder::new(&self.ctx); -- cgit v1.2.3 From 6c2414430aca92f95eda9f0238dce8af2de552af Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 May 2020 20:34:45 +0200 Subject: use GroupLabel for type safety --- crates/ra_assists/src/assist_ctx.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 1020fed29..d88ae4413 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -116,7 +116,8 @@ impl<'a> AssistCtx<'a> { } pub(crate) fn add_assist_group(self, group_name: impl Into) -> AssistGroup<'a> { - AssistGroup { ctx: self, group: group_name.into(), assists: Vec::new() } + let group = GroupLabel(group_name.into()); + AssistGroup { ctx: self, group, assists: Vec::new() } } pub(crate) fn token_at_offset(&self) -> TokenAtOffset { @@ -146,7 +147,7 @@ impl<'a> AssistCtx<'a> { pub(crate) struct AssistGroup<'a> { ctx: AssistCtx<'a>, - group: String, + group: GroupLabel, assists: Vec, } @@ -159,7 +160,7 @@ impl<'a> AssistGroup<'a> { ) { let label = AssistLabel::new(id, label.into()); - let mut info = AssistInfo::new(label).with_group(GroupLabel(self.group.clone())); + let mut info = AssistInfo::new(label).with_group(self.group.clone()); if self.ctx.should_compute_edit { let action = { let mut edit = ActionBuilder::new(&self.ctx); -- cgit v1.2.3 From aee22c73c3cafdb6f4b3f97bc483791d4ed2e902 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 May 2020 20:42:52 +0200 Subject: Move group_label where it belongs --- crates/ra_assists/src/assist_ctx.rs | 7 +++---- crates/ra_assists/src/lib.rs | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'crates') diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index d88ae4413..82f61bc8f 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -38,8 +38,7 @@ impl AssistInfo { pub(crate) fn into_resolved(self) -> Option { let label = self.label; - let group_label = self.group_label; - self.action.map(|action| ResolvedAssist { label, group_label, action }) + self.action.map(|action| ResolvedAssist { label, action }) } } @@ -100,7 +99,7 @@ impl<'a> AssistCtx<'a> { label: impl Into, f: impl FnOnce(&mut ActionBuilder), ) -> Option { - let label = AssistLabel::new(id, label.into()); + let label = AssistLabel::new(id, label.into(), None); let mut info = AssistInfo::new(label); if self.should_compute_edit { @@ -158,7 +157,7 @@ impl<'a> AssistGroup<'a> { label: impl Into, f: impl FnOnce(&mut ActionBuilder), ) { - let label = AssistLabel::new(id, label.into()); + let label = AssistLabel::new(id, label.into(), Some(self.group.clone())); let mut info = AssistInfo::new(label).with_group(self.group.clone()); if self.ctx.should_compute_edit { diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 6156f4e2c..1b31d655b 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -35,16 +35,17 @@ pub struct AssistLabel { pub id: AssistId, /// Short description of the assist, as shown in the UI. pub label: String, + pub group: Option, } #[derive(Clone, Debug)] pub struct GroupLabel(pub String); impl AssistLabel { - pub(crate) fn new(id: AssistId, label: String) -> AssistLabel { + pub(crate) fn new(id: AssistId, label: String, group: Option) -> AssistLabel { // FIXME: make fields private, so that this invariant can't be broken assert!(label.starts_with(|c: char| c.is_uppercase())); - AssistLabel { label, id } + AssistLabel { id, label, group } } } @@ -60,7 +61,6 @@ pub struct AssistAction { #[derive(Debug, Clone)] pub struct ResolvedAssist { pub label: AssistLabel, - pub group_label: Option, pub action: AssistAction, } -- cgit v1.2.3 From df00da15c435f3105007146cbbfc9afc34ad311c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 May 2020 20:44:13 +0200 Subject: Fix compilation --- crates/ra_assists/src/lib.rs | 2 +- crates/ra_ide/src/assists.rs | 19 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) (limited to 'crates') diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 1b31d655b..5cec10088 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -17,13 +17,13 @@ mod doc_tests; pub mod utils; pub mod ast_transform; +use hir::Semantics; use ra_db::{FileId, FileRange}; use ra_ide_db::RootDatabase; use ra_syntax::{TextRange, TextSize}; use ra_text_edit::TextEdit; pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler}; -use hir::Semantics; /// Unique identifier of the assist, should not be shown to the user /// directly. diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs index 2b5d11681..389339a03 100644 --- a/crates/ra_ide/src/assists.rs +++ b/crates/ra_ide/src/assists.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use ra_assists::{resolved_assists, AssistAction, AssistLabel}; +use ra_assists::{resolved_assists, AssistAction}; use ra_db::{FilePosition, FileRange}; use ra_ide_db::RootDatabase; @@ -21,27 +21,22 @@ pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec { .into_iter() .map(|assist| { let file_id = frange.file_id; - let assist_label = &assist.label; Assist { - id: assist_label.id, - label: assist_label.label.clone(), - group_label: assist.group_label.map(|it| it.0), - source_change: action_to_edit(assist.action, file_id, assist_label), + id: assist.label.id, + label: assist.label.label.clone(), + group_label: assist.label.group.map(|it| it.0), + source_change: action_to_edit(assist.action, file_id, assist.label.label.clone()), } }) .collect() } -fn action_to_edit( - action: AssistAction, - file_id: FileId, - assist_label: &AssistLabel, -) -> SourceChange { +fn action_to_edit(action: AssistAction, file_id: FileId, label: String) -> SourceChange { let file_id = match action.file { ra_assists::AssistFile::TargetFile(it) => it, _ => file_id, }; let file_edit = SourceFileEdit { file_id, edit: action.edit }; - SourceChange::source_file_edit(assist_label.label.clone(), file_edit) + SourceChange::source_file_edit(label, file_edit) .with_cursor_opt(action.cursor_position.map(|offset| FilePosition { offset, file_id })) } -- cgit v1.2.3 From 3908fad1fe02efedc810d7bd8f765b1434684cef Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 May 2020 20:55:12 +0200 Subject: Normalize naming of diagnostics --- crates/ra_ide/src/diagnostics.rs | 12 ++++++------ crates/ra_ide/src/references/rename.rs | 10 +++++----- crates/ra_ide/src/source_change.rs | 4 +++- crates/ra_ide/src/typing/on_enter.rs | 2 +- crates/rust-analyzer/tests/heavy_tests/main.rs | 16 ++++++++-------- 5 files changed, 23 insertions(+), 21 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index a6b4c2c28..4c04cee07 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs @@ -64,7 +64,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec .unwrap_or_else(|| RelativePath::new("")) .join(&d.candidate); let create_file = FileSystemEdit::CreateFile { source_root, path }; - let fix = SourceChange::file_system_edit("create module", create_file); + let fix = SourceChange::file_system_edit("Create module", create_file); res.borrow_mut().push(Diagnostic { range: sema.diagnostics_range(d).range, message: d.message(), @@ -92,7 +92,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec algo::diff(&d.ast(db).syntax(), &field_list.syntax()).into_text_edit(&mut builder); Some(SourceChange::source_file_edit_from( - "fill struct fields", + "Fill struct fields", file_id, builder.finish(), )) @@ -117,7 +117,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec let node = d.ast(db); let replacement = format!("Ok({})", node.syntax()); let edit = TextEdit::replace(node.syntax().text_range(), replacement); - let fix = SourceChange::source_file_edit_from("wrap with ok", file_id, edit); + let fix = SourceChange::source_file_edit_from("Wrap with ok", file_id, edit); res.borrow_mut().push(Diagnostic { range: sema.diagnostics_range(d).range, message: d.message(), @@ -199,7 +199,7 @@ fn check_struct_shorthand_initialization( message: "Shorthand struct initialization".to_string(), severity: Severity::WeakWarning, fix: Some(SourceChange::source_file_edit( - "use struct shorthand initialization", + "Use struct shorthand initialization", SourceFileEdit { file_id, edit }, )), }); @@ -606,7 +606,7 @@ mod tests { range: 0..8, fix: Some( SourceChange { - label: "create module", + label: "Create module", source_file_edits: [], file_system_edits: [ CreateFile { @@ -655,7 +655,7 @@ mod tests { range: 224..233, fix: Some( SourceChange { - label: "fill struct fields", + label: "Fill struct fields", source_file_edits: [ SourceFileEdit { file_id: FileId( diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 916edaef2..52e55b0a0 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs @@ -122,7 +122,7 @@ fn rename_mod( source_file_edits.extend(ref_edits); } - Some(SourceChange::from_edits("rename", source_file_edits, file_system_edits)) + Some(SourceChange::from_edits("Rename", source_file_edits, file_system_edits)) } fn rename_reference( @@ -141,7 +141,7 @@ fn rename_reference( return None; } - Some(RangeInfo::new(range, SourceChange::source_file_edits("rename", edit))) + Some(RangeInfo::new(range, SourceChange::source_file_edits("Rename", edit))) } #[cfg(test)] @@ -530,7 +530,7 @@ mod tests { RangeInfo { range: 4..7, info: SourceChange { - label: "rename", + label: "Rename", source_file_edits: [ SourceFileEdit { file_id: FileId( @@ -582,7 +582,7 @@ mod tests { RangeInfo { range: 4..7, info: SourceChange { - label: "rename", + label: "Rename", source_file_edits: [ SourceFileEdit { file_id: FileId( @@ -665,7 +665,7 @@ mod tests { RangeInfo { range: 8..11, info: SourceChange { - label: "rename", + label: "Rename", source_file_edits: [ SourceFileEdit { file_id: FileId( diff --git a/crates/ra_ide/src/source_change.rs b/crates/ra_ide/src/source_change.rs index 71b0e8f75..10afd7825 100644 --- a/crates/ra_ide/src/source_change.rs +++ b/crates/ra_ide/src/source_change.rs @@ -35,8 +35,10 @@ impl SourceChange { /// Creates a new SourceChange with the given label, /// containing only the given `SourceFileEdits`. pub(crate) fn source_file_edits>(label: L, edits: Vec) -> Self { + let label = label.into(); + assert!(label.starts_with(char::is_uppercase)); SourceChange { - label: label.into(), + label: label, source_file_edits: edits, file_system_edits: vec![], cursor_position: None, diff --git a/crates/ra_ide/src/typing/on_enter.rs b/crates/ra_ide/src/typing/on_enter.rs index 30c8c5572..725237464 100644 --- a/crates/ra_ide/src/typing/on_enter.rs +++ b/crates/ra_ide/src/typing/on_enter.rs @@ -44,7 +44,7 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option Date: Tue, 5 May 2020 22:14:01 +0200 Subject: Minor cleanups --- crates/ra_assists/src/assist_ctx.rs | 1 - crates/ra_assists/src/lib.rs | 14 +++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'crates') diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 82f61bc8f..89547ce03 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -42,7 +42,6 @@ impl AssistInfo { } } -pub(crate) type AssistHandler = fn(AssistCtx) -> Option; /// `AssistCtx` allows to apply an assist or check if it could be applied. /// diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 5cec10088..ad85f5553 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -23,7 +23,7 @@ use ra_ide_db::RootDatabase; use ra_syntax::{TextRange, TextSize}; use ra_text_edit::TextEdit; -pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler}; +pub(crate) use crate::assist_ctx::{Assist, AssistCtx}; /// Unique identifier of the assist, should not be shown to the user /// directly. @@ -109,7 +109,9 @@ pub fn resolved_assists(db: &RootDatabase, range: FileRange) -> Vec Option; mod add_custom_impl; mod add_derive; @@ -145,12 +147,13 @@ mod handlers { mod reorder_fields; mod unwrap_block; - pub(crate) fn all() -> &'static [AssistHandler] { + pub(crate) fn all() -> &'static [Handler] { &[ // These are alphabetic for the foolish consistency add_custom_impl::add_custom_impl, add_derive::add_derive, add_explicit_type::add_explicit_type, + add_from_impl_for_enum::add_from_impl_for_enum, add_function::add_function, add_impl::add_impl, add_new::add_new, @@ -176,17 +179,18 @@ mod handlers { raw_string::remove_hash, remove_dbg::remove_dbg, remove_mut::remove_mut, + reorder_fields::reorder_fields, replace_if_let_with_match::replace_if_let_with_match, replace_let_with_if_let::replace_let_with_if_let, replace_qualified_name_with_use::replace_qualified_name_with_use, replace_unwrap_with_match::replace_unwrap_with_match, split_import::split_import, - add_from_impl_for_enum::add_from_impl_for_enum, unwrap_block::unwrap_block, // These are manually sorted for better priorities add_missing_impl_members::add_missing_impl_members, add_missing_impl_members::add_missing_default_members, - reorder_fields::reorder_fields, + // Are you sure you want to add new assist here, and not to the + // sorted list above? ] } } -- cgit v1.2.3 From c22660179c3f892a56ad5bacfddd4c2ec563d35e Mon Sep 17 00:00:00 2001 From: guigui64 Date: Tue, 5 May 2020 22:44:39 +0200 Subject: add the allFeatures flag (true by default) --- crates/ra_flycheck/src/lib.rs | 7 +++++-- crates/rust-analyzer/src/config.rs | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/ra_flycheck/src/lib.rs b/crates/ra_flycheck/src/lib.rs index b54a30ab8..f27252949 100644 --- a/crates/ra_flycheck/src/lib.rs +++ b/crates/ra_flycheck/src/lib.rs @@ -24,7 +24,7 @@ pub use crate::conv::url_from_path_with_drive_lowercasing; #[derive(Clone, Debug, PartialEq, Eq)] pub enum FlycheckConfig { - CargoCommand { command: String, all_targets: bool, extra_args: Vec }, + CargoCommand { command: String, all_targets: bool, all_features: bool, extra_args: Vec }, CustomCommand { command: String, args: Vec }, } @@ -215,7 +215,7 @@ impl FlycheckThread { self.check_process = None; let mut cmd = match &self.config { - FlycheckConfig::CargoCommand { command, all_targets, extra_args } => { + FlycheckConfig::CargoCommand { command, all_targets, all_features, extra_args } => { let mut cmd = Command::new(cargo_binary()); cmd.arg(command); cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]); @@ -223,6 +223,9 @@ impl FlycheckThread { if *all_targets { cmd.arg("--all-targets"); } + if *all_features { + cmd.arg("--all-features"); + } cmd.args(extra_args); cmd } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 8d85c60cf..ccc38e3bb 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -89,6 +89,7 @@ impl Default for Config { check: Some(FlycheckConfig::CargoCommand { command: "check".to_string(), all_targets: true, + all_features: true, extra_args: Vec::new(), }), @@ -173,12 +174,13 @@ impl Config { } // otherwise configure command customizations _ => { - if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets }) + if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets, all_features }) = &mut self.check { set(value, "/checkOnSave/extraArgs", extra_args); set(value, "/checkOnSave/command", command); set(value, "/checkOnSave/allTargets", all_targets); + set(value, "/checkOnSave/allFeatures", all_features); } } }; -- cgit v1.2.3 From 4a6fa8f0dfcebbb4ea80394e5e4ca21f076f58f2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 May 2020 23:15:49 +0200 Subject: Rename AtomTextEdit -> Indel --- crates/ra_assists/src/assist_ctx.rs | 4 +- crates/ra_ide/src/completion/completion_context.rs | 4 +- crates/ra_ide/src/completion/completion_item.rs | 4 +- crates/ra_ide_db/src/line_index_utils.rs | 6 +- crates/ra_syntax/src/fuzz.rs | 6 +- crates/ra_syntax/src/lib.rs | 14 +-- crates/ra_syntax/src/parsing/reparsing.rs | 16 +-- crates/ra_text_edit/src/lib.rs | 131 ++++++++++++++++++--- crates/ra_text_edit/src/text_edit.rs | 102 ---------------- crates/rust-analyzer/src/conv.rs | 29 +++-- 10 files changed, 154 insertions(+), 162 deletions(-) delete mode 100644 crates/ra_text_edit/src/text_edit.rs (limited to 'crates') diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 89547ce03..83dd270c6 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -4,14 +4,13 @@ use ra_db::FileRange; use ra_fmt::{leading_indent, reindent}; use ra_ide_db::RootDatabase; use ra_syntax::{ - algo::{self, find_covering_element, find_node_at_offset}, + algo::{self, find_covering_element, find_node_at_offset, SyntaxRewriter}, AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, }; use ra_text_edit::TextEditBuilder; use crate::{AssistAction, AssistFile, AssistId, AssistLabel, GroupLabel, ResolvedAssist}; -use algo::SyntaxRewriter; #[derive(Clone, Debug)] pub(crate) struct Assist(pub(crate) Vec); @@ -42,7 +41,6 @@ impl AssistInfo { } } - /// `AssistCtx` allows to apply an assist or check if it could be applied. /// /// Assists use a somewhat over-engineered approach, given the current needs. The diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index dd87bd119..b6b9627de 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -9,7 +9,7 @@ use ra_syntax::{ SyntaxKind::*, SyntaxNode, SyntaxToken, TextRange, TextSize, }; -use ra_text_edit::AtomTextEdit; +use ra_text_edit::Indel; use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition}; @@ -76,7 +76,7 @@ impl<'a> CompletionContext<'a> { // actual completion. let file_with_fake_ident = { let parse = db.parse(position.file_id); - let edit = AtomTextEdit::insert(position.offset, "intellijRulezz".to_string()); + let edit = Indel::insert(position.offset, "intellijRulezz".to_string()); parse.reparse(&edit).tree() }; let fake_ident_token = diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index 5936fb8f7..383b23ac4 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs @@ -62,8 +62,8 @@ impl fmt::Debug for CompletionItem { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut s = f.debug_struct("CompletionItem"); s.field("label", &self.label()).field("source_range", &self.source_range()); - if self.text_edit().as_atoms().len() == 1 { - let atom = &self.text_edit().as_atoms()[0]; + if self.text_edit().as_indels().len() == 1 { + let atom = &self.text_edit().as_indels()[0]; s.field("delete", &atom.delete); s.field("insert", &atom.insert); } else { diff --git a/crates/ra_ide_db/src/line_index_utils.rs b/crates/ra_ide_db/src/line_index_utils.rs index 039a12c0d..7fa6fc448 100644 --- a/crates/ra_ide_db/src/line_index_utils.rs +++ b/crates/ra_ide_db/src/line_index_utils.rs @@ -10,7 +10,7 @@ use std::convert::TryInto; use ra_syntax::{TextRange, TextSize}; -use ra_text_edit::{AtomTextEdit, TextEdit}; +use ra_text_edit::{Indel, TextEdit}; use crate::line_index::{LineCol, LineIndex, Utf16Char}; @@ -182,14 +182,14 @@ struct TranslatedEdit<'a> { } struct Edits<'a> { - edits: &'a [AtomTextEdit], + edits: &'a [Indel], current: Option>, acc_diff: i64, } impl<'a> Edits<'a> { fn from_text_edit(text_edit: &'a TextEdit) -> Edits<'a> { - let mut x = Edits { edits: text_edit.as_atoms(), current: None, acc_diff: 0 }; + let mut x = Edits { edits: text_edit.as_indels(), current: None, acc_diff: 0 }; x.advance_edit(); x } diff --git a/crates/ra_syntax/src/fuzz.rs b/crates/ra_syntax/src/fuzz.rs index 10fbe3176..39f9b12ab 100644 --- a/crates/ra_syntax/src/fuzz.rs +++ b/crates/ra_syntax/src/fuzz.rs @@ -5,7 +5,7 @@ use std::{ str::{self, FromStr}, }; -use ra_text_edit::AtomTextEdit; +use ra_text_edit::Indel; use crate::{validation, AstNode, SourceFile, TextRange}; @@ -22,7 +22,7 @@ pub fn check_parser(text: &str) { #[derive(Debug, Clone)] pub struct CheckReparse { text: String, - edit: AtomTextEdit, + edit: Indel, edited_text: String, } @@ -43,7 +43,7 @@ impl CheckReparse { TextRange::at(delete_start.try_into().unwrap(), delete_len.try_into().unwrap()); let edited_text = format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]); - let edit = AtomTextEdit { delete, insert }; + let edit = Indel { delete, insert }; Some(CheckReparse { text, edit, edited_text }) } diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index d0234cada..1a7348dac 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs @@ -39,7 +39,7 @@ pub mod fuzz; use std::{marker::PhantomData, sync::Arc}; -use ra_text_edit::AtomTextEdit; +use ra_text_edit::Indel; use stdx::format_to; use crate::syntax_node::GreenNode; @@ -126,13 +126,13 @@ impl Parse { buf } - pub fn reparse(&self, edit: &AtomTextEdit) -> Parse { - self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) + pub fn reparse(&self, indel: &Indel) -> Parse { + self.incremental_reparse(indel).unwrap_or_else(|| self.full_reparse(indel)) } - fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option> { + fn incremental_reparse(&self, indel: &Indel) -> Option> { // FIXME: validation errors are not handled here - parsing::incremental_reparse(self.tree().syntax(), edit, self.errors.to_vec()).map( + parsing::incremental_reparse(self.tree().syntax(), indel, self.errors.to_vec()).map( |(green_node, errors, _reparsed_range)| Parse { green: green_node, errors: Arc::new(errors), @@ -141,8 +141,8 @@ impl Parse { ) } - fn full_reparse(&self, edit: &AtomTextEdit) -> Parse { - let text = edit.apply(self.tree().syntax().text().to_string()); + fn full_reparse(&self, indel: &Indel) -> Parse { + let text = indel.apply(self.tree().syntax().text().to_string()); SourceFile::parse(&text) } } diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs index ffff0a7b2..6257e3f33 100644 --- a/crates/ra_syntax/src/parsing/reparsing.rs +++ b/crates/ra_syntax/src/parsing/reparsing.rs @@ -7,7 +7,7 @@ //! and try to parse only this block. use ra_parser::Reparser; -use ra_text_edit::AtomTextEdit; +use ra_text_edit::Indel; use crate::{ algo, @@ -24,7 +24,7 @@ use crate::{ pub(crate) fn incremental_reparse( node: &SyntaxNode, - edit: &AtomTextEdit, + edit: &Indel, errors: Vec, ) -> Option<(GreenNode, Vec, TextRange)> { if let Some((green, new_errors, old_range)) = reparse_token(node, &edit) { @@ -39,7 +39,7 @@ pub(crate) fn incremental_reparse( fn reparse_token<'node>( root: &'node SyntaxNode, - edit: &AtomTextEdit, + edit: &Indel, ) -> Option<(GreenNode, Vec, TextRange)> { let prev_token = algo::find_covering_element(root, edit.delete).as_token()?.clone(); let prev_token_kind = prev_token.kind(); @@ -88,7 +88,7 @@ fn reparse_token<'node>( fn reparse_block<'node>( root: &'node SyntaxNode, - edit: &AtomTextEdit, + edit: &Indel, ) -> Option<(GreenNode, Vec, TextRange)> { let (node, reparser) = find_reparsable_node(root, edit.delete)?; let text = get_text_after_edit(node.clone().into(), edit); @@ -108,9 +108,9 @@ fn reparse_block<'node>( Some((node.replace_with(green), new_parser_errors, node.text_range())) } -fn get_text_after_edit(element: SyntaxElement, edit: &AtomTextEdit) -> String { +fn get_text_after_edit(element: SyntaxElement, edit: &Indel) -> String { let edit = - AtomTextEdit::replace(edit.delete - element.text_range().start(), edit.insert.clone()); + Indel::replace(edit.delete - element.text_range().start(), edit.insert.clone()); let text = match element { NodeOrToken::Token(token) => token.text().to_string(), @@ -167,7 +167,7 @@ fn merge_errors( old_errors: Vec, new_errors: Vec, range_before_reparse: TextRange, - edit: &AtomTextEdit, + edit: &Indel, ) -> Vec { let mut res = Vec::new(); @@ -198,7 +198,7 @@ mod tests { fn do_check(before: &str, replace_with: &str, reparsed_len: u32) { let (range, before) = extract_range(before); - let edit = AtomTextEdit::replace(range, replace_with.to_owned()); + let edit = Indel::replace(range, replace_with.to_owned()); let after = edit.apply(before.clone()); let fully_reparsed = SourceFile::parse(&after); diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs index e656260c7..c41bf324b 100644 --- a/crates/ra_text_edit/src/lib.rs +++ b/crates/ra_text_edit/src/lib.rs @@ -1,30 +1,40 @@ -//! FIXME: write short doc here - -mod text_edit; +//! Representation of a `TextEdit`. +//! +//! `rust-analyzer` never mutates text itself and only sends diffs to clients, +//! so `TextEdit` is the ultimate representation of the work done by +//! rust-analyzer. use text_size::{TextRange, TextSize}; -pub use crate::text_edit::{TextEdit, TextEditBuilder}; - -/// Must not overlap with other `AtomTextEdit`s +/// `InsertDelete` -- a single "atomic" change to text +/// +/// Must not overlap with other `InDel`s #[derive(Debug, Clone)] -pub struct AtomTextEdit { +pub struct Indel { + pub insert: String, /// Refers to offsets in the original text pub delete: TextRange, - pub insert: String, } -impl AtomTextEdit { - pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit { - AtomTextEdit { delete: range, insert: replace_with } - } +#[derive(Debug, Clone)] +pub struct TextEdit { + indels: Vec, +} - pub fn delete(range: TextRange) -> AtomTextEdit { - AtomTextEdit::replace(range, String::new()) - } +#[derive(Debug, Default)] +pub struct TextEditBuilder { + indels: Vec, +} - pub fn insert(offset: TextSize, text: String) -> AtomTextEdit { - AtomTextEdit::replace(TextRange::empty(offset), text) +impl Indel { + pub fn insert(offset: TextSize, text: String) -> Indel { + Indel::replace(TextRange::empty(offset), text) + } + pub fn delete(range: TextRange) -> Indel { + Indel::replace(range, String::new()) + } + pub fn replace(range: TextRange, replace_with: String) -> Indel { + Indel { delete: range, insert: replace_with } } pub fn apply(&self, mut text: String) -> String { @@ -34,3 +44,90 @@ impl AtomTextEdit { text } } + +impl TextEdit { + pub fn insert(offset: TextSize, text: String) -> TextEdit { + let mut builder = TextEditBuilder::default(); + builder.insert(offset, text); + builder.finish() + } + + pub fn delete(range: TextRange) -> TextEdit { + let mut builder = TextEditBuilder::default(); + builder.delete(range); + builder.finish() + } + + pub fn replace(range: TextRange, replace_with: String) -> TextEdit { + let mut builder = TextEditBuilder::default(); + builder.replace(range, replace_with); + builder.finish() + } + + pub(crate) fn from_indels(mut indels: Vec) -> TextEdit { + indels.sort_by_key(|a| (a.delete.start(), a.delete.end())); + for (a1, a2) in indels.iter().zip(indels.iter().skip(1)) { + assert!(a1.delete.end() <= a2.delete.start()) + } + TextEdit { indels } + } + + pub fn as_indels(&self) -> &[Indel] { + &self.indels + } + + pub fn apply(&self, text: &str) -> String { + let mut total_len = TextSize::of(text); + for indel in self.indels.iter() { + total_len += TextSize::of(&indel.insert); + total_len -= indel.delete.end() - indel.delete.start(); + } + let mut buf = String::with_capacity(total_len.into()); + let mut prev = 0; + for indel in self.indels.iter() { + let start: usize = indel.delete.start().into(); + let end: usize = indel.delete.end().into(); + if start > prev { + buf.push_str(&text[prev..start]); + } + buf.push_str(&indel.insert); + prev = end; + } + buf.push_str(&text[prev..text.len()]); + assert_eq!(TextSize::of(&buf), total_len); + buf + } + + pub fn apply_to_offset(&self, offset: TextSize) -> Option { + let mut res = offset; + for indel in self.indels.iter() { + if indel.delete.start() >= offset { + break; + } + if offset < indel.delete.end() { + return None; + } + res += TextSize::of(&indel.insert); + res -= indel.delete.len(); + } + Some(res) + } +} + +impl TextEditBuilder { + pub fn replace(&mut self, range: TextRange, replace_with: String) { + self.indels.push(Indel::replace(range, replace_with)) + } + pub fn delete(&mut self, range: TextRange) { + self.indels.push(Indel::delete(range)) + } + pub fn insert(&mut self, offset: TextSize, text: String) { + self.indels.push(Indel::insert(offset, text)) + } + pub fn finish(self) -> TextEdit { + TextEdit::from_indels(self.indels) + } + pub fn invalidates_offset(&self, offset: TextSize) -> bool { + self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset)) + } +} diff --git a/crates/ra_text_edit/src/text_edit.rs b/crates/ra_text_edit/src/text_edit.rs deleted file mode 100644 index eabab4b4d..000000000 --- a/crates/ra_text_edit/src/text_edit.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! FIXME: write short doc here - -use crate::AtomTextEdit; - -use text_size::{TextRange, TextSize}; - -#[derive(Debug, Clone)] -pub struct TextEdit { - atoms: Vec, -} - -#[derive(Debug, Default)] -pub struct TextEditBuilder { - atoms: Vec, -} - -impl TextEditBuilder { - pub fn replace(&mut self, range: TextRange, replace_with: String) { - self.atoms.push(AtomTextEdit::replace(range, replace_with)) - } - pub fn delete(&mut self, range: TextRange) { - self.atoms.push(AtomTextEdit::delete(range)) - } - pub fn insert(&mut self, offset: TextSize, text: String) { - self.atoms.push(AtomTextEdit::insert(offset, text)) - } - pub fn finish(self) -> TextEdit { - TextEdit::from_atoms(self.atoms) - } - pub fn invalidates_offset(&self, offset: TextSize) -> bool { - self.atoms.iter().any(|atom| atom.delete.contains_inclusive(offset)) - } -} - -impl TextEdit { - pub fn insert(offset: TextSize, text: String) -> TextEdit { - let mut builder = TextEditBuilder::default(); - builder.insert(offset, text); - builder.finish() - } - - pub fn delete(range: TextRange) -> TextEdit { - let mut builder = TextEditBuilder::default(); - builder.delete(range); - builder.finish() - } - - pub fn replace(range: TextRange, replace_with: String) -> TextEdit { - let mut builder = TextEditBuilder::default(); - builder.replace(range, replace_with); - builder.finish() - } - - pub(crate) fn from_atoms(mut atoms: Vec) -> TextEdit { - atoms.sort_by_key(|a| (a.delete.start(), a.delete.end())); - for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) { - assert!(a1.delete.end() <= a2.delete.start()) - } - TextEdit { atoms } - } - - pub fn as_atoms(&self) -> &[AtomTextEdit] { - &self.atoms - } - - pub fn apply(&self, text: &str) -> String { - let mut total_len = TextSize::of(text); - for atom in self.atoms.iter() { - total_len += TextSize::of(&atom.insert); - total_len -= atom.delete.end() - atom.delete.start(); - } - let mut buf = String::with_capacity(total_len.into()); - let mut prev = 0; - for atom in self.atoms.iter() { - let start: usize = atom.delete.start().into(); - let end: usize = atom.delete.end().into(); - if start > prev { - buf.push_str(&text[prev..start]); - } - buf.push_str(&atom.insert); - prev = end; - } - buf.push_str(&text[prev..text.len()]); - assert_eq!(TextSize::of(&buf), total_len); - buf - } - - pub fn apply_to_offset(&self, offset: TextSize) -> Option { - let mut res = offset; - for atom in self.atoms.iter() { - if atom.delete.start() >= offset { - break; - } - if offset < atom.delete.end() { - return None; - } - res += TextSize::of(&atom.insert); - res -= atom.delete.len(); - } - Some(res) - } -} diff --git a/crates/rust-analyzer/src/conv.rs b/crates/rust-analyzer/src/conv.rs index 7be5ebcdb..f64c90b5b 100644 --- a/crates/rust-analyzer/src/conv.rs +++ b/crates/rust-analyzer/src/conv.rs @@ -15,7 +15,7 @@ use ra_ide::{ ReferenceAccess, Severity, SourceChange, SourceFileEdit, }; use ra_syntax::{SyntaxKind, TextRange, TextSize}; -use ra_text_edit::{AtomTextEdit, TextEdit}; +use ra_text_edit::{Indel, TextEdit}; use ra_vfs::LineEndings; use crate::{ @@ -124,23 +124,22 @@ impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem { let mut text_edit = None; // LSP does not allow arbitrary edits in completion, so we have to do a // non-trivial mapping here. - for atom_edit in self.text_edit().as_atoms() { - if atom_edit.delete.contains_range(self.source_range()) { - text_edit = Some(if atom_edit.delete == self.source_range() { - atom_edit.conv_with((ctx.0, ctx.1)) + for indel in self.text_edit().as_indels() { + if indel.delete.contains_range(self.source_range()) { + text_edit = Some(if indel.delete == self.source_range() { + indel.conv_with((ctx.0, ctx.1)) } else { - assert!(self.source_range().end() == atom_edit.delete.end()); - let range1 = - TextRange::new(atom_edit.delete.start(), self.source_range().start()); + assert!(self.source_range().end() == indel.delete.end()); + let range1 = TextRange::new(indel.delete.start(), self.source_range().start()); let range2 = self.source_range(); - let edit1 = AtomTextEdit::replace(range1, String::new()); - let edit2 = AtomTextEdit::replace(range2, atom_edit.insert.clone()); + let edit1 = Indel::replace(range1, String::new()); + let edit2 = Indel::replace(range2, indel.insert.clone()); additional_text_edits.push(edit1.conv_with((ctx.0, ctx.1))); edit2.conv_with((ctx.0, ctx.1)) }) } else { - assert!(self.source_range().intersect(atom_edit.delete).is_none()); - additional_text_edits.push(atom_edit.conv_with((ctx.0, ctx.1))); + assert!(self.source_range().intersect(indel.delete).is_none()); + additional_text_edits.push(indel.conv_with((ctx.0, ctx.1))); } } let text_edit = text_edit.unwrap(); @@ -257,11 +256,11 @@ impl ConvWith<(&LineIndex, LineEndings)> for TextEdit { type Output = Vec; fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> Vec { - self.as_atoms().iter().map_conv_with(ctx).collect() + self.as_indels().iter().map_conv_with(ctx).collect() } } -impl ConvWith<(&LineIndex, LineEndings)> for &AtomTextEdit { +impl ConvWith<(&LineIndex, LineEndings)> for &Indel { type Output = lsp_types::TextEdit; fn conv_with( @@ -522,7 +521,7 @@ impl TryConvWith<&WorldSnapshot> for SourceFileEdit { let line_index = world.analysis().file_line_index(self.file_id)?; let line_endings = world.file_line_endings(self.file_id); let edits = - self.edit.as_atoms().iter().map_conv_with((&line_index, line_endings)).collect(); + self.edit.as_indels().iter().map_conv_with((&line_index, line_endings)).collect(); Ok(TextDocumentEdit { text_document, edits }) } } -- cgit v1.2.3 From 27c7ef6d65ffa6a642768377d3f0ba85ac8564bf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 May 2020 23:23:29 +0200 Subject: Use more natural signature for Edit::apply --- crates/ra_ide/src/ssr.rs | 24 +++++++++++++++--------- crates/ra_syntax/src/lib.rs | 3 ++- crates/ra_syntax/src/parsing/reparsing.rs | 14 +++++++++----- crates/ra_text_edit/src/lib.rs | 21 ++++++++++++++++----- 4 files changed, 42 insertions(+), 20 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs index 7b93ff2d2..e213da606 100644 --- a/crates/ra_ide/src/ssr.rs +++ b/crates/ra_ide/src/ssr.rs @@ -401,16 +401,22 @@ fn render_replace( ignored_comments: &Vec, template: &SsrTemplate, ) -> String { - let mut builder = TextEditBuilder::default(); - for element in template.template.descendants() { - if let Some(var) = template.placeholders.get(&element) { - builder.replace(element.text_range(), binding[var].to_string()) + let edit = { + let mut builder = TextEditBuilder::default(); + for element in template.template.descendants() { + if let Some(var) = template.placeholders.get(&element) { + builder.replace(element.text_range(), binding[var].to_string()) + } } - } - for comment in ignored_comments { - builder.insert(template.template.text_range().end(), comment.syntax().to_string()) - } - builder.finish().apply(&template.template.text().to_string()) + for comment in ignored_comments { + builder.insert(template.template.text_range().end(), comment.syntax().to_string()) + } + builder.finish() + }; + + let mut text = template.template.text().to_string(); + edit.apply(&mut text); + text } #[cfg(test)] diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 1a7348dac..61e686da5 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs @@ -142,7 +142,8 @@ impl Parse { } fn full_reparse(&self, indel: &Indel) -> Parse { - let text = indel.apply(self.tree().syntax().text().to_string()); + let mut text = self.tree().syntax().text().to_string(); + indel.apply(&mut text); SourceFile::parse(&text) } } diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs index 6257e3f33..edbc190f8 100644 --- a/crates/ra_syntax/src/parsing/reparsing.rs +++ b/crates/ra_syntax/src/parsing/reparsing.rs @@ -109,14 +109,14 @@ fn reparse_block<'node>( } fn get_text_after_edit(element: SyntaxElement, edit: &Indel) -> String { - let edit = - Indel::replace(edit.delete - element.text_range().start(), edit.insert.clone()); + let edit = Indel::replace(edit.delete - element.text_range().start(), edit.insert.clone()); - let text = match element { + let mut text = match element { NodeOrToken::Token(token) => token.text().to_string(), NodeOrToken::Node(node) => node.text().to_string(), }; - edit.apply(text) + edit.apply(&mut text); + text } fn is_contextual_kw(text: &str) -> bool { @@ -199,7 +199,11 @@ mod tests { fn do_check(before: &str, replace_with: &str, reparsed_len: u32) { let (range, before) = extract_range(before); let edit = Indel::replace(range, replace_with.to_owned()); - let after = edit.apply(before.clone()); + let after = { + let mut after = before.clone(); + edit.apply(&mut after); + after + }; let fully_reparsed = SourceFile::parse(&after); let incrementally_reparsed: Parse = { diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs index c41bf324b..7138bbc65 100644 --- a/crates/ra_text_edit/src/lib.rs +++ b/crates/ra_text_edit/src/lib.rs @@ -37,11 +37,10 @@ impl Indel { Indel { delete: range, insert: replace_with } } - pub fn apply(&self, mut text: String) -> String { + pub fn apply(&self, text: &mut String) { let start: usize = self.delete.start().into(); let end: usize = self.delete.end().into(); text.replace_range(start..end, &self.insert); - text } } @@ -76,8 +75,17 @@ impl TextEdit { &self.indels } - pub fn apply(&self, text: &str) -> String { - let mut total_len = TextSize::of(text); + pub fn apply(&self, text: &mut String) { + match self.indels.len() { + 0 => return, + 1 => { + self.indels[0].apply(text); + return; + } + _ => (), + } + + let mut total_len = TextSize::of(&*text); for indel in self.indels.iter() { total_len += TextSize::of(&indel.insert); total_len -= indel.delete.end() - indel.delete.start(); @@ -95,7 +103,10 @@ impl TextEdit { } buf.push_str(&text[prev..text.len()]); assert_eq!(TextSize::of(&buf), total_len); - buf + + // FIXME: figure out a way to mutate the text in-place or reuse the + // memory in some other way + *text = buf } pub fn apply_to_offset(&self, offset: TextSize) -> Option { -- cgit v1.2.3 From ca9e0f5fe9ad29ab0c5a0771a0d0eaec97e4104b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 May 2020 23:48:26 +0200 Subject: Fixup tests --- crates/ra_assists/src/doc_tests.rs | 6 +++++- crates/ra_assists/src/lib.rs | 20 ++++++++------------ crates/ra_ide/src/diagnostics.rs | 24 ++++++++++++++++++------ crates/ra_ide/src/join_lines.rs | 6 +++++- crates/ra_ide/src/references/rename.rs | 32 ++++++++++++++++---------------- crates/ra_ide/src/ssr.rs | 8 ++++++-- crates/ra_ide/src/test_utils.rs | 6 +++++- crates/ra_ide/src/typing.rs | 9 ++++++--- crates/ra_ide/src/typing/on_enter.rs | 3 ++- 9 files changed, 71 insertions(+), 43 deletions(-) (limited to 'crates') diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs index c0f9bc1fb..f627f31dc 100644 --- a/crates/ra_assists/src/doc_tests.rs +++ b/crates/ra_assists/src/doc_tests.rs @@ -30,6 +30,10 @@ fn check(assist_id: &str, before: &str, after: &str) { ) }); - let actual = assist.action.edit.apply(&before); + let actual = { + let mut actual = before.clone(); + assist.action.edit.apply(&mut actual); + actual + }; assert_eq_text!(after, &actual); } diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index ad85f5553..0f94f5ee8 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -199,12 +199,12 @@ mod handlers { mod helpers { use std::sync::Arc; + use hir::Semantics; use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset}; - use crate::{AssistCtx, AssistFile, AssistHandler}; - use hir::Semantics; + use crate::{handlers::Handler, AssistCtx, AssistFile}; pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { let (mut db, file_id) = RootDatabase::with_single_file(text); @@ -214,22 +214,18 @@ mod helpers { (db, file_id) } - pub(crate) fn check_assist( - assist: AssistHandler, - ra_fixture_before: &str, - ra_fixture_after: &str, - ) { + pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_after: &str) { check(assist, ra_fixture_before, ExpectedResult::After(ra_fixture_after)); } // FIXME: instead of having a separate function here, maybe use // `extract_ranges` and mark the target as ` ` in the // fixuture? - pub(crate) fn check_assist_target(assist: AssistHandler, ra_fixture: &str, target: &str) { + pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) { check(assist, ra_fixture, ExpectedResult::Target(target)); } - pub(crate) fn check_assist_not_applicable(assist: AssistHandler, ra_fixture: &str) { + pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) { check(assist, ra_fixture, ExpectedResult::NotApplicable); } @@ -239,7 +235,7 @@ mod helpers { Target(&'a str), } - fn check(assist: AssistHandler, before: &str, expected: ExpectedResult) { + fn check(assist: Handler, before: &str, expected: ExpectedResult) { let (text_without_caret, file_with_caret_id, range_or_offset, db) = if before.contains("//-") { let (mut db, position) = RootDatabase::with_position(before); @@ -265,13 +261,13 @@ mod helpers { (Some(assist), ExpectedResult::After(after)) => { let action = assist.0[0].action.clone().unwrap(); - let assisted_file_text = if let AssistFile::TargetFile(file_id) = action.file { + let mut actual = if let AssistFile::TargetFile(file_id) = action.file { db.file_text(file_id).as_ref().to_owned() } else { text_without_caret }; + action.edit.apply(&mut actual); - let mut actual = action.edit.apply(&assisted_file_text); match action.cursor_position { None => { if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index 4c04cee07..87a0b80f1 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs @@ -241,7 +241,11 @@ mod tests { diagnostics.pop().unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before)); let mut fix = diagnostic.fix.unwrap(); let edit = fix.source_file_edits.pop().unwrap().edit; - let actual = edit.apply(&before); + let actual = { + let mut actual = before.to_string(); + edit.apply(&mut actual); + actual + }; assert_eq_text!(after, &actual); } @@ -256,7 +260,11 @@ mod tests { let mut fix = diagnostic.fix.unwrap(); let edit = fix.source_file_edits.pop().unwrap().edit; let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); - let actual = edit.apply(&target_file_contents); + let actual = { + let mut actual = target_file_contents.to_string(); + edit.apply(&mut actual); + actual + }; // Strip indent and empty lines from `after`, to match the behaviour of // `parse_fixture` called from `analysis_and_position`. @@ -288,7 +296,11 @@ mod tests { let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); let mut fix = diagnostic.fix.unwrap(); let edit = fix.source_file_edits.pop().unwrap().edit; - let actual = edit.apply(&before); + let actual = { + let mut actual = before.to_string(); + edit.apply(&mut actual); + actual + }; assert_eq_text!(after, &actual); } @@ -662,10 +674,10 @@ mod tests { 1, ), edit: TextEdit { - atoms: [ - AtomTextEdit { - delete: 3..9, + indels: [ + Indel { insert: "{a:42, b: ()}", + delete: 3..9, }, ], }, diff --git a/crates/ra_ide/src/join_lines.rs b/crates/ra_ide/src/join_lines.rs index 63fd6b3e4..d3af780c4 100644 --- a/crates/ra_ide/src/join_lines.rs +++ b/crates/ra_ide/src/join_lines.rs @@ -569,7 +569,11 @@ fn foo() { let (sel, before) = extract_range(before); let parse = SourceFile::parse(&before); let result = join_lines(&parse.tree(), sel); - let actual = result.apply(&before); + let actual = { + let mut actual = before.to_string(); + result.apply(&mut actual); + actual + }; assert_eq_text!(after, &actual); } diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 52e55b0a0..0398d53bc 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs @@ -537,10 +537,10 @@ mod tests { 2, ), edit: TextEdit { - atoms: [ - AtomTextEdit { - delete: 4..7, + indels: [ + Indel { insert: "foo2", + delete: 4..7, }, ], }, @@ -589,10 +589,10 @@ mod tests { 1, ), edit: TextEdit { - atoms: [ - AtomTextEdit { - delete: 4..7, + indels: [ + Indel { insert: "foo2", + delete: 4..7, }, ], }, @@ -672,10 +672,10 @@ mod tests { 2, ), edit: TextEdit { - atoms: [ - AtomTextEdit { - delete: 8..11, + indels: [ + Indel { insert: "foo2", + delete: 8..11, }, ], }, @@ -685,10 +685,10 @@ mod tests { 1, ), edit: TextEdit { - atoms: [ - AtomTextEdit { - delete: 27..30, + indels: [ + Indel { insert: "foo2", + delete: 27..30, }, ], }, @@ -720,13 +720,13 @@ mod tests { if let Some(change) = source_change { for edit in change.info.source_file_edits { file_id = Some(edit.file_id); - for atom in edit.edit.as_atoms() { - text_edit_builder.replace(atom.delete, atom.insert.clone()); + for indel in edit.edit.as_indels() { + text_edit_builder.replace(indel.delete, indel.insert.clone()); } } } - let result = - text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap()).unwrap()); + let mut result = analysis.file_text(file_id.unwrap()).unwrap().to_string(); + text_edit_builder.finish().apply(&mut result); assert_eq_text!(expected, &*result); } } diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs index e213da606..8bf52d0fa 100644 --- a/crates/ra_ide/src/ssr.rs +++ b/crates/ra_ide/src/ssr.rs @@ -511,7 +511,9 @@ mod tests { ); let edit = replace(&matches, &query.template); - assert_eq!(edit.apply(input), "fn main() { bar(1+2); }"); + let mut after = input.to_string(); + edit.apply(&mut after); + assert_eq!(after, "fn main() { bar(1+2); }"); } fn assert_ssr_transform(query: &str, input: &str, result: &str) { @@ -519,7 +521,9 @@ mod tests { let code = SourceFile::parse(input).tree(); let matches = find(&query.pattern, code.syntax()); let edit = replace(&matches, &query.template); - assert_eq!(edit.apply(input), result); + let mut after = input.to_string(); + edit.apply(&mut after); + assert_eq!(after, result); } #[test] diff --git a/crates/ra_ide/src/test_utils.rs b/crates/ra_ide/src/test_utils.rs index f14533e14..48c8fd1f4 100644 --- a/crates/ra_ide/src/test_utils.rs +++ b/crates/ra_ide/src/test_utils.rs @@ -13,7 +13,11 @@ pub fn check_action Option>( let (before_cursor_pos, before) = extract_offset(before); let file = SourceFile::parse(&before).ok().unwrap(); let result = f(&file, before_cursor_pos).expect("code action is not applicable"); - let actual = result.apply(&before); + let actual = { + let mut actual = before.to_string(); + result.apply(&mut actual); + actual + }; let actual_cursor_pos = result.apply_to_offset(before_cursor_pos).expect("cursor position is affected by the edit"); let actual = add_cursor(&actual, actual_cursor_pos); diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs index 2a8b4327f..a03da4693 100644 --- a/crates/ra_ide/src/typing.rs +++ b/crates/ra_ide/src/typing.rs @@ -142,10 +142,13 @@ mod tests { fn do_type_char(char_typed: char, before: &str) -> Option<(String, SingleFileChange)> { let (offset, before) = extract_offset(before); let edit = TextEdit::insert(offset, char_typed.to_string()); - let before = edit.apply(&before); + let mut before = before.to_string(); + edit.apply(&mut before); let parse = SourceFile::parse(&before); - on_char_typed_inner(&parse.tree(), offset, char_typed) - .map(|it| (it.edit.apply(&before), it)) + on_char_typed_inner(&parse.tree(), offset, char_typed).map(|it| { + it.edit.apply(&mut before); + (before.to_string(), it) + }) } fn type_char(char_typed: char, before: &str, after: &str) { diff --git a/crates/ra_ide/src/typing/on_enter.rs b/crates/ra_ide/src/typing/on_enter.rs index 725237464..78a40cc94 100644 --- a/crates/ra_ide/src/typing/on_enter.rs +++ b/crates/ra_ide/src/typing/on_enter.rs @@ -96,7 +96,8 @@ mod tests { let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?; assert_eq!(result.source_file_edits.len(), 1); - let actual = result.source_file_edits[0].edit.apply(&before); + let mut actual = before.to_string(); + result.source_file_edits[0].edit.apply(&mut actual); let actual = add_cursor(&actual, result.cursor_position.unwrap().offset); Some(actual) } -- cgit v1.2.3