From b4af02d110b2515295d8375b40311c630b90d7be Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Tue, 2 Jun 2020 01:29:54 +0200 Subject: Add top level keywords completion --- crates/ra_ide/src/completion/complete_keyword.rs | 187 ++++++++++++++++++++++- 1 file changed, 186 insertions(+), 1 deletion(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index fd95bc410..36280b703 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -1,8 +1,9 @@ //! FIXME: write short doc here use ra_syntax::{ + algo::non_trivia_sibling, ast::{self, LoopBodyOwner}, - match_ast, AstNode, + match_ast, AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind::*, SyntaxToken, }; @@ -52,7 +53,28 @@ fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem { .build() } +fn add_top_level_keywords(acc: &mut Completions, ctx: &CompletionContext) { + if let Some(token) = previous_non_triva_element(&ctx.token).and_then(|it| it.into_token()) { + if token.kind() == UNSAFE_KW { + acc.add(keyword(ctx, "impl", "impl $0 {}")); + acc.add(keyword(ctx, "trait", "trait $0 {}")); + acc.add(keyword(ctx, "fn", "fn $0() {}")); + return; + } + } + acc.add(keyword(ctx, "impl", "impl $0 {}")); + acc.add(keyword(ctx, "enum", "enum $0 {}")); + acc.add(keyword(ctx, "struct", "struct $0 {}")); + acc.add(keyword(ctx, "trait", "trait $0 {}")); + acc.add(keyword(ctx, "fn", "fn $0() {}")); + acc.add(keyword(ctx, "unsafe", "unsafe ")); +} + pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { + if ctx.is_new_item { + add_top_level_keywords(acc, ctx); + return; + } if !ctx.is_trivial_path { return; } @@ -82,6 +104,36 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte acc.add_all(complete_return(ctx, &fn_def, ctx.can_be_stmt)); } +fn previous_non_triva_element(token: &SyntaxToken) -> Option { + // trying to get first non triva sibling if we have one + let token_sibling = non_trivia_sibling(NodeOrToken::Token(token.to_owned()), Direction::Prev); + let mut wrapped = if let Some(sibling) = token_sibling { + sibling + } else { + // if not trying to find first ancestor which has such a sibling + let node = token.parent(); + let range = node.text_range(); + let top_node = node.ancestors().take_while(|it| it.text_range() == range).last()?; + let prev_sibling_node = top_node.ancestors().find(|it| { + non_trivia_sibling(NodeOrToken::Node(it.to_owned()), Direction::Prev).is_some() + })?; + non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev)? + }; + // traversing the tree down to get the last token or node, i.e. the closest one + loop { + if let Some(token) = wrapped.as_token() { + return Some(NodeOrToken::Token(token.clone())); + } else { + let new = wrapped.as_node().and_then(|n| n.last_child_or_token()); + if new.is_some() { + wrapped = new.unwrap().clone(); + } else { + return Some(wrapped); + } + } + } +} + fn is_in_loop_body(leaf: &SyntaxToken) -> bool { // FIXME move this to CompletionContext and make it handle macros for node in leaf.parent().ancestors() { @@ -268,6 +320,139 @@ mod tests { ); } + #[test] + fn completes_unsafe_context_in_item_position_with_non_empty_token() { + assert_debug_snapshot!( + do_keyword_completion( + r" + mod my_mod { + unsafe i<|> + } + ", + ), + @r###" + [ + CompletionItem { + label: "fn", + source_range: 57..58, + delete: 57..58, + insert: "fn $0() {}", + kind: Keyword, + }, + CompletionItem { + label: "impl", + source_range: 57..58, + delete: 57..58, + insert: "impl $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "trait", + source_range: 57..58, + delete: 57..58, + insert: "trait $0 {}", + kind: Keyword, + }, + ] + "### + ); + } + + #[test] + fn completes_unsafe_context_in_item_position_with_empty_token() { + assert_debug_snapshot!( + do_keyword_completion( + r" + mod my_mod { + unsafe <|> + } + ", + ), + @r###" + [ + CompletionItem { + label: "fn", + source_range: 57..57, + delete: 57..57, + insert: "fn $0() {}", + kind: Keyword, + }, + CompletionItem { + label: "impl", + source_range: 57..57, + delete: 57..57, + insert: "impl $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "trait", + source_range: 57..57, + delete: 57..57, + insert: "trait $0 {}", + kind: Keyword, + }, + ] + "### + ); + } + + #[test] + fn completes_keywords_in_item_position_with_empty_token() { + assert_debug_snapshot!( + do_keyword_completion( + r" + <|> + ", + ), + @r###" + [ + CompletionItem { + label: "enum", + source_range: 17..17, + delete: 17..17, + insert: "enum $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "fn", + source_range: 17..17, + delete: 17..17, + insert: "fn $0() {}", + kind: Keyword, + }, + CompletionItem { + label: "impl", + source_range: 17..17, + delete: 17..17, + insert: "impl $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "struct", + source_range: 17..17, + delete: 17..17, + insert: "struct $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "trait", + source_range: 17..17, + delete: 17..17, + insert: "trait $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "unsafe", + source_range: 17..17, + delete: 17..17, + insert: "unsafe ", + kind: Keyword, + }, + ] + "### + ); + } + #[test] fn completes_else_after_if() { assert_debug_snapshot!( -- cgit v1.2.3 From 9f91901f7e55915b359909b5422c03f70e4ab79b Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Thu, 11 Jun 2020 14:16:35 +0200 Subject: Add more keywords --- crates/ra_ide/src/completion/complete_keyword.rs | 271 ++++------------------- 1 file changed, 39 insertions(+), 232 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 36280b703..5b56c6275 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -1,12 +1,6 @@ //! FIXME: write short doc here -use ra_syntax::{ - algo::non_trivia_sibling, - ast::{self, LoopBodyOwner}, - match_ast, AstNode, Direction, NodeOrToken, SyntaxElement, - SyntaxKind::*, - SyntaxToken, -}; +use ra_syntax::ast; use crate::completion::{ CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, @@ -53,110 +47,56 @@ fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem { .build() } -fn add_top_level_keywords(acc: &mut Completions, ctx: &CompletionContext) { - if let Some(token) = previous_non_triva_element(&ctx.token).and_then(|it| it.into_token()) { - if token.kind() == UNSAFE_KW { - acc.add(keyword(ctx, "impl", "impl $0 {}")); - acc.add(keyword(ctx, "trait", "trait $0 {}")); - acc.add(keyword(ctx, "fn", "fn $0() {}")); - return; - } +fn add_keyword( + ctx: &CompletionContext, + acc: &mut Completions, + kw: &str, + snippet: &str, + should_add: bool, +) { + if should_add { + acc.add(keyword(ctx, kw, snippet)); } - acc.add(keyword(ctx, "impl", "impl $0 {}")); - acc.add(keyword(ctx, "enum", "enum $0 {}")); - acc.add(keyword(ctx, "struct", "struct $0 {}")); - acc.add(keyword(ctx, "trait", "trait $0 {}")); - acc.add(keyword(ctx, "fn", "fn $0() {}")); - acc.add(keyword(ctx, "unsafe", "unsafe ")); } pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { - if ctx.is_new_item { - add_top_level_keywords(acc, ctx); - return; - } - if !ctx.is_trivial_path { - return; - } + add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); + add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); + add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.after_unsafe); + add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !ctx.after_unsafe); + add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !ctx.after_unsafe); + add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent); + add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent); + add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); + add_keyword(ctx, acc, "let", "let ", ctx.after_if || ctx.block_expr_parent); + add_keyword(ctx, acc, "let", "let ", ctx.after_if || ctx.block_expr_parent); + add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if); + add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); + add_keyword(ctx, acc, "mod", "mod $0 {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "mut", "mut ", ctx.bind_pat_parent || ctx.ref_pat_parent); + add_keyword(ctx, acc, "true", "true", !ctx.is_new_item); // this should be defined properly + add_keyword(ctx, acc, "false", "false", !ctx.is_new_item); // this should be defined properly + add_keyword(ctx, acc, "const", "const ", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "static", "static ", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "extern", "extern ", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "unsafe", "unsafe ", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "continue", "continue;", ctx.in_loop_body && ctx.can_be_stmt); + add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt); + add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt); + add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); + complete_use_tree_keyword(acc, ctx); let fn_def = match &ctx.function_syntax { Some(it) => it, None => return, }; - acc.add(keyword(ctx, "if", "if $0 {}")); - acc.add(keyword(ctx, "match", "match $0 {}")); - acc.add(keyword(ctx, "while", "while $0 {}")); - acc.add(keyword(ctx, "loop", "loop {$0}")); - - if ctx.after_if { - acc.add(keyword(ctx, "else", "else {$0}")); - acc.add(keyword(ctx, "else if", "else if $0 {}")); - } - if is_in_loop_body(&ctx.token) { - if ctx.can_be_stmt { - acc.add(keyword(ctx, "continue", "continue;")); - acc.add(keyword(ctx, "break", "break;")); - } else { - acc.add(keyword(ctx, "continue", "continue")); - acc.add(keyword(ctx, "break", "break")); - } - } acc.add_all(complete_return(ctx, &fn_def, ctx.can_be_stmt)); } -fn previous_non_triva_element(token: &SyntaxToken) -> Option { - // trying to get first non triva sibling if we have one - let token_sibling = non_trivia_sibling(NodeOrToken::Token(token.to_owned()), Direction::Prev); - let mut wrapped = if let Some(sibling) = token_sibling { - sibling - } else { - // if not trying to find first ancestor which has such a sibling - let node = token.parent(); - let range = node.text_range(); - let top_node = node.ancestors().take_while(|it| it.text_range() == range).last()?; - let prev_sibling_node = top_node.ancestors().find(|it| { - non_trivia_sibling(NodeOrToken::Node(it.to_owned()), Direction::Prev).is_some() - })?; - non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev)? - }; - // traversing the tree down to get the last token or node, i.e. the closest one - loop { - if let Some(token) = wrapped.as_token() { - return Some(NodeOrToken::Token(token.clone())); - } else { - let new = wrapped.as_node().and_then(|n| n.last_child_or_token()); - if new.is_some() { - wrapped = new.unwrap().clone(); - } else { - return Some(wrapped); - } - } - } -} - -fn is_in_loop_body(leaf: &SyntaxToken) -> bool { - // FIXME move this to CompletionContext and make it handle macros - for node in leaf.parent().ancestors() { - if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR { - break; - } - let loop_body = match_ast! { - match node { - ast::ForExpr(it) => it.loop_body(), - ast::WhileExpr(it) => it.loop_body(), - ast::LoopExpr(it) => it.loop_body(), - _ => None, - } - }; - if let Some(body) = loop_body { - if body.syntax().text_range().contains_range(leaf.text_range()) { - return true; - } - } - } - false -} - fn complete_return( ctx: &CompletionContext, fn_def: &ast::FnDef, @@ -320,139 +260,6 @@ mod tests { ); } - #[test] - fn completes_unsafe_context_in_item_position_with_non_empty_token() { - assert_debug_snapshot!( - do_keyword_completion( - r" - mod my_mod { - unsafe i<|> - } - ", - ), - @r###" - [ - CompletionItem { - label: "fn", - source_range: 57..58, - delete: 57..58, - insert: "fn $0() {}", - kind: Keyword, - }, - CompletionItem { - label: "impl", - source_range: 57..58, - delete: 57..58, - insert: "impl $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "trait", - source_range: 57..58, - delete: 57..58, - insert: "trait $0 {}", - kind: Keyword, - }, - ] - "### - ); - } - - #[test] - fn completes_unsafe_context_in_item_position_with_empty_token() { - assert_debug_snapshot!( - do_keyword_completion( - r" - mod my_mod { - unsafe <|> - } - ", - ), - @r###" - [ - CompletionItem { - label: "fn", - source_range: 57..57, - delete: 57..57, - insert: "fn $0() {}", - kind: Keyword, - }, - CompletionItem { - label: "impl", - source_range: 57..57, - delete: 57..57, - insert: "impl $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "trait", - source_range: 57..57, - delete: 57..57, - insert: "trait $0 {}", - kind: Keyword, - }, - ] - "### - ); - } - - #[test] - fn completes_keywords_in_item_position_with_empty_token() { - assert_debug_snapshot!( - do_keyword_completion( - r" - <|> - ", - ), - @r###" - [ - CompletionItem { - label: "enum", - source_range: 17..17, - delete: 17..17, - insert: "enum $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "fn", - source_range: 17..17, - delete: 17..17, - insert: "fn $0() {}", - kind: Keyword, - }, - CompletionItem { - label: "impl", - source_range: 17..17, - delete: 17..17, - insert: "impl $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "struct", - source_range: 17..17, - delete: 17..17, - insert: "struct $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "trait", - source_range: 17..17, - delete: 17..17, - insert: "trait $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "unsafe", - source_range: 17..17, - delete: 17..17, - insert: "unsafe ", - kind: Keyword, - }, - ] - "### - ); - } - #[test] fn completes_else_after_if() { assert_debug_snapshot!( -- cgit v1.2.3 From f46bc12199dc88b88bd826f49d5c5af6e9caf727 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Thu, 11 Jun 2020 23:25:58 +0200 Subject: Add more patterns and keywords --- crates/ra_ide/src/completion/complete_keyword.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 5b56c6275..50f003949 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -62,7 +62,7 @@ fn add_keyword( pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); - add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.after_unsafe); @@ -72,7 +72,6 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent); add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); add_keyword(ctx, acc, "let", "let ", ctx.after_if || ctx.block_expr_parent); - add_keyword(ctx, acc, "let", "let ", ctx.after_if || ctx.block_expr_parent); add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if); add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); add_keyword(ctx, acc, "mod", "mod $0 {}", ctx.is_new_item || ctx.block_expr_parent); @@ -88,6 +87,8 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt); add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt); add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); + add_keyword(ctx, acc, "pub", "pub ", ctx.is_new_item && !ctx.inside_trait); + add_keyword(ctx, acc, "where", "where ", ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling); complete_use_tree_keyword(acc, ctx); let fn_def = match &ctx.function_syntax { -- cgit v1.2.3 From a2b4385f161134955fd729087f142d54c3a5e035 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Fri, 12 Jun 2020 00:17:30 +0200 Subject: Add few smoke tests for patterns and refactoring --- crates/ra_ide/src/completion/complete_keyword.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 50f003949..675991154 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -65,13 +65,13 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); - add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.after_unsafe); - add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !ctx.after_unsafe); - add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !ctx.after_unsafe); + add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); + add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); + add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent); add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent); add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); - add_keyword(ctx, acc, "let", "let ", ctx.after_if || ctx.block_expr_parent); + add_keyword(ctx, acc, "let", "let ", ctx.if_is_prev || ctx.block_expr_parent); add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if); add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); add_keyword(ctx, acc, "mod", "mod $0 {}", ctx.is_new_item || ctx.block_expr_parent); -- cgit v1.2.3 From 396167eadbea168e0d9858b5f45b7db860873f8b Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Fri, 12 Jun 2020 08:49:12 +0200 Subject: New testing approach for keywords --- crates/ra_ide/src/completion/complete_keyword.rs | 43 +++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 675991154..7eddf76b9 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -76,8 +76,6 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); add_keyword(ctx, acc, "mod", "mod $0 {}", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "mut", "mut ", ctx.bind_pat_parent || ctx.ref_pat_parent); - add_keyword(ctx, acc, "true", "true", !ctx.is_new_item); // this should be defined properly - add_keyword(ctx, acc, "false", "false", !ctx.is_new_item); // this should be defined properly add_keyword(ctx, acc, "const", "const ", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "static", "static ", ctx.is_new_item || ctx.block_expr_parent); @@ -89,7 +87,6 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); add_keyword(ctx, acc, "pub", "pub ", ctx.is_new_item && !ctx.inside_trait); add_keyword(ctx, acc, "where", "where ", ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling); - complete_use_tree_keyword(acc, ctx); let fn_def = match &ctx.function_syntax { Some(it) => it, @@ -114,13 +111,51 @@ fn complete_return( #[cfg(test)] mod tests { - use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; + use crate::{ + completion::{ + test_utils::{do_completion, do_completion_with_position}, + CompletionItem, CompletionKind, + }, + CompletionItemKind, + }; use insta::assert_debug_snapshot; + use rustc_hash::FxHashSet; fn do_keyword_completion(code: &str) -> Vec { do_completion(code, CompletionKind::Keyword) } + fn assert_completion_keyword(code: &str, keywords: &[(&str, &str)]) { + let (position, completion_items) = + do_completion_with_position(code, CompletionKind::Keyword); + let mut set = FxHashSet::<(String, String)>::default(); + for (key, value) in keywords { + set.insert(((*key).to_string(), (*value).to_string())); + } + + for item in completion_items { + assert!(item.text_edit().len() == 1); + assert!(item.kind() == Some(CompletionItemKind::Keyword)); + let atom = item.text_edit().iter().next().unwrap().clone(); + assert!(atom.delete.start() == position.offset); + assert!(atom.delete.end() == position.offset); + let pair = (item.label().to_string(), atom.insert); + assert!(set.contains(&pair)); + set.remove(&pair); + } + assert!(set.is_empty()); + } + + #[test] + fn completes_keywords_in_use_stmt_new_approach() { + assert_completion_keyword( + r" + use <|> + ", + &[("crate", "crate::"), ("self", "self"), ("super", "super::")], + ); + } + #[test] fn completes_keywords_in_use_stmt() { assert_debug_snapshot!( -- cgit v1.2.3 From f123539ad20c6c082a5e6aa69816429c3f73935a Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Fri, 12 Jun 2020 12:15:53 +0200 Subject: More assert refactoring --- crates/ra_ide/src/completion/complete_keyword.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 7eddf76b9..2e76f8592 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -118,7 +118,7 @@ mod tests { }, CompletionItemKind, }; - use insta::assert_debug_snapshot; + use insta::{assert_snapshot, assert_debug_snapshot}; use rustc_hash::FxHashSet; fn do_keyword_completion(code: &str) -> Vec { @@ -128,11 +128,12 @@ mod tests { fn assert_completion_keyword(code: &str, keywords: &[(&str, &str)]) { let (position, completion_items) = do_completion_with_position(code, CompletionKind::Keyword); - let mut set = FxHashSet::<(String, String)>::default(); + let mut expected_keywords = FxHashSet::<(String, String)>::default(); for (key, value) in keywords { - set.insert(((*key).to_string(), (*value).to_string())); + expected_keywords.insert(((*key).to_string(), (*value).to_string())); } - + let mut returned_keywords = FxHashSet::<(String, String)>::default(); + for item in completion_items { assert!(item.text_edit().len() == 1); assert!(item.kind() == Some(CompletionItemKind::Keyword)); @@ -140,10 +141,10 @@ mod tests { assert!(atom.delete.start() == position.offset); assert!(atom.delete.end() == position.offset); let pair = (item.label().to_string(), atom.insert); - assert!(set.contains(&pair)); - set.remove(&pair); + returned_keywords.insert(pair); } - assert!(set.is_empty()); + let assert_failed_message = format!("Expected keywords: {:#?}\nReceived keywords: {:#?}", expected_keywords, returned_keywords); + debug_assert!(returned_keywords == expected_keywords, assert_failed_message); } #[test] -- cgit v1.2.3 From d38bf1624d335651dc297fdd92672cdb0ee2ef4f Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Fri, 12 Jun 2020 13:06:26 +0200 Subject: Return snapshots to tests --- crates/ra_ide/src/completion/complete_keyword.rs | 52 ++++++++++++++++-------- 1 file changed, 34 insertions(+), 18 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 2e76f8592..feaa438af 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -118,43 +118,59 @@ mod tests { }, CompletionItemKind, }; - use insta::{assert_snapshot, assert_debug_snapshot}; - use rustc_hash::FxHashSet; + use insta::assert_debug_snapshot; fn do_keyword_completion(code: &str) -> Vec { do_completion(code, CompletionKind::Keyword) } - fn assert_completion_keyword(code: &str, keywords: &[(&str, &str)]) { + fn get_completion_text_and_assert_positions(code: &str) -> Vec<(String, String)> { let (position, completion_items) = do_completion_with_position(code, CompletionKind::Keyword); - let mut expected_keywords = FxHashSet::<(String, String)>::default(); - for (key, value) in keywords { - expected_keywords.insert(((*key).to_string(), (*value).to_string())); - } - let mut returned_keywords = FxHashSet::<(String, String)>::default(); - + let mut returned_keywords = Vec::<(String, String)>::new(); + for item in completion_items { - assert!(item.text_edit().len() == 1); + debug_assert!(item.text_edit().len() == 1); assert!(item.kind() == Some(CompletionItemKind::Keyword)); let atom = item.text_edit().iter().next().unwrap().clone(); assert!(atom.delete.start() == position.offset); assert!(atom.delete.end() == position.offset); let pair = (item.label().to_string(), atom.insert); - returned_keywords.insert(pair); + returned_keywords.push(pair); } - let assert_failed_message = format!("Expected keywords: {:#?}\nReceived keywords: {:#?}", expected_keywords, returned_keywords); - debug_assert!(returned_keywords == expected_keywords, assert_failed_message); + returned_keywords.sort(); + returned_keywords } #[test] fn completes_keywords_in_use_stmt_new_approach() { - assert_completion_keyword( - r" - use <|> - ", - &[("crate", "crate::"), ("self", "self"), ("super", "super::")], + assert_debug_snapshot!( + get_completion_text_and_assert_positions(r" + use <|> + "), + @r###" + [ + ( + "crate", + "crate::", + ), + ( + "self", + "self", + ), + ( + "super", + "super::", + ), + ] + "### ); + // assert_completion_keyword( + // r" + // use <|> + // ", + // &[("crate", "crate::"), ("self", "self"), ("super", "super::")], + // ); } #[test] -- cgit v1.2.3 From 42a719ad255c62933f58c2b2a5e767fb3b3c5a26 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Fri, 12 Jun 2020 13:14:53 +0200 Subject: Remove comment and incorrect assert --- crates/ra_ide/src/completion/complete_keyword.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index feaa438af..8ea51c7aa 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -130,7 +130,7 @@ mod tests { let mut returned_keywords = Vec::<(String, String)>::new(); for item in completion_items { - debug_assert!(item.text_edit().len() == 1); + assert!(item.text_edit().len() == 1); assert!(item.kind() == Some(CompletionItemKind::Keyword)); let atom = item.text_edit().iter().next().unwrap().clone(); assert!(atom.delete.start() == position.offset); @@ -165,12 +165,6 @@ mod tests { ] "### ); - // assert_completion_keyword( - // r" - // use <|> - // ", - // &[("crate", "crate::"), ("self", "self"), ("super", "super::")], - // ); } #[test] -- cgit v1.2.3 From 357667104371d446cc029267e8095365c17ba085 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Fri, 12 Jun 2020 20:30:57 +0200 Subject: Rewrite snapshot checks --- crates/ra_ide/src/completion/complete_keyword.rs | 183 ++++------------------- 1 file changed, 29 insertions(+), 154 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 8ea51c7aa..432793de2 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -61,7 +61,6 @@ fn add_keyword( pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); - add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); @@ -111,12 +110,9 @@ fn complete_return( #[cfg(test)] mod tests { - use crate::{ - completion::{ - test_utils::{do_completion, do_completion_with_position}, - CompletionItem, CompletionKind, - }, - CompletionItemKind, + use crate::completion::{ + test_utils::{do_completion, get_completions}, + CompletionItem, CompletionKind, }; use insta::assert_debug_snapshot; @@ -124,132 +120,39 @@ mod tests { do_completion(code, CompletionKind::Keyword) } - fn get_completion_text_and_assert_positions(code: &str) -> Vec<(String, String)> { - let (position, completion_items) = - do_completion_with_position(code, CompletionKind::Keyword); - let mut returned_keywords = Vec::<(String, String)>::new(); - - for item in completion_items { - assert!(item.text_edit().len() == 1); - assert!(item.kind() == Some(CompletionItemKind::Keyword)); - let atom = item.text_edit().iter().next().unwrap().clone(); - assert!(atom.delete.start() == position.offset); - assert!(atom.delete.end() == position.offset); - let pair = (item.label().to_string(), atom.insert); - returned_keywords.push(pair); - } - returned_keywords.sort(); - returned_keywords - } - - #[test] - fn completes_keywords_in_use_stmt_new_approach() { - assert_debug_snapshot!( - get_completion_text_and_assert_positions(r" - use <|> - "), - @r###" - [ - ( - "crate", - "crate::", - ), - ( - "self", - "self", - ), - ( - "super", - "super::", - ), - ] - "### - ); + fn get_keyword_completions(code: &str) -> Vec { + get_completions(code, CompletionKind::Keyword) } #[test] fn completes_keywords_in_use_stmt() { assert_debug_snapshot!( - do_keyword_completion( - r" - use <|> - ", - ), + get_keyword_completions(r"use <|>"), @r###" [ - CompletionItem { - label: "crate", - source_range: 21..21, - delete: 21..21, - insert: "crate::", - kind: Keyword, - }, - CompletionItem { - label: "self", - source_range: 21..21, - delete: 21..21, - insert: "self", - kind: Keyword, - }, - CompletionItem { - label: "super", - source_range: 21..21, - delete: 21..21, - insert: "super::", - kind: Keyword, - }, + "kw crate", + "kw self", + "kw super", ] "### ); assert_debug_snapshot!( - do_keyword_completion( - r" - use a::<|> - ", - ), + get_keyword_completions(r"use a::<|>"), @r###" [ - CompletionItem { - label: "self", - source_range: 24..24, - delete: 24..24, - insert: "self", - kind: Keyword, - }, - CompletionItem { - label: "super", - source_range: 24..24, - delete: 24..24, - insert: "super::", - kind: Keyword, - }, + "kw self", + "kw super", ] "### ); assert_debug_snapshot!( - do_keyword_completion( - r" - use a::{b, <|>} - ", - ), + get_keyword_completions(r"use a::{b, <|>}"), @r###" [ - CompletionItem { - label: "self", - source_range: 28..28, - delete: 28..28, - insert: "self", - kind: Keyword, - }, - CompletionItem { - label: "super", - source_range: 28..28, - delete: 28..28, - insert: "super::", - kind: Keyword, - }, + "kw self", + "kw super", ] "### ); @@ -258,50 +161,22 @@ mod tests { #[test] fn completes_various_keywords_in_function() { assert_debug_snapshot!( - do_keyword_completion( - r" - fn quux() { - <|> - } - ", - ), + get_keyword_completions(r"fn quux() { <|> }"), @r###" [ - CompletionItem { - label: "if", - source_range: 49..49, - delete: 49..49, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 49..49, - delete: 49..49, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 49..49, - delete: 49..49, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 49..49, - delete: 49..49, - insert: "return;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 49..49, - delete: 49..49, - insert: "while $0 {}", - kind: Keyword, - }, + "kw const", + "kw extern", + "kw fn", + "kw let", + "kw loop", + "kw match", + "kw mod", + "kw return", + "kw static", + "kw type", + "kw unsafe", + "kw use", + "kw while", ] "### ); -- cgit v1.2.3 From 6feb52c12accbf0ef54475cf66a03e035b922749 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Sat, 13 Jun 2020 00:55:21 +0200 Subject: Add more patterns, tests and fix keywords --- crates/ra_ide/src/completion/complete_keyword.rs | 690 ++++++++--------------- 1 file changed, 237 insertions(+), 453 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 432793de2..79432113c 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -60,32 +60,104 @@ fn add_keyword( } pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { + let has_trait_or_impl_parent = ctx.has_impl_parent || ctx.has_trait_parent; + if ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling { + add_keyword(ctx, acc, "where", "where ", true); + return; + } + if ctx.unsafe_is_prev { + add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "trait", + "trait $0 {}", + (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + ); + add_keyword( + ctx, + acc, + "impl", + "impl $0 {}", + (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + ); + return; + } add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); - add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); - add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); - add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); - add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); - add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); - add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); - add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent); - add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "use", + "use ", + (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + ); + add_keyword( + ctx, + acc, + "impl", + "impl $0 {}", + (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + ); + add_keyword( + ctx, + acc, + "trait", + "trait $0 {}", + (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + ); + add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !has_trait_or_impl_parent); + add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !has_trait_or_impl_parent); + add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !has_trait_or_impl_parent); + add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent || ctx.is_match_arm); + add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent || ctx.is_match_arm); add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); add_keyword(ctx, acc, "let", "let ", ctx.if_is_prev || ctx.block_expr_parent); + add_keyword(ctx, acc, "if", "if ", ctx.if_is_prev || ctx.block_expr_parent || ctx.is_match_arm); + add_keyword( + ctx, + acc, + "if let", + "if let ", + ctx.if_is_prev || ctx.block_expr_parent || ctx.is_match_arm, + ); add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if); add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); - add_keyword(ctx, acc, "mod", "mod $0 {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "mod", + "mod $0 {}", + (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + ); add_keyword(ctx, acc, "mut", "mut ", ctx.bind_pat_parent || ctx.ref_pat_parent); add_keyword(ctx, acc, "const", "const ", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); - add_keyword(ctx, acc, "static", "static ", ctx.is_new_item || ctx.block_expr_parent); - add_keyword(ctx, acc, "extern", "extern ", ctx.is_new_item || ctx.block_expr_parent); - add_keyword(ctx, acc, "unsafe", "unsafe ", ctx.is_new_item || ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "static", + "static ", + (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + ); + add_keyword( + ctx, + acc, + "extern", + "extern ", + (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + ); + add_keyword( + ctx, + acc, + "unsafe", + "unsafe ", + ctx.is_new_item || ctx.block_expr_parent || ctx.is_match_arm, + ); add_keyword(ctx, acc, "continue", "continue;", ctx.in_loop_body && ctx.can_be_stmt); add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt); add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt); add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); - add_keyword(ctx, acc, "pub", "pub ", ctx.is_new_item && !ctx.inside_trait); - add_keyword(ctx, acc, "where", "where ", ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling); + add_keyword(ctx, acc, "pub", "pub ", ctx.is_new_item && !ctx.has_trait_parent); let fn_def = match &ctx.function_syntax { Some(it) => it, @@ -111,21 +183,17 @@ fn complete_return( #[cfg(test)] mod tests { use crate::completion::{ - test_utils::{do_completion, get_completions}, - CompletionItem, CompletionKind, + test_utils::get_completions, + CompletionKind, }; use insta::assert_debug_snapshot; - fn do_keyword_completion(code: &str) -> Vec { - do_completion(code, CompletionKind::Keyword) - } - fn get_keyword_completions(code: &str) -> Vec { get_completions(code, CompletionKind::Keyword) } #[test] - fn completes_keywords_in_use_stmt() { + fn test_keywords_in_use_stmt() { assert_debug_snapshot!( get_keyword_completions(r"use <|>"), @r###" @@ -159,7 +227,7 @@ mod tests { } #[test] - fn completes_various_keywords_in_function() { + fn test_keywords_in_function() { assert_debug_snapshot!( get_keyword_completions(r"fn quux() { <|> }"), @r###" @@ -167,12 +235,16 @@ mod tests { "kw const", "kw extern", "kw fn", + "kw if", + "kw if let", + "kw impl", "kw let", "kw loop", "kw match", "kw mod", "kw return", "kw static", + "kw trait", "kw type", "kw unsafe", "kw use", @@ -183,9 +255,37 @@ mod tests { } #[test] - fn completes_else_after_if() { + fn test_keywords_inside_block() { assert_debug_snapshot!( - do_keyword_completion( + get_keyword_completions(r"fn quux() { if true { <|> } }"), + @r###" + [ + "kw const", + "kw extern", + "kw fn", + "kw if", + "kw if let", + "kw impl", + "kw let", + "kw loop", + "kw match", + "kw mod", + "kw return", + "kw static", + "kw trait", + "kw type", + "kw unsafe", + "kw use", + "kw while", + ] + "### + ); + } + + #[test] + fn test_keywords_after_if() { + assert_debug_snapshot!( + get_keyword_completions( r" fn quux() { if true { @@ -196,505 +296,189 @@ mod tests { ), @r###" [ - CompletionItem { - label: "else", - source_range: 108..108, - delete: 108..108, - insert: "else {$0}", - kind: Keyword, - }, - CompletionItem { - label: "else if", - source_range: 108..108, - delete: 108..108, - insert: "else if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "if", - source_range: 108..108, - delete: 108..108, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 108..108, - delete: 108..108, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 108..108, - delete: 108..108, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 108..108, - delete: 108..108, - insert: "return;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 108..108, - delete: 108..108, - insert: "while $0 {}", - kind: Keyword, - }, + "kw const", + "kw else", + "kw else if", + "kw extern", + "kw fn", + "kw if", + "kw if let", + "kw impl", + "kw let", + "kw loop", + "kw match", + "kw mod", + "kw return", + "kw static", + "kw trait", + "kw type", + "kw unsafe", + "kw use", + "kw while", ] "### ); } #[test] - fn test_completion_return_value() { + fn test_keywords_in_match_arm() { assert_debug_snapshot!( - do_keyword_completion( + get_keyword_completions( r" fn quux() -> i32 { - <|> - 92 + match () { + () => <|> + } } ", ), @r###" [ - CompletionItem { - label: "if", - source_range: 56..56, - delete: 56..56, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 56..56, - delete: 56..56, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 56..56, - delete: 56..56, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 56..56, - delete: 56..56, - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 56..56, - delete: 56..56, - insert: "while $0 {}", - kind: Keyword, - }, + "kw if", + "kw if let", + "kw loop", + "kw match", + "kw return", + "kw unsafe", ] "### ); + } + + #[test] + fn test_keywords_in_trait_def() { assert_debug_snapshot!( - do_keyword_completion( - r" - fn quux() { - <|> - 92 - } - ", - ), + get_keyword_completions(r"trait My { <|> }"), @r###" [ - CompletionItem { - label: "if", - source_range: 49..49, - delete: 49..49, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 49..49, - delete: 49..49, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 49..49, - delete: 49..49, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 49..49, - delete: 49..49, - insert: "return;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 49..49, - delete: 49..49, - insert: "while $0 {}", - kind: Keyword, - }, + "kw const", + "kw fn", + "kw type", + "kw unsafe", ] "### ); } #[test] - fn dont_add_semi_after_return_if_not_a_statement() { + fn test_keywords_in_impl_def() { assert_debug_snapshot!( - do_keyword_completion( - r" - fn quux() -> i32 { - match () { - () => <|> - } - } - ", - ), + get_keyword_completions(r"impl My { <|> }"), @r###" [ - CompletionItem { - label: "if", - source_range: 97..97, - delete: 97..97, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 97..97, - delete: 97..97, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 97..97, - delete: 97..97, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 97..97, - delete: 97..97, - insert: "return $0", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 97..97, - delete: 97..97, - insert: "while $0 {}", - kind: Keyword, - }, + "kw const", + "kw fn", + "kw pub", + "kw type", + "kw unsafe", ] "### ); } #[test] - fn last_return_in_block_has_semi() { + fn test_keywords_in_loop() { assert_debug_snapshot!( - do_keyword_completion( - r" - fn quux() -> i32 { - if condition { - <|> - } - } - ", - ), + get_keyword_completions(r"fn my() { loop { <|> } }"), @r###" [ - CompletionItem { - label: "if", - source_range: 95..95, - delete: 95..95, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 95..95, - delete: 95..95, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 95..95, - delete: 95..95, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 95..95, - delete: 95..95, - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 95..95, - delete: 95..95, - insert: "while $0 {}", - kind: Keyword, - }, + "kw break", + "kw const", + "kw continue", + "kw extern", + "kw fn", + "kw if", + "kw if let", + "kw impl", + "kw let", + "kw loop", + "kw match", + "kw mod", + "kw return", + "kw static", + "kw trait", + "kw type", + "kw unsafe", + "kw use", + "kw while", ] "### ); + } + + #[test] + fn test_keywords_after_unsafe_in_item_list() { assert_debug_snapshot!( - do_keyword_completion( - r" - fn quux() -> i32 { - if condition { - <|> - } - let x = 92; - x - } - ", - ), + get_keyword_completions(r"unsafe <|>"), @r###" [ - CompletionItem { - label: "if", - source_range: 95..95, - delete: 95..95, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 95..95, - delete: 95..95, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 95..95, - delete: 95..95, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 95..95, - delete: 95..95, - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 95..95, - delete: 95..95, - insert: "while $0 {}", - kind: Keyword, - }, + "kw fn", + "kw impl", + "kw trait", ] "### ); } #[test] - fn completes_break_and_continue_in_loops() { + fn test_keywords_after_unsafe_in_block_expr() { assert_debug_snapshot!( - do_keyword_completion( - r" - fn quux() -> i32 { - loop { <|> } - } - ", - ), + get_keyword_completions(r"fn my_fn() { unsafe <|> }"), @r###" [ - CompletionItem { - label: "break", - source_range: 63..63, - delete: 63..63, - insert: "break;", - kind: Keyword, - }, - CompletionItem { - label: "continue", - source_range: 63..63, - delete: 63..63, - insert: "continue;", - kind: Keyword, - }, - CompletionItem { - label: "if", - source_range: 63..63, - delete: 63..63, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 63..63, - delete: 63..63, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 63..63, - delete: 63..63, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 63..63, - delete: 63..63, - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 63..63, - delete: 63..63, - insert: "while $0 {}", - kind: Keyword, - }, + "kw fn", + "kw impl", + "kw trait", ] "### ); + } - // No completion: lambda isolates control flow + #[test] + fn test_mut_in_ref_and_in_fn_parameters_list() { assert_debug_snapshot!( - do_keyword_completion( - r" - fn quux() -> i32 { - loop { || { <|> } } - } - ", - ), + get_keyword_completions(r"fn my_fn(&<|>) {}"), + @r###" + [ + "kw mut", + ] + "### + ); + assert_debug_snapshot!( + get_keyword_completions(r"fn my_fn(<|>) {}"), + @r###" + [ + "kw mut", + ] + "### + ); + assert_debug_snapshot!( + get_keyword_completions(r"fn my_fn() { let &<|> }"), @r###" [ - CompletionItem { - label: "if", - source_range: 68..68, - delete: 68..68, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 68..68, - delete: 68..68, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 68..68, - delete: 68..68, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 68..68, - delete: 68..68, - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 68..68, - delete: 68..68, - insert: "while $0 {}", - kind: Keyword, - }, + "kw mut", ] "### ); } #[test] - fn no_semi_after_break_continue_in_expr() { + fn test_where_keyword() { assert_debug_snapshot!( - do_keyword_completion( - r" - fn f() { - loop { - match () { - () => br<|> - } - } - } - ", - ), + get_keyword_completions(r"trait A <|>"), + @r###" + [ + "kw where", + ] + "### + ); + assert_debug_snapshot!( + get_keyword_completions(r"impl A <|>"), @r###" [ - CompletionItem { - label: "break", - source_range: 122..124, - delete: 122..124, - insert: "break", - kind: Keyword, - }, - CompletionItem { - label: "continue", - source_range: 122..124, - delete: 122..124, - insert: "continue", - kind: Keyword, - }, - CompletionItem { - label: "if", - source_range: 122..124, - delete: 122..124, - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: 122..124, - delete: 122..124, - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: 122..124, - delete: 122..124, - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: 122..124, - delete: 122..124, - insert: "return", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: 122..124, - delete: 122..124, - insert: "while $0 {}", - kind: Keyword, - }, + "kw where", ] "### - ) + ); } } -- cgit v1.2.3 From eeb8b9e236796da8734ba81a49164864497f7226 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Sat, 13 Jun 2020 01:21:48 +0200 Subject: Fix tests and remove unused methods --- crates/ra_ide/src/completion/complete_keyword.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 79432113c..025097e49 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -159,6 +159,9 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); add_keyword(ctx, acc, "pub", "pub ", ctx.is_new_item && !ctx.has_trait_parent); + if !ctx.is_trivial_path { + return; + } let fn_def = match &ctx.function_syntax { Some(it) => it, None => return, @@ -182,10 +185,7 @@ fn complete_return( #[cfg(test)] mod tests { - use crate::completion::{ - test_utils::get_completions, - CompletionKind, - }; + use crate::completion::{test_utils::get_completions, CompletionKind}; use insta::assert_debug_snapshot; fn get_keyword_completions(code: &str) -> Vec { -- cgit v1.2.3 From 912f38200fb6c8c6cea750a84c04de810992dec7 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Sat, 13 Jun 2020 10:43:39 +0200 Subject: Add keywords completions on source file position --- crates/ra_ide/src/completion/complete_keyword.rs | 115 +++++++++++++++++++---- 1 file changed, 98 insertions(+), 17 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 025097e49..d016f0c7c 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -66,48 +66,83 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte return; } if ctx.unsafe_is_prev { - add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "fn", + "fn $0() {}", + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, + ); add_keyword( ctx, acc, "trait", "trait $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "impl", "impl $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); return; } - add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "fn", + "fn $0() {}", + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, + ); add_keyword( ctx, acc, "use", "use ", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "impl", "impl $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "trait", "trait $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, + ); + add_keyword( + ctx, + acc, + "enum", + "enum $0 {}", + ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, + ); + add_keyword( + ctx, + acc, + "struct", + "struct $0 {}", + ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, + ); + add_keyword( + ctx, + acc, + "union", + "union $0 {}", + ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, ); - add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !has_trait_or_impl_parent); - add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !has_trait_or_impl_parent); - add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !has_trait_or_impl_parent); add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent || ctx.is_match_arm); add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent || ctx.is_match_arm); add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); @@ -127,37 +162,58 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte acc, "mod", "mod $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword(ctx, acc, "mut", "mut ", ctx.bind_pat_parent || ctx.ref_pat_parent); - add_keyword(ctx, acc, "const", "const ", ctx.is_new_item || ctx.block_expr_parent); - add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "const", + "const ", + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, + ); + add_keyword( + ctx, + acc, + "type", + "type ", + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, + ); add_keyword( ctx, acc, "static", "static ", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "extern", "extern ", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "unsafe", "unsafe ", - ctx.is_new_item || ctx.block_expr_parent || ctx.is_match_arm, + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent || ctx.is_match_arm, ); add_keyword(ctx, acc, "continue", "continue;", ctx.in_loop_body && ctx.can_be_stmt); add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt); add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt); add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); - add_keyword(ctx, acc, "pub", "pub ", ctx.is_new_item && !ctx.has_trait_parent); + add_keyword( + ctx, + acc, + "pub", + "pub ", + ctx.has_item_list_or_source_file_parent && !ctx.has_trait_parent, + ); if !ctx.is_trivial_path { return; @@ -226,6 +282,31 @@ mod tests { ); } + #[test] + fn test_keywords_at_source_file_level() { + assert_debug_snapshot!( + get_keyword_completions(r"m<|>"), + @r###" + [ + "kw const", + "kw enum", + "kw extern", + "kw fn", + "kw impl", + "kw mod", + "kw pub", + "kw static", + "kw struct", + "kw trait", + "kw type", + "kw union", + "kw unsafe", + "kw use", + ] + "### + ); + } + #[test] fn test_keywords_in_function() { assert_debug_snapshot!( -- cgit v1.2.3 From ef70076f1da391be8697aaf3c534e4e770561429 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Jun 2020 13:47:30 +0200 Subject: Cleanup --- crates/ra_ide/src/completion/complete_keyword.rs | 269 +++++++++-------------- 1 file changed, 99 insertions(+), 170 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index d016f0c7c..0ab330b73 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -36,184 +36,98 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC } } -fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem { - let res = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) - .kind(CompletionItemKind::Keyword); - - match ctx.config.snippet_cap { - Some(cap) => res.insert_snippet(cap, snippet), - _ => res.insert_text(if snippet.contains('$') { kw } else { snippet }), - } - .build() -} - -fn add_keyword( - ctx: &CompletionContext, - acc: &mut Completions, - kw: &str, - snippet: &str, - should_add: bool, -) { - if should_add { - acc.add(keyword(ctx, kw, snippet)); - } -} - pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { let has_trait_or_impl_parent = ctx.has_impl_parent || ctx.has_trait_parent; if ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling { - add_keyword(ctx, acc, "where", "where ", true); + add_keyword(ctx, acc, "where", "where "); return; } if ctx.unsafe_is_prev { - add_keyword( - ctx, - acc, - "fn", - "fn $0() {}", - ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "trait", - "trait $0 {}", - (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) - || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "impl", - "impl $0 {}", - (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) - || ctx.block_expr_parent, - ); + if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent { + add_keyword(ctx, acc, "fn", "fn $0() {}") + } + + if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent + { + add_keyword(ctx, acc, "trait", "trait $0 {}"); + add_keyword(ctx, acc, "impl", "impl $0 {}"); + } + return; } - add_keyword( - ctx, - acc, - "fn", - "fn $0() {}", - ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "use", - "use ", - (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) - || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "impl", - "impl $0 {}", - (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) - || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "trait", - "trait $0 {}", - (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) - || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "enum", - "enum $0 {}", - ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, - ); - add_keyword( - ctx, - acc, - "struct", - "struct $0 {}", - ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, - ); - add_keyword( - ctx, - acc, - "union", - "union $0 {}", - ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, - ); - add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent || ctx.is_match_arm); - add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent || ctx.is_match_arm); - add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); - add_keyword(ctx, acc, "let", "let ", ctx.if_is_prev || ctx.block_expr_parent); - add_keyword(ctx, acc, "if", "if ", ctx.if_is_prev || ctx.block_expr_parent || ctx.is_match_arm); - add_keyword( - ctx, - acc, - "if let", - "if let ", - ctx.if_is_prev || ctx.block_expr_parent || ctx.is_match_arm, - ); - add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if); - add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); - add_keyword( - ctx, - acc, - "mod", - "mod $0 {}", - (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) - || ctx.block_expr_parent, - ); - add_keyword(ctx, acc, "mut", "mut ", ctx.bind_pat_parent || ctx.ref_pat_parent); - add_keyword( - ctx, - acc, - "const", - "const ", - ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "type", - "type ", - ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "static", - "static ", - (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) - || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "extern", - "extern ", - (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) - || ctx.block_expr_parent, - ); - add_keyword( - ctx, - acc, - "unsafe", - "unsafe ", - ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent || ctx.is_match_arm, - ); - add_keyword(ctx, acc, "continue", "continue;", ctx.in_loop_body && ctx.can_be_stmt); - add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt); - add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt); - add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); - add_keyword( - ctx, - acc, - "pub", - "pub ", - ctx.has_item_list_or_source_file_parent && !ctx.has_trait_parent, - ); + if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent { + add_keyword(ctx, acc, "fn", "fn $0() {}"); + } + if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent + { + add_keyword(ctx, acc, "use", "use "); + add_keyword(ctx, acc, "impl", "impl $0 {}"); + add_keyword(ctx, acc, "trait", "trait $0 {}"); + } + + if ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent { + add_keyword(ctx, acc, "enum", "enum $0 {}"); + add_keyword(ctx, acc, "struct", "struct $0 {}"); + add_keyword(ctx, acc, "union", "union $0 {}"); + } + + if ctx.block_expr_parent || ctx.is_match_arm { + add_keyword(ctx, acc, "match", "match $0 {}"); + add_keyword(ctx, acc, "loop", "loop {$0}"); + } + if ctx.block_expr_parent { + add_keyword(ctx, acc, "while", "while $0 {}"); + } + if ctx.if_is_prev || ctx.block_expr_parent { + add_keyword(ctx, acc, "let", "let "); + } + if ctx.if_is_prev || ctx.block_expr_parent || ctx.is_match_arm { + add_keyword(ctx, acc, "if", "if "); + add_keyword(ctx, acc, "if let", "if let "); + } + if ctx.after_if { + add_keyword(ctx, acc, "else", "else {$0}"); + add_keyword(ctx, acc, "else if", "else if $0 {}"); + } + if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent + { + add_keyword(ctx, acc, "mod", "mod $0 {}"); + } + if ctx.bind_pat_parent || ctx.ref_pat_parent { + add_keyword(ctx, acc, "mut", "mut "); + } + if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent { + add_keyword(ctx, acc, "const", "const "); + add_keyword(ctx, acc, "type", "type "); + } + if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent + { + add_keyword(ctx, acc, "static", "static "); + }; + if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent + { + add_keyword(ctx, acc, "extern", "extern "); + } + if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent || ctx.is_match_arm { + add_keyword(ctx, acc, "unsafe", "unsafe "); + } + if ctx.in_loop_body { + if ctx.can_be_stmt { + add_keyword(ctx, acc, "continue", "continue;"); + add_keyword(ctx, acc, "break", "break;"); + } else { + add_keyword(ctx, acc, "continue", "continue"); + add_keyword(ctx, acc, "break", "break"); + } + } + if ctx.has_item_list_or_source_file_parent && !ctx.has_trait_parent { + add_keyword(ctx, acc, "pub", "pub ") + } if !ctx.is_trivial_path { return; @@ -225,6 +139,21 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte acc.add_all(complete_return(ctx, &fn_def, ctx.can_be_stmt)); } +fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem { + let res = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) + .kind(CompletionItemKind::Keyword); + + match ctx.config.snippet_cap { + Some(cap) => res.insert_snippet(cap, snippet), + _ => res.insert_text(if snippet.contains('$') { kw } else { snippet }), + } + .build() +} + +fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) { + acc.add(keyword(ctx, kw, snippet)); +} + fn complete_return( ctx: &CompletionContext, fn_def: &ast::FnDef, -- cgit v1.2.3 From b99b4953c9a4791f7f39ab208a1842086ad0f04c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Jun 2020 13:57:18 +0200 Subject: More concise completion tests --- crates/ra_ide/src/completion/complete_keyword.rs | 318 ++++++++++------------- 1 file changed, 141 insertions(+), 177 deletions(-) (limited to 'crates/ra_ide/src/completion/complete_keyword.rs') diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 0ab330b73..b2f621a11 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -170,131 +170,119 @@ fn complete_return( #[cfg(test)] mod tests { - use crate::completion::{test_utils::get_completions, CompletionKind}; - use insta::assert_debug_snapshot; + use crate::completion::{test_utils::completion_list, CompletionKind}; + use insta::assert_snapshot; - fn get_keyword_completions(code: &str) -> Vec { - get_completions(code, CompletionKind::Keyword) + fn get_keyword_completions(code: &str) -> String { + completion_list(code, CompletionKind::Keyword) } #[test] fn test_keywords_in_use_stmt() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"use <|>"), @r###" - [ - "kw crate", - "kw self", - "kw super", - ] + kw crate + kw self + kw super "### ); - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"use a::<|>"), @r###" - [ - "kw self", - "kw super", - ] + kw self + kw super "### ); - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"use a::{b, <|>}"), @r###" - [ - "kw self", - "kw super", - ] + kw self + kw super "### ); } #[test] fn test_keywords_at_source_file_level() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"m<|>"), @r###" - [ - "kw const", - "kw enum", - "kw extern", - "kw fn", - "kw impl", - "kw mod", - "kw pub", - "kw static", - "kw struct", - "kw trait", - "kw type", - "kw union", - "kw unsafe", - "kw use", - ] + kw const + kw enum + kw extern + kw fn + kw impl + kw mod + kw pub + kw static + kw struct + kw trait + kw type + kw union + kw unsafe + kw use "### ); } #[test] fn test_keywords_in_function() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"fn quux() { <|> }"), @r###" - [ - "kw const", - "kw extern", - "kw fn", - "kw if", - "kw if let", - "kw impl", - "kw let", - "kw loop", - "kw match", - "kw mod", - "kw return", - "kw static", - "kw trait", - "kw type", - "kw unsafe", - "kw use", - "kw while", - ] + kw const + kw extern + kw fn + kw if + kw if let + kw impl + kw let + kw loop + kw match + kw mod + kw return + kw static + kw trait + kw type + kw unsafe + kw use + kw while "### ); } #[test] fn test_keywords_inside_block() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"fn quux() { if true { <|> } }"), @r###" - [ - "kw const", - "kw extern", - "kw fn", - "kw if", - "kw if let", - "kw impl", - "kw let", - "kw loop", - "kw match", - "kw mod", - "kw return", - "kw static", - "kw trait", - "kw type", - "kw unsafe", - "kw use", - "kw while", - ] + kw const + kw extern + kw fn + kw if + kw if let + kw impl + kw let + kw loop + kw match + kw mod + kw return + kw static + kw trait + kw type + kw unsafe + kw use + kw while "### ); } #[test] fn test_keywords_after_if() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions( r" fn quux() { @@ -305,34 +293,32 @@ mod tests { ", ), @r###" - [ - "kw const", - "kw else", - "kw else if", - "kw extern", - "kw fn", - "kw if", - "kw if let", - "kw impl", - "kw let", - "kw loop", - "kw match", - "kw mod", - "kw return", - "kw static", - "kw trait", - "kw type", - "kw unsafe", - "kw use", - "kw while", - ] + kw const + kw else + kw else if + kw extern + kw fn + kw if + kw if let + kw impl + kw let + kw loop + kw match + kw mod + kw return + kw static + kw trait + kw type + kw unsafe + kw use + kw while "### ); } #[test] fn test_keywords_in_match_arm() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions( r" fn quux() -> i32 { @@ -343,151 +329,129 @@ mod tests { ", ), @r###" - [ - "kw if", - "kw if let", - "kw loop", - "kw match", - "kw return", - "kw unsafe", - ] + kw if + kw if let + kw loop + kw match + kw return + kw unsafe "### ); } #[test] fn test_keywords_in_trait_def() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"trait My { <|> }"), @r###" - [ - "kw const", - "kw fn", - "kw type", - "kw unsafe", - ] + kw const + kw fn + kw type + kw unsafe "### ); } #[test] fn test_keywords_in_impl_def() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"impl My { <|> }"), @r###" - [ - "kw const", - "kw fn", - "kw pub", - "kw type", - "kw unsafe", - ] + kw const + kw fn + kw pub + kw type + kw unsafe "### ); } #[test] fn test_keywords_in_loop() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"fn my() { loop { <|> } }"), @r###" - [ - "kw break", - "kw const", - "kw continue", - "kw extern", - "kw fn", - "kw if", - "kw if let", - "kw impl", - "kw let", - "kw loop", - "kw match", - "kw mod", - "kw return", - "kw static", - "kw trait", - "kw type", - "kw unsafe", - "kw use", - "kw while", - ] + kw break + kw const + kw continue + kw extern + kw fn + kw if + kw if let + kw impl + kw let + kw loop + kw match + kw mod + kw return + kw static + kw trait + kw type + kw unsafe + kw use + kw while "### ); } #[test] fn test_keywords_after_unsafe_in_item_list() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"unsafe <|>"), @r###" - [ - "kw fn", - "kw impl", - "kw trait", - ] + kw fn + kw impl + kw trait "### ); } #[test] fn test_keywords_after_unsafe_in_block_expr() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"fn my_fn() { unsafe <|> }"), @r###" - [ - "kw fn", - "kw impl", - "kw trait", - ] + kw fn + kw impl + kw trait "### ); } #[test] fn test_mut_in_ref_and_in_fn_parameters_list() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"fn my_fn(&<|>) {}"), @r###" - [ - "kw mut", - ] + kw mut "### ); - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"fn my_fn(<|>) {}"), @r###" - [ - "kw mut", - ] + kw mut "### ); - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"fn my_fn() { let &<|> }"), @r###" - [ - "kw mut", - ] + kw mut "### ); } #[test] fn test_where_keyword() { - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"trait A <|>"), @r###" - [ - "kw where", - ] + kw where "### ); - assert_debug_snapshot!( + assert_snapshot!( get_keyword_completions(r"impl A <|>"), @r###" - [ - "kw where", - ] + kw where "### ); } -- cgit v1.2.3