mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Introduce EffectExpr
This commit is contained in:
parent
3c96de5380
commit
4f2134cc33
25 changed files with 242 additions and 261 deletions
|
@ -2,7 +2,7 @@ use std::{iter::once, ops::RangeInclusive};
|
||||||
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo::replace_children,
|
algo::replace_children,
|
||||||
ast::{self, edit::IndentLevel, make, Block, Pat::TupleStructPat},
|
ast::{self, edit::IndentLevel, make},
|
||||||
AstNode,
|
AstNode,
|
||||||
SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE},
|
SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE},
|
||||||
SyntaxNode,
|
SyntaxNode,
|
||||||
|
@ -47,7 +47,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
|
||||||
// Check if there is an IfLet that we can handle.
|
// Check if there is an IfLet that we can handle.
|
||||||
let if_let_pat = match cond.pat() {
|
let if_let_pat = match cond.pat() {
|
||||||
None => None, // No IfLet, supported.
|
None => None, // No IfLet, supported.
|
||||||
Some(TupleStructPat(pat)) if pat.args().count() == 1 => {
|
Some(ast::Pat::TupleStructPat(pat)) if pat.args().count() == 1 => {
|
||||||
let path = pat.path()?;
|
let path = pat.path()?;
|
||||||
match path.qualifier() {
|
match path.qualifier() {
|
||||||
None => {
|
None => {
|
||||||
|
@ -61,9 +61,9 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let cond_expr = cond.expr()?;
|
let cond_expr = cond.expr()?;
|
||||||
let then_block = if_expr.then_branch()?.block()?;
|
let then_block = if_expr.then_branch()?;
|
||||||
|
|
||||||
let parent_block = if_expr.syntax().parent()?.ancestors().find_map(ast::Block::cast)?;
|
let parent_block = if_expr.syntax().parent()?.ancestors().find_map(ast::BlockExpr::cast)?;
|
||||||
|
|
||||||
if parent_block.expr()? != if_expr.clone().into() {
|
if parent_block.expr()? != if_expr.clone().into() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -80,7 +80,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let parent_container = parent_block.syntax().parent()?.parent()?;
|
let parent_container = parent_block.syntax().parent()?;
|
||||||
|
|
||||||
let early_expression: ast::Expr = match parent_container.kind() {
|
let early_expression: ast::Expr = match parent_container.kind() {
|
||||||
WHILE_EXPR | LOOP_EXPR => make::expr_continue(),
|
WHILE_EXPR | LOOP_EXPR => make::expr_continue(),
|
||||||
|
@ -144,13 +144,13 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
edit.target(if_expr.syntax().text_range());
|
edit.target(if_expr.syntax().text_range());
|
||||||
edit.replace_ast(parent_block, ast::Block::cast(new_block).unwrap());
|
edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap());
|
||||||
edit.set_cursor(cursor_position);
|
edit.set_cursor(cursor_position);
|
||||||
|
|
||||||
fn replace(
|
fn replace(
|
||||||
new_expr: &SyntaxNode,
|
new_expr: &SyntaxNode,
|
||||||
then_block: &Block,
|
then_block: &ast::BlockExpr,
|
||||||
parent_block: &Block,
|
parent_block: &ast::BlockExpr,
|
||||||
if_expr: &ast::IfExpr,
|
if_expr: &ast::IfExpr,
|
||||||
) -> SyntaxNode {
|
) -> SyntaxNode {
|
||||||
let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone());
|
let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone());
|
||||||
|
|
|
@ -89,6 +89,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> {
|
||||||
| (ast::Expr::ParenExpr(_), _)
|
| (ast::Expr::ParenExpr(_), _)
|
||||||
| (ast::Expr::PathExpr(_), _)
|
| (ast::Expr::PathExpr(_), _)
|
||||||
| (ast::Expr::BlockExpr(_), _)
|
| (ast::Expr::BlockExpr(_), _)
|
||||||
|
| (ast::Expr::EffectExpr(_), _)
|
||||||
| (_, ast::Expr::CallExpr(_))
|
| (_, ast::Expr::CallExpr(_))
|
||||||
| (_, ast::Expr::TupleExpr(_))
|
| (_, ast::Expr::TupleExpr(_))
|
||||||
| (_, ast::Expr::ArrayExpr(_))
|
| (_, ast::Expr::ArrayExpr(_))
|
||||||
|
|
|
@ -111,7 +111,7 @@ fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> {
|
||||||
/// expression like a lambda or match arm.
|
/// expression like a lambda or match arm.
|
||||||
fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
|
fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
|
||||||
expr.syntax().ancestors().find_map(|node| {
|
expr.syntax().ancestors().find_map(|node| {
|
||||||
if let Some(expr) = node.parent().and_then(ast::Block::cast).and_then(|it| it.expr()) {
|
if let Some(expr) = node.parent().and_then(ast::BlockExpr::cast).and_then(|it| it.expr()) {
|
||||||
if expr.syntax() == &node {
|
if expr.syntax() == &node {
|
||||||
tested_by!(test_introduce_var_last_expr);
|
tested_by!(test_introduce_var_last_expr);
|
||||||
return Some((node, false));
|
return Some((node, false));
|
||||||
|
|
|
@ -113,9 +113,9 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> {
|
||||||
"Move condition to match guard",
|
"Move condition to match guard",
|
||||||
|edit| {
|
|edit| {
|
||||||
edit.target(if_expr.syntax().text_range());
|
edit.target(if_expr.syntax().text_range());
|
||||||
let then_only_expr = then_block.block().and_then(|it| it.statements().next()).is_none();
|
let then_only_expr = then_block.statements().next().is_none();
|
||||||
|
|
||||||
match &then_block.block().and_then(|it| it.expr()) {
|
match &then_block.expr() {
|
||||||
Some(then_expr) if then_only_expr => {
|
Some(then_expr) if then_only_expr => {
|
||||||
edit.replace(if_expr.syntax().text_range(), then_expr.syntax().text())
|
edit.replace(if_expr.syntax().text_range(), then_expr.syntax().text())
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,6 @@ pub fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
|
pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
|
||||||
let block = block.block()?;
|
|
||||||
let has_anything_else = |thing: &SyntaxNode| -> bool {
|
let has_anything_else = |thing: &SyntaxNode| -> bool {
|
||||||
let mut non_trivial_children =
|
let mut non_trivial_children =
|
||||||
block.syntax().children_with_tokens().filter(|it| match it.kind() {
|
block.syntax().children_with_tokens().filter(|it| match it.kind() {
|
||||||
|
|
|
@ -203,10 +203,16 @@ impl ExprCollector<'_> {
|
||||||
|
|
||||||
self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
|
self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
|
||||||
}
|
}
|
||||||
ast::Expr::TryBlockExpr(e) => {
|
ast::Expr::EffectExpr(e) => match e.effect() {
|
||||||
let body = self.collect_block_opt(e.body());
|
ast::Effect::Try(_) => {
|
||||||
|
let body = self.collect_block_opt(e.block_expr());
|
||||||
self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
|
self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
|
||||||
}
|
}
|
||||||
|
// FIXME: we need to record these effects somewhere...
|
||||||
|
ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => {
|
||||||
|
self.collect_block_opt(e.block_expr())
|
||||||
|
}
|
||||||
|
},
|
||||||
ast::Expr::BlockExpr(e) => self.collect_block(e),
|
ast::Expr::BlockExpr(e) => self.collect_block(e),
|
||||||
ast::Expr::LoopExpr(e) => {
|
ast::Expr::LoopExpr(e) => {
|
||||||
let body = self.collect_block_opt(e.loop_body());
|
let body = self.collect_block_opt(e.loop_body());
|
||||||
|
@ -494,12 +500,8 @@ impl ExprCollector<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId {
|
fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
|
||||||
let syntax_node_ptr = AstPtr::new(&expr.clone().into());
|
let syntax_node_ptr = AstPtr::new(&block.clone().into());
|
||||||
let block = match expr.block() {
|
|
||||||
Some(block) => block,
|
|
||||||
None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
|
|
||||||
};
|
|
||||||
self.collect_block_items(&block);
|
self.collect_block_items(&block);
|
||||||
let statements = block
|
let statements = block
|
||||||
.statements()
|
.statements()
|
||||||
|
@ -517,7 +519,7 @@ impl ExprCollector<'_> {
|
||||||
self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
|
self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_block_items(&mut self, block: &ast::Block) {
|
fn collect_block_items(&mut self, block: &ast::BlockExpr) {
|
||||||
let container = ContainerId::DefWithBodyId(self.def);
|
let container = ContainerId::DefWithBodyId(self.def);
|
||||||
for item in block.items() {
|
for item in block.items() {
|
||||||
let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
|
let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
|
||||||
|
|
|
@ -330,7 +330,7 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
|
||||||
FragmentKind::Expr
|
FragmentKind::Expr
|
||||||
}
|
}
|
||||||
// FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that
|
// FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that
|
||||||
EXPR_STMT | BLOCK => FragmentKind::Expr,
|
EXPR_STMT | BLOCK_EXPR => FragmentKind::Expr,
|
||||||
ARG_LIST => FragmentKind::Expr,
|
ARG_LIST => FragmentKind::Expr,
|
||||||
TRY_EXPR => FragmentKind::Expr,
|
TRY_EXPR => FragmentKind::Expr,
|
||||||
TUPLE_EXPR => FragmentKind::Expr,
|
TUPLE_EXPR => FragmentKind::Expr,
|
||||||
|
@ -342,7 +342,6 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
|
||||||
CONDITION => FragmentKind::Expr,
|
CONDITION => FragmentKind::Expr,
|
||||||
BREAK_EXPR => FragmentKind::Expr,
|
BREAK_EXPR => FragmentKind::Expr,
|
||||||
RETURN_EXPR => FragmentKind::Expr,
|
RETURN_EXPR => FragmentKind::Expr,
|
||||||
BLOCK_EXPR => FragmentKind::Expr,
|
|
||||||
MATCH_EXPR => FragmentKind::Expr,
|
MATCH_EXPR => FragmentKind::Expr,
|
||||||
MATCH_ARM => FragmentKind::Expr,
|
MATCH_ARM => FragmentKind::Expr,
|
||||||
MATCH_GUARD => FragmentKind::Expr,
|
MATCH_GUARD => FragmentKind::Expr,
|
||||||
|
|
|
@ -344,7 +344,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
stmt.syntax().text_range() == name_ref.syntax().text_range(),
|
stmt.syntax().text_range() == name_ref.syntax().text_range(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if let Some(block) = ast::Block::cast(node) {
|
if let Some(block) = ast::BlockExpr::cast(node) {
|
||||||
return Some(
|
return Some(
|
||||||
block.expr().map(|e| e.syntax().text_range())
|
block.expr().map(|e| e.syntax().text_range())
|
||||||
== Some(name_ref.syntax().text_range()),
|
== Some(name_ref.syntax().text_range()),
|
||||||
|
|
|
@ -88,7 +88,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
|
||||||
| ITEM_LIST
|
| ITEM_LIST
|
||||||
| EXTERN_ITEM_LIST
|
| EXTERN_ITEM_LIST
|
||||||
| USE_TREE_LIST
|
| USE_TREE_LIST
|
||||||
| BLOCK
|
| BLOCK_EXPR
|
||||||
| MATCH_ARM_LIST
|
| MATCH_ARM_LIST
|
||||||
| ENUM_VARIANT_LIST
|
| ENUM_VARIANT_LIST
|
||||||
| TOKEN_TREE => Some(FoldKind::Block),
|
| TOKEN_TREE => Some(FoldKind::Block),
|
||||||
|
|
|
@ -129,8 +129,7 @@ fn has_comma_after(node: &SyntaxNode) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> {
|
fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> {
|
||||||
let block = ast::Block::cast(token.parent())?;
|
let block_expr = ast::BlockExpr::cast(token.parent())?;
|
||||||
let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
|
|
||||||
if !block_expr.is_standalone() {
|
if !block_expr.is_standalone() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,6 @@ SOURCE_FILE@0..11
|
||||||
R_PAREN@7..8 ")"
|
R_PAREN@7..8 ")"
|
||||||
WHITESPACE@8..9 " "
|
WHITESPACE@8..9 " "
|
||||||
BLOCK_EXPR@9..11
|
BLOCK_EXPR@9..11
|
||||||
BLOCK@9..11
|
|
||||||
L_CURLY@9..10 "{"
|
L_CURLY@9..10 "{"
|
||||||
R_CURLY@10..11 "}"
|
R_CURLY@10..11 "}"
|
||||||
"#
|
"#
|
||||||
|
@ -153,7 +152,6 @@ SOURCE_FILE@0..60
|
||||||
R_PAREN@8..9 ")"
|
R_PAREN@8..9 ")"
|
||||||
WHITESPACE@9..10 " "
|
WHITESPACE@9..10 " "
|
||||||
BLOCK_EXPR@10..60
|
BLOCK_EXPR@10..60
|
||||||
BLOCK@10..60
|
|
||||||
L_CURLY@10..11 "{"
|
L_CURLY@10..11 "{"
|
||||||
WHITESPACE@11..16 "\n "
|
WHITESPACE@11..16 "\n "
|
||||||
EXPR_STMT@16..58
|
EXPR_STMT@16..58
|
||||||
|
@ -196,7 +194,6 @@ FN_DEF@0..11
|
||||||
R_PAREN@7..8 ")"
|
R_PAREN@7..8 ")"
|
||||||
WHITESPACE@8..9 " "
|
WHITESPACE@8..9 " "
|
||||||
BLOCK_EXPR@9..11
|
BLOCK_EXPR@9..11
|
||||||
BLOCK@9..11
|
|
||||||
L_CURLY@9..10 "{"
|
L_CURLY@9..10 "{"
|
||||||
R_CURLY@10..11 "}"
|
R_CURLY@10..11 "}"
|
||||||
"#
|
"#
|
||||||
|
@ -265,7 +262,6 @@ SOURCE_FILE@0..12
|
||||||
R_PAREN@7..8 ")"
|
R_PAREN@7..8 ")"
|
||||||
WHITESPACE@8..9 " "
|
WHITESPACE@8..9 " "
|
||||||
BLOCK_EXPR@9..12
|
BLOCK_EXPR@9..12
|
||||||
BLOCK@9..12
|
|
||||||
L_CURLY@9..10 "{"
|
L_CURLY@9..10 "{"
|
||||||
WHITESPACE@10..11 "\n"
|
WHITESPACE@10..11 "\n"
|
||||||
R_CURLY@11..12 "}"
|
R_CURLY@11..12 "}"
|
||||||
|
@ -300,7 +296,6 @@ SOURCE_FILE@0..12
|
||||||
R_PAREN@7..8 ")"
|
R_PAREN@7..8 ")"
|
||||||
WHITESPACE@8..9 " "
|
WHITESPACE@8..9 " "
|
||||||
BLOCK_EXPR@9..12
|
BLOCK_EXPR@9..12
|
||||||
BLOCK@9..12
|
|
||||||
L_CURLY@9..10 "{"
|
L_CURLY@9..10 "{"
|
||||||
WHITESPACE@10..11 "\n"
|
WHITESPACE@10..11 "\n"
|
||||||
R_CURLY@11..12 "}"
|
R_CURLY@11..12 "}"
|
||||||
|
@ -334,7 +329,6 @@ SOURCE_FILE@0..25
|
||||||
R_PAREN@7..8 ")"
|
R_PAREN@7..8 ")"
|
||||||
WHITESPACE@8..9 " "
|
WHITESPACE@8..9 " "
|
||||||
BLOCK_EXPR@9..12
|
BLOCK_EXPR@9..12
|
||||||
BLOCK@9..12
|
|
||||||
L_CURLY@9..10 "{"
|
L_CURLY@9..10 "{"
|
||||||
WHITESPACE@10..11 "\n"
|
WHITESPACE@10..11 "\n"
|
||||||
R_CURLY@11..12 "}"
|
R_CURLY@11..12 "}"
|
||||||
|
@ -349,7 +343,6 @@ SOURCE_FILE@0..25
|
||||||
R_PAREN@20..21 ")"
|
R_PAREN@20..21 ")"
|
||||||
WHITESPACE@21..22 " "
|
WHITESPACE@21..22 " "
|
||||||
BLOCK_EXPR@22..25
|
BLOCK_EXPR@22..25
|
||||||
BLOCK@22..25
|
|
||||||
L_CURLY@22..23 "{"
|
L_CURLY@22..23 "{"
|
||||||
WHITESPACE@23..24 "\n"
|
WHITESPACE@23..24 "\n"
|
||||||
R_CURLY@24..25 "}"
|
R_CURLY@24..25 "}"
|
||||||
|
|
|
@ -266,7 +266,6 @@ fn test_expr_order() {
|
||||||
L_PAREN@5..6 "("
|
L_PAREN@5..6 "("
|
||||||
R_PAREN@6..7 ")"
|
R_PAREN@6..7 ")"
|
||||||
BLOCK_EXPR@7..15
|
BLOCK_EXPR@7..15
|
||||||
BLOCK@7..15
|
|
||||||
L_CURLY@7..8 "{"
|
L_CURLY@7..8 "{"
|
||||||
EXPR_STMT@8..14
|
EXPR_STMT@8..14
|
||||||
BIN_EXPR@8..13
|
BIN_EXPR@8..13
|
||||||
|
@ -1114,7 +1113,6 @@ fn test_vec() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{:#?}", tree).trim(),
|
format!("{:#?}", tree).trim(),
|
||||||
r#"BLOCK_EXPR@0..45
|
r#"BLOCK_EXPR@0..45
|
||||||
BLOCK@0..45
|
|
||||||
L_CURLY@0..1 "{"
|
L_CURLY@0..1 "{"
|
||||||
LET_STMT@1..20
|
LET_STMT@1..20
|
||||||
LET_KW@1..4 "let"
|
LET_KW@1..4 "let"
|
||||||
|
|
|
@ -143,7 +143,7 @@ pub(crate) fn reparser(
|
||||||
parent: Option<SyntaxKind>,
|
parent: Option<SyntaxKind>,
|
||||||
) -> Option<fn(&mut Parser)> {
|
) -> Option<fn(&mut Parser)> {
|
||||||
let res = match node {
|
let res = match node {
|
||||||
BLOCK => expressions::naked_block,
|
BLOCK_EXPR => expressions::block,
|
||||||
RECORD_FIELD_DEF_LIST => items::record_field_def_list,
|
RECORD_FIELD_DEF_LIST => items::record_field_def_list,
|
||||||
RECORD_FIELD_LIST => items::record_field_list,
|
RECORD_FIELD_LIST => items::record_field_list,
|
||||||
ENUM_VARIANT_LIST => items::enum_variant_list,
|
ENUM_VARIANT_LIST => items::enum_variant_list,
|
||||||
|
|
|
@ -59,16 +59,7 @@ pub(crate) fn block(p: &mut Parser) {
|
||||||
p.error("expected a block");
|
p.error("expected a block");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
atom::block_expr(p, None);
|
atom::block_expr(p);
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn naked_block(p: &mut Parser) {
|
|
||||||
assert!(p.at(T!['{']));
|
|
||||||
let m = p.start();
|
|
||||||
p.bump(T!['{']);
|
|
||||||
expr_block_contents(p);
|
|
||||||
p.expect(T!['}']);
|
|
||||||
m.complete(p, BLOCK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool {
|
fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool {
|
||||||
|
@ -197,7 +188,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn expr_block_contents(p: &mut Parser) {
|
pub(super) fn expr_block_contents(p: &mut Parser) {
|
||||||
// This is checked by a validator
|
// This is checked by a validator
|
||||||
attributes::inner_attributes(p);
|
attributes::inner_attributes(p);
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,10 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
|
||||||
T![loop] => loop_expr(p, Some(m)),
|
T![loop] => loop_expr(p, Some(m)),
|
||||||
T![for] => for_expr(p, Some(m)),
|
T![for] => for_expr(p, Some(m)),
|
||||||
T![while] => while_expr(p, Some(m)),
|
T![while] => while_expr(p, Some(m)),
|
||||||
T!['{'] => block_expr(p, Some(m)),
|
T!['{'] => {
|
||||||
|
block_expr(p);
|
||||||
|
m.complete(p, EFFECT_EXPR)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// test_err misplaced_label_err
|
// test_err misplaced_label_err
|
||||||
// fn main() {
|
// fn main() {
|
||||||
|
@ -108,13 +111,15 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
p.bump(T![async]);
|
p.bump(T![async]);
|
||||||
p.eat(T![move]);
|
p.eat(T![move]);
|
||||||
block_expr(p, Some(m))
|
block_expr(p);
|
||||||
|
m.complete(p, EFFECT_EXPR)
|
||||||
}
|
}
|
||||||
T![match] => match_expr(p),
|
T![match] => match_expr(p),
|
||||||
T![unsafe] if la == T!['{'] => {
|
T![unsafe] if la == T!['{'] => {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
p.bump(T![unsafe]);
|
p.bump(T![unsafe]);
|
||||||
block_expr(p, Some(m))
|
block_expr(p);
|
||||||
|
m.complete(p, EFFECT_EXPR)
|
||||||
}
|
}
|
||||||
T!['{'] => {
|
T!['{'] => {
|
||||||
// test for_range_from
|
// test for_range_from
|
||||||
|
@ -123,7 +128,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
block_expr(p, None)
|
block_expr(p)
|
||||||
}
|
}
|
||||||
T![return] => return_expr(p),
|
T![return] => return_expr(p),
|
||||||
T![continue] => continue_expr(p),
|
T![continue] => continue_expr(p),
|
||||||
|
@ -134,7 +139,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let blocklike = match done.kind() {
|
let blocklike = match done.kind() {
|
||||||
IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_BLOCK_EXPR => {
|
IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | EFFECT_EXPR => {
|
||||||
BlockLike::Block
|
BlockLike::Block
|
||||||
}
|
}
|
||||||
_ => BlockLike::NotBlock,
|
_ => BlockLike::NotBlock,
|
||||||
|
@ -234,7 +239,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
|
||||||
if p.at(T!['{']) {
|
if p.at(T!['{']) {
|
||||||
// test lambda_ret_block
|
// test lambda_ret_block
|
||||||
// fn main() { || -> i32 { 92 }(); }
|
// fn main() { || -> i32 { 92 }(); }
|
||||||
block_expr(p, None);
|
block_expr(p);
|
||||||
} else {
|
} else {
|
||||||
p.error("expected `{`");
|
p.error("expected `{`");
|
||||||
}
|
}
|
||||||
|
@ -464,10 +469,12 @@ fn match_guard(p: &mut Parser) -> CompletedMarker {
|
||||||
// unsafe {};
|
// unsafe {};
|
||||||
// 'label: {};
|
// 'label: {};
|
||||||
// }
|
// }
|
||||||
pub(super) fn block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
|
pub(super) fn block_expr(p: &mut Parser) -> CompletedMarker {
|
||||||
assert!(p.at(T!['{']));
|
assert!(p.at(T!['{']));
|
||||||
let m = m.unwrap_or_else(|| p.start());
|
let m = p.start();
|
||||||
naked_block(p);
|
p.bump(T!['{']);
|
||||||
|
expr_block_contents(p);
|
||||||
|
p.expect(T!['}']);
|
||||||
m.complete(p, BLOCK_EXPR)
|
m.complete(p, BLOCK_EXPR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,8 +559,8 @@ fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
|
||||||
}
|
}
|
||||||
|
|
||||||
p.bump(T![try]);
|
p.bump(T![try]);
|
||||||
block(p);
|
block_expr(p);
|
||||||
m.complete(p, TRY_EXPR)
|
m.complete(p, EFFECT_EXPR)
|
||||||
}
|
}
|
||||||
|
|
||||||
// test box_expr
|
// test box_expr
|
||||||
|
|
|
@ -191,7 +191,7 @@ pub enum SyntaxKind {
|
||||||
RECORD_LIT,
|
RECORD_LIT,
|
||||||
RECORD_FIELD_LIST,
|
RECORD_FIELD_LIST,
|
||||||
RECORD_FIELD,
|
RECORD_FIELD,
|
||||||
TRY_BLOCK_EXPR,
|
EFFECT_EXPR,
|
||||||
BOX_EXPR,
|
BOX_EXPR,
|
||||||
CALL_EXPR,
|
CALL_EXPR,
|
||||||
INDEX_EXPR,
|
INDEX_EXPR,
|
||||||
|
@ -204,7 +204,6 @@ pub enum SyntaxKind {
|
||||||
PREFIX_EXPR,
|
PREFIX_EXPR,
|
||||||
RANGE_EXPR,
|
RANGE_EXPR,
|
||||||
BIN_EXPR,
|
BIN_EXPR,
|
||||||
BLOCK,
|
|
||||||
EXTERN_BLOCK,
|
EXTERN_BLOCK,
|
||||||
EXTERN_ITEM_LIST,
|
EXTERN_ITEM_LIST,
|
||||||
ENUM_VARIANT,
|
ENUM_VARIANT,
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
|
expr_extensions::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp},
|
||||||
extensions::{
|
extensions::{
|
||||||
AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
|
AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
|
||||||
StructKind, TypeBoundKind, VisibilityKind,
|
StructKind, TypeBoundKind, VisibilityKind,
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl ast::BinExpr {
|
||||||
|
|
||||||
impl ast::FnDef {
|
impl ast::FnDef {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_body(&self, body: ast::Block) -> ast::FnDef {
|
pub fn with_body(&self, body: ast::BlockExpr) -> ast::FnDef {
|
||||||
let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
|
let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
|
||||||
let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() {
|
let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() {
|
||||||
old_body.syntax().clone().into()
|
old_body.syntax().clone().into()
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl ast::Expr {
|
||||||
| ast::Expr::WhileExpr(_)
|
| ast::Expr::WhileExpr(_)
|
||||||
| ast::Expr::BlockExpr(_)
|
| ast::Expr::BlockExpr(_)
|
||||||
| ast::Expr::MatchExpr(_)
|
| ast::Expr::MatchExpr(_)
|
||||||
| ast::Expr::TryBlockExpr(_) => true,
|
| ast::Expr::EffectExpr(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,6 +359,33 @@ impl ast::Literal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum Effect {
|
||||||
|
Async(SyntaxToken),
|
||||||
|
Unsafe(SyntaxToken),
|
||||||
|
Try(SyntaxToken),
|
||||||
|
// Very much not an effect, but we stuff it into this node anyway
|
||||||
|
Label(ast::Label),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ast::EffectExpr {
|
||||||
|
pub fn effect(&self) -> Effect {
|
||||||
|
if let Some(token) = self.async_token() {
|
||||||
|
return Effect::Async(token);
|
||||||
|
}
|
||||||
|
if let Some(token) = self.unsafe_token() {
|
||||||
|
return Effect::Unsafe(token);
|
||||||
|
}
|
||||||
|
if let Some(token) = self.try_token() {
|
||||||
|
return Effect::Try(token);
|
||||||
|
}
|
||||||
|
if let Some(label) = self.label() {
|
||||||
|
return Effect::Label(label);
|
||||||
|
}
|
||||||
|
unreachable!("ast::EffectExpr without Effect")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ast::BlockExpr {
|
impl ast::BlockExpr {
|
||||||
/// false if the block is an intrinsic part of the syntax and can't be
|
/// false if the block is an intrinsic part of the syntax and can't be
|
||||||
/// replaced with arbitrary expression.
|
/// replaced with arbitrary expression.
|
||||||
|
@ -368,15 +395,12 @@ impl ast::BlockExpr {
|
||||||
/// const FOO: () = { stand_alone };
|
/// const FOO: () = { stand_alone };
|
||||||
/// ```
|
/// ```
|
||||||
pub fn is_standalone(&self) -> bool {
|
pub fn is_standalone(&self) -> bool {
|
||||||
if self.unsafe_token().is_some() || self.async_token().is_some() {
|
let parent = match self.syntax().parent() {
|
||||||
return false;
|
Some(it) => it,
|
||||||
}
|
|
||||||
let kind = match self.syntax().parent() {
|
|
||||||
None => return true,
|
None => return true,
|
||||||
Some(it) => it.kind(),
|
|
||||||
};
|
};
|
||||||
match kind {
|
match parent.kind() {
|
||||||
FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | TRY_BLOCK_EXPR => false,
|
FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR => false,
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,13 +476,16 @@ impl LoopExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct TryBlockExpr {
|
pub struct EffectExpr {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
}
|
}
|
||||||
impl ast::AttrsOwner for TryBlockExpr {}
|
impl ast::AttrsOwner for EffectExpr {}
|
||||||
impl TryBlockExpr {
|
impl EffectExpr {
|
||||||
|
pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
|
||||||
pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
|
pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
|
||||||
pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
|
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
|
||||||
|
pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
|
||||||
|
pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -551,11 +554,12 @@ pub struct BlockExpr {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
}
|
}
|
||||||
impl ast::AttrsOwner for BlockExpr {}
|
impl ast::AttrsOwner for BlockExpr {}
|
||||||
|
impl ast::ModuleItemOwner for BlockExpr {}
|
||||||
impl BlockExpr {
|
impl BlockExpr {
|
||||||
pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
|
pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
|
||||||
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
|
pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
|
||||||
pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
|
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
||||||
pub fn block(&self) -> Option<Block> { support::child(&self.syntax) }
|
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -627,8 +631,8 @@ pub struct TryExpr {
|
||||||
}
|
}
|
||||||
impl ast::AttrsOwner for TryExpr {}
|
impl ast::AttrsOwner for TryExpr {}
|
||||||
impl TryExpr {
|
impl TryExpr {
|
||||||
pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
|
|
||||||
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
||||||
|
pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -1121,19 +1125,6 @@ impl Condition {
|
||||||
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub struct Block {
|
|
||||||
pub(crate) syntax: SyntaxNode,
|
|
||||||
}
|
|
||||||
impl ast::AttrsOwner for Block {}
|
|
||||||
impl ast::ModuleItemOwner for Block {}
|
|
||||||
impl Block {
|
|
||||||
pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
|
|
||||||
pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
|
|
||||||
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
|
||||||
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ParamList {
|
pub struct ParamList {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
@ -1477,7 +1468,7 @@ pub enum Expr {
|
||||||
FieldExpr(FieldExpr),
|
FieldExpr(FieldExpr),
|
||||||
AwaitExpr(AwaitExpr),
|
AwaitExpr(AwaitExpr),
|
||||||
TryExpr(TryExpr),
|
TryExpr(TryExpr),
|
||||||
TryBlockExpr(TryBlockExpr),
|
EffectExpr(EffectExpr),
|
||||||
CastExpr(CastExpr),
|
CastExpr(CastExpr),
|
||||||
RefExpr(RefExpr),
|
RefExpr(RefExpr),
|
||||||
PrefixExpr(PrefixExpr),
|
PrefixExpr(PrefixExpr),
|
||||||
|
@ -1960,8 +1951,8 @@ impl AstNode for LoopExpr {
|
||||||
}
|
}
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
}
|
}
|
||||||
impl AstNode for TryBlockExpr {
|
impl AstNode for EffectExpr {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_BLOCK_EXPR }
|
fn can_cast(kind: SyntaxKind) -> bool { kind == EFFECT_EXPR }
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
if Self::can_cast(syntax.kind()) {
|
if Self::can_cast(syntax.kind()) {
|
||||||
Some(Self { syntax })
|
Some(Self { syntax })
|
||||||
|
@ -2653,17 +2644,6 @@ impl AstNode for Condition {
|
||||||
}
|
}
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
}
|
}
|
||||||
impl AstNode for Block {
|
|
||||||
fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK }
|
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
|
||||||
if Self::can_cast(syntax.kind()) {
|
|
||||||
Some(Self { syntax })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
|
||||||
}
|
|
||||||
impl AstNode for ParamList {
|
impl AstNode for ParamList {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
|
fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
|
@ -3312,8 +3292,8 @@ impl From<AwaitExpr> for Expr {
|
||||||
impl From<TryExpr> for Expr {
|
impl From<TryExpr> for Expr {
|
||||||
fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
|
fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
|
||||||
}
|
}
|
||||||
impl From<TryBlockExpr> for Expr {
|
impl From<EffectExpr> for Expr {
|
||||||
fn from(node: TryBlockExpr) -> Expr { Expr::TryBlockExpr(node) }
|
fn from(node: EffectExpr) -> Expr { Expr::EffectExpr(node) }
|
||||||
}
|
}
|
||||||
impl From<CastExpr> for Expr {
|
impl From<CastExpr> for Expr {
|
||||||
fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) }
|
fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) }
|
||||||
|
@ -3345,9 +3325,10 @@ impl AstNode for Expr {
|
||||||
TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR
|
TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR
|
||||||
| LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL
|
| LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL
|
||||||
| BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR
|
| BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR
|
||||||
| METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR
|
| METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | EFFECT_EXPR | CAST_EXPR
|
||||||
| CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL
|
| REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL | BOX_EXPR => {
|
||||||
| BOX_EXPR => true,
|
true
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3375,7 +3356,7 @@ impl AstNode for Expr {
|
||||||
FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }),
|
FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }),
|
||||||
AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }),
|
AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }),
|
||||||
TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
|
TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
|
||||||
TRY_BLOCK_EXPR => Expr::TryBlockExpr(TryBlockExpr { syntax }),
|
EFFECT_EXPR => Expr::EffectExpr(EffectExpr { syntax }),
|
||||||
CAST_EXPR => Expr::CastExpr(CastExpr { syntax }),
|
CAST_EXPR => Expr::CastExpr(CastExpr { syntax }),
|
||||||
REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
|
REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
|
||||||
PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }),
|
PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }),
|
||||||
|
@ -3412,7 +3393,7 @@ impl AstNode for Expr {
|
||||||
Expr::FieldExpr(it) => &it.syntax,
|
Expr::FieldExpr(it) => &it.syntax,
|
||||||
Expr::AwaitExpr(it) => &it.syntax,
|
Expr::AwaitExpr(it) => &it.syntax,
|
||||||
Expr::TryExpr(it) => &it.syntax,
|
Expr::TryExpr(it) => &it.syntax,
|
||||||
Expr::TryBlockExpr(it) => &it.syntax,
|
Expr::EffectExpr(it) => &it.syntax,
|
||||||
Expr::CastExpr(it) => &it.syntax,
|
Expr::CastExpr(it) => &it.syntax,
|
||||||
Expr::RefExpr(it) => &it.syntax,
|
Expr::RefExpr(it) => &it.syntax,
|
||||||
Expr::PrefixExpr(it) => &it.syntax,
|
Expr::PrefixExpr(it) => &it.syntax,
|
||||||
|
@ -3893,7 +3874,7 @@ impl std::fmt::Display for LoopExpr {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for TryBlockExpr {
|
impl std::fmt::Display for EffectExpr {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
|
@ -4208,11 +4189,6 @@ impl std::fmt::Display for Condition {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for Block {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::fmt::Display for ParamList {
|
impl std::fmt::Display for ParamList {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
|
|
@ -82,10 +82,10 @@ pub fn block_expr(
|
||||||
ast_from_text(&format!("fn f() {}", buf))
|
ast_from_text(&format!("fn f() {}", buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_from_expr(e: ast::Expr) -> ast::Block {
|
pub fn block_from_expr(e: ast::Expr) -> ast::BlockExpr {
|
||||||
return from_text(&format!("{{ {} }}", e));
|
return from_text(&format!("{{ {} }}", e));
|
||||||
|
|
||||||
fn from_text(text: &str) -> ast::Block {
|
fn from_text(text: &str) -> ast::BlockExpr {
|
||||||
ast_from_text(&format!("fn f() {}", text))
|
ast_from_text(&format!("fn f() {}", text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,8 +237,7 @@ fn api_walkthrough() {
|
||||||
|
|
||||||
// Let's get the `1 + 1` expression!
|
// Let's get the `1 + 1` expression!
|
||||||
let body: ast::BlockExpr = func.body().unwrap();
|
let body: ast::BlockExpr = func.body().unwrap();
|
||||||
let block = body.block().unwrap();
|
let expr: ast::Expr = body.expr().unwrap();
|
||||||
let expr: ast::Expr = block.expr().unwrap();
|
|
||||||
|
|
||||||
// Enums are used to group related ast nodes together, and can be used for
|
// Enums are used to group related ast nodes together, and can be used for
|
||||||
// matching. However, because there are no public fields, it's possible to
|
// matching. However, because there are no public fields, it's possible to
|
||||||
|
@ -274,8 +273,8 @@ fn api_walkthrough() {
|
||||||
assert_eq!(text.to_string(), "1 + 1");
|
assert_eq!(text.to_string(), "1 + 1");
|
||||||
|
|
||||||
// There's a bunch of traversal methods on `SyntaxNode`:
|
// There's a bunch of traversal methods on `SyntaxNode`:
|
||||||
assert_eq!(expr_syntax.parent().as_ref(), Some(block.syntax()));
|
assert_eq!(expr_syntax.parent().as_ref(), Some(body.syntax()));
|
||||||
assert_eq!(block.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{']));
|
assert_eq!(body.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{']));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expr_syntax.next_sibling_or_token().map(|it| it.kind()),
|
expr_syntax.next_sibling_or_token().map(|it| it.kind()),
|
||||||
Some(SyntaxKind::WHITESPACE)
|
Some(SyntaxKind::WHITESPACE)
|
||||||
|
|
|
@ -6,19 +6,17 @@ use crate::{
|
||||||
SyntaxKind::*,
|
SyntaxKind::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn validate_block_expr(expr: ast::BlockExpr, errors: &mut Vec<SyntaxError>) {
|
pub(crate) fn validate_block_expr(block: ast::BlockExpr, errors: &mut Vec<SyntaxError>) {
|
||||||
if let Some(parent) = expr.syntax().parent() {
|
if let Some(parent) = block.syntax().parent() {
|
||||||
match parent.kind() {
|
match parent.kind() {
|
||||||
FN_DEF | EXPR_STMT | BLOCK => return,
|
FN_DEF | EXPR_STMT | BLOCK_EXPR => return,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(block) = expr.block() {
|
|
||||||
errors.extend(block.attrs().map(|attr| {
|
errors.extend(block.attrs().map(|attr| {
|
||||||
SyntaxError::new(
|
SyntaxError::new(
|
||||||
"A block in this position cannot accept inner attributes",
|
"A block in this position cannot accept inner attributes",
|
||||||
attr.syntax().text_range(),
|
attr.syntax().text_range(),
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
|
||||||
"RECORD_LIT",
|
"RECORD_LIT",
|
||||||
"RECORD_FIELD_LIST",
|
"RECORD_FIELD_LIST",
|
||||||
"RECORD_FIELD",
|
"RECORD_FIELD",
|
||||||
"TRY_BLOCK_EXPR",
|
"EFFECT_EXPR",
|
||||||
"BOX_EXPR",
|
"BOX_EXPR",
|
||||||
// postfix
|
// postfix
|
||||||
"CALL_EXPR",
|
"CALL_EXPR",
|
||||||
|
@ -177,7 +177,6 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
|
||||||
"PREFIX_EXPR",
|
"PREFIX_EXPR",
|
||||||
"RANGE_EXPR", // just weird
|
"RANGE_EXPR", // just weird
|
||||||
"BIN_EXPR",
|
"BIN_EXPR",
|
||||||
"BLOCK",
|
|
||||||
"EXTERN_BLOCK",
|
"EXTERN_BLOCK",
|
||||||
"EXTERN_ITEM_LIST",
|
"EXTERN_ITEM_LIST",
|
||||||
"ENUM_VARIANT",
|
"ENUM_VARIANT",
|
||||||
|
@ -440,7 +439,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
}
|
}
|
||||||
struct IfExpr: AttrsOwner { T![if], Condition }
|
struct IfExpr: AttrsOwner { T![if], Condition }
|
||||||
struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] }
|
struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] }
|
||||||
struct TryBlockExpr: AttrsOwner { T![try], body: BlockExpr }
|
struct EffectExpr: AttrsOwner { Label, T![try], T![unsafe], T![async], BlockExpr }
|
||||||
struct ForExpr: AttrsOwner, LoopBodyOwner {
|
struct ForExpr: AttrsOwner, LoopBodyOwner {
|
||||||
T![for],
|
T![for],
|
||||||
Pat,
|
Pat,
|
||||||
|
@ -451,7 +450,9 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] }
|
struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] }
|
||||||
struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr }
|
struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr }
|
||||||
struct Label { T![lifetime] }
|
struct Label { T![lifetime] }
|
||||||
struct BlockExpr: AttrsOwner { Label, T![unsafe], T![async], Block }
|
struct BlockExpr: AttrsOwner, ModuleItemOwner {
|
||||||
|
T!['{'], statements: [Stmt], Expr, T!['}'],
|
||||||
|
}
|
||||||
struct ReturnExpr: AttrsOwner { Expr }
|
struct ReturnExpr: AttrsOwner { Expr }
|
||||||
struct CallExpr: ArgListOwner { Expr }
|
struct CallExpr: ArgListOwner { Expr }
|
||||||
struct MethodCallExpr: AttrsOwner, ArgListOwner {
|
struct MethodCallExpr: AttrsOwner, ArgListOwner {
|
||||||
|
@ -460,7 +461,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
struct IndexExpr: AttrsOwner { T!['['], T![']'] }
|
struct IndexExpr: AttrsOwner { T!['['], T![']'] }
|
||||||
struct FieldExpr: AttrsOwner { Expr, T![.], NameRef }
|
struct FieldExpr: AttrsOwner { Expr, T![.], NameRef }
|
||||||
struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] }
|
struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] }
|
||||||
struct TryExpr: AttrsOwner { T![try], Expr }
|
struct TryExpr: AttrsOwner { Expr, T![?] }
|
||||||
struct CastExpr: AttrsOwner { Expr, T![as], TypeRef }
|
struct CastExpr: AttrsOwner { Expr, T![as], TypeRef }
|
||||||
struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr }
|
struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr }
|
||||||
struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr }
|
struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr }
|
||||||
|
@ -556,12 +557,6 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
T![;],
|
T![;],
|
||||||
}
|
}
|
||||||
struct Condition { T![let], Pat, T![=], Expr }
|
struct Condition { T![let], Pat, T![=], Expr }
|
||||||
struct Block: AttrsOwner, ModuleItemOwner {
|
|
||||||
T!['{'],
|
|
||||||
statements: [Stmt],
|
|
||||||
Expr,
|
|
||||||
T!['}'],
|
|
||||||
}
|
|
||||||
struct ParamList {
|
struct ParamList {
|
||||||
T!['('],
|
T!['('],
|
||||||
SelfParam,
|
SelfParam,
|
||||||
|
@ -722,7 +717,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
FieldExpr,
|
FieldExpr,
|
||||||
AwaitExpr,
|
AwaitExpr,
|
||||||
TryExpr,
|
TryExpr,
|
||||||
TryBlockExpr,
|
EffectExpr,
|
||||||
CastExpr,
|
CastExpr,
|
||||||
RefExpr,
|
RefExpr,
|
||||||
PrefixExpr,
|
PrefixExpr,
|
||||||
|
|
|
@ -432,6 +432,7 @@ impl Field<'_> {
|
||||||
":" => "colon",
|
":" => "colon",
|
||||||
"::" => "coloncolon",
|
"::" => "coloncolon",
|
||||||
"#" => "pound",
|
"#" => "pound",
|
||||||
|
"?" => "question_mark",
|
||||||
_ => name,
|
_ => name,
|
||||||
};
|
};
|
||||||
format_ident!("{}_token", name)
|
format_ident!("{}_token", name)
|
||||||
|
|
Loading…
Reference in a new issue