Factor out return type handling for both function and method
This commit is contained in:
parent
0834e05045
commit
a5c46e5a88
@ -171,7 +171,7 @@ struct FunctionTemplate {
|
|||||||
insert_offset: TextSize,
|
insert_offset: TextSize,
|
||||||
leading_ws: String,
|
leading_ws: String,
|
||||||
fn_def: ast::Fn,
|
fn_def: ast::Fn,
|
||||||
ret_type: ast::RetType,
|
ret_type: Option<ast::RetType>,
|
||||||
should_focus_tail_expr: bool,
|
should_focus_tail_expr: bool,
|
||||||
trailing_ws: String,
|
trailing_ws: String,
|
||||||
file: FileId,
|
file: FileId,
|
||||||
@ -183,7 +183,11 @@ impl FunctionTemplate {
|
|||||||
let f = match cap {
|
let f = match cap {
|
||||||
Some(cap) => {
|
Some(cap) => {
|
||||||
let cursor = if self.should_focus_tail_expr {
|
let cursor = if self.should_focus_tail_expr {
|
||||||
self.ret_type.syntax()
|
if let Some(ref ret_type) = self.ret_type {
|
||||||
|
ret_type.syntax()
|
||||||
|
} else {
|
||||||
|
self.tail_expr.syntax()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.tail_expr.syntax()
|
self.tail_expr.syntax()
|
||||||
};
|
};
|
||||||
@ -201,7 +205,7 @@ struct FunctionBuilder {
|
|||||||
fn_name: ast::Name,
|
fn_name: ast::Name,
|
||||||
type_params: Option<ast::GenericParamList>,
|
type_params: Option<ast::GenericParamList>,
|
||||||
params: ast::ParamList,
|
params: ast::ParamList,
|
||||||
ret_type: ast::RetType,
|
ret_type: Option<ast::RetType>,
|
||||||
should_focus_tail_expr: bool,
|
should_focus_tail_expr: bool,
|
||||||
file: FileId,
|
file: FileId,
|
||||||
needs_pub: bool,
|
needs_pub: bool,
|
||||||
@ -235,33 +239,8 @@ impl FunctionBuilder {
|
|||||||
let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
|
let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
|
||||||
let is_async = await_expr.is_some();
|
let is_async = await_expr.is_some();
|
||||||
|
|
||||||
// should_focus_tail_expr intends to express a rough level of confidence about
|
let (ret_type, should_focus_tail_expr) =
|
||||||
// the correctness of the return type.
|
make_return_type(ctx, &ast::Expr::CallExpr(call.clone()), target_module);
|
||||||
//
|
|
||||||
// If we are able to infer some return type, and that return type is not unit, we
|
|
||||||
// don't want to render the snippet. The assumption here is in this situation the
|
|
||||||
// return type is just as likely to be correct as any other part of the generated
|
|
||||||
// function.
|
|
||||||
//
|
|
||||||
// In the case where the return type is inferred as unit it is likely that the
|
|
||||||
// user does in fact intend for this generated function to return some non unit
|
|
||||||
// type, but that the current state of their code doesn't allow that return type
|
|
||||||
// to be accurately inferred.
|
|
||||||
let (ret_ty, should_focus_tail_expr) = {
|
|
||||||
match ctx.sema.type_of_expr(&ast::Expr::CallExpr(call.clone())).map(TypeInfo::original)
|
|
||||||
{
|
|
||||||
Some(ty) if ty.is_unknown() || ty.is_unit() => (make::ty_unit(), true),
|
|
||||||
Some(ty) => {
|
|
||||||
let rendered = ty.display_source_code(ctx.db(), target_module.into());
|
|
||||||
match rendered {
|
|
||||||
Ok(rendered) => (make::ty(&rendered), false),
|
|
||||||
Err(_) => (make::ty_unit(), true),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => (make::ty_unit(), true),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let ret_type = make::ret_type(ret_ty);
|
|
||||||
|
|
||||||
Some(Self {
|
Some(Self {
|
||||||
target,
|
target,
|
||||||
@ -305,36 +284,8 @@ impl FunctionBuilder {
|
|||||||
let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
|
let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
|
||||||
let is_async = await_expr.is_some();
|
let is_async = await_expr.is_some();
|
||||||
|
|
||||||
// should_render_snippet intends to express a rough level of confidence about
|
let (ret_type, should_focus_tail_expr) =
|
||||||
// the correctness of the return type.
|
make_return_type(ctx, &ast::Expr::MethodCallExpr(call.clone()), target_module);
|
||||||
//
|
|
||||||
// If we are able to infer some return type, and that return type is not unit, we
|
|
||||||
// don't want to render the snippet. The assumption here is in this situation the
|
|
||||||
// return type is just as likely to be correct as any other part of the generated
|
|
||||||
// function.
|
|
||||||
//
|
|
||||||
// In the case where the return type is inferred as unit it is likely that the
|
|
||||||
// user does in fact intend for this generated function to return some non unit
|
|
||||||
// type, but that the current state of their code doesn't allow that return type
|
|
||||||
// to be accurately inferred.
|
|
||||||
let (ret_ty, should_render_snippet) = {
|
|
||||||
match ctx
|
|
||||||
.sema
|
|
||||||
.type_of_expr(&ast::Expr::MethodCallExpr(call.clone()))
|
|
||||||
.map(TypeInfo::original)
|
|
||||||
{
|
|
||||||
Some(ty) if ty.is_unknown() || ty.is_unit() => (make::ty_unit(), true),
|
|
||||||
Some(ty) => {
|
|
||||||
let rendered = ty.display_source_code(ctx.db(), target_module.into());
|
|
||||||
match rendered {
|
|
||||||
Ok(rendered) => (make::ty(&rendered), false),
|
|
||||||
Err(_) => (make::ty_unit(), true),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => (make::ty_unit(), true),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let ret_type = make::ret_type(ret_ty);
|
|
||||||
|
|
||||||
Some(Self {
|
Some(Self {
|
||||||
target,
|
target,
|
||||||
@ -342,7 +293,7 @@ impl FunctionBuilder {
|
|||||||
type_params,
|
type_params,
|
||||||
params,
|
params,
|
||||||
ret_type,
|
ret_type,
|
||||||
should_focus_tail_expr: should_render_snippet,
|
should_focus_tail_expr,
|
||||||
file,
|
file,
|
||||||
needs_pub,
|
needs_pub,
|
||||||
is_async,
|
is_async,
|
||||||
@ -359,7 +310,7 @@ impl FunctionBuilder {
|
|||||||
self.type_params,
|
self.type_params,
|
||||||
self.params,
|
self.params,
|
||||||
fn_body,
|
fn_body,
|
||||||
Some(self.ret_type),
|
self.ret_type,
|
||||||
self.is_async,
|
self.is_async,
|
||||||
);
|
);
|
||||||
let leading_ws;
|
let leading_ws;
|
||||||
@ -386,7 +337,7 @@ impl FunctionBuilder {
|
|||||||
insert_offset,
|
insert_offset,
|
||||||
leading_ws,
|
leading_ws,
|
||||||
// PANIC: we guarantee we always create a function with a return type
|
// PANIC: we guarantee we always create a function with a return type
|
||||||
ret_type: fn_def.ret_type().unwrap(),
|
ret_type: fn_def.ret_type(),
|
||||||
// PANIC: we guarantee we always create a function body with a tail expr
|
// PANIC: we guarantee we always create a function body with a tail expr
|
||||||
tail_expr: fn_def.body().unwrap().tail_expr().unwrap(),
|
tail_expr: fn_def.body().unwrap().tail_expr().unwrap(),
|
||||||
should_focus_tail_expr: self.should_focus_tail_expr,
|
should_focus_tail_expr: self.should_focus_tail_expr,
|
||||||
@ -397,6 +348,29 @@ impl FunctionBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_return_type(
|
||||||
|
ctx: &AssistContext,
|
||||||
|
call: &ast::Expr,
|
||||||
|
target_module: Module,
|
||||||
|
) -> (Option<ast::RetType>, bool) {
|
||||||
|
let (ret_ty, should_focus_tail_expr) = {
|
||||||
|
match ctx.sema.type_of_expr(call).map(TypeInfo::original) {
|
||||||
|
Some(ty) if ty.is_unit() => (None, false),
|
||||||
|
Some(ty) if ty.is_unknown() => (Some(make::ty_unit()), true),
|
||||||
|
None => (Some(make::ty_unit()), true),
|
||||||
|
Some(ty) => {
|
||||||
|
let rendered = ty.display_source_code(ctx.db(), target_module.into());
|
||||||
|
match rendered {
|
||||||
|
Ok(rendered) => (Some(make::ty(&rendered)), false),
|
||||||
|
Err(_) => (Some(make::ty_unit()), true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let ret_type = ret_ty.map(|rt| make::ret_type(rt));
|
||||||
|
(ret_type, should_focus_tail_expr)
|
||||||
|
}
|
||||||
|
|
||||||
enum GeneratedFunctionTarget {
|
enum GeneratedFunctionTarget {
|
||||||
BehindItem(SyntaxNode),
|
BehindItem(SyntaxNode),
|
||||||
InEmptyItemList(SyntaxNode),
|
InEmptyItemList(SyntaxNode),
|
||||||
@ -825,8 +799,8 @@ fn foo() {
|
|||||||
bar("bar")
|
bar("bar")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(arg: &str) ${0:-> ()} {
|
fn bar(arg: &str) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
@ -846,8 +820,8 @@ fn foo() {
|
|||||||
bar('x')
|
bar('x')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(arg: char) ${0:-> ()} {
|
fn bar(arg: char) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
@ -867,8 +841,8 @@ fn foo() {
|
|||||||
bar(42)
|
bar(42)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(arg: i32) ${0:-> ()} {
|
fn bar(arg: i32) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -888,8 +862,8 @@ fn foo() {
|
|||||||
bar(42 as u8)
|
bar(42 as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(arg: u8) ${0:-> ()} {
|
fn bar(arg: u8) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -913,8 +887,8 @@ fn foo() {
|
|||||||
bar(x as u8)
|
bar(x as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(x: u8) ${0:-> ()} {
|
fn bar(x: u8) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -936,8 +910,8 @@ fn foo() {
|
|||||||
bar(worble)
|
bar(worble)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(worble: ()) ${0:-> ()} {
|
fn bar(worble: ()) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -965,8 +939,8 @@ fn baz() {
|
|||||||
bar(foo())
|
bar(foo())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(foo: impl Foo) ${0:-> ()} {
|
fn bar(foo: impl Foo) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -992,8 +966,8 @@ fn foo() {
|
|||||||
bar(&baz())
|
bar(&baz())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(baz: &Baz) ${0:-> ()} {
|
fn bar(baz: &Baz) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -1021,8 +995,8 @@ fn foo() {
|
|||||||
bar(Baz::baz())
|
bar(Baz::baz())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(baz: Baz::Bof) ${0:-> ()} {
|
fn bar(baz: Baz::Bof) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -1043,8 +1017,8 @@ fn foo<T>(t: T) {
|
|||||||
bar(t)
|
bar(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(t: T) ${0:-> ()} {
|
fn bar(t: T) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -1097,8 +1071,8 @@ fn foo() {
|
|||||||
bar(closure)
|
bar(closure)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(closure: ()) ${0:-> ()} {
|
fn bar(closure: ()) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -1118,8 +1092,8 @@ fn foo() {
|
|||||||
bar(baz)
|
bar(baz)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(baz: ()) ${0:-> ()} {
|
fn bar(baz: ()) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -1143,8 +1117,8 @@ fn foo() {
|
|||||||
bar(baz(), baz())
|
bar(baz(), baz())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(baz_1: Baz, baz_2: Baz) ${0:-> ()} {
|
fn bar(baz_1: Baz, baz_2: Baz) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
@ -1168,8 +1142,8 @@ fn foo() {
|
|||||||
bar(baz(), baz(), "foo", "bar")
|
bar(baz(), baz(), "foo", "bar")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) ${0:-> ()} {
|
fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
@ -1188,8 +1162,8 @@ fn foo() {
|
|||||||
",
|
",
|
||||||
r"
|
r"
|
||||||
mod bar {
|
mod bar {
|
||||||
pub(crate) fn my_fn() ${0:-> ()} {
|
pub(crate) fn my_fn() {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1224,8 +1198,8 @@ fn bar() {
|
|||||||
baz(foo)
|
baz(foo)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn baz(foo: foo::Foo) ${0:-> ()} {
|
fn baz(foo: foo::Foo) {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
@ -1248,8 +1222,8 @@ fn foo() {
|
|||||||
mod bar {
|
mod bar {
|
||||||
fn something_else() {}
|
fn something_else() {}
|
||||||
|
|
||||||
pub(crate) fn my_fn() ${0:-> ()} {
|
pub(crate) fn my_fn() {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1276,8 +1250,8 @@ fn foo() {
|
|||||||
r"
|
r"
|
||||||
mod bar {
|
mod bar {
|
||||||
mod baz {
|
mod baz {
|
||||||
pub(crate) fn my_fn() ${0:-> ()} {
|
pub(crate) fn my_fn() {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1305,8 +1279,8 @@ fn main() {
|
|||||||
r"
|
r"
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn bar() ${0:-> ()} {
|
pub(crate) fn bar() {
|
||||||
todo!()
|
${0:todo!()}
|
||||||
}",
|
}",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user