let loc_needing_lifetime =
loc_needing_lifetime.and_then(|it| it.make_mut(builder).to_position());
- add_lifetime_param(fn_def.get_or_create_generic_param_list(), new_lifetime_param);
- ted::replace(
- lifetime.syntax(),
- make_ast_lifetime(new_lifetime_param).clone_for_update().syntax(),
+ fn_def.get_or_create_generic_param_list().add_generic_param(
+ make::lifetime_param(new_lifetime_param.clone()).clone_for_update().into(),
);
- loc_needing_lifetime.map(|position| {
- ted::insert(position, make_ast_lifetime(new_lifetime_param).clone_for_update().syntax())
- });
+ ted::replace(lifetime.syntax(), new_lifetime_param.clone_for_update().syntax());
+ loc_needing_lifetime
+ .map(|position| ted::insert(position, new_lifetime_param.clone_for_update().syntax()));
})
}
let impl_def = builder.make_ast_mut(impl_def);
let lifetime = builder.make_ast_mut(lifetime);
- add_lifetime_param(impl_def.get_or_create_generic_param_list(), new_lifetime_param);
- ted::replace(
- lifetime.syntax(),
- make_ast_lifetime(new_lifetime_param).clone_for_update().syntax(),
+ impl_def.get_or_create_generic_param_list().add_generic_param(
+ make::lifetime_param(new_lifetime_param.clone()).clone_for_update().into(),
);
+ ted::replace(lifetime.syntax(), new_lifetime_param.clone_for_update().syntax());
})
}
/// which is not in the list
fn generate_unique_lifetime_param_name(
existing_type_param_list: Option<ast::GenericParamList>,
-) -> Option<char> {
+) -> Option<ast::Lifetime> {
match existing_type_param_list {
Some(type_params) => {
- let used_lifetime_params: FxHashSet<_> = type_params
- .lifetime_params()
- .map(|p| p.syntax().text().to_string()[1..].to_owned())
- .collect();
- (b'a'..=b'z').map(char::from).find(|c| !used_lifetime_params.contains(&c.to_string()))
+ let used_lifetime_params: FxHashSet<_> =
+ type_params.lifetime_params().map(|p| p.syntax().text().to_string()).collect();
+ ('a'..='z').map(|it| format!("'{}", it)).find(|it| !used_lifetime_params.contains(it))
}
- None => Some('a'),
+ None => Some("'a".to_string()),
}
-}
-
-fn add_lifetime_param(type_params: ast::GenericParamList, new_lifetime_param: char) {
- let generic_param =
- make::generic_param(&format!("'{}", new_lifetime_param), None).clone_for_update();
- type_params.add_generic_param(generic_param);
-}
-
-fn make_ast_lifetime(new_lifetime_param: char) -> ast::Lifetime {
- make::generic_param(&format!("'{}", new_lifetime_param), None)
- .syntax()
- .descendants()
- .find_map(ast::Lifetime::cast)
- .unwrap()
+ .map(|it| make::lifetime(&it))
}
enum NeedsLifetime {
//! `parse(format!())` we use internally is an implementation detail -- long
//! term, it will be replaced with direct tree manipulation.
use itertools::Itertools;
-use stdx::format_to;
+use stdx::{format_to, never};
use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken};
ast_from_text(&format!("fn f() {{ {}{}; }}", raw_ident_esc(text), text))
}
+pub fn lifetime(text: &str) -> ast::Lifetime {
+ let mut text = text;
+ let tmp;
+ if never!(!text.starts_with('\'')) {
+ tmp = format!("'{}", text);
+ text = &tmp;
+ }
+ ast_from_text(&format!("fn f<{}>() {{ }}", text))
+}
+
fn raw_ident_esc(ident: &str) -> &'static str {
let is_keyword = parser::SyntaxKind::from_keyword(ident).is_some();
if is_keyword && !matches!(ident, "self" | "crate" | "super" | "Self") {
// FIXME: replace stringly-typed constructor with a family of typed ctors, a-la
// `expr_xxx`.
pub fn ty(text: &str) -> ast::Type {
- ast_from_text(&format!("fn f() -> {} {{}}", text))
+ ty_from_text(text)
}
pub fn ty_unit() -> ast::Type {
- ty("()")
+ ty_from_text("()")
+}
+pub fn ty_bool() -> ast::Type {
+ ty_path(path_unqualified(path_segment(name_ref("bool"))))
}
pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
let mut count: usize = 0;
contents.push(',');
}
- ty(&format!("({})", contents))
+ ty_from_text(&format!("({})", contents))
}
// FIXME: handle path to type
pub fn ty_generic(name: ast::NameRef, types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
let contents = types.into_iter().join(", ");
- ty(&format!("{}<{}>", name, contents))
+ ty_from_text(&format!("{}<{}>", name, contents))
}
pub fn ty_ref(target: ast::Type, exclusive: bool) -> ast::Type {
- ty(&if exclusive { format!("&mut {}", target) } else { format!("&{}", target) })
+ ty_from_text(&if exclusive { format!("&mut {}", target) } else { format!("&{}", target) })
+}
+pub fn ty_path(path: ast::Path) -> ast::Type {
+ ty_from_text(&path.to_string())
+}
+fn ty_from_text(text: &str) -> ast::Type {
+ ast_from_text(&format!("type _T = {};", text))
}
pub fn assoc_item_list() -> ast::AssocItemList {
};
ast_from_text(&list)
}
-// FIXME: s/&str/ast:Name
-pub fn generic_param(name: &str, ty: Option<ast::TypeBoundList>) -> ast::GenericParam {
+
+pub fn type_param(name: ast::Name, ty: Option<ast::TypeBoundList>) -> ast::TypeParam {
let bound = match ty {
Some(it) => format!(": {}", it),
None => String::new(),
ast_from_text(&format!("fn f<{}{}>() {{ }}", name, bound))
}
+pub fn lifetime_param(lifetime: ast::Lifetime) -> ast::LifetimeParam {
+ ast_from_text(&format!("fn f<{}>() {{ }}", lifetime))
+}
+
pub fn generic_param_list(
pats: impl IntoIterator<Item = ast::GenericParam>,
) -> ast::GenericParamList {