|
1 | | -use itertools::Itertools; |
2 | | -use stdx::{format_to, to_lower_snake_case}; |
| 1 | +use stdx::format_to; |
3 | 2 | use syntax::{ |
4 | | - ast::{self, AstNode, NameOwner}, |
| 3 | + ast::{self, AstNode}, |
5 | 4 | SyntaxKind::{ |
6 | 5 | BLOCK_EXPR, BREAK_EXPR, CLOSURE_EXPR, COMMENT, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, |
7 | 6 | }, |
8 | 7 | SyntaxNode, |
9 | 8 | }; |
10 | 9 | use test_utils::mark; |
11 | 10 |
|
12 | | -use crate::{AssistContext, AssistId, AssistKind, Assists}; |
| 11 | +use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; |
13 | 12 |
|
14 | 13 | // Assist: extract_variable |
15 | 14 | // |
@@ -55,7 +54,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option |
55 | 54 |
|
56 | 55 | let var_name = match &field_shorthand { |
57 | 56 | Some(it) => it.to_string(), |
58 | | - None => suggest_variable_name(ctx, &to_extract), |
| 57 | + None => suggest_name::variable(&to_extract, &ctx.sema), |
59 | 58 | }; |
60 | 59 | let expr_range = match &field_shorthand { |
61 | 60 | Some(it) => it.syntax().text_range().cover(to_extract.syntax().text_range()), |
@@ -174,89 +173,6 @@ impl Anchor { |
174 | 173 | } |
175 | 174 | } |
176 | 175 |
|
177 | | -fn suggest_variable_name(ctx: &AssistContext, expr: &ast::Expr) -> String { |
178 | | - // FIXME: account for existing names in the scope |
179 | | - suggest_name_from_param(ctx, expr) |
180 | | - .or_else(|| suggest_name_from_func(expr)) |
181 | | - .or_else(|| suggest_name_from_method(expr)) |
182 | | - .or_else(|| suggest_name_by_type(ctx, expr)) |
183 | | - .unwrap_or_else(|| "var_name".to_string()) |
184 | | -} |
185 | | - |
186 | | -fn normalize_name(name: &str) -> Option<String> { |
187 | | - let name = to_lower_snake_case(name); |
188 | | - |
189 | | - let useless_names = ["new", "default", "some", "none", "ok", "err"]; |
190 | | - if useless_names.contains(&name.as_str()) { |
191 | | - return None; |
192 | | - } |
193 | | - |
194 | | - Some(name) |
195 | | -} |
196 | | - |
197 | | -fn suggest_name_from_func(expr: &ast::Expr) -> Option<String> { |
198 | | - let call = match expr { |
199 | | - ast::Expr::CallExpr(call) => call, |
200 | | - _ => return None, |
201 | | - }; |
202 | | - let func = match call.expr()? { |
203 | | - ast::Expr::PathExpr(path) => path, |
204 | | - _ => return None, |
205 | | - }; |
206 | | - let ident = func.path()?.segment()?.name_ref()?.ident_token()?; |
207 | | - normalize_name(ident.text()) |
208 | | -} |
209 | | - |
210 | | -fn suggest_name_from_method(expr: &ast::Expr) -> Option<String> { |
211 | | - let method = match expr { |
212 | | - ast::Expr::MethodCallExpr(call) => call, |
213 | | - _ => return None, |
214 | | - }; |
215 | | - let ident = method.name_ref()?.ident_token()?; |
216 | | - normalize_name(ident.text()) |
217 | | -} |
218 | | - |
219 | | -fn suggest_name_from_param(ctx: &AssistContext, expr: &ast::Expr) -> Option<String> { |
220 | | - let arg_list = expr.syntax().parent().and_then(ast::ArgList::cast)?; |
221 | | - let args_parent = arg_list.syntax().parent()?; |
222 | | - let func = if let Some(call) = ast::CallExpr::cast(args_parent.clone()) { |
223 | | - let func = call.expr()?; |
224 | | - let func_ty = ctx.sema.type_of_expr(&func)?; |
225 | | - func_ty.as_callable(ctx.db())? |
226 | | - } else if let Some(method) = ast::MethodCallExpr::cast(args_parent) { |
227 | | - ctx.sema.resolve_method_call_as_callable(&method)? |
228 | | - } else { |
229 | | - return None; |
230 | | - }; |
231 | | - |
232 | | - let (idx, _) = arg_list.args().find_position(|it| it == expr).unwrap(); |
233 | | - let (pat, _) = func.params(ctx.db()).into_iter().nth(idx)?; |
234 | | - let param = match pat? { |
235 | | - either::Either::Right(ast::Pat::IdentPat(param)) => param, |
236 | | - _ => return None, |
237 | | - }; |
238 | | - let name = param.name()?; |
239 | | - normalize_name(&name.to_string()) |
240 | | -} |
241 | | - |
242 | | -fn suggest_name_by_type(ctx: &AssistContext, expr: &ast::Expr) -> Option<String> { |
243 | | - let ty = ctx.sema.type_of_expr(expr)?; |
244 | | - let ty = ty.remove_ref().unwrap_or(ty); |
245 | | - |
246 | | - name_from_type(ty, ctx) |
247 | | -} |
248 | | - |
249 | | -fn name_from_type(ty: hir::Type, ctx: &AssistContext) -> Option<String> { |
250 | | - let name = if let Some(adt) = ty.as_adt() { |
251 | | - adt.name(ctx.db()).to_string() |
252 | | - } else if let Some(trait_) = ty.as_dyn_trait() { |
253 | | - trait_.name(ctx.db()).to_string() |
254 | | - } else { |
255 | | - return None; |
256 | | - }; |
257 | | - normalize_name(&name) |
258 | | -} |
259 | | - |
260 | 176 | #[cfg(test)] |
261 | 177 | mod tests { |
262 | 178 | use test_utils::mark; |
|
0 commit comments