mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +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::{
|
||||
algo::replace_children,
|
||||
ast::{self, edit::IndentLevel, make, Block, Pat::TupleStructPat},
|
||||
ast::{self, edit::IndentLevel, make},
|
||||
AstNode,
|
||||
SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE},
|
||||
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.
|
||||
let if_let_pat = match cond.pat() {
|
||||
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()?;
|
||||
match path.qualifier() {
|
||||
None => {
|
||||
|
@ -61,9 +61,9 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
|
|||
};
|
||||
|
||||
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() {
|
||||
return None;
|
||||
|
@ -80,7 +80,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
|
|||
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() {
|
||||
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.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);
|
||||
|
||||
fn replace(
|
||||
new_expr: &SyntaxNode,
|
||||
then_block: &Block,
|
||||
parent_block: &Block,
|
||||
then_block: &ast::BlockExpr,
|
||||
parent_block: &ast::BlockExpr,
|
||||
if_expr: &ast::IfExpr,
|
||||
) -> SyntaxNode {
|
||||
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::PathExpr(_), _)
|
||||
| (ast::Expr::BlockExpr(_), _)
|
||||
| (ast::Expr::EffectExpr(_), _)
|
||||
| (_, ast::Expr::CallExpr(_))
|
||||
| (_, ast::Expr::TupleExpr(_))
|
||||
| (_, ast::Expr::ArrayExpr(_))
|
||||
|
|
|
@ -111,7 +111,7 @@ fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> {
|
|||
/// expression like a lambda or match arm.
|
||||
fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
|
||||
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 {
|
||||
tested_by!(test_introduce_var_last_expr);
|
||||
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",
|
||||
|edit| {
|
||||
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 => {
|
||||
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> {
|
||||
let block = block.block()?;
|
||||
let has_anything_else = |thing: &SyntaxNode| -> bool {
|
||||
let mut non_trivial_children =
|
||||
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)
|
||||
}
|
||||
ast::Expr::TryBlockExpr(e) => {
|
||||
let body = self.collect_block_opt(e.body());
|
||||
ast::Expr::EffectExpr(e) => match e.effect() {
|
||||
ast::Effect::Try(_) => {
|
||||
let body = self.collect_block_opt(e.block_expr());
|
||||
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::LoopExpr(e) => {
|
||||
let body = self.collect_block_opt(e.loop_body());
|
||||
|
@ -494,12 +500,8 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId {
|
||||
let syntax_node_ptr = AstPtr::new(&expr.clone().into());
|
||||
let block = match expr.block() {
|
||||
Some(block) => block,
|
||||
None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
|
||||
};
|
||||
fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
|
||||
let syntax_node_ptr = AstPtr::new(&block.clone().into());
|
||||
self.collect_block_items(&block);
|
||||
let statements = block
|
||||
.statements()
|
||||
|
@ -517,7 +519,7 @@ impl ExprCollector<'_> {
|
|||
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);
|
||||
for item in block.items() {
|
||||
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
|
||||
}
|
||||
// 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,
|
||||
TRY_EXPR => FragmentKind::Expr,
|
||||
TUPLE_EXPR => FragmentKind::Expr,
|
||||
|
@ -342,7 +342,6 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
|
|||
CONDITION => FragmentKind::Expr,
|
||||
BREAK_EXPR => FragmentKind::Expr,
|
||||
RETURN_EXPR => FragmentKind::Expr,
|
||||
BLOCK_EXPR => FragmentKind::Expr,
|
||||
MATCH_EXPR => FragmentKind::Expr,
|
||||
MATCH_ARM => FragmentKind::Expr,
|
||||
MATCH_GUARD => FragmentKind::Expr,
|
||||
|
|
|
@ -344,7 +344,7 @@ impl<'a> CompletionContext<'a> {
|
|||
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(
|
||||
block.expr().map(|e| e.syntax().text_range())
|
||||
== Some(name_ref.syntax().text_range()),
|
||||
|
|
|
@ -88,7 +88,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
|
|||
| ITEM_LIST
|
||||
| EXTERN_ITEM_LIST
|
||||
| USE_TREE_LIST
|
||||
| BLOCK
|
||||
| BLOCK_EXPR
|
||||
| MATCH_ARM_LIST
|
||||
| ENUM_VARIANT_LIST
|
||||
| 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<()> {
|
||||
let block = ast::Block::cast(token.parent())?;
|
||||
let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
|
||||
let block_expr = ast::BlockExpr::cast(token.parent())?;
|
||||
if !block_expr.is_standalone() {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,6 @@ SOURCE_FILE@0..11
|
|||
R_PAREN@7..8 ")"
|
||||
WHITESPACE@8..9 " "
|
||||
BLOCK_EXPR@9..11
|
||||
BLOCK@9..11
|
||||
L_CURLY@9..10 "{"
|
||||
R_CURLY@10..11 "}"
|
||||
"#
|
||||
|
@ -153,7 +152,6 @@ SOURCE_FILE@0..60
|
|||
R_PAREN@8..9 ")"
|
||||
WHITESPACE@9..10 " "
|
||||
BLOCK_EXPR@10..60
|
||||
BLOCK@10..60
|
||||
L_CURLY@10..11 "{"
|
||||
WHITESPACE@11..16 "\n "
|
||||
EXPR_STMT@16..58
|
||||
|
@ -196,7 +194,6 @@ FN_DEF@0..11
|
|||
R_PAREN@7..8 ")"
|
||||
WHITESPACE@8..9 " "
|
||||
BLOCK_EXPR@9..11
|
||||
BLOCK@9..11
|
||||
L_CURLY@9..10 "{"
|
||||
R_CURLY@10..11 "}"
|
||||
"#
|
||||
|
@ -265,7 +262,6 @@ SOURCE_FILE@0..12
|
|||
R_PAREN@7..8 ")"
|
||||
WHITESPACE@8..9 " "
|
||||
BLOCK_EXPR@9..12
|
||||
BLOCK@9..12
|
||||
L_CURLY@9..10 "{"
|
||||
WHITESPACE@10..11 "\n"
|
||||
R_CURLY@11..12 "}"
|
||||
|
@ -300,7 +296,6 @@ SOURCE_FILE@0..12
|
|||
R_PAREN@7..8 ")"
|
||||
WHITESPACE@8..9 " "
|
||||
BLOCK_EXPR@9..12
|
||||
BLOCK@9..12
|
||||
L_CURLY@9..10 "{"
|
||||
WHITESPACE@10..11 "\n"
|
||||
R_CURLY@11..12 "}"
|
||||
|
@ -334,7 +329,6 @@ SOURCE_FILE@0..25
|
|||
R_PAREN@7..8 ")"
|
||||
WHITESPACE@8..9 " "
|
||||
BLOCK_EXPR@9..12
|
||||
BLOCK@9..12
|
||||
L_CURLY@9..10 "{"
|
||||
WHITESPACE@10..11 "\n"
|
||||
R_CURLY@11..12 "}"
|
||||
|
@ -349,7 +343,6 @@ SOURCE_FILE@0..25
|
|||
R_PAREN@20..21 ")"
|
||||
WHITESPACE@21..22 " "
|
||||
BLOCK_EXPR@22..25
|
||||
BLOCK@22..25
|
||||
L_CURLY@22..23 "{"
|
||||
WHITESPACE@23..24 "\n"
|
||||
R_CURLY@24..25 "}"
|
||||
|
|
|
@ -266,7 +266,6 @@ fn test_expr_order() {
|
|||
L_PAREN@5..6 "("
|
||||
R_PAREN@6..7 ")"
|
||||
BLOCK_EXPR@7..15
|
||||
BLOCK@7..15
|
||||
L_CURLY@7..8 "{"
|
||||
EXPR_STMT@8..14
|
||||
BIN_EXPR@8..13
|
||||
|
@ -1114,7 +1113,6 @@ fn test_vec() {
|
|||
assert_eq!(
|
||||
format!("{:#?}", tree).trim(),
|
||||
r#"BLOCK_EXPR@0..45
|
||||
BLOCK@0..45
|
||||
L_CURLY@0..1 "{"
|
||||
LET_STMT@1..20
|
||||
LET_KW@1..4 "let"
|
||||
|
|
|
@ -143,7 +143,7 @@ pub(crate) fn reparser(
|
|||
parent: Option<SyntaxKind>,
|
||||
) -> Option<fn(&mut Parser)> {
|
||||
let res = match node {
|
||||
BLOCK => expressions::naked_block,
|
||||
BLOCK_EXPR => expressions::block,
|
||||
RECORD_FIELD_DEF_LIST => items::record_field_def_list,
|
||||
RECORD_FIELD_LIST => items::record_field_list,
|
||||
ENUM_VARIANT_LIST => items::enum_variant_list,
|
||||
|
|
|
@ -59,16 +59,7 @@ pub(crate) fn block(p: &mut Parser) {
|
|||
p.error("expected a block");
|
||||
return;
|
||||
}
|
||||
atom::block_expr(p, None);
|
||||
}
|
||||
|
||||
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);
|
||||
atom::block_expr(p);
|
||||
}
|
||||
|
||||
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
|
||||
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![for] => for_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
|
||||
// fn main() {
|
||||
|
@ -108,13 +111,15 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
|
|||
let m = p.start();
|
||||
p.bump(T![async]);
|
||||
p.eat(T![move]);
|
||||
block_expr(p, Some(m))
|
||||
block_expr(p);
|
||||
m.complete(p, EFFECT_EXPR)
|
||||
}
|
||||
T![match] => match_expr(p),
|
||||
T![unsafe] if la == T!['{'] => {
|
||||
let m = p.start();
|
||||
p.bump(T![unsafe]);
|
||||
block_expr(p, Some(m))
|
||||
block_expr(p);
|
||||
m.complete(p, EFFECT_EXPR)
|
||||
}
|
||||
T!['{'] => {
|
||||
// test for_range_from
|
||||
|
@ -123,7 +128,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
|
|||
// break;
|
||||
// }
|
||||
// }
|
||||
block_expr(p, None)
|
||||
block_expr(p)
|
||||
}
|
||||
T![return] => return_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() {
|
||||
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::NotBlock,
|
||||
|
@ -234,7 +239,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
|
|||
if p.at(T!['{']) {
|
||||
// test lambda_ret_block
|
||||
// fn main() { || -> i32 { 92 }(); }
|
||||
block_expr(p, None);
|
||||
block_expr(p);
|
||||
} else {
|
||||
p.error("expected `{`");
|
||||
}
|
||||
|
@ -464,10 +469,12 @@ fn match_guard(p: &mut Parser) -> CompletedMarker {
|
|||
// unsafe {};
|
||||
// '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!['{']));
|
||||
let m = m.unwrap_or_else(|| p.start());
|
||||
naked_block(p);
|
||||
let m = p.start();
|
||||
p.bump(T!['{']);
|
||||
expr_block_contents(p);
|
||||
p.expect(T!['}']);
|
||||
m.complete(p, BLOCK_EXPR)
|
||||
}
|
||||
|
||||
|
@ -552,8 +559,8 @@ fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
|
|||
}
|
||||
|
||||
p.bump(T![try]);
|
||||
block(p);
|
||||
m.complete(p, TRY_EXPR)
|
||||
block_expr(p);
|
||||
m.complete(p, EFFECT_EXPR)
|
||||
}
|
||||
|
||||
// test box_expr
|
||||
|
|
|
@ -191,7 +191,7 @@ pub enum SyntaxKind {
|
|||
RECORD_LIT,
|
||||
RECORD_FIELD_LIST,
|
||||
RECORD_FIELD,
|
||||
TRY_BLOCK_EXPR,
|
||||
EFFECT_EXPR,
|
||||
BOX_EXPR,
|
||||
CALL_EXPR,
|
||||
INDEX_EXPR,
|
||||
|
@ -204,7 +204,6 @@ pub enum SyntaxKind {
|
|||
PREFIX_EXPR,
|
||||
RANGE_EXPR,
|
||||
BIN_EXPR,
|
||||
BLOCK,
|
||||
EXTERN_BLOCK,
|
||||
EXTERN_ITEM_LIST,
|
||||
ENUM_VARIANT,
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub use self::{
|
||||
expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
|
||||
expr_extensions::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp},
|
||||
extensions::{
|
||||
AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
|
||||
StructKind, TypeBoundKind, VisibilityKind,
|
||||
|
|
|
@ -28,7 +28,7 @@ impl ast::BinExpr {
|
|||
|
||||
impl ast::FnDef {
|
||||
#[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 old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() {
|
||||
old_body.syntax().clone().into()
|
||||
|
|
|
@ -16,7 +16,7 @@ impl ast::Expr {
|
|||
| ast::Expr::WhileExpr(_)
|
||||
| ast::Expr::BlockExpr(_)
|
||||
| ast::Expr::MatchExpr(_)
|
||||
| ast::Expr::TryBlockExpr(_) => true,
|
||||
| ast::Expr::EffectExpr(_) => true,
|
||||
_ => 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 {
|
||||
/// false if the block is an intrinsic part of the syntax and can't be
|
||||
/// replaced with arbitrary expression.
|
||||
|
@ -368,15 +395,12 @@ impl ast::BlockExpr {
|
|||
/// const FOO: () = { stand_alone };
|
||||
/// ```
|
||||
pub fn is_standalone(&self) -> bool {
|
||||
if self.unsafe_token().is_some() || self.async_token().is_some() {
|
||||
return false;
|
||||
}
|
||||
let kind = match self.syntax().parent() {
|
||||
let parent = match self.syntax().parent() {
|
||||
Some(it) => it,
|
||||
None => return true,
|
||||
Some(it) => it.kind(),
|
||||
};
|
||||
match kind {
|
||||
FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | TRY_BLOCK_EXPR => false,
|
||||
match parent.kind() {
|
||||
FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -476,13 +476,16 @@ impl LoopExpr {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct TryBlockExpr {
|
||||
pub struct EffectExpr {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl ast::AttrsOwner for TryBlockExpr {}
|
||||
impl TryBlockExpr {
|
||||
impl ast::AttrsOwner for EffectExpr {}
|
||||
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 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)]
|
||||
|
@ -551,11 +554,12 @@ pub struct BlockExpr {
|
|||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl ast::AttrsOwner for BlockExpr {}
|
||||
impl ast::ModuleItemOwner for BlockExpr {}
|
||||
impl BlockExpr {
|
||||
pub fn label(&self) -> Option<Label> { 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(&self) -> Option<Block> { support::child(&self.syntax) }
|
||||
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)]
|
||||
|
@ -627,8 +631,8 @@ pub struct TryExpr {
|
|||
}
|
||||
impl ast::AttrsOwner for 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 question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -1121,19 +1125,6 @@ impl Condition {
|
|||
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)]
|
||||
pub struct ParamList {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
|
@ -1477,7 +1468,7 @@ pub enum Expr {
|
|||
FieldExpr(FieldExpr),
|
||||
AwaitExpr(AwaitExpr),
|
||||
TryExpr(TryExpr),
|
||||
TryBlockExpr(TryBlockExpr),
|
||||
EffectExpr(EffectExpr),
|
||||
CastExpr(CastExpr),
|
||||
RefExpr(RefExpr),
|
||||
PrefixExpr(PrefixExpr),
|
||||
|
@ -1960,8 +1951,8 @@ impl AstNode for LoopExpr {
|
|||
}
|
||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||
}
|
||||
impl AstNode for TryBlockExpr {
|
||||
fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_BLOCK_EXPR }
|
||||
impl AstNode for EffectExpr {
|
||||
fn can_cast(kind: SyntaxKind) -> bool { kind == EFFECT_EXPR }
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
if Self::can_cast(syntax.kind()) {
|
||||
Some(Self { syntax })
|
||||
|
@ -2653,17 +2644,6 @@ impl AstNode for Condition {
|
|||
}
|
||||
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 {
|
||||
fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
|
@ -3312,8 +3292,8 @@ impl From<AwaitExpr> for Expr {
|
|||
impl From<TryExpr> for Expr {
|
||||
fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
|
||||
}
|
||||
impl From<TryBlockExpr> for Expr {
|
||||
fn from(node: TryBlockExpr) -> Expr { Expr::TryBlockExpr(node) }
|
||||
impl From<EffectExpr> for Expr {
|
||||
fn from(node: EffectExpr) -> Expr { Expr::EffectExpr(node) }
|
||||
}
|
||||
impl From<CastExpr> for Expr {
|
||||
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
|
||||
| LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL
|
||||
| BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR
|
||||
| METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR
|
||||
| CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL
|
||||
| BOX_EXPR => true,
|
||||
| METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | EFFECT_EXPR | CAST_EXPR
|
||||
| REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL | BOX_EXPR => {
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -3375,7 +3356,7 @@ impl AstNode for Expr {
|
|||
FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }),
|
||||
AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { 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 }),
|
||||
REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
|
||||
PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }),
|
||||
|
@ -3412,7 +3393,7 @@ impl AstNode for Expr {
|
|||
Expr::FieldExpr(it) => &it.syntax,
|
||||
Expr::AwaitExpr(it) => &it.syntax,
|
||||
Expr::TryExpr(it) => &it.syntax,
|
||||
Expr::TryBlockExpr(it) => &it.syntax,
|
||||
Expr::EffectExpr(it) => &it.syntax,
|
||||
Expr::CastExpr(it) => &it.syntax,
|
||||
Expr::RefExpr(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)
|
||||
}
|
||||
}
|
||||
impl std::fmt::Display for TryBlockExpr {
|
||||
impl std::fmt::Display for EffectExpr {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self.syntax(), f)
|
||||
}
|
||||
|
@ -4208,11 +4189,6 @@ impl std::fmt::Display for Condition {
|
|||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self.syntax(), f)
|
||||
|
|
|
@ -82,10 +82,10 @@ pub fn block_expr(
|
|||
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));
|
||||
|
||||
fn from_text(text: &str) -> ast::Block {
|
||||
fn from_text(text: &str) -> ast::BlockExpr {
|
||||
ast_from_text(&format!("fn f() {}", text))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,8 +237,7 @@ fn api_walkthrough() {
|
|||
|
||||
// Let's get the `1 + 1` expression!
|
||||
let body: ast::BlockExpr = func.body().unwrap();
|
||||
let block = body.block().unwrap();
|
||||
let expr: ast::Expr = block.expr().unwrap();
|
||||
let expr: ast::Expr = body.expr().unwrap();
|
||||
|
||||
// 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
|
||||
|
@ -274,8 +273,8 @@ fn api_walkthrough() {
|
|||
assert_eq!(text.to_string(), "1 + 1");
|
||||
|
||||
// There's a bunch of traversal methods on `SyntaxNode`:
|
||||
assert_eq!(expr_syntax.parent().as_ref(), Some(block.syntax()));
|
||||
assert_eq!(block.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{']));
|
||||
assert_eq!(expr_syntax.parent().as_ref(), Some(body.syntax()));
|
||||
assert_eq!(body.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{']));
|
||||
assert_eq!(
|
||||
expr_syntax.next_sibling_or_token().map(|it| it.kind()),
|
||||
Some(SyntaxKind::WHITESPACE)
|
||||
|
|
|
@ -6,14 +6,13 @@ use crate::{
|
|||
SyntaxKind::*,
|
||||
};
|
||||
|
||||
pub(crate) fn validate_block_expr(expr: ast::BlockExpr, errors: &mut Vec<SyntaxError>) {
|
||||
if let Some(parent) = expr.syntax().parent() {
|
||||
pub(crate) fn validate_block_expr(block: ast::BlockExpr, errors: &mut Vec<SyntaxError>) {
|
||||
if let Some(parent) = block.syntax().parent() {
|
||||
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| {
|
||||
SyntaxError::new(
|
||||
"A block in this position cannot accept inner attributes",
|
||||
|
@ -21,4 +20,3 @@ pub(crate) fn validate_block_expr(expr: ast::BlockExpr, errors: &mut Vec<SyntaxE
|
|||
)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
|
|||
"RECORD_LIT",
|
||||
"RECORD_FIELD_LIST",
|
||||
"RECORD_FIELD",
|
||||
"TRY_BLOCK_EXPR",
|
||||
"EFFECT_EXPR",
|
||||
"BOX_EXPR",
|
||||
// postfix
|
||||
"CALL_EXPR",
|
||||
|
@ -177,7 +177,6 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
|
|||
"PREFIX_EXPR",
|
||||
"RANGE_EXPR", // just weird
|
||||
"BIN_EXPR",
|
||||
"BLOCK",
|
||||
"EXTERN_BLOCK",
|
||||
"EXTERN_ITEM_LIST",
|
||||
"ENUM_VARIANT",
|
||||
|
@ -440,7 +439,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
}
|
||||
struct IfExpr: AttrsOwner { T![if], Condition }
|
||||
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 {
|
||||
T![for],
|
||||
Pat,
|
||||
|
@ -451,7 +450,9 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] }
|
||||
struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr }
|
||||
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 CallExpr: ArgListOwner { Expr }
|
||||
struct MethodCallExpr: AttrsOwner, ArgListOwner {
|
||||
|
@ -460,7 +461,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
struct IndexExpr: AttrsOwner { T!['['], T![']'] }
|
||||
struct FieldExpr: AttrsOwner { Expr, T![.], NameRef }
|
||||
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 RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr }
|
||||
struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr }
|
||||
|
@ -556,12 +557,6 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
T![;],
|
||||
}
|
||||
struct Condition { T![let], Pat, T![=], Expr }
|
||||
struct Block: AttrsOwner, ModuleItemOwner {
|
||||
T!['{'],
|
||||
statements: [Stmt],
|
||||
Expr,
|
||||
T!['}'],
|
||||
}
|
||||
struct ParamList {
|
||||
T!['('],
|
||||
SelfParam,
|
||||
|
@ -722,7 +717,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
FieldExpr,
|
||||
AwaitExpr,
|
||||
TryExpr,
|
||||
TryBlockExpr,
|
||||
EffectExpr,
|
||||
CastExpr,
|
||||
RefExpr,
|
||||
PrefixExpr,
|
||||
|
|
|
@ -432,6 +432,7 @@ impl Field<'_> {
|
|||
":" => "colon",
|
||||
"::" => "coloncolon",
|
||||
"#" => "pound",
|
||||
"?" => "question_mark",
|
||||
_ => name,
|
||||
};
|
||||
format_ident!("{}_token", name)
|
||||
|
|
Loading…
Reference in a new issue