From 5637ce4250247eef4c2ae1892cead69b6d6a172b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 9 May 2021 17:17:28 +0300 Subject: fix: join lines doesn't add space before closing quote --- crates/ide/src/join_lines.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'crates') diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs index 482b23cf5..3e30e71ce 100644 --- a/crates/ide/src/join_lines.rs +++ b/crates/ide/src/join_lines.rs @@ -1,3 +1,5 @@ +use std::convert::TryFrom; + use ide_assists::utils::extract_trivial_expression; use itertools::Itertools; use syntax::{ @@ -85,6 +87,21 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextS suff.bytes().take_while(|&b| b == b' ').count() }; + let mut no_space = false; + if let Some(string) = ast::String::cast(token.clone()) { + if let Some(range) = string.open_quote_text_range() { + cov_mark::hit!(join_string_literal_open_quote); + no_space |= range.end() == offset; + } + if let Some(range) = string.close_quote_text_range() { + cov_mark::hit!(join_string_literal_close_quote); + no_space |= range.start() + == offset + + TextSize::of('\n') + + TextSize::try_from(n_spaces_after_line_break).unwrap(); + } + } + let range = TextRange::at(offset, ((n_spaces_after_line_break + 1) as u32).into()); let replace_with = if no_space { "" } else { " " }; edit.replace(range, replace_with.to_string()); @@ -833,6 +850,19 @@ fn main() { fn main() { $0"hello"; } +"#, + ); + check_join_lines( + r#" +fn main() { + $0r"hello + "; +} +"#, + r#" +fn main() { + $0r"hello"; +} "#, ); } -- cgit v1.2.3 From edeb4927829380ed25e3899e85b2809bbb39a846 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 9 May 2021 17:41:25 +0300 Subject: minor: fix test style --- crates/ide/src/join_lines.rs | 12 --- .../handlers/replace_impl_trait_with_generic.rs | 86 ++++++++-------------- 2 files changed, 31 insertions(+), 67 deletions(-) (limited to 'crates') diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs index 3e30e71ce..61dcbb399 100644 --- a/crates/ide/src/join_lines.rs +++ b/crates/ide/src/join_lines.rs @@ -67,18 +67,6 @@ fn remove_newlines(edit: &mut TextEditBuilder, token: &SyntaxToken, range: TextR fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextSize) { if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 { - let mut no_space = false; - if let Some(string) = ast::String::cast(token.clone()) { - if let Some(range) = string.open_quote_text_range() { - cov_mark::hit!(join_string_literal_open_quote); - no_space |= range.end() == offset; - } - if let Some(range) = string.close_quote_text_range() { - cov_mark::hit!(join_string_literal_close_quote); - no_space |= range.start() == offset + TextSize::of('\n'); - } - } - let n_spaces_after_line_break = { let suff = &token.text()[TextRange::new( offset - token.text_range().start() + TextSize::of('\n'), diff --git a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs index ff25b61ea..8509a5e11 100644 --- a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs +++ b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs @@ -55,12 +55,8 @@ mod tests { fn replace_impl_trait_with_generic_params() { check_assist( replace_impl_trait_with_generic, - r#" - fn foo(bar: $0impl Bar) {} - "#, - r#" - fn foo(bar: B) {} - "#, + r#"fn foo(bar: $0impl Bar) {}"#, + r#"fn foo(bar: B) {}"#, ); } @@ -68,12 +64,8 @@ mod tests { fn replace_impl_trait_without_generic_params() { check_assist( replace_impl_trait_with_generic, - r#" - fn foo(bar: $0impl Bar) {} - "#, - r#" - fn foo(bar: B) {} - "#, + r#"fn foo(bar: $0impl Bar) {}"#, + r#"fn foo(bar: B) {}"#, ); } @@ -81,12 +73,8 @@ mod tests { fn replace_two_impl_trait_with_generic_params() { check_assist( replace_impl_trait_with_generic, - r#" - fn foo(foo: impl Foo, bar: $0impl Bar) {} - "#, - r#" - fn foo(foo: impl Foo, bar: B) {} - "#, + r#"fn foo(foo: impl Foo, bar: $0impl Bar) {}"#, + r#"fn foo(foo: impl Foo, bar: B) {}"#, ); } @@ -94,12 +82,8 @@ mod tests { fn replace_impl_trait_with_empty_generic_params() { check_assist( replace_impl_trait_with_generic, - r#" - fn foo<>(bar: $0impl Bar) {} - "#, - r#" - fn foo(bar: B) {} - "#, + r#"fn foo<>(bar: $0impl Bar) {}"#, + r#"fn foo(bar: B) {}"#, ); } @@ -108,13 +92,13 @@ mod tests { check_assist( replace_impl_trait_with_generic, r#" - fn foo< - >(bar: $0impl Bar) {} - "#, +fn foo< +>(bar: $0impl Bar) {} +"#, r#" - fn foo(bar: B) {} - "#, +fn foo(bar: B) {} +"#, ); } @@ -123,12 +107,8 @@ mod tests { fn replace_impl_trait_with_exist_generic_letter() { check_assist( replace_impl_trait_with_generic, - r#" - fn foo(bar: $0impl Bar) {} - "#, - r#" - fn foo(bar: C) {} - "#, + r#"fn foo(bar: $0impl Bar) {}"#, + r#"fn foo(bar: C) {}"#, ); } @@ -137,19 +117,19 @@ mod tests { check_assist( replace_impl_trait_with_generic, r#" - fn foo< - G: Foo, - F, - H, - >(bar: $0impl Bar) {} - "#, - r#" - fn foo< - G: Foo, - F, - H, B: Bar - >(bar: B) {} - "#, +fn foo< + G: Foo, + F, + H, +>(bar: $0impl Bar) {} +"#, + r#" +fn foo< + G: Foo, + F, + H, B: Bar +>(bar: B) {} +"#, ); } @@ -157,12 +137,8 @@ mod tests { fn replace_impl_trait_multiple() { check_assist( replace_impl_trait_with_generic, - r#" - fn foo(bar: $0impl Foo + Bar) {} - "#, - r#" - fn foo(bar: F) {} - "#, + r#"fn foo(bar: $0impl Foo + Bar) {}"#, + r#"fn foo(bar: F) {}"#, ); } } -- cgit v1.2.3 From d9c9f6dc2cd3080009c4ce2c3f0f340949f4f53c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 9 May 2021 17:58:03 +0300 Subject: cleanups --- .../src/handlers/introduce_named_lifetime.rs | 4 ++-- .../handlers/replace_impl_trait_with_generic.rs | 24 +++++++++++----------- crates/ide_assists/src/utils/suggest_name.rs | 10 ++++++++- crates/syntax/src/ast/make.rs | 4 ++-- 4 files changed, 25 insertions(+), 17 deletions(-) (limited to 'crates') diff --git a/crates/ide_assists/src/handlers/introduce_named_lifetime.rs b/crates/ide_assists/src/handlers/introduce_named_lifetime.rs index 9f4f71d6c..cb71ca8bd 100644 --- a/crates/ide_assists/src/handlers/introduce_named_lifetime.rs +++ b/crates/ide_assists/src/handlers/introduce_named_lifetime.rs @@ -139,12 +139,12 @@ fn generate_unique_lifetime_param_name( fn add_lifetime_param(type_params: ast::GenericParamList, new_lifetime_param: char) { let generic_param = - make::generic_param(format!("'{}", new_lifetime_param), None).clone_for_update(); + make::generic_param(&format!("'{}", new_lifetime_param), None).clone_for_update(); type_params.add_generic_param(generic_param); } fn make_ast_lifetime(new_lifetime_param: char) -> ast::Lifetime { - make::generic_param(format!("'{}", new_lifetime_param), None) + make::generic_param(&format!("'{}", new_lifetime_param), None) .syntax() .descendants() .find_map(ast::Lifetime::cast) diff --git a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs index 8509a5e11..26a0e81f0 100644 --- a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs +++ b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs @@ -1,6 +1,6 @@ use syntax::ast::{self, edit::AstNodeEdit, make, AstNode, GenericParamsOwner}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; // Assist: replace_impl_trait_with_generic // @@ -17,30 +17,30 @@ pub(crate) fn replace_impl_trait_with_generic( acc: &mut Assists, ctx: &AssistContext, ) -> Option<()> { - let type_impl_trait = ctx.find_node_at_offset::()?; - let type_param = type_impl_trait.syntax().parent().and_then(ast::Param::cast)?; - let type_fn = type_param.syntax().ancestors().find_map(ast::Fn::cast)?; + let impl_trait_type = ctx.find_node_at_offset::()?; + let param = impl_trait_type.syntax().parent().and_then(ast::Param::cast)?; + let fn_ = param.syntax().ancestors().find_map(ast::Fn::cast)?; - let impl_trait_ty = type_impl_trait.type_bound_list()?; + let type_bound_list = impl_trait_type.type_bound_list()?; - let target = type_fn.syntax().text_range(); + let target = fn_.syntax().text_range(); acc.add( AssistId("replace_impl_trait_with_generic", AssistKind::RefactorRewrite), "Replace impl trait with generic", target, |edit| { - let generic_letter = impl_trait_ty.to_string().chars().next().unwrap().to_string(); + let type_param_name = suggest_name::generic_parameter(&impl_trait_type); - let generic_param_list = type_fn + let generic_param_list = fn_ .generic_param_list() .unwrap_or_else(|| make::generic_param_list(None)) - .append_param(make::generic_param(generic_letter.clone(), Some(impl_trait_ty))); + .append_param(make::generic_param(&type_param_name, Some(type_bound_list))); - let new_type_fn = type_fn - .replace_descendant::(type_impl_trait.into(), make::ty(&generic_letter)) + let new_type_fn = fn_ + .replace_descendant::(impl_trait_type.into(), make::ty(&type_param_name)) .with_generic_param_list(generic_param_list); - edit.replace_ast(type_fn.clone(), new_type_fn); + edit.replace_ast(fn_.clone(), new_type_fn); }, ) } diff --git a/crates/ide_assists/src/utils/suggest_name.rs b/crates/ide_assists/src/utils/suggest_name.rs index deafcd630..c8487846d 100644 --- a/crates/ide_assists/src/utils/suggest_name.rs +++ b/crates/ide_assists/src/utils/suggest_name.rs @@ -6,7 +6,7 @@ use itertools::Itertools; use stdx::to_lower_snake_case; use syntax::{ ast::{self, NameOwner}, - match_ast, AstNode, + match_ast, AstNode, SmolStr, }; /// Trait names, that will be ignored when in `impl Trait` and `dyn Trait` @@ -57,6 +57,14 @@ const USELESS_METHODS: &[&str] = &[ "iter_mut", ]; +pub(crate) fn generic_parameter(ty: &ast::ImplTraitType) -> SmolStr { + let c = ty + .type_bound_list() + .and_then(|bounds| bounds.syntax().text().char_at(0.into())) + .unwrap_or('T'); + c.encode_utf8(&mut [0; 4]).into() +} + /// Suggest name of variable for given expression /// /// **NOTE**: it is caller's responsibility to guarantee uniqueness of the name. diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 5a6687397..2289d8f3e 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -475,8 +475,8 @@ pub fn param_list( }; ast_from_text(&list) } - -pub fn generic_param(name: String, ty: Option) -> ast::GenericParam { +// FIXME: s/&str/ast:Name +pub fn generic_param(name: &str, ty: Option) -> ast::GenericParam { let bound = match ty { Some(it) => format!(": {}", it), None => String::new(), -- cgit v1.2.3 From 984d20aad8445ecbdc05d1dc3ea2de104c685af0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 9 May 2021 17:59:52 +0300 Subject: cleanups --- crates/ide_assists/src/handlers/extract_variable.rs | 2 +- crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs | 2 +- crates/ide_assists/src/utils/suggest_name.rs | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'crates') diff --git a/crates/ide_assists/src/handlers/extract_variable.rs b/crates/ide_assists/src/handlers/extract_variable.rs index 136b9a55b..ae084c86c 100644 --- a/crates/ide_assists/src/handlers/extract_variable.rs +++ b/crates/ide_assists/src/handlers/extract_variable.rs @@ -54,7 +54,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option let var_name = match &field_shorthand { Some(it) => it.to_string(), - None => suggest_name::variable(&to_extract, &ctx.sema), + None => suggest_name::for_variable(&to_extract, &ctx.sema), }; let expr_range = match &field_shorthand { Some(it) => it.syntax().text_range().cover(to_extract.syntax().text_range()), diff --git a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs index 26a0e81f0..899c773df 100644 --- a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs +++ b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs @@ -29,7 +29,7 @@ pub(crate) fn replace_impl_trait_with_generic( "Replace impl trait with generic", target, |edit| { - let type_param_name = suggest_name::generic_parameter(&impl_trait_type); + let type_param_name = suggest_name::for_generic_parameter(&impl_trait_type); let generic_param_list = fn_ .generic_param_list() diff --git a/crates/ide_assists/src/utils/suggest_name.rs b/crates/ide_assists/src/utils/suggest_name.rs index c8487846d..b3aabeab3 100644 --- a/crates/ide_assists/src/utils/suggest_name.rs +++ b/crates/ide_assists/src/utils/suggest_name.rs @@ -57,7 +57,7 @@ const USELESS_METHODS: &[&str] = &[ "iter_mut", ]; -pub(crate) fn generic_parameter(ty: &ast::ImplTraitType) -> SmolStr { +pub(crate) fn for_generic_parameter(ty: &ast::ImplTraitType) -> SmolStr { let c = ty .type_bound_list() .and_then(|bounds| bounds.syntax().text().char_at(0.into())) @@ -83,7 +83,8 @@ pub(crate) fn generic_parameter(ty: &ast::ImplTraitType) -> SmolStr { /// It also applies heuristics to filter out less informative names /// /// Currently it sticks to the first name found. -pub(crate) fn variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> String { +// FIXME: Microoptimize and return a `SmolStr` here. +pub(crate) fn for_variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> String { // `from_param` does not benifit from stripping // it need the largest context possible // so we check firstmost @@ -284,7 +285,7 @@ mod tests { frange.range, "selection is not an expression(yet contained in one)" ); - let name = variable(&expr, &sema); + let name = for_variable(&expr, &sema); assert_eq!(&name, expected); } -- cgit v1.2.3 From 5342800147679a0ded5546322c94aa6339d58fbc Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 9 May 2021 18:20:37 +0300 Subject: internal: rewrite **Repalce impl Trait** assist to mutable syntax trees --- .../handlers/replace_impl_trait_with_generic.rs | 24 ++++++++++++---------- crates/syntax/src/ast/edit_in_place.rs | 19 +++++++---------- 2 files changed, 20 insertions(+), 23 deletions(-) (limited to 'crates') diff --git a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs index 899c773df..16cae0281 100644 --- a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs +++ b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs @@ -1,4 +1,7 @@ -use syntax::ast::{self, edit::AstNodeEdit, make, AstNode, GenericParamsOwner}; +use syntax::{ + ast::{self, edit_in_place::GenericParamsOwnerEdit, make, AstNode}, + ted, +}; use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; @@ -29,18 +32,17 @@ pub(crate) fn replace_impl_trait_with_generic( "Replace impl trait with generic", target, |edit| { - let type_param_name = suggest_name::for_generic_parameter(&impl_trait_type); + let impl_trait_type = edit.make_ast_mut(impl_trait_type); + let fn_ = edit.make_ast_mut(fn_); - let generic_param_list = fn_ - .generic_param_list() - .unwrap_or_else(|| make::generic_param_list(None)) - .append_param(make::generic_param(&type_param_name, Some(type_bound_list))); + let type_param_name = suggest_name::for_generic_parameter(&impl_trait_type); - let new_type_fn = fn_ - .replace_descendant::(impl_trait_type.into(), make::ty(&type_param_name)) - .with_generic_param_list(generic_param_list); + let type_param = + make::generic_param(&type_param_name, Some(type_bound_list)).clone_for_update(); + let new_ty = make::ty(&type_param_name).clone_for_update(); - edit.replace_ast(fn_.clone(), new_type_fn); + ted::replace(impl_trait_type.syntax(), new_ty.syntax()); + fn_.get_or_create_generic_param_list().add_generic_param(type_param) }, ) } @@ -127,7 +129,7 @@ fn foo< fn foo< G: Foo, F, - H, B: Bar + H, B: Bar, >(bar: B) {} "#, ); diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 04f97f368..168355555 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -195,18 +195,13 @@ impl ast::GenericParamList { pub fn add_generic_param(&self, generic_param: ast::GenericParam) { match self.generic_params().last() { Some(last_param) => { - let mut elems = Vec::new(); - if !last_param - .syntax() - .siblings_with_tokens(Direction::Next) - .any(|it| it.kind() == T![,]) - { - elems.push(make::token(T![,]).into()); - elems.push(make::tokens::single_space().into()); - }; - elems.push(generic_param.syntax().clone().into()); - let after_last_param = Position::after(last_param.syntax()); - ted::insert_all(after_last_param, elems); + let position = Position::after(last_param.syntax()); + let elements = vec![ + make::token(T![,]).into(), + make::tokens::single_space().into(), + generic_param.syntax().clone().into(), + ]; + ted::insert_all(position, elements); } None => { let after_l_angle = Position::after(self.l_angle_token().unwrap()); -- cgit v1.2.3