aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion/completion_context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion/completion_context.rs')
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs31
1 files changed, 29 insertions, 2 deletions
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 8b3401595..37880448a 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{Semantics, SemanticsScope}; 3use hir::{Semantics, SemanticsScope, Type};
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::{ 6use ra_syntax::{
@@ -11,7 +11,7 @@ use ra_syntax::{
11}; 11};
12use ra_text_edit::AtomTextEdit; 12use ra_text_edit::AtomTextEdit;
13 13
14use crate::{completion::CompletionConfig, FilePosition}; 14use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition};
15 15
16/// `CompletionContext` is created early during completion to figure out, where 16/// `CompletionContext` is created early during completion to figure out, where
17/// exactly is the cursor, syntax-wise. 17/// exactly is the cursor, syntax-wise.
@@ -31,7 +31,10 @@ pub(crate) struct CompletionContext<'a> {
31 pub(super) use_item_syntax: Option<ast::UseItem>, 31 pub(super) use_item_syntax: Option<ast::UseItem>,
32 pub(super) record_lit_syntax: Option<ast::RecordLit>, 32 pub(super) record_lit_syntax: Option<ast::RecordLit>,
33 pub(super) record_pat_syntax: Option<ast::RecordPat>, 33 pub(super) record_pat_syntax: Option<ast::RecordPat>,
34 pub(super) record_field_syntax: Option<ast::RecordField>,
34 pub(super) impl_def: Option<ast::ImplDef>, 35 pub(super) impl_def: Option<ast::ImplDef>,
36 /// FIXME: `ActiveParameter` is string-based, which is very wrong
37 pub(super) active_parameter: Option<ActiveParameter>,
35 pub(super) is_param: bool, 38 pub(super) is_param: bool,
36 /// If a name-binding or reference to a const in a pattern. 39 /// If a name-binding or reference to a const in a pattern.
37 /// Irrefutable patterns (like let) are excluded. 40 /// Irrefutable patterns (like let) are excluded.
@@ -54,6 +57,7 @@ pub(crate) struct CompletionContext<'a> {
54 pub(super) is_macro_call: bool, 57 pub(super) is_macro_call: bool,
55 pub(super) is_path_type: bool, 58 pub(super) is_path_type: bool,
56 pub(super) has_type_args: bool, 59 pub(super) has_type_args: bool,
60 pub(super) is_attribute: bool,
57} 61}
58 62
59impl<'a> CompletionContext<'a> { 63impl<'a> CompletionContext<'a> {
@@ -94,7 +98,9 @@ impl<'a> CompletionContext<'a> {
94 use_item_syntax: None, 98 use_item_syntax: None,
95 record_lit_syntax: None, 99 record_lit_syntax: None,
96 record_pat_syntax: None, 100 record_pat_syntax: None,
101 record_field_syntax: None,
97 impl_def: None, 102 impl_def: None,
103 active_parameter: ActiveParameter::at(db, position),
98 is_param: false, 104 is_param: false,
99 is_pat_binding_or_const: false, 105 is_pat_binding_or_const: false,
100 is_trivial_path: false, 106 is_trivial_path: false,
@@ -108,6 +114,7 @@ impl<'a> CompletionContext<'a> {
108 is_path_type: false, 114 is_path_type: false,
109 has_type_args: false, 115 has_type_args: false,
110 dot_receiver_is_ambiguous_float_literal: false, 116 dot_receiver_is_ambiguous_float_literal: false,
117 is_attribute: false,
111 }; 118 };
112 119
113 let mut original_file = original_file.syntax().clone(); 120 let mut original_file = original_file.syntax().clone();
@@ -168,6 +175,17 @@ impl<'a> CompletionContext<'a> {
168 self.sema.scope_at_offset(&self.token.parent(), self.offset) 175 self.sema.scope_at_offset(&self.token.parent(), self.offset)
169 } 176 }
170 177
178 pub(crate) fn expected_type_of(&self, node: &SyntaxNode) -> Option<Type> {
179 for ancestor in node.ancestors() {
180 if let Some(pat) = ast::Pat::cast(ancestor.clone()) {
181 return self.sema.type_of_pat(&pat);
182 } else if let Some(expr) = ast::Expr::cast(ancestor) {
183 return self.sema.type_of_expr(&expr);
184 }
185 }
186 None
187 }
188
171 fn fill( 189 fn fill(
172 &mut self, 190 &mut self,
173 original_file: &SyntaxNode, 191 original_file: &SyntaxNode,
@@ -268,6 +286,14 @@ impl<'a> CompletionContext<'a> {
268 .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) 286 .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
269 .find_map(ast::FnDef::cast); 287 .find_map(ast::FnDef::cast);
270 288
289 self.record_field_syntax = self
290 .sema
291 .ancestors_with_macros(self.token.parent())
292 .take_while(|it| {
293 it.kind() != SOURCE_FILE && it.kind() != MODULE && it.kind() != CALL_EXPR
294 })
295 .find_map(ast::RecordField::cast);
296
271 let parent = match name_ref.syntax().parent() { 297 let parent = match name_ref.syntax().parent() {
272 Some(it) => it, 298 Some(it) => it,
273 None => return, 299 None => return,
@@ -282,6 +308,7 @@ impl<'a> CompletionContext<'a> {
282 .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) 308 .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast))
283 .is_some(); 309 .is_some();
284 self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some(); 310 self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some();
311 self.is_attribute = path.syntax().parent().and_then(ast::Attr::cast).is_some();
285 312
286 self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); 313 self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some();
287 self.has_type_args = segment.type_arg_list().is_some(); 314 self.has_type_args = segment.type_arg_list().is_some();