mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
very rough but comments get extracted
This commit is contained in:
parent
f662d8bf38
commit
4f3dd5bc08
2 changed files with 230 additions and 28 deletions
|
@ -69,11 +69,16 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("initial node: {:?}", node);
|
||||||
|
|
||||||
let node = match node {
|
let node = match node {
|
||||||
syntax::NodeOrToken::Node(n) => n,
|
syntax::NodeOrToken::Node(n) => n,
|
||||||
syntax::NodeOrToken::Token(t) => t.parent()?,
|
syntax::NodeOrToken::Token(t) => t.parent()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
println!("next node: {:?}", node);
|
||||||
let body = extraction_target(&node, range)?;
|
let body = extraction_target(&node, range)?;
|
||||||
|
println!("body: {:?}", body);
|
||||||
let container_info = body.analyze_container(&ctx.sema)?;
|
let container_info = body.analyze_container(&ctx.sema)?;
|
||||||
|
|
||||||
let (locals_used, self_param) = body.analyze(&ctx.sema);
|
let (locals_used, self_param) = body.analyze(&ctx.sema);
|
||||||
|
@ -182,6 +187,8 @@ fn extraction_target(node: &SyntaxNode, selection_range: TextRange) -> Option<Fu
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("node: {:?}", node);
|
||||||
|
|
||||||
// Covering element returned the parent block of one or multiple statements that have been selected
|
// Covering element returned the parent block of one or multiple statements that have been selected
|
||||||
if let Some(stmt_list) = ast::StmtList::cast(node.clone()) {
|
if let Some(stmt_list) = ast::StmtList::cast(node.clone()) {
|
||||||
if let Some(block_expr) = stmt_list.syntax().parent().and_then(ast::BlockExpr::cast) {
|
if let Some(block_expr) = stmt_list.syntax().parent().and_then(ast::BlockExpr::cast) {
|
||||||
|
@ -191,6 +198,8 @@ fn extraction_target(node: &SyntaxNode, selection_range: TextRange) -> Option<Fu
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the full statements.
|
// Extract the full statements.
|
||||||
|
println!("stmt_list: {:?}", stmt_list);
|
||||||
|
println!("selection_range: {:?}", selection_range);
|
||||||
return Some(FunctionBody::from_range(stmt_list, selection_range));
|
return Some(FunctionBody::from_range(stmt_list, selection_range));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,12 +484,21 @@ impl FunctionBody {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// selection: 36..67
|
||||||
|
// resulting: 57..67
|
||||||
|
|
||||||
fn from_range(parent: ast::StmtList, selected: TextRange) -> FunctionBody {
|
fn from_range(parent: ast::StmtList, selected: TextRange) -> FunctionBody {
|
||||||
let mut text_range = parent
|
let full_body = parent.syntax().children_with_tokens();
|
||||||
.statements()
|
for st in parent.syntax().children_with_tokens() {
|
||||||
.map(|stmt| stmt.syntax().text_range())
|
println!("Statement: {:?}", &st);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut text_range = full_body
|
||||||
|
.map(|stmt| stmt.text_range())
|
||||||
.filter(|&stmt| selected.intersect(stmt).filter(|it| !it.is_empty()).is_some())
|
.filter(|&stmt| selected.intersect(stmt).filter(|it| !it.is_empty()).is_some())
|
||||||
.reduce(|acc, stmt| acc.cover(stmt));
|
.reduce(|acc, stmt| acc.cover(stmt));
|
||||||
|
|
||||||
|
println!("from_range text_range first: {:?}", text_range);
|
||||||
if let Some(tail_range) = parent
|
if let Some(tail_range) = parent
|
||||||
.tail_expr()
|
.tail_expr()
|
||||||
.map(|it| it.syntax().text_range())
|
.map(|it| it.syntax().text_range())
|
||||||
|
@ -490,6 +508,8 @@ impl FunctionBody {
|
||||||
Some(text_range) => text_range.cover(tail_range),
|
Some(text_range) => text_range.cover(tail_range),
|
||||||
None => tail_range,
|
None => tail_range,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
println!("from_range text_range second: {:?}", text_range);
|
||||||
}
|
}
|
||||||
Self::Span { parent, text_range: text_range.unwrap_or(selected) }
|
Self::Span { parent, text_range: text_range.unwrap_or(selected) }
|
||||||
}
|
}
|
||||||
|
@ -1420,6 +1440,8 @@ fn make_body(
|
||||||
} else {
|
} else {
|
||||||
FlowHandler::from_ret_ty(fun, &ret_ty)
|
FlowHandler::from_ret_ty(fun, &ret_ty)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
println!("making body: {:?}", fun.body);
|
||||||
let block = match &fun.body {
|
let block = match &fun.body {
|
||||||
FunctionBody::Expr(expr) => {
|
FunctionBody::Expr(expr) => {
|
||||||
let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax());
|
let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax());
|
||||||
|
@ -1441,17 +1463,32 @@ fn make_body(
|
||||||
FunctionBody::Span { parent, text_range } => {
|
FunctionBody::Span { parent, text_range } => {
|
||||||
let mut elements: Vec<_> = parent
|
let mut elements: Vec<_> = parent
|
||||||
.syntax()
|
.syntax()
|
||||||
.children()
|
.children_with_tokens()
|
||||||
.filter(|it| text_range.contains_range(it.text_range()))
|
.filter(|it| text_range.contains_range(it.text_range()))
|
||||||
.map(|it| rewrite_body_segment(ctx, &fun.params, &handler, &it))
|
.map(|it| match it {
|
||||||
|
syntax::NodeOrToken::Node(n) => {
|
||||||
|
return syntax::NodeOrToken::try_from(rewrite_body_segment(
|
||||||
|
ctx,
|
||||||
|
&fun.params,
|
||||||
|
&handler,
|
||||||
|
&n,
|
||||||
|
))
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
syntax::NodeOrToken::Token(t) => {
|
||||||
|
return syntax::NodeOrToken::try_from(t).unwrap()
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut tail_expr = match elements.pop() {
|
let mut tail_expr = match elements.pop() {
|
||||||
Some(node) => ast::Expr::cast(node.clone()).or_else(|| {
|
Some(node) if node.as_node().is_some() => {
|
||||||
elements.push(node);
|
ast::Expr::cast(node.as_node().unwrap().clone()).or_else(|| {
|
||||||
None
|
elements.push(node);
|
||||||
}),
|
None
|
||||||
None => None,
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if tail_expr.is_none() {
|
if tail_expr.is_none() {
|
||||||
|
@ -1467,20 +1504,30 @@ fn make_body(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let elements = elements.into_iter().filter_map(|node| match ast::Stmt::cast(node) {
|
|
||||||
Some(stmt) => Some(stmt),
|
|
||||||
None => {
|
|
||||||
stdx::never!("block contains non-statement");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let body_indent = IndentLevel(1);
|
let body_indent = IndentLevel(1);
|
||||||
let elements = elements.map(|stmt| stmt.dedent(old_indent).indent(body_indent));
|
let elements: Vec<SyntaxElement> = elements.into_iter().map(|stmt| {
|
||||||
|
match stmt {
|
||||||
|
syntax::NodeOrToken::Node(n) => {
|
||||||
|
let ast_element = ast::Stmt::cast(n).unwrap();
|
||||||
|
let indented = ast_element.dedent(old_indent).indent(body_indent);
|
||||||
|
let ast_node = indented.syntax().clone_subtree();
|
||||||
|
syntax::NodeOrToken::try_from(ast_node).unwrap()
|
||||||
|
},
|
||||||
|
syntax::NodeOrToken::Token(t) => syntax::NodeOrToken::try_from(t).unwrap()
|
||||||
|
}
|
||||||
|
}).collect::<Vec<SyntaxElement>>();
|
||||||
let tail_expr = tail_expr.map(|expr| expr.dedent(old_indent).indent(body_indent));
|
let tail_expr = tail_expr.map(|expr| expr.dedent(old_indent).indent(body_indent));
|
||||||
|
|
||||||
make::block_expr(elements, tail_expr)
|
for element in &elements {
|
||||||
|
println!("element: {:?}", element);
|
||||||
|
}
|
||||||
|
|
||||||
|
make::block_expr_full(elements, tail_expr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// make::block_expr(parent.statements().into_iter(), tail_expr)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4092,14 +4139,14 @@ fn foo() {
|
||||||
"#,
|
"#,
|
||||||
r#"
|
r#"
|
||||||
fn foo() {
|
fn foo() {
|
||||||
/**/
|
|
||||||
fun_name();
|
fun_name();
|
||||||
/**/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn $0fun_name() {
|
fn $0fun_name() {
|
||||||
|
/**/
|
||||||
foo();
|
foo();
|
||||||
foo();
|
foo();
|
||||||
|
/**/
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
@ -4399,16 +4446,14 @@ fn $0fun_name(arg: &mut Foo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn extract_function_copies_comments() {
|
fn extract_function_copies_comment_at_start() {
|
||||||
check_assist(
|
check_assist(
|
||||||
extract_function,
|
extract_function,
|
||||||
r#"
|
r#"
|
||||||
fn func() {
|
fn func() {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
$0
|
$0// comment here!
|
||||||
// comment here!
|
let x = 0;$0
|
||||||
let x = 0;
|
|
||||||
$0
|
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
r#"
|
r#"
|
||||||
|
@ -4421,6 +4466,140 @@ fn $0fun_name() {
|
||||||
// comment here!
|
// comment here!
|
||||||
let x = 0;
|
let x = 0;
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extract_function_copies_comment_in_between() {
|
||||||
|
check_assist(
|
||||||
|
extract_function,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
$0
|
||||||
|
let a = 0;
|
||||||
|
// comment here!
|
||||||
|
let x = 0;$0
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
fun_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn $0fun_name() {
|
||||||
|
let a = 0;
|
||||||
|
// comment here!
|
||||||
|
let x = 0;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extract_function_copies_comment_at_end() {
|
||||||
|
check_assist(
|
||||||
|
extract_function,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
$0let x = 0;
|
||||||
|
// comment here!$0
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
fun_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn $0fun_name() {
|
||||||
|
let x = 0;
|
||||||
|
// comment here!
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extract_function_copies_comment_indented() {
|
||||||
|
check_assist(
|
||||||
|
extract_function,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
$0let x = 0;
|
||||||
|
while(true) {
|
||||||
|
// comment here!
|
||||||
|
}$0
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
fun_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn $0fun_name() {
|
||||||
|
let x = 0;
|
||||||
|
while(true) {
|
||||||
|
// comment here!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extract_function_does_not_preserve_whitespace() {
|
||||||
|
check_assist(
|
||||||
|
extract_function,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
$0let a = 0;
|
||||||
|
|
||||||
|
let x = 0;$0
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
fun_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn $0fun_name() {
|
||||||
|
let a = 0;
|
||||||
|
let x = 0;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extract_function_long_form_comment() {
|
||||||
|
check_assist(
|
||||||
|
extract_function,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
$0/* a comment */
|
||||||
|
let x = 0;$0
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let i = 0;
|
||||||
|
fun_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn $0fun_name() {
|
||||||
|
/* a comment */
|
||||||
|
let x = 0;
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -329,6 +329,29 @@ pub fn block_expr(
|
||||||
ast_from_text(&format!("fn f() {}", buf))
|
ast_from_text(&format!("fn f() {}", buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn block_expr_full(
|
||||||
|
stmts: impl IntoIterator<Item = crate::SyntaxElement>,
|
||||||
|
tail_expr: Option<ast::Expr>,
|
||||||
|
) -> ast::BlockExpr {
|
||||||
|
let mut buf = "{\n".to_string();
|
||||||
|
for stmt in stmts.into_iter() {
|
||||||
|
|
||||||
|
match stmt {
|
||||||
|
rowan::NodeOrToken::Node(n) => {
|
||||||
|
println!("Node: {:?}", n.text());
|
||||||
|
format_to!(buf, " {}\n", n)
|
||||||
|
},
|
||||||
|
rowan::NodeOrToken::Token(t) if t.kind() == SyntaxKind::COMMENT => format_to!(buf, " {}\n", t),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(tail_expr) = tail_expr {
|
||||||
|
format_to!(buf, " {}\n", tail_expr);
|
||||||
|
}
|
||||||
|
buf += "}";
|
||||||
|
ast_from_text(&format!("fn f() {}", buf))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn expr_unit() -> ast::Expr {
|
pub fn expr_unit() -> ast::Expr {
|
||||||
expr_from_text("()")
|
expr_from_text("()")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue