aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs2
-rw-r--r--crates/ide_assists/src/handlers/introduce_named_lifetime.rs46
-rw-r--r--crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs6
-rw-r--r--crates/syntax/src/ast/make.rs39
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
125fn generate_unique_lifetime_param_name( 122fn 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
140fn 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
146fn 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
154enum NeedsLifetime { 136enum 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.
12use itertools::Itertools; 12use itertools::Itertools;
13use stdx::format_to; 13use stdx::{format_to, never};
14 14
15use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; 15use 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
25pub 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
25fn raw_ident_esc(ident: &str) -> &'static str { 35fn 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`.
36pub fn ty(text: &str) -> ast::Type { 46pub fn ty(text: &str) -> ast::Type {
37 ast_from_text(&format!("fn f() -> {} {{}}", text)) 47 ty_from_text(text)
38} 48}
39pub fn ty_unit() -> ast::Type { 49pub fn ty_unit() -> ast::Type {
40 ty("()") 50 ty_from_text("()")
51}
52pub fn ty_bool() -> ast::Type {
53 ty_path(path_unqualified(path_segment(name_ref("bool"))))
41} 54}
42pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type { 55pub 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
52pub fn ty_generic(name: ast::NameRef, types: impl IntoIterator<Item = ast::Type>) -> ast::Type { 65pub 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}
56pub fn ty_ref(target: ast::Type, exclusive: bool) -> ast::Type { 69pub 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}
72pub fn ty_path(path: ast::Path) -> ast::Type {
73 ty_from_text(&path.to_string())
74}
75fn ty_from_text(text: &str) -> ast::Type {
76 ast_from_text(&format!("type _T = {};", text))
58} 77}
59 78
60pub fn assoc_item_list() -> ast::AssocItemList { 79pub 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
479pub fn generic_param(name: &str, ty: Option<ast::TypeBoundList>) -> ast::GenericParam { 498pub 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
506pub fn lifetime_param(lifetime: ast::Lifetime) -> ast::LifetimeParam {
507 ast_from_text(&format!("fn f<{}>() {{ }}", lifetime))
508}
509
487pub fn generic_param_list( 510pub fn generic_param_list(
488 pats: impl IntoIterator<Item = ast::GenericParam>, 511 pats: impl IntoIterator<Item = ast::GenericParam>,
489) -> ast::GenericParamList { 512) -> ast::GenericParamList {