From 6f006b7524f80ef8fe1e61d7939afb9e9aabba5b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 24 May 2022 21:58:47 +0200 Subject: [PATCH 1/2] Simplify --- crates/ide-completion/src/completions/flyimport.rs | 1 - crates/ide-completion/src/context.rs | 9 +-------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs index bbb50cb2657..873db300b84 100644 --- a/crates/ide-completion/src/completions/flyimport.rs +++ b/crates/ide-completion/src/completions/flyimport.rs @@ -114,7 +114,6 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext) || ctx.is_path_disallowed() || ctx.expects_item() || ctx.expects_assoc_item() - || ctx.expects_variant() { return None; } diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 4530d88af8c..5e2118ae14b 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -322,10 +322,6 @@ impl<'a> CompletionContext<'a> { matches!(self.completion_location, Some(ImmediateLocation::Trait | ImmediateLocation::Impl)) } - pub(crate) fn expects_variant(&self) -> bool { - matches!(self.name_ctx(), Some(NameContext { kind: NameKind::Variant, .. })) - } - pub(crate) fn expects_non_trait_assoc_item(&self) -> bool { matches!(self.completion_location, Some(ImmediateLocation::Impl)) } @@ -379,10 +375,7 @@ impl<'a> CompletionContext<'a> { pub(crate) fn is_path_disallowed(&self) -> bool { self.previous_token_is(T![unsafe]) || matches!(self.prev_sibling, Some(ImmediatePrevSibling::Visibility)) - || matches!( - self.name_ctx(), - Some(NameContext { kind: NameKind::Module(_) | NameKind::Rename, .. }) - ) + || (matches!(self.name_ctx(), Some(NameContext { .. })) && self.pattern_ctx.is_none()) || matches!(self.pattern_ctx, Some(PatternContext { record_pat: Some(_), .. })) || matches!( self.nameref_ctx(), From 86d1d9067e34b322e7eca500ada0364733bdbd1a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 24 May 2022 22:33:42 +0200 Subject: [PATCH 2/2] fix: Insert whitespace into trait-impl completions when coming from macros --- .../src/handlers/add_missing_impl_members.rs | 1 - .../src/completions/trait_impl.rs | 108 +++++++++++++++--- .../insert_whitespace_into_node.rs | 4 + crates/ide/src/expand_macro.rs | 17 +-- crates/syntax/src/display.rs | 51 --------- crates/syntax/src/lib.rs | 1 - 6 files changed, 99 insertions(+), 83 deletions(-) delete mode 100644 crates/syntax/src/display.rs diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 6e700695fb4..573c362c818 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -939,7 +939,6 @@ struct Foo(usize); impl FooB for Foo { $0fn foo< 'lt>(& 'lt self){} - } "#, ) diff --git a/crates/ide-completion/src/completions/trait_impl.rs b/crates/ide-completion/src/completions/trait_impl.rs index 61c5d126493..54bd77526e9 100644 --- a/crates/ide-completion/src/completions/trait_impl.rs +++ b/crates/ide-completion/src/completions/trait_impl.rs @@ -32,10 +32,12 @@ //! ``` use hir::{self, HasAttrs}; -use ide_db::{path_transform::PathTransform, traits::get_missing_assoc_items, SymbolKind}; +use ide_db::{ + path_transform::PathTransform, syntax_helpers::insert_whitespace_into_node, + traits::get_missing_assoc_items, SymbolKind, +}; use syntax::{ ast::{self, edit_in_place::AttrsOwnerEdit}, - display::function_declaration, AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, T, }; use text_edit::TextEdit; @@ -179,7 +181,7 @@ fn add_function_impl( _ => unreachable!(), }; - let function_decl = function_declaration(&transformed_fn); + let function_decl = function_declaration(&transformed_fn, source.file_id.is_macro()); match ctx.config.snippet_cap { Some(cap) => { let snippet = format!("{} {{\n $0\n}}", function_decl); @@ -260,7 +262,7 @@ fn add_const_impl( _ => unreachable!(), }; - let label = make_const_compl_syntax(&transformed_const); + let label = make_const_compl_syntax(&transformed_const, source.file_id.is_macro()); let replacement = format!("{} ", label); let mut item = CompletionItem::new(SymbolKind::Const, replacement_range, label); @@ -283,17 +285,18 @@ fn add_const_impl( } } -fn make_const_compl_syntax(const_: &ast::Const) -> String { +fn make_const_compl_syntax(const_: &ast::Const, needs_whitespace: bool) -> String { const_.remove_attrs_and_docs(); + let const_ = if needs_whitespace { + insert_whitespace_into_node::insert_ws_into(const_.syntax().clone()) + } else { + const_.syntax().clone() + }; - let const_start = const_.syntax().text_range().start(); - let const_end = const_.syntax().text_range().end(); - - let start = - const_.syntax().first_child_or_token().map_or(const_start, |f| f.text_range().start()); + let start = const_.text_range().start(); + let const_end = const_.text_range().end(); let end = const_ - .syntax() .children_with_tokens() .find(|s| s.kind() == T![;] || s.kind() == T![=]) .map_or(const_end, |f| f.text_range().start()); @@ -301,11 +304,36 @@ fn make_const_compl_syntax(const_: &ast::Const) -> String { let len = end - start; let range = TextRange::new(0.into(), len); - let syntax = const_.syntax().text().slice(range).to_string(); + let syntax = const_.text().slice(range).to_string(); format!("{} =", syntax.trim_end()) } +fn function_declaration(node: &ast::Fn, needs_whitespace: bool) -> String { + node.remove_attrs_and_docs(); + + let node = if needs_whitespace { + insert_whitespace_into_node::insert_ws_into(node.syntax().clone()) + } else { + node.syntax().clone() + }; + + let start = node.text_range().start(); + let end = node.text_range().end(); + + let end = node + .last_child_or_token() + .filter(|s| s.kind() == T![;] || s.kind() == SyntaxKind::BLOCK_EXPR) + .map_or(end, |f| f.text_range().start()); + + let len = end - start; + let range = TextRange::new(0.into(), len); + + let syntax = node.text().slice(range).to_string(); + + syntax.trim_end().to_owned() +} + fn replacement_range(ctx: &CompletionContext, item: &SyntaxNode) -> TextRange { let first_child = item .children_with_tokens() @@ -655,8 +683,7 @@ trait Test { struct T; impl Test for T { - fn foo() -where T: Into { + fn foo() where T: Into { $0 } } @@ -992,7 +1019,7 @@ trait SomeTrait {} trait Foo { fn function() - where Self: SomeTrait; + where Self: SomeTrait; } struct Bar; @@ -1005,13 +1032,13 @@ trait SomeTrait {} trait Foo { fn function() - where Self: SomeTrait; + where Self: SomeTrait; } struct Bar; impl Foo for Bar { fn function() -where Self: SomeTrait { + where Self: SomeTrait { $0 } } @@ -1052,4 +1079,51 @@ impl Tr for () { "#]], ); } + + #[test] + fn fixes_up_macro_generated() { + check_edit( + "fn foo", + r#" +macro_rules! noop { + ($($item: item)*) => { + $($item)* + } +} + +noop! { + trait Foo { + fn foo(&mut self, bar: i64, baz: &mut u32) -> Result<(), u32>; + } +} + +struct Test; + +impl Foo for Test { + $0 +} +"#, + r#" +macro_rules! noop { + ($($item: item)*) => { + $($item)* + } +} + +noop! { + trait Foo { + fn foo(&mut self, bar: i64, baz: &mut u32) -> Result<(), u32>; + } +} + +struct Test; + +impl Foo for Test { + fn foo(&mut self,bar:i64,baz: &mut u32) -> Result<(),u32> { + $0 +} +} +"#, + ); + } } diff --git a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs index b5db8c1967b..a06f18543fc 100644 --- a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs +++ b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs @@ -114,6 +114,10 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { ted::insert(pos, insert); } + if let Some(it) = syn.last_token().filter(|it| it.kind() == SyntaxKind::WHITESPACE) { + ted::remove(it); + } + syn } diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index a578aba01f3..806f816898b 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -250,8 +250,7 @@ fn main() { "#, expect![[r#" bar - for _ in 0..42{} - "#]], + for _ in 0..42{}"#]], ); } @@ -273,7 +272,6 @@ f$0oo!(); expect![[r#" foo fn b(){} - "#]], ); } @@ -297,8 +295,7 @@ f$0oo!(); fn some_thing() -> u32 { let a = 0; a+10 - } - "#]], + }"#]], ); } @@ -359,8 +356,7 @@ fn main() { "#, expect![[r#" match_ast - {} - "#]], + {}"#]], ); } @@ -421,8 +417,7 @@ fn main() { "#, expect![[r#" foo - fn f(_: &dyn ::std::marker::Copy){} - "#]], + fn f(_: &dyn ::std::marker::Copy){}"#]], ); } @@ -440,7 +435,6 @@ struct Foo {} expect![[r#" Clone impl < >core::clone::Clone for Foo< >{} - "#]], ); } @@ -458,7 +452,6 @@ struct Foo {} expect![[r#" Copy impl < >core::marker::Copy for Foo< >{} - "#]], ); } @@ -475,7 +468,6 @@ struct Foo {} expect![[r#" Copy impl < >core::marker::Copy for Foo< >{} - "#]], ); check( @@ -488,7 +480,6 @@ struct Foo {} expect![[r#" Clone impl < >core::clone::Clone for Foo< >{} - "#]], ); } diff --git a/crates/syntax/src/display.rs b/crates/syntax/src/display.rs deleted file mode 100644 index f7322656a3e..00000000000 --- a/crates/syntax/src/display.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! This module contains utilities for rendering syntax nodes into a string representing their signature. - -use crate::ast::{self, HasGenericParams, HasName}; - -use ast::HasVisibility; -use stdx::format_to; - -pub fn function_declaration(node: &ast::Fn) -> String { - let mut buf = String::new(); - if let Some(vis) = node.visibility() { - format_to!(buf, "{} ", vis); - } - if node.async_token().is_some() { - format_to!(buf, "async "); - } - if node.const_token().is_some() { - format_to!(buf, "const "); - } - if node.unsafe_token().is_some() { - format_to!(buf, "unsafe "); - } - if let Some(abi) = node.abi() { - // Keyword `extern` is included in the string. - format_to!(buf, "{} ", abi); - } - if let Some(name) = node.name() { - format_to!(buf, "fn {}", name); - } - if let Some(type_params) = node.generic_param_list() { - format_to!(buf, "{}", type_params); - } - if let Some(param_list) = node.param_list() { - let params: Vec = param_list - .self_param() - .into_iter() - .map(|self_param| self_param.to_string()) - .chain(param_list.params().map(|param| param.to_string())) - .collect(); - // Useful to inline parameters - format_to!(buf, "({})", params.join(", ")); - } - if let Some(ret_type) = node.ret_type() { - if ret_type.ty().is_some() { - format_to!(buf, " {}", ret_type); - } - } - if let Some(where_clause) = node.where_clause() { - format_to!(buf, "\n{}", where_clause); - } - buf -} diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index e30f6cd79c3..e0309756b8a 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -33,7 +33,6 @@ mod token_text; #[cfg(test)] mod tests; -pub mod display; pub mod algo; pub mod ast; #[doc(hidden)]