diff options
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 35 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_path.rs | 17 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_postfix.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_scope.rs | 37 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 32 |
5 files changed, 97 insertions, 26 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index b6fe48627..294964887 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -27,7 +27,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | |||
27 | complete_methods(acc, ctx, &receiver_ty); | 27 | complete_methods(acc, ctx, &receiver_ty); |
28 | 28 | ||
29 | // Suggest .await syntax for types that implement Future trait | 29 | // Suggest .await syntax for types that implement Future trait |
30 | if ctx.analyzer.impls_future(ctx.db, receiver_ty.into_ty()) { | 30 | if ctx.analyzer.impls_future(ctx.db, receiver_ty) { |
31 | CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") | 31 | CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") |
32 | .detail("expr.await") | 32 | .detail("expr.await") |
33 | .insert_text("await") | 33 | .insert_text("await") |
@@ -217,6 +217,39 @@ mod tests { | |||
217 | } | 217 | } |
218 | 218 | ||
219 | #[test] | 219 | #[test] |
220 | fn test_method_completion_only_fitting_impls() { | ||
221 | assert_debug_snapshot!( | ||
222 | do_ref_completion( | ||
223 | r" | ||
224 | struct A<T> {} | ||
225 | impl A<u32> { | ||
226 | fn the_method(&self) {} | ||
227 | } | ||
228 | impl A<i32> { | ||
229 | fn the_other_method(&self) {} | ||
230 | } | ||
231 | fn foo(a: A<u32>) { | ||
232 | a.<|> | ||
233 | } | ||
234 | ", | ||
235 | ), | ||
236 | @r###" | ||
237 | [ | ||
238 | CompletionItem { | ||
239 | label: "the_method()", | ||
240 | source_range: [243; 243), | ||
241 | delete: [243; 243), | ||
242 | insert: "the_method()$0", | ||
243 | kind: Method, | ||
244 | lookup: "the_method", | ||
245 | detail: "fn the_method(&self)", | ||
246 | }, | ||
247 | ] | ||
248 | "### | ||
249 | ); | ||
250 | } | ||
251 | |||
252 | #[test] | ||
220 | fn test_trait_method_completion() { | 253 | fn test_trait_method_completion() { |
221 | assert_debug_snapshot!( | 254 | assert_debug_snapshot!( |
222 | do_ref_completion( | 255 | do_ref_completion( |
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 89e0009a1..cc1f7c830 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{Adt, Either, HasSource, PathResolution}; | 3 | use hir::{Adt, PathResolution, ScopeDef}; |
4 | use ra_syntax::AstNode; | 4 | use ra_syntax::AstNode; |
5 | use test_utils::tested_by; | 5 | use test_utils::tested_by; |
6 | 6 | ||
@@ -18,17 +18,15 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
18 | match def { | 18 | match def { |
19 | hir::ModuleDef::Module(module) => { | 19 | hir::ModuleDef::Module(module) => { |
20 | let module_scope = module.scope(ctx.db); | 20 | let module_scope = module.scope(ctx.db); |
21 | for (name, def, import) in module_scope { | 21 | for (name, def) in module_scope { |
22 | if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { | 22 | if ctx.use_item_syntax.is_some() { |
23 | if ctx.use_item_syntax.is_some() { | 23 | if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { |
24 | tested_by!(dont_complete_primitive_in_use); | 24 | tested_by!(dont_complete_primitive_in_use); |
25 | continue; | 25 | continue; |
26 | } | 26 | } |
27 | } | 27 | if let ScopeDef::Unknown = def { |
28 | if Some(module) == ctx.module { | 28 | if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { |
29 | if let Some(import) = import { | 29 | if &name_ref.syntax().text() == name.to_string().as_str() { |
30 | if let Either::A(use_tree) = import.source(ctx.db).value { | ||
31 | if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { | ||
32 | // for `use self::foo<|>`, don't suggest `foo` as a completion | 30 | // for `use self::foo<|>`, don't suggest `foo` as a completion |
33 | tested_by!(dont_complete_current_use); | 31 | tested_by!(dont_complete_current_use); |
34 | continue; | 32 | continue; |
@@ -36,6 +34,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
36 | } | 34 | } |
37 | } | 35 | } |
38 | } | 36 | } |
37 | |||
39 | acc.add_resolution(ctx, name.to_string(), &def); | 38 | acc.add_resolution(ctx, name.to_string(), &def); |
40 | } | 39 | } |
41 | } | 40 | } |
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs index 646a30c76..5470dc291 100644 --- a/crates/ra_ide/src/completion/complete_postfix.rs +++ b/crates/ra_ide/src/completion/complete_postfix.rs | |||
@@ -12,7 +12,7 @@ use crate::{ | |||
12 | }; | 12 | }; |
13 | 13 | ||
14 | pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | 14 | pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { |
15 | if ctx.db.feature_flags.get("completion.enable-postfix") == false { | 15 | if !ctx.db.feature_flags.get("completion.enable-postfix") { |
16 | return; | 16 | return; |
17 | } | 17 | } |
18 | 18 | ||
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index d5739b58a..458d7525e 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs | |||
@@ -873,4 +873,41 @@ mod tests { | |||
873 | "### | 873 | "### |
874 | ); | 874 | ); |
875 | } | 875 | } |
876 | |||
877 | #[test] | ||
878 | fn completes_local_item() { | ||
879 | assert_debug_snapshot!( | ||
880 | do_reference_completion( | ||
881 | " | ||
882 | //- /main.rs | ||
883 | fn main() { | ||
884 | return f<|>; | ||
885 | fn frobnicate() {} | ||
886 | } | ||
887 | " | ||
888 | ), | ||
889 | @r###" | ||
890 | [ | ||
891 | CompletionItem { | ||
892 | label: "frobnicate()", | ||
893 | source_range: [23; 24), | ||
894 | delete: [23; 24), | ||
895 | insert: "frobnicate()$0", | ||
896 | kind: Function, | ||
897 | lookup: "frobnicate", | ||
898 | detail: "fn frobnicate()", | ||
899 | }, | ||
900 | CompletionItem { | ||
901 | label: "main()", | ||
902 | source_range: [23; 24), | ||
903 | delete: [23; 24), | ||
904 | insert: "main()$0", | ||
905 | kind: Function, | ||
906 | lookup: "main", | ||
907 | detail: "fn main()", | ||
908 | }, | ||
909 | ] | ||
910 | "### | ||
911 | ) | ||
912 | } | ||
876 | } | 913 | } |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index b8345c91d..48d69f7e5 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -19,6 +19,7 @@ pub(crate) struct CompletionContext<'a> { | |||
19 | pub(super) offset: TextUnit, | 19 | pub(super) offset: TextUnit, |
20 | pub(super) token: SyntaxToken, | 20 | pub(super) token: SyntaxToken, |
21 | pub(super) module: Option<hir::Module>, | 21 | pub(super) module: Option<hir::Module>, |
22 | pub(super) name_ref_syntax: Option<ast::NameRef>, | ||
22 | pub(super) function_syntax: Option<ast::FnDef>, | 23 | pub(super) function_syntax: Option<ast::FnDef>, |
23 | pub(super) use_item_syntax: Option<ast::UseItem>, | 24 | pub(super) use_item_syntax: Option<ast::UseItem>, |
24 | pub(super) record_lit_syntax: Option<ast::RecordLit>, | 25 | pub(super) record_lit_syntax: Option<ast::RecordLit>, |
@@ -54,13 +55,13 @@ impl<'a> CompletionContext<'a> { | |||
54 | let src = hir::ModuleSource::from_position(db, position); | 55 | let src = hir::ModuleSource::from_position(db, position); |
55 | let module = hir::Module::from_definition( | 56 | let module = hir::Module::from_definition( |
56 | db, | 57 | db, |
57 | hir::Source { file_id: position.file_id.into(), value: src }, | 58 | hir::InFile { file_id: position.file_id.into(), value: src }, |
58 | ); | 59 | ); |
59 | let token = | 60 | let token = |
60 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; | 61 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; |
61 | let analyzer = hir::SourceAnalyzer::new( | 62 | let analyzer = hir::SourceAnalyzer::new( |
62 | db, | 63 | db, |
63 | hir::Source::new(position.file_id.into(), &token.parent()), | 64 | hir::InFile::new(position.file_id.into(), &token.parent()), |
64 | Some(position.offset), | 65 | Some(position.offset), |
65 | ); | 66 | ); |
66 | let mut ctx = CompletionContext { | 67 | let mut ctx = CompletionContext { |
@@ -69,6 +70,7 @@ impl<'a> CompletionContext<'a> { | |||
69 | token, | 70 | token, |
70 | offset: position.offset, | 71 | offset: position.offset, |
71 | module, | 72 | module, |
73 | name_ref_syntax: None, | ||
72 | function_syntax: None, | 74 | function_syntax: None, |
73 | use_item_syntax: None, | 75 | use_item_syntax: None, |
74 | record_lit_syntax: None, | 76 | record_lit_syntax: None, |
@@ -142,6 +144,8 @@ impl<'a> CompletionContext<'a> { | |||
142 | } | 144 | } |
143 | 145 | ||
144 | fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) { | 146 | fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) { |
147 | self.name_ref_syntax = | ||
148 | find_node_at_offset(original_file.syntax(), name_ref.syntax().text_range().start()); | ||
145 | let name_range = name_ref.syntax().text_range(); | 149 | let name_range = name_ref.syntax().text_range(); |
146 | if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() { | 150 | if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() { |
147 | self.record_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset); | 151 | self.record_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset); |
@@ -188,10 +192,9 @@ impl<'a> CompletionContext<'a> { | |||
188 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); | 192 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); |
189 | self.has_type_args = segment.type_arg_list().is_some(); | 193 | self.has_type_args = segment.type_arg_list().is_some(); |
190 | 194 | ||
191 | if let Some(mut path) = hir::Path::from_ast(path.clone()) { | 195 | if let Some(path) = hir::Path::from_ast(path.clone()) { |
192 | if !path.is_ident() { | 196 | if let Some(path_prefix) = path.qualifier() { |
193 | path.segments.pop().unwrap(); | 197 | self.path_prefix = Some(path_prefix); |
194 | self.path_prefix = Some(path); | ||
195 | return; | 198 | return; |
196 | } | 199 | } |
197 | } | 200 | } |
@@ -240,16 +243,15 @@ impl<'a> CompletionContext<'a> { | |||
240 | .expr() | 243 | .expr() |
241 | .map(|e| e.syntax().text_range()) | 244 | .map(|e| e.syntax().text_range()) |
242 | .and_then(|r| find_node_with_range(original_file.syntax(), r)); | 245 | .and_then(|r| find_node_with_range(original_file.syntax(), r)); |
243 | self.dot_receiver_is_ambiguous_float_literal = if let Some(ast::Expr::Literal(l)) = | 246 | self.dot_receiver_is_ambiguous_float_literal = |
244 | &self.dot_receiver | 247 | if let Some(ast::Expr::Literal(l)) = &self.dot_receiver { |
245 | { | 248 | match l.kind() { |
246 | match l.kind() { | 249 | ast::LiteralKind::FloatNumber { .. } => l.token().text().ends_with('.'), |
247 | ast::LiteralKind::FloatNumber { suffix: _ } => l.token().text().ends_with('.'), | 250 | _ => false, |
248 | _ => false, | 251 | } |
252 | } else { | ||
253 | false | ||
249 | } | 254 | } |
250 | } else { | ||
251 | false | ||
252 | } | ||
253 | } | 255 | } |
254 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { | 256 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { |
255 | // As above | 257 | // As above |