Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e33c0b4

Browse files
committed
Auto merge of rust-lang#14842 - alibektas:internal/ast-make-improve, r=Veykril
Improve ast::make Add `ty_alias` and make `impl_trait` , `fn` and `impl_` have more coverage.
2 parents 76d8650 + 51ec2ce commit e33c0b4

File tree

3 files changed

+126
-34
lines changed

3 files changed

+126
-34
lines changed

crates/ide-assists/src/handlers/generate_delegate_methods.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,25 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
119119
);
120120
let ret_type = method_source.ret_type();
121121
let is_async = method_source.async_token().is_some();
122+
let is_const = method_source.const_token().is_some();
123+
let is_unsafe = method_source.unsafe_token().is_some();
122124
let tail_expr_finished =
123125
if is_async { make::expr_await(tail_expr) } else { tail_expr };
124126
let body = make::block_expr([], Some(tail_expr_finished));
125-
let f = make::fn_(vis, name, type_params, None, params, body, ret_type, is_async)
126-
.indent(ast::edit::IndentLevel(1))
127-
.clone_for_update();
127+
let f = make::fn_(
128+
vis,
129+
name,
130+
type_params,
131+
None,
132+
params,
133+
body,
134+
ret_type,
135+
is_async,
136+
is_const,
137+
is_unsafe,
138+
)
139+
.indent(ast::edit::IndentLevel(1))
140+
.clone_for_update();
128141

129142
let cursor = Cursor::Before(f.syntax());
130143

@@ -156,8 +169,16 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
156169
let name = &strukt_name.to_string();
157170
let params = strukt.generic_param_list();
158171
let ty_params = params.clone();
159-
let impl_def = make::impl_(make::ext::ident_path(name), params, ty_params)
160-
.clone_for_update();
172+
let where_clause = strukt.where_clause();
173+
174+
let impl_def = make::impl_(
175+
ty_params,
176+
None,
177+
make::ty_path(make::ext::ident_path(name)),
178+
where_clause,
179+
None,
180+
)
181+
.clone_for_update();
161182
let assoc_items = impl_def.get_or_create_assoc_item_list();
162183
assoc_items.add_item(f.clone().into());
163184

crates/ide-assists/src/handlers/generate_function.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,8 @@ impl FunctionBuilder {
378378
fn_body,
379379
self.ret_type,
380380
self.is_async,
381+
false, // FIXME : const and unsafe are not handled yet.
382+
false,
381383
);
382384
let leading_ws;
383385
let trailing_ws;

crates/syntax/src/ast/make.rs

Lines changed: 98 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,6 @@ fn ty_from_text(text: &str) -> ast::Type {
158158
ast_from_text(&format!("type _T = {text};"))
159159
}
160160

161-
/// Related goto [link](https://doc.rust-lang.org/reference/items/type-aliases.html)
162-
/// Type Alias syntax is
163-
/// ```
164-
/// TypeAlias :
165-
/// type IDENTIFIER GenericParams? ( : TypeParamBounds )? WhereClause? ( = Type WhereClause?)? ;
166-
/// ```
167-
/// FIXME : ident should be of type ast::Ident
168161
pub fn ty_alias(
169162
ident: &str,
170163
generic_param_list: Option<ast::GenericParamList>,
@@ -173,7 +166,7 @@ pub fn ty_alias(
173166
assignment: Option<(ast::Type, Option<ast::WhereClause>)>,
174167
) -> ast::TypeAlias {
175168
let mut s = String::new();
176-
s.push_str(&format!("type {}", ident));
169+
s.push_str(&format!("type {} ", ident));
177170

178171
if let Some(list) = generic_param_list {
179172
s.push_str(&list.to_string());
@@ -203,33 +196,106 @@ pub fn assoc_item_list() -> ast::AssocItemList {
203196
ast_from_text("impl C for D {}")
204197
}
205198

206-
// FIXME: `ty_params` should be `ast::GenericArgList`
199+
fn merge_gen_params(
200+
ps: Option<ast::GenericParamList>,
201+
bs: Option<ast::GenericParamList>,
202+
) -> Option<ast::GenericParamList> {
203+
match (ps, bs) {
204+
(None, None) => None,
205+
(None, Some(bs)) => Some(bs),
206+
(Some(ps), None) => Some(ps),
207+
(Some(ps), Some(bs)) => {
208+
for b in bs.generic_params() {
209+
ps.add_generic_param(b);
210+
}
211+
Some(ps)
212+
}
213+
}
214+
}
215+
207216
pub fn impl_(
208-
ty: ast::Path,
209-
params: Option<ast::GenericParamList>,
210-
ty_params: Option<ast::GenericParamList>,
217+
generic_params: Option<ast::GenericParamList>,
218+
generic_args: Option<ast::GenericParamList>,
219+
path_type: ast::Type,
220+
where_clause: Option<ast::WhereClause>,
221+
body: Option<Vec<either::Either<ast::Attr, ast::AssocItem>>>,
211222
) -> ast::Impl {
212-
let params = match params {
213-
Some(params) => params.to_string(),
214-
None => String::new(),
223+
let (gen_params, tr_gen_args) = match (generic_params, generic_args) {
224+
(None, None) => (String::new(), String::new()),
225+
(None, Some(args)) => (String::new(), args.to_generic_args().to_string()),
226+
(Some(params), None) => (params.to_string(), params.to_generic_args().to_string()),
227+
(Some(params), Some(args)) => match merge_gen_params(Some(params.clone()), Some(args)) {
228+
Some(merged) => (params.to_string(), merged.to_generic_args().to_string()),
229+
None => (params.to_string(), String::new()),
230+
},
215231
};
216-
let ty_params = match ty_params {
217-
Some(params) => params.to_string(),
232+
233+
let where_clause = match where_clause {
234+
Some(pr) => pr.to_string(),
235+
None => " ".to_string(),
236+
};
237+
238+
let body = match body {
239+
Some(bd) => bd.iter().map(|elem| elem.to_string()).join(""),
218240
None => String::new(),
219241
};
220-
ast_from_text(&format!("impl{params} {ty}{ty_params} {{}}"))
242+
243+
ast_from_text(&format!("impl{gen_params} {path_type}{tr_gen_args}{where_clause}{{{}}}", body))
221244
}
222245

246+
// FIXME : We must make *_gen_args' type ast::GenericArgList but in order to do so we must implement in `edit_in_place.rs`
247+
// `add_generic_arg()` just like `add_generic_param()`
248+
// is implemented for `ast::GenericParamList`
223249
pub fn impl_trait(
224-
trait_: ast::Path,
225-
ty: ast::Path,
226-
ty_params: Option<ast::GenericParamList>,
250+
is_unsafe: bool,
251+
trait_gen_params: Option<ast::GenericParamList>,
252+
trait_gen_args: Option<ast::GenericParamList>,
253+
type_gen_params: Option<ast::GenericParamList>,
254+
type_gen_args: Option<ast::GenericParamList>,
255+
is_negative: bool,
256+
path_type: ast::Type,
257+
ty: ast::Type,
258+
trait_where_clause: Option<ast::WhereClause>,
259+
ty_where_clause: Option<ast::WhereClause>,
260+
body: Option<Vec<either::Either<ast::Attr, ast::AssocItem>>>,
227261
) -> ast::Impl {
228-
// TODO : If this function is now correct we can also change `impl_` accordingly`
229-
let ty_params_str = ty_params.as_ref().map_or_else(String::new, |params| params.to_string());
230-
let ty_genargs_str =
231-
ty_params.map_or_else(String::new, |params| params.to_generic_args().to_string());
232-
ast_from_text(&format!("impl{ty_params_str} {trait_} for {ty}{ty_genargs_str} {{}}"))
262+
let is_unsafe = if is_unsafe { "unsafe " } else { "" };
263+
let ty_gen_args = match merge_gen_params(type_gen_params.clone(), type_gen_args) {
264+
Some(pars) => pars.to_generic_args().to_string(),
265+
None => String::new(),
266+
};
267+
268+
let tr_gen_args = match merge_gen_params(trait_gen_params.clone(), trait_gen_args) {
269+
Some(pars) => pars.to_generic_args().to_string(),
270+
None => String::new(),
271+
};
272+
273+
let gen_params = match merge_gen_params(trait_gen_params, type_gen_params) {
274+
Some(pars) => pars.to_string(),
275+
None => String::new(),
276+
};
277+
278+
let is_negative = if is_negative { "! " } else { "" };
279+
280+
let where_clause = match (ty_where_clause, trait_where_clause) {
281+
(None, None) => " ".to_string(),
282+
(None, Some(tr)) => format!("\n{}\n", tr).to_string(),
283+
(Some(ty), None) => format!("\n{}\n", ty).to_string(),
284+
(Some(ty), Some(tr)) => {
285+
let updated = ty.clone_for_update();
286+
tr.predicates().for_each(|p| {
287+
ty.add_predicate(p);
288+
});
289+
format!("\n{}\n", updated).to_string()
290+
}
291+
};
292+
293+
let body = match body {
294+
Some(bd) => bd.iter().map(|elem| elem.to_string()).join(""),
295+
None => String::new(),
296+
};
297+
298+
ast_from_text(&format!("{is_unsafe}impl{gen_params} {is_negative}{path_type}{tr_gen_args} for {ty}{ty_gen_args}{where_clause}{{{}}}" , body))
233299
}
234300

235301
pub fn impl_trait_type(bounds: ast::TypeBoundList) -> ast::ImplTraitType {
@@ -875,6 +941,8 @@ pub fn fn_(
875941
body: ast::BlockExpr,
876942
ret_type: Option<ast::RetType>,
877943
is_async: bool,
944+
is_const: bool,
945+
is_unsafe: bool,
878946
) -> ast::Fn {
879947
let type_params = match type_params {
880948
Some(type_params) => format!("{type_params}"),
@@ -894,12 +962,13 @@ pub fn fn_(
894962
};
895963

896964
let async_literal = if is_async { "async " } else { "" };
965+
let const_literal = if is_const { "const " } else { "" };
966+
let unsafe_literal = if is_unsafe { "unsafe " } else { "" };
897967

898968
ast_from_text(&format!(
899-
"{visibility}{async_literal}fn {fn_name}{type_params}{params} {ret_type}{where_clause}{body}",
969+
"{visibility}{async_literal}{const_literal}{unsafe_literal}fn {fn_name}{type_params}{params} {ret_type}{where_clause}{body}",
900970
))
901971
}
902-
903972
pub fn struct_(
904973
visibility: Option<ast::Visibility>,
905974
strukt_name: ast::Name,
@@ -949,7 +1018,7 @@ pub mod tokens {
9491018

9501019
pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| {
9511020
SourceFile::parse(
952-
"const C: <()>::Item = (1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p)\n;\n\n",
1021+
"const C: <()>::Item = (1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p, &p , &mut p)\n;\n\n",
9531022
)
9541023
});
9551024

0 commit comments

Comments
 (0)