diff options
author | Benjamin Coenen <[email protected]> | 2020-04-11 21:54:22 +0100 |
---|---|---|
committer | Benjamin Coenen <[email protected]> | 2020-04-11 22:45:09 +0100 |
commit | 93bfc2d05d36a47dc05a1799210327473d702dbc (patch) | |
tree | dee25e78b24b5d1b23d73ae1009bddbd060927cf /crates/ra_ide/src | |
parent | d42346fed61f706d68fe888631a41ea5f2752d7f (diff) | |
parent | fd06fe7b13045185ab4e630b0044aa9d8bbcdf8a (diff) |
Improve autocompletion by looking on the type and name
Signed-off-by: Benjamin Coenen <[email protected]>
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_fn_param.rs | 30 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_trait_impl.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_unqualified_path.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 13 | ||||
-rw-r--r-- | crates/ra_ide/src/display/function_signature.rs | 21 | ||||
-rw-r--r-- | crates/ra_ide/src/inlay_hints.rs | 61 | ||||
-rw-r--r-- | crates/ra_ide/src/references.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_tree.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide/src/typing.rs | 2 |
10 files changed, 103 insertions, 41 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index 358b041aa..b5448af5c 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -72,7 +72,6 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Ty | |||
72 | } | 72 | } |
73 | for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() { | 73 | for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() { |
74 | // FIXME: Handle visibility | 74 | // FIXME: Handle visibility |
75 | // TODO: add the same behavior with type ? | ||
76 | acc.add_tuple_field(ctx, i, &ty); | 75 | acc.add_tuple_field(ctx, i, &ty); |
77 | } | 76 | } |
78 | } | 77 | } |
diff --git a/crates/ra_ide/src/completion/complete_fn_param.rs b/crates/ra_ide/src/completion/complete_fn_param.rs index 62ae5ccb4..f84b559fc 100644 --- a/crates/ra_ide/src/completion/complete_fn_param.rs +++ b/crates/ra_ide/src/completion/complete_fn_param.rs | |||
@@ -1,6 +1,9 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use ra_syntax::{ast, match_ast, AstNode}; | 3 | use ra_syntax::{ |
4 | ast::{self, ModuleItemOwner}, | ||
5 | match_ast, AstNode, | ||
6 | }; | ||
4 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
5 | 8 | ||
6 | use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions}; | 9 | use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions}; |
@@ -16,11 +19,19 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) | |||
16 | 19 | ||
17 | let mut params = FxHashMap::default(); | 20 | let mut params = FxHashMap::default(); |
18 | for node in ctx.token.parent().ancestors() { | 21 | for node in ctx.token.parent().ancestors() { |
19 | match_ast! { | 22 | let items = match_ast! { |
20 | match node { | 23 | match node { |
21 | ast::SourceFile(it) => process(it, &mut params), | 24 | ast::SourceFile(it) => it.items(), |
22 | ast::ItemList(it) => process(it, &mut params), | 25 | ast::ItemList(it) => it.items(), |
23 | _ => (), | 26 | _ => continue, |
27 | } | ||
28 | }; | ||
29 | for item in items { | ||
30 | if let ast::ModuleItem::FnDef(func) = item { | ||
31 | func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| { | ||
32 | let text = param.syntax().text().to_string(); | ||
33 | params.entry(text).or_insert((0, param)).0 += 1; | ||
34 | }) | ||
24 | } | 35 | } |
25 | } | 36 | } |
26 | } | 37 | } |
@@ -39,15 +50,6 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) | |||
39 | .lookup_by(lookup) | 50 | .lookup_by(lookup) |
40 | .add_to(acc) | 51 | .add_to(acc) |
41 | }); | 52 | }); |
42 | |||
43 | fn process<N: ast::FnDefOwner>(node: N, params: &mut FxHashMap<String, (u32, ast::Param)>) { | ||
44 | node.functions().filter_map(|it| it.param_list()).flat_map(|it| it.params()).for_each( | ||
45 | |param| { | ||
46 | let text = param.syntax().text().to_string(); | ||
47 | params.entry(text).or_insert((0, param)).0 += 1; | ||
48 | }, | ||
49 | ) | ||
50 | } | ||
51 | } | 53 | } |
52 | 54 | ||
53 | #[cfg(test)] | 55 | #[cfg(test)] |
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index ded1ff3bc..fab02945c 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs | |||
@@ -35,7 +35,7 @@ use hir::{self, Docs, HasSource}; | |||
35 | use ra_assists::utils::get_missing_impl_items; | 35 | use ra_assists::utils::get_missing_impl_items; |
36 | use ra_syntax::{ | 36 | use ra_syntax::{ |
37 | ast::{self, edit, ImplDef}, | 37 | ast::{self, edit, ImplDef}, |
38 | AstNode, SyntaxKind, SyntaxNode, TextRange, | 38 | AstNode, SyntaxKind, SyntaxNode, TextRange, T, |
39 | }; | 39 | }; |
40 | use ra_text_edit::TextEdit; | 40 | use ra_text_edit::TextEdit; |
41 | 41 | ||
@@ -204,7 +204,7 @@ fn make_const_compl_syntax(const_: &ast::ConstDef) -> String { | |||
204 | let end = const_ | 204 | let end = const_ |
205 | .syntax() | 205 | .syntax() |
206 | .children_with_tokens() | 206 | .children_with_tokens() |
207 | .find(|s| s.kind() == SyntaxKind::SEMI || s.kind() == SyntaxKind::EQ) | 207 | .find(|s| s.kind() == T![;] || s.kind() == T![=]) |
208 | .map_or(const_end, |f| f.text_range().start()); | 208 | .map_or(const_end, |f| f.text_range().start()); |
209 | 209 | ||
210 | let len = end - start; | 210 | let len = end - start; |
diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs index efde9bf73..0b0da6ee4 100644 --- a/crates/ra_ide/src/completion/complete_unqualified_path.rs +++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use crate::completion::{CompletionContext, Completions}; | 3 | use crate::completion::{CompletionContext, Completions}; |
4 | 4 | ||
5 | pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { | 5 | pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { |
6 | if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const) { | 6 | if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const && !ctx.record_lit_syntax.is_some()) { |
7 | return; | 7 | return; |
8 | } | 8 | } |
9 | 9 | ||
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index fddaf21e4..eb8016dd1 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -1,13 +1,11 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{db::HirDatabase, Semantics, SemanticsScope}; | 3 | use hir::{Semantics, SemanticsScope}; |
4 | use ra_db::SourceDatabase; | 4 | use ra_db::SourceDatabase; |
5 | use ra_ide_db::RootDatabase; | 5 | use ra_ide_db::RootDatabase; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
7 | algo::{find_covering_element, find_node_at_offset}, | 7 | algo::{find_covering_element, find_node_at_offset}, |
8 | ast, | 8 | ast, AstNode, |
9 | ast::ArgListOwner, | ||
10 | AstNode, | ||
11 | SyntaxKind::*, | 9 | SyntaxKind::*, |
12 | SyntaxNode, SyntaxToken, TextRange, TextUnit, | 10 | SyntaxNode, SyntaxToken, TextRange, TextUnit, |
13 | }; | 11 | }; |
@@ -196,7 +194,10 @@ impl<'a> CompletionContext<'a> { | |||
196 | if let Some(name) = find_node_at_offset::<ast::Name>(&file_with_fake_ident, offset) { | 194 | if let Some(name) = find_node_at_offset::<ast::Name>(&file_with_fake_ident, offset) { |
197 | if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { | 195 | if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { |
198 | self.is_pat_binding_or_const = true; | 196 | self.is_pat_binding_or_const = true; |
199 | if bind_pat.has_at() || bind_pat.is_ref() || bind_pat.is_mutable() { | 197 | if bind_pat.at_token().is_some() |
198 | || bind_pat.ref_token().is_some() | ||
199 | || bind_pat.mut_token().is_some() | ||
200 | { | ||
200 | self.is_pat_binding_or_const = false; | 201 | self.is_pat_binding_or_const = false; |
201 | } | 202 | } |
202 | if bind_pat.syntax().parent().and_then(ast::RecordFieldPatList::cast).is_some() { | 203 | if bind_pat.syntax().parent().and_then(ast::RecordFieldPatList::cast).is_some() { |
@@ -230,7 +231,7 @@ impl<'a> CompletionContext<'a> { | |||
230 | self.name_ref_syntax = | 231 | self.name_ref_syntax = |
231 | find_node_at_offset(&original_file, name_ref.syntax().text_range().start()); | 232 | find_node_at_offset(&original_file, name_ref.syntax().text_range().start()); |
232 | let name_range = name_ref.syntax().text_range(); | 233 | let name_range = name_ref.syntax().text_range(); |
233 | if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() { | 234 | if ast::RecordField::for_field_name(&name_ref).is_some() { |
234 | self.record_lit_syntax = | 235 | self.record_lit_syntax = |
235 | self.sema.find_node_at_offset_with_macros(&original_file, offset); | 236 | self.sema.find_node_at_offset_with_macros(&original_file, offset); |
236 | } | 237 | } |
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index e58a78271..2d175882b 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs | |||
@@ -69,7 +69,13 @@ impl FunctionSignature { | |||
69 | for field in st.fields(db).into_iter() { | 69 | for field in st.fields(db).into_iter() { |
70 | let ty = field.signature_ty(db); | 70 | let ty = field.signature_ty(db); |
71 | let raw_param = format!("{}", ty.display(db)); | 71 | let raw_param = format!("{}", ty.display(db)); |
72 | parameter_types.push(raw_param.split(':').nth(1).unwrap()[1..].to_string()); | 72 | |
73 | if let Some(param_type) = raw_param.split(':').nth(1) { | ||
74 | parameter_types.push(param_type[1..].to_string()); | ||
75 | } else { | ||
76 | // The unwrap_or_else is useful when you have tuple struct | ||
77 | parameter_types.push(raw_param.clone()); | ||
78 | } | ||
73 | params.push(raw_param); | 79 | params.push(raw_param); |
74 | } | 80 | } |
75 | 81 | ||
@@ -107,8 +113,15 @@ impl FunctionSignature { | |||
107 | for field in variant.fields(db).into_iter() { | 113 | for field in variant.fields(db).into_iter() { |
108 | let ty = field.signature_ty(db); | 114 | let ty = field.signature_ty(db); |
109 | let raw_param = format!("{}", ty.display(db)); | 115 | let raw_param = format!("{}", ty.display(db)); |
110 | parameter_types.push(raw_param.split(':').nth(1).unwrap()[1..].to_string()); | 116 | if let Some(param_type) = raw_param.split(':').nth(1) { |
111 | params.push(raw_param); | 117 | parameter_types.push(param_type[1..].to_string()); |
118 | } else { | ||
119 | // The unwrap_or_else is useful when you have tuple | ||
120 | parameter_types.push(raw_param); | ||
121 | } | ||
122 | let name = field.name(db); | ||
123 | |||
124 | params.push(format!("{}: {}", name, ty.display(db))); | ||
112 | } | 125 | } |
113 | 126 | ||
114 | Some( | 127 | Some( |
@@ -164,7 +177,7 @@ impl From<&'_ ast::FnDef> for FunctionSignature { | |||
164 | has_self_param = true; | 177 | has_self_param = true; |
165 | let raw_param = self_param.syntax().text().to_string(); | 178 | let raw_param = self_param.syntax().text().to_string(); |
166 | 179 | ||
167 | // TODO: better solution ? | 180 | // FIXME: better solution ? |
168 | res_types.push( | 181 | res_types.push( |
169 | raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(), | 182 | raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(), |
170 | ); | 183 | ); |
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 4b133b19b..45b9f7802 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! This module defines multiple types of inlay hints and their visibility |
2 | 2 | ||
3 | use hir::{Adt, HirDisplay, Semantics, Type}; | 3 | use hir::{Adt, HirDisplay, Semantics, Type}; |
4 | use ra_ide_db::RootDatabase; | 4 | use ra_ide_db::RootDatabase; |
@@ -235,8 +235,10 @@ fn should_show_param_hint( | |||
235 | param_name: &str, | 235 | param_name: &str, |
236 | argument: &ast::Expr, | 236 | argument: &ast::Expr, |
237 | ) -> bool { | 237 | ) -> bool { |
238 | let argument_string = argument.syntax().to_string(); | 238 | if param_name.is_empty() |
239 | if param_name.is_empty() || argument_string.ends_with(param_name) { | 239 | || is_argument_similar_to_param(argument, param_name) |
240 | || Some(param_name) == fn_signature.name.as_ref().map(String::as_str) | ||
241 | { | ||
240 | return false; | 242 | return false; |
241 | } | 243 | } |
242 | 244 | ||
@@ -245,12 +247,32 @@ fn should_show_param_hint( | |||
245 | } else { | 247 | } else { |
246 | fn_signature.parameters.len() | 248 | fn_signature.parameters.len() |
247 | }; | 249 | }; |
250 | |||
248 | // avoid displaying hints for common functions like map, filter, etc. | 251 | // avoid displaying hints for common functions like map, filter, etc. |
249 | if parameters_len == 1 && (param_name.len() == 1 || param_name == "predicate") { | 252 | // or other obvious words used in std |
250 | return false; | 253 | parameters_len != 1 || !is_obvious_param(param_name) |
254 | } | ||
255 | |||
256 | fn is_argument_similar_to_param(argument: &ast::Expr, param_name: &str) -> bool { | ||
257 | let argument_string = remove_ref(argument.clone()).syntax().to_string(); | ||
258 | argument_string.starts_with(¶m_name) || argument_string.ends_with(¶m_name) | ||
259 | } | ||
260 | |||
261 | fn remove_ref(expr: ast::Expr) -> ast::Expr { | ||
262 | if let ast::Expr::RefExpr(ref_expr) = &expr { | ||
263 | if let Some(inner) = ref_expr.expr() { | ||
264 | return inner; | ||
265 | } | ||
251 | } | 266 | } |
267 | expr | ||
268 | } | ||
252 | 269 | ||
253 | true | 270 | fn is_obvious_param(param_name: &str) -> bool { |
271 | let is_obvious_param_name = match param_name { | ||
272 | "predicate" | "value" | "pat" | "rhs" | "other" => true, | ||
273 | _ => false, | ||
274 | }; | ||
275 | param_name.len() == 1 || is_obvious_param_name | ||
254 | } | 276 | } |
255 | 277 | ||
256 | fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<FunctionSignature> { | 278 | fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<FunctionSignature> { |
@@ -1059,9 +1081,22 @@ impl Test { | |||
1059 | self | 1081 | self |
1060 | } | 1082 | } |
1061 | 1083 | ||
1084 | fn field(self, value: i32) -> Self { | ||
1085 | self | ||
1086 | } | ||
1087 | |||
1062 | fn no_hints_expected(&self, _: i32, test_var: i32) {} | 1088 | fn no_hints_expected(&self, _: i32, test_var: i32) {} |
1089 | |||
1090 | fn frob(&self, frob: bool) {} | ||
1063 | } | 1091 | } |
1064 | 1092 | ||
1093 | struct Param {} | ||
1094 | |||
1095 | fn different_order(param: &Param) {} | ||
1096 | fn different_order_mut(param: &mut Param) {} | ||
1097 | |||
1098 | fn twiddle(twiddle: bool) {} | ||
1099 | |||
1065 | fn main() { | 1100 | fn main() { |
1066 | let container: TestVarContainer = TestVarContainer { test_var: 42 }; | 1101 | let container: TestVarContainer = TestVarContainer { test_var: 42 }; |
1067 | let test: Test = Test {}; | 1102 | let test: Test = Test {}; |
@@ -1069,11 +1104,23 @@ fn main() { | |||
1069 | map(22); | 1104 | map(22); |
1070 | filter(33); | 1105 | filter(33); |
1071 | 1106 | ||
1072 | let test_processed: Test = test.map(1).filter(2); | 1107 | let test_processed: Test = test.map(1).filter(2).field(3); |
1073 | 1108 | ||
1074 | let test_var: i32 = 55; | 1109 | let test_var: i32 = 55; |
1075 | test_processed.no_hints_expected(22, test_var); | 1110 | test_processed.no_hints_expected(22, test_var); |
1076 | test_processed.no_hints_expected(33, container.test_var); | 1111 | test_processed.no_hints_expected(33, container.test_var); |
1112 | test_processed.frob(false); | ||
1113 | |||
1114 | twiddle(true); | ||
1115 | |||
1116 | let param_begin: Param = Param {}; | ||
1117 | different_order(¶m_begin); | ||
1118 | different_order(&mut param_begin); | ||
1119 | |||
1120 | let a: f64 = 7.0; | ||
1121 | let b: f64 = 4.0; | ||
1122 | let _: f64 = a.div_euclid(b); | ||
1123 | let _: f64 = a.abs_sub(b); | ||
1077 | }"#, | 1124 | }"#, |
1078 | ); | 1125 | ); |
1079 | 1126 | ||
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index 746cc86ba..7d0544ff4 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -152,7 +152,7 @@ fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Optio | |||
152 | if stmt.initializer().is_some() { | 152 | if stmt.initializer().is_some() { |
153 | let pat = stmt.pat()?; | 153 | let pat = stmt.pat()?; |
154 | if let ast::Pat::BindPat(it) = pat { | 154 | if let ast::Pat::BindPat(it) = pat { |
155 | if it.is_mutable() { | 155 | if it.mut_token().is_some() { |
156 | return Some(ReferenceAccess::Write); | 156 | return Some(ReferenceAccess::Write); |
157 | } | 157 | } |
158 | } | 158 | } |
diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs index f58e436d1..5842ae2e8 100644 --- a/crates/ra_ide/src/syntax_tree.rs +++ b/crates/ra_ide/src/syntax_tree.rs | |||
@@ -165,7 +165,7 @@ SOURCE_FILE@[0; 60) | |||
165 | PATH_SEGMENT@[16; 22) | 165 | PATH_SEGMENT@[16; 22) |
166 | NAME_REF@[16; 22) | 166 | NAME_REF@[16; 22) |
167 | IDENT@[16; 22) "assert" | 167 | IDENT@[16; 22) "assert" |
168 | EXCL@[22; 23) "!" | 168 | BANG@[22; 23) "!" |
169 | TOKEN_TREE@[23; 57) | 169 | TOKEN_TREE@[23; 57) |
170 | L_PAREN@[23; 24) "(" | 170 | L_PAREN@[23; 24) "(" |
171 | STRING@[24; 52) "\"\n fn foo() {\n ..." | 171 | STRING@[24; 52) "\"\n fn foo() {\n ..." |
@@ -173,7 +173,7 @@ SOURCE_FILE@[0; 60) | |||
173 | WHITESPACE@[53; 54) " " | 173 | WHITESPACE@[53; 54) " " |
174 | STRING@[54; 56) "\"\"" | 174 | STRING@[54; 56) "\"\"" |
175 | R_PAREN@[56; 57) ")" | 175 | R_PAREN@[56; 57) ")" |
176 | SEMI@[57; 58) ";" | 176 | SEMICOLON@[57; 58) ";" |
177 | WHITESPACE@[58; 59) "\n" | 177 | WHITESPACE@[58; 59) "\n" |
178 | R_CURLY@[59; 60) "}" | 178 | R_CURLY@[59; 60) "}" |
179 | "# | 179 | "# |
@@ -226,7 +226,7 @@ EXPR_STMT@[16; 58) | |||
226 | PATH_SEGMENT@[16; 22) | 226 | PATH_SEGMENT@[16; 22) |
227 | NAME_REF@[16; 22) | 227 | NAME_REF@[16; 22) |
228 | IDENT@[16; 22) "assert" | 228 | IDENT@[16; 22) "assert" |
229 | EXCL@[22; 23) "!" | 229 | BANG@[22; 23) "!" |
230 | TOKEN_TREE@[23; 57) | 230 | TOKEN_TREE@[23; 57) |
231 | L_PAREN@[23; 24) "(" | 231 | L_PAREN@[23; 24) "(" |
232 | STRING@[24; 52) "\"\n fn foo() {\n ..." | 232 | STRING@[24; 52) "\"\n fn foo() {\n ..." |
@@ -234,7 +234,7 @@ EXPR_STMT@[16; 58) | |||
234 | WHITESPACE@[53; 54) " " | 234 | WHITESPACE@[53; 54) " " |
235 | STRING@[54; 56) "\"\"" | 235 | STRING@[54; 56) "\"\"" |
236 | R_PAREN@[56; 57) ")" | 236 | R_PAREN@[56; 57) ")" |
237 | SEMI@[57; 58) ";" | 237 | SEMICOLON@[57; 58) ";" |
238 | "# | 238 | "# |
239 | .trim() | 239 | .trim() |
240 | ); | 240 | ); |
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs index cb2cd2479..f55cd3bf5 100644 --- a/crates/ra_ide/src/typing.rs +++ b/crates/ra_ide/src/typing.rs | |||
@@ -63,7 +63,7 @@ fn on_char_typed_inner( | |||
63 | fn on_eq_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChange> { | 63 | fn on_eq_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChange> { |
64 | assert_eq!(file.syntax().text().char_at(offset), Some('=')); | 64 | assert_eq!(file.syntax().text().char_at(offset), Some('=')); |
65 | let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?; | 65 | let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?; |
66 | if let_stmt.has_semi() { | 66 | if let_stmt.semicolon_token().is_some() { |
67 | return None; | 67 | return None; |
68 | } | 68 | } |
69 | if let Some(expr) = let_stmt.initializer() { | 69 | if let Some(expr) = let_stmt.initializer() { |