|
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