diff options
Diffstat (limited to 'crates')
4 files changed, 49 insertions, 44 deletions
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs index 4116985ae..494ef4621 100644 --- a/crates/ide_assists/src/handlers/extract_function.rs +++ b/crates/ide_assists/src/handlers/extract_function.rs | |||
@@ -1192,7 +1192,7 @@ fn make_ret_ty(ctx: &AssistContext, module: hir::Module, fun: &Function) -> Opti | |||
1192 | vec![fun_ty.make_ty(ctx, module), handler_ty], | 1192 | vec![fun_ty.make_ty(ctx, module), handler_ty], |
1193 | ) | 1193 | ) |
1194 | } | 1194 | } |
1195 | FlowHandler::If { .. } => make::ty("bool"), | 1195 | FlowHandler::If { .. } => make::ty_bool(), |
1196 | FlowHandler::IfOption { action } => { | 1196 | FlowHandler::IfOption { action } => { |
1197 | let handler_ty = action | 1197 | let handler_ty = action |
1198 | .expr_ty(ctx) | 1198 | .expr_ty(ctx) |
diff --git a/crates/ide_assists/src/handlers/introduce_named_lifetime.rs b/crates/ide_assists/src/handlers/introduce_named_lifetime.rs index cb71ca8bd..68bc15120 100644 --- a/crates/ide_assists/src/handlers/introduce_named_lifetime.rs +++ b/crates/ide_assists/src/handlers/introduce_named_lifetime.rs | |||
@@ -89,14 +89,12 @@ fn generate_fn_def_assist( | |||
89 | let loc_needing_lifetime = | 89 | let loc_needing_lifetime = |
90 | loc_needing_lifetime.and_then(|it| it.make_mut(builder).to_position()); | 90 | loc_needing_lifetime.and_then(|it| it.make_mut(builder).to_position()); |
91 | 91 | ||
92 | add_lifetime_param(fn_def.get_or_create_generic_param_list(), new_lifetime_param); | 92 | fn_def.get_or_create_generic_param_list().add_generic_param( |
93 | ted::replace( | 93 | make::lifetime_param(new_lifetime_param.clone()).clone_for_update().into(), |
94 | lifetime.syntax(), | ||
95 | make_ast_lifetime(new_lifetime_param).clone_for_update().syntax(), | ||
96 | ); | 94 | ); |
97 | loc_needing_lifetime.map(|position| { | 95 | ted::replace(lifetime.syntax(), new_lifetime_param.clone_for_update().syntax()); |
98 | ted::insert(position, make_ast_lifetime(new_lifetime_param).clone_for_update().syntax()) | 96 | loc_needing_lifetime |
99 | }); | 97 | .map(|position| ted::insert(position, new_lifetime_param.clone_for_update().syntax())); |
100 | }) | 98 | }) |
101 | } | 99 | } |
102 | 100 | ||
@@ -112,11 +110,10 @@ fn generate_impl_def_assist( | |||
112 | let impl_def = builder.make_ast_mut(impl_def); | 110 | let impl_def = builder.make_ast_mut(impl_def); |
113 | let lifetime = builder.make_ast_mut(lifetime); | 111 | let lifetime = builder.make_ast_mut(lifetime); |
114 | 112 | ||
115 | add_lifetime_param(impl_def.get_or_create_generic_param_list(), new_lifetime_param); | 113 | impl_def.get_or_create_generic_param_list().add_generic_param( |
116 | ted::replace( | 114 | make::lifetime_param(new_lifetime_param.clone()).clone_for_update().into(), |
117 | lifetime.syntax(), | ||
118 | make_ast_lifetime(new_lifetime_param).clone_for_update().syntax(), | ||
119 | ); | 115 | ); |
116 | ted::replace(lifetime.syntax(), new_lifetime_param.clone_for_update().syntax()); | ||
120 | }) | 117 | }) |
121 | } | 118 | } |
122 | 119 | ||
@@ -124,31 +121,16 @@ fn generate_impl_def_assist( | |||
124 | /// which is not in the list | 121 | /// which is not in the list |
125 | fn generate_unique_lifetime_param_name( | 122 | fn generate_unique_lifetime_param_name( |
126 | existing_type_param_list: Option<ast::GenericParamList>, | 123 | existing_type_param_list: Option<ast::GenericParamList>, |
127 | ) -> Option<char> { | 124 | ) -> Option<ast::Lifetime> { |
128 | match existing_type_param_list { | 125 | match existing_type_param_list { |
129 | Some(type_params) => { | 126 | Some(type_params) => { |
130 | let used_lifetime_params: FxHashSet<_> = type_params | 127 | let used_lifetime_params: FxHashSet<_> = |
131 | .lifetime_params() | 128 | type_params.lifetime_params().map(|p| p.syntax().text().to_string()).collect(); |
132 | .map(|p| p.syntax().text().to_string()[1..].to_owned()) | 129 | ('a'..='z').map(|it| format!("'{}", it)).find(|it| !used_lifetime_params.contains(it)) |
133 | .collect(); | ||
134 | (b'a'..=b'z').map(char::from).find(|c| !used_lifetime_params.contains(&c.to_string())) | ||
135 | } | 130 | } |
136 | None => Some('a'), | 131 | None => Some("'a".to_string()), |
137 | } | 132 | } |
138 | } | 133 | .map(|it| make::lifetime(&it)) |
139 | |||
140 | fn add_lifetime_param(type_params: ast::GenericParamList, new_lifetime_param: char) { | ||
141 | let generic_param = | ||
142 | make::generic_param(&format!("'{}", new_lifetime_param), None).clone_for_update(); | ||
143 | type_params.add_generic_param(generic_param); | ||
144 | } | ||
145 | |||
146 | fn make_ast_lifetime(new_lifetime_param: char) -> ast::Lifetime { | ||
147 | make::generic_param(&format!("'{}", new_lifetime_param), None) | ||
148 | .syntax() | ||
149 | .descendants() | ||
150 | .find_map(ast::Lifetime::cast) | ||
151 | .unwrap() | ||
152 | } | 134 | } |
153 | 135 | ||
154 | enum NeedsLifetime { | 136 | enum NeedsLifetime { |
diff --git a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs index 16cae0281..15420aedf 100644 --- a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs +++ b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs | |||
@@ -37,12 +37,12 @@ pub(crate) fn replace_impl_trait_with_generic( | |||
37 | 37 | ||
38 | let type_param_name = suggest_name::for_generic_parameter(&impl_trait_type); | 38 | let type_param_name = suggest_name::for_generic_parameter(&impl_trait_type); |
39 | 39 | ||
40 | let type_param = | 40 | let type_param = make::type_param(make::name(&type_param_name), Some(type_bound_list)) |
41 | make::generic_param(&type_param_name, Some(type_bound_list)).clone_for_update(); | 41 | .clone_for_update(); |
42 | let new_ty = make::ty(&type_param_name).clone_for_update(); | 42 | let new_ty = make::ty(&type_param_name).clone_for_update(); |
43 | 43 | ||
44 | ted::replace(impl_trait_type.syntax(), new_ty.syntax()); | 44 | ted::replace(impl_trait_type.syntax(), new_ty.syntax()); |
45 | fn_.get_or_create_generic_param_list().add_generic_param(type_param) | 45 | fn_.get_or_create_generic_param_list().add_generic_param(type_param.into()) |
46 | }, | 46 | }, |
47 | ) | 47 | ) |
48 | } | 48 | } |
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 2289d8f3e..c39e248ce 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs | |||
@@ -10,7 +10,7 @@ | |||
10 | //! `parse(format!())` we use internally is an implementation detail -- long | 10 | //! `parse(format!())` we use internally is an implementation detail -- long |
11 | //! term, it will be replaced with direct tree manipulation. | 11 | //! term, it will be replaced with direct tree manipulation. |
12 | use itertools::Itertools; | 12 | use itertools::Itertools; |
13 | use stdx::format_to; | 13 | use stdx::{format_to, never}; |
14 | 14 | ||
15 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; | 15 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; |
16 | 16 | ||
@@ -22,6 +22,16 @@ pub fn name_ref(text: &str) -> ast::NameRef { | |||
22 | ast_from_text(&format!("fn f() {{ {}{}; }}", raw_ident_esc(text), text)) | 22 | ast_from_text(&format!("fn f() {{ {}{}; }}", raw_ident_esc(text), text)) |
23 | } | 23 | } |
24 | 24 | ||
25 | pub fn lifetime(text: &str) -> ast::Lifetime { | ||
26 | let mut text = text; | ||
27 | let tmp; | ||
28 | if never!(!text.starts_with('\'')) { | ||
29 | tmp = format!("'{}", text); | ||
30 | text = &tmp; | ||
31 | } | ||
32 | ast_from_text(&format!("fn f<{}>() {{ }}", text)) | ||
33 | } | ||
34 | |||
25 | fn raw_ident_esc(ident: &str) -> &'static str { | 35 | fn raw_ident_esc(ident: &str) -> &'static str { |
26 | let is_keyword = parser::SyntaxKind::from_keyword(ident).is_some(); | 36 | let is_keyword = parser::SyntaxKind::from_keyword(ident).is_some(); |
27 | if is_keyword && !matches!(ident, "self" | "crate" | "super" | "Self") { | 37 | if is_keyword && !matches!(ident, "self" | "crate" | "super" | "Self") { |
@@ -34,10 +44,13 @@ fn raw_ident_esc(ident: &str) -> &'static str { | |||
34 | // FIXME: replace stringly-typed constructor with a family of typed ctors, a-la | 44 | // FIXME: replace stringly-typed constructor with a family of typed ctors, a-la |
35 | // `expr_xxx`. | 45 | // `expr_xxx`. |
36 | pub fn ty(text: &str) -> ast::Type { | 46 | pub fn ty(text: &str) -> ast::Type { |
37 | ast_from_text(&format!("fn f() -> {} {{}}", text)) | 47 | ty_from_text(text) |
38 | } | 48 | } |
39 | pub fn ty_unit() -> ast::Type { | 49 | pub fn ty_unit() -> ast::Type { |
40 | ty("()") | 50 | ty_from_text("()") |
51 | } | ||
52 | pub fn ty_bool() -> ast::Type { | ||
53 | ty_path(path_unqualified(path_segment(name_ref("bool")))) | ||
41 | } | 54 | } |
42 | pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type { | 55 | pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type { |
43 | let mut count: usize = 0; | 56 | let mut count: usize = 0; |
@@ -46,15 +59,21 @@ pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type { | |||
46 | contents.push(','); | 59 | contents.push(','); |
47 | } | 60 | } |
48 | 61 | ||
49 | ty(&format!("({})", contents)) | 62 | ty_from_text(&format!("({})", contents)) |
50 | } | 63 | } |
51 | // FIXME: handle path to type | 64 | // FIXME: handle path to type |
52 | pub fn ty_generic(name: ast::NameRef, types: impl IntoIterator<Item = ast::Type>) -> ast::Type { | 65 | pub fn ty_generic(name: ast::NameRef, types: impl IntoIterator<Item = ast::Type>) -> ast::Type { |
53 | let contents = types.into_iter().join(", "); | 66 | let contents = types.into_iter().join(", "); |
54 | ty(&format!("{}<{}>", name, contents)) | 67 | ty_from_text(&format!("{}<{}>", name, contents)) |
55 | } | 68 | } |
56 | pub fn ty_ref(target: ast::Type, exclusive: bool) -> ast::Type { | 69 | pub fn ty_ref(target: ast::Type, exclusive: bool) -> ast::Type { |
57 | ty(&if exclusive { format!("&mut {}", target) } else { format!("&{}", target) }) | 70 | ty_from_text(&if exclusive { format!("&mut {}", target) } else { format!("&{}", target) }) |
71 | } | ||
72 | pub fn ty_path(path: ast::Path) -> ast::Type { | ||
73 | ty_from_text(&path.to_string()) | ||
74 | } | ||
75 | fn ty_from_text(text: &str) -> ast::Type { | ||
76 | ast_from_text(&format!("type _T = {};", text)) | ||
58 | } | 77 | } |
59 | 78 | ||
60 | pub fn assoc_item_list() -> ast::AssocItemList { | 79 | pub fn assoc_item_list() -> ast::AssocItemList { |
@@ -475,8 +494,8 @@ pub fn param_list( | |||
475 | }; | 494 | }; |
476 | ast_from_text(&list) | 495 | ast_from_text(&list) |
477 | } | 496 | } |
478 | // FIXME: s/&str/ast:Name | 497 | |
479 | pub fn generic_param(name: &str, ty: Option<ast::TypeBoundList>) -> ast::GenericParam { | 498 | pub fn type_param(name: ast::Name, ty: Option<ast::TypeBoundList>) -> ast::TypeParam { |
480 | let bound = match ty { | 499 | let bound = match ty { |
481 | Some(it) => format!(": {}", it), | 500 | Some(it) => format!(": {}", it), |
482 | None => String::new(), | 501 | None => String::new(), |
@@ -484,6 +503,10 @@ pub fn generic_param(name: &str, ty: Option<ast::TypeBoundList>) -> ast::Generic | |||
484 | ast_from_text(&format!("fn f<{}{}>() {{ }}", name, bound)) | 503 | ast_from_text(&format!("fn f<{}{}>() {{ }}", name, bound)) |
485 | } | 504 | } |
486 | 505 | ||
506 | pub fn lifetime_param(lifetime: ast::Lifetime) -> ast::LifetimeParam { | ||
507 | ast_from_text(&format!("fn f<{}>() {{ }}", lifetime)) | ||
508 | } | ||
509 | |||
487 | pub fn generic_param_list( | 510 | pub fn generic_param_list( |
488 | pats: impl IntoIterator<Item = ast::GenericParam>, | 511 | pats: impl IntoIterator<Item = ast::GenericParam>, |
489 | ) -> ast::GenericParamList { | 512 | ) -> ast::GenericParamList { |