mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
Introduce EffectExpr
This commit is contained in:
parent
3c96de5380
commit
4f2134cc33
25 changed files with 242 additions and 261 deletions
|
@ -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,19 +6,17 @@ 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",
|
||||
attr.syntax().text_range(),
|
||||
)
|
||||
}))
|
||||
}
|
||||
errors.extend(block.attrs().map(|attr| {
|
||||
SyntaxError::new(
|
||||
"A block in this position cannot accept inner attributes",
|
||||
attr.syntax().text_range(),
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue