diff options
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/edit.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/expr_extensions.rs | 31 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/extensions.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated/nodes.rs | 83 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 8 | ||||
-rw-r--r-- | crates/ra_syntax/src/lib.rs | 7 | ||||
-rw-r--r-- | crates/ra_syntax/src/parsing/lexer.rs | 37 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 119 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation/block.rs | 20 |
10 files changed, 175 insertions, 138 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 521ca8ab8..1876afe95 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -16,9 +16,7 @@ use crate::{ | |||
16 | }; | 16 | }; |
17 | 17 | ||
18 | pub use self::{ | 18 | pub use self::{ |
19 | expr_extensions::{ | 19 | expr_extensions::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp}, |
20 | ArrayExprKind, BinOp, BlockModifier, ElseBranch, LiteralKind, PrefixOp, RangeOp, | ||
21 | }, | ||
22 | extensions::{ | 20 | extensions::{ |
23 | AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents, | 21 | AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents, |
24 | StructKind, TypeBoundKind, VisibilityKind, | 22 | StructKind, TypeBoundKind, VisibilityKind, |
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 26e4576ff..c507dc683 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -28,7 +28,7 @@ impl ast::BinExpr { | |||
28 | 28 | ||
29 | impl ast::FnDef { | 29 | impl ast::FnDef { |
30 | #[must_use] | 30 | #[must_use] |
31 | pub fn with_body(&self, body: ast::Block) -> ast::FnDef { | 31 | pub fn with_body(&self, body: ast::BlockExpr) -> ast::FnDef { |
32 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); | 32 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); |
33 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { | 33 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { |
34 | old_body.syntax().clone().into() | 34 | old_body.syntax().clone().into() |
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs index 352c0d2c5..7ee36e60c 100644 --- a/crates/ra_syntax/src/ast/expr_extensions.rs +++ b/crates/ra_syntax/src/ast/expr_extensions.rs | |||
@@ -16,7 +16,7 @@ impl ast::Expr { | |||
16 | | ast::Expr::WhileExpr(_) | 16 | | ast::Expr::WhileExpr(_) |
17 | | ast::Expr::BlockExpr(_) | 17 | | ast::Expr::BlockExpr(_) |
18 | | ast::Expr::MatchExpr(_) | 18 | | ast::Expr::MatchExpr(_) |
19 | | ast::Expr::TryExpr(_) => true, | 19 | | ast::Expr::EffectExpr(_) => true, |
20 | _ => false, | 20 | _ => false, |
21 | } | 21 | } |
22 | } | 22 | } |
@@ -359,22 +359,34 @@ impl ast::Literal { | |||
359 | } | 359 | } |
360 | } | 360 | } |
361 | 361 | ||
362 | pub enum BlockModifier { | 362 | #[derive(Debug, Clone, PartialEq, Eq)] |
363 | pub enum Effect { | ||
363 | Async(SyntaxToken), | 364 | Async(SyntaxToken), |
364 | Unsafe(SyntaxToken), | 365 | Unsafe(SyntaxToken), |
366 | Try(SyntaxToken), | ||
367 | // Very much not an effect, but we stuff it into this node anyway | ||
368 | Label(ast::Label), | ||
365 | } | 369 | } |
366 | 370 | ||
367 | impl ast::BlockExpr { | 371 | impl ast::EffectExpr { |
368 | pub fn modifier(&self) -> Option<BlockModifier> { | 372 | pub fn effect(&self) -> Effect { |
369 | if let Some(token) = self.async_token() { | 373 | if let Some(token) = self.async_token() { |
370 | return Some(BlockModifier::Async(token)); | 374 | return Effect::Async(token); |
371 | } | 375 | } |
372 | if let Some(token) = self.unsafe_token() { | 376 | if let Some(token) = self.unsafe_token() { |
373 | return Some(BlockModifier::Unsafe(token)); | 377 | return Effect::Unsafe(token); |
378 | } | ||
379 | if let Some(token) = self.try_token() { | ||
380 | return Effect::Try(token); | ||
381 | } | ||
382 | if let Some(label) = self.label() { | ||
383 | return Effect::Label(label); | ||
374 | } | 384 | } |
375 | None | 385 | unreachable!("ast::EffectExpr without Effect") |
376 | } | 386 | } |
387 | } | ||
377 | 388 | ||
389 | impl ast::BlockExpr { | ||
378 | /// false if the block is an intrinsic part of the syntax and can't be | 390 | /// false if the block is an intrinsic part of the syntax and can't be |
379 | /// replaced with arbitrary expression. | 391 | /// replaced with arbitrary expression. |
380 | /// | 392 | /// |
@@ -383,15 +395,12 @@ impl ast::BlockExpr { | |||
383 | /// const FOO: () = { stand_alone }; | 395 | /// const FOO: () = { stand_alone }; |
384 | /// ``` | 396 | /// ``` |
385 | pub fn is_standalone(&self) -> bool { | 397 | pub fn is_standalone(&self) -> bool { |
386 | if self.modifier().is_some() { | ||
387 | return false; | ||
388 | } | ||
389 | let parent = match self.syntax().parent() { | 398 | let parent = match self.syntax().parent() { |
390 | Some(it) => it, | 399 | Some(it) => it, |
391 | None => return true, | 400 | None => return true, |
392 | }; | 401 | }; |
393 | match parent.kind() { | 402 | match parent.kind() { |
394 | FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR => false, | 403 | FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR => false, |
395 | _ => true, | 404 | _ => true, |
396 | } | 405 | } |
397 | } | 406 | } |
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index d68f1029f..528c873e0 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs | |||
@@ -407,7 +407,7 @@ impl ast::Visibility { | |||
407 | } else if self.super_token().is_some() { | 407 | } else if self.super_token().is_some() { |
408 | VisibilityKind::PubSuper | 408 | VisibilityKind::PubSuper |
409 | } else if self.self_token().is_some() { | 409 | } else if self.self_token().is_some() { |
410 | VisibilityKind::PubSuper | 410 | VisibilityKind::PubSelf |
411 | } else { | 411 | } else { |
412 | VisibilityKind::Pub | 412 | VisibilityKind::Pub |
413 | } | 413 | } |
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 81260680f..5e844d5ae 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs | |||
@@ -476,6 +476,19 @@ impl LoopExpr { | |||
476 | } | 476 | } |
477 | 477 | ||
478 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 478 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
479 | pub struct EffectExpr { | ||
480 | pub(crate) syntax: SyntaxNode, | ||
481 | } | ||
482 | impl ast::AttrsOwner for EffectExpr {} | ||
483 | impl EffectExpr { | ||
484 | pub fn label(&self) -> Option<Label> { support::child(&self.syntax) } | ||
485 | pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } | ||
486 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } | ||
487 | pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } | ||
488 | pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } | ||
489 | } | ||
490 | |||
491 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
479 | pub struct ForExpr { | 492 | pub struct ForExpr { |
480 | pub(crate) syntax: SyntaxNode, | 493 | pub(crate) syntax: SyntaxNode, |
481 | } | 494 | } |
@@ -541,11 +554,12 @@ pub struct BlockExpr { | |||
541 | pub(crate) syntax: SyntaxNode, | 554 | pub(crate) syntax: SyntaxNode, |
542 | } | 555 | } |
543 | impl ast::AttrsOwner for BlockExpr {} | 556 | impl ast::AttrsOwner for BlockExpr {} |
557 | impl ast::ModuleItemOwner for BlockExpr {} | ||
544 | impl BlockExpr { | 558 | impl BlockExpr { |
545 | pub fn label(&self) -> Option<Label> { support::child(&self.syntax) } | 559 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } |
546 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } | 560 | pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } |
547 | pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } | 561 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } |
548 | pub fn block(&self) -> Option<Block> { support::child(&self.syntax) } | 562 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } |
549 | } | 563 | } |
550 | 564 | ||
551 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 565 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -617,8 +631,8 @@ pub struct TryExpr { | |||
617 | } | 631 | } |
618 | impl ast::AttrsOwner for TryExpr {} | 632 | impl ast::AttrsOwner for TryExpr {} |
619 | impl TryExpr { | 633 | impl TryExpr { |
620 | pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } | ||
621 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | 634 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } |
635 | pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) } | ||
622 | } | 636 | } |
623 | 637 | ||
624 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 638 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -1112,19 +1126,6 @@ impl Condition { | |||
1112 | } | 1126 | } |
1113 | 1127 | ||
1114 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1128 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1115 | pub struct Block { | ||
1116 | pub(crate) syntax: SyntaxNode, | ||
1117 | } | ||
1118 | impl ast::AttrsOwner for Block {} | ||
1119 | impl ast::ModuleItemOwner for Block {} | ||
1120 | impl Block { | ||
1121 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
1122 | pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } | ||
1123 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1124 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
1125 | } | ||
1126 | |||
1127 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1128 | pub struct ParamList { | 1129 | pub struct ParamList { |
1129 | pub(crate) syntax: SyntaxNode, | 1130 | pub(crate) syntax: SyntaxNode, |
1130 | } | 1131 | } |
@@ -1241,6 +1242,8 @@ pub struct PathSegment { | |||
1241 | impl PathSegment { | 1242 | impl PathSegment { |
1242 | pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } | 1243 | pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } |
1243 | pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } | 1244 | pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } |
1245 | pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } | ||
1246 | pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) } | ||
1244 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } | 1247 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } |
1245 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | 1248 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } |
1246 | pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } | 1249 | pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } |
@@ -1465,6 +1468,7 @@ pub enum Expr { | |||
1465 | FieldExpr(FieldExpr), | 1468 | FieldExpr(FieldExpr), |
1466 | AwaitExpr(AwaitExpr), | 1469 | AwaitExpr(AwaitExpr), |
1467 | TryExpr(TryExpr), | 1470 | TryExpr(TryExpr), |
1471 | EffectExpr(EffectExpr), | ||
1468 | CastExpr(CastExpr), | 1472 | CastExpr(CastExpr), |
1469 | RefExpr(RefExpr), | 1473 | RefExpr(RefExpr), |
1470 | PrefixExpr(PrefixExpr), | 1474 | PrefixExpr(PrefixExpr), |
@@ -1947,6 +1951,17 @@ impl AstNode for LoopExpr { | |||
1947 | } | 1951 | } |
1948 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1952 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1949 | } | 1953 | } |
1954 | impl AstNode for EffectExpr { | ||
1955 | fn can_cast(kind: SyntaxKind) -> bool { kind == EFFECT_EXPR } | ||
1956 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
1957 | if Self::can_cast(syntax.kind()) { | ||
1958 | Some(Self { syntax }) | ||
1959 | } else { | ||
1960 | None | ||
1961 | } | ||
1962 | } | ||
1963 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
1964 | } | ||
1950 | impl AstNode for ForExpr { | 1965 | impl AstNode for ForExpr { |
1951 | fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR } | 1966 | fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR } |
1952 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1967 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2629,17 +2644,6 @@ impl AstNode for Condition { | |||
2629 | } | 2644 | } |
2630 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2645 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2631 | } | 2646 | } |
2632 | impl AstNode for Block { | ||
2633 | fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK } | ||
2634 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
2635 | if Self::can_cast(syntax.kind()) { | ||
2636 | Some(Self { syntax }) | ||
2637 | } else { | ||
2638 | None | ||
2639 | } | ||
2640 | } | ||
2641 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
2642 | } | ||
2643 | impl AstNode for ParamList { | 2647 | impl AstNode for ParamList { |
2644 | fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST } | 2648 | fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST } |
2645 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2649 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -3288,6 +3292,9 @@ impl From<AwaitExpr> for Expr { | |||
3288 | impl From<TryExpr> for Expr { | 3292 | impl From<TryExpr> for Expr { |
3289 | fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) } | 3293 | fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) } |
3290 | } | 3294 | } |
3295 | impl From<EffectExpr> for Expr { | ||
3296 | fn from(node: EffectExpr) -> Expr { Expr::EffectExpr(node) } | ||
3297 | } | ||
3291 | impl From<CastExpr> for Expr { | 3298 | impl From<CastExpr> for Expr { |
3292 | fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) } | 3299 | fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) } |
3293 | } | 3300 | } |
@@ -3318,8 +3325,10 @@ impl AstNode for Expr { | |||
3318 | TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR | 3325 | TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR |
3319 | | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL | 3326 | | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL |
3320 | | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR | 3327 | | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR |
3321 | | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | CAST_EXPR | REF_EXPR | 3328 | | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | EFFECT_EXPR | CAST_EXPR |
3322 | | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL | BOX_EXPR => true, | 3329 | | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL | BOX_EXPR => { |
3330 | true | ||
3331 | } | ||
3323 | _ => false, | 3332 | _ => false, |
3324 | } | 3333 | } |
3325 | } | 3334 | } |
@@ -3347,6 +3356,7 @@ impl AstNode for Expr { | |||
3347 | FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }), | 3356 | FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }), |
3348 | AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }), | 3357 | AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }), |
3349 | TRY_EXPR => Expr::TryExpr(TryExpr { syntax }), | 3358 | TRY_EXPR => Expr::TryExpr(TryExpr { syntax }), |
3359 | EFFECT_EXPR => Expr::EffectExpr(EffectExpr { syntax }), | ||
3350 | CAST_EXPR => Expr::CastExpr(CastExpr { syntax }), | 3360 | CAST_EXPR => Expr::CastExpr(CastExpr { syntax }), |
3351 | REF_EXPR => Expr::RefExpr(RefExpr { syntax }), | 3361 | REF_EXPR => Expr::RefExpr(RefExpr { syntax }), |
3352 | PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }), | 3362 | PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }), |
@@ -3383,6 +3393,7 @@ impl AstNode for Expr { | |||
3383 | Expr::FieldExpr(it) => &it.syntax, | 3393 | Expr::FieldExpr(it) => &it.syntax, |
3384 | Expr::AwaitExpr(it) => &it.syntax, | 3394 | Expr::AwaitExpr(it) => &it.syntax, |
3385 | Expr::TryExpr(it) => &it.syntax, | 3395 | Expr::TryExpr(it) => &it.syntax, |
3396 | Expr::EffectExpr(it) => &it.syntax, | ||
3386 | Expr::CastExpr(it) => &it.syntax, | 3397 | Expr::CastExpr(it) => &it.syntax, |
3387 | Expr::RefExpr(it) => &it.syntax, | 3398 | Expr::RefExpr(it) => &it.syntax, |
3388 | Expr::PrefixExpr(it) => &it.syntax, | 3399 | Expr::PrefixExpr(it) => &it.syntax, |
@@ -3863,6 +3874,11 @@ impl std::fmt::Display for LoopExpr { | |||
3863 | std::fmt::Display::fmt(self.syntax(), f) | 3874 | std::fmt::Display::fmt(self.syntax(), f) |
3864 | } | 3875 | } |
3865 | } | 3876 | } |
3877 | impl std::fmt::Display for EffectExpr { | ||
3878 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
3879 | std::fmt::Display::fmt(self.syntax(), f) | ||
3880 | } | ||
3881 | } | ||
3866 | impl std::fmt::Display for ForExpr { | 3882 | impl std::fmt::Display for ForExpr { |
3867 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 3883 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
3868 | std::fmt::Display::fmt(self.syntax(), f) | 3884 | std::fmt::Display::fmt(self.syntax(), f) |
@@ -4173,11 +4189,6 @@ impl std::fmt::Display for Condition { | |||
4173 | std::fmt::Display::fmt(self.syntax(), f) | 4189 | std::fmt::Display::fmt(self.syntax(), f) |
4174 | } | 4190 | } |
4175 | } | 4191 | } |
4176 | impl std::fmt::Display for Block { | ||
4177 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
4178 | std::fmt::Display::fmt(self.syntax(), f) | ||
4179 | } | ||
4180 | } | ||
4181 | impl std::fmt::Display for ParamList { | 4192 | impl std::fmt::Display for ParamList { |
4182 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 4193 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
4183 | std::fmt::Display::fmt(self.syntax(), f) | 4194 | std::fmt::Display::fmt(self.syntax(), f) |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 492088353..7b17fef49 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -82,14 +82,6 @@ pub fn block_expr( | |||
82 | ast_from_text(&format!("fn f() {}", buf)) | 82 | ast_from_text(&format!("fn f() {}", buf)) |
83 | } | 83 | } |
84 | 84 | ||
85 | pub fn block_from_expr(e: ast::Expr) -> ast::Block { | ||
86 | return from_text(&format!("{{ {} }}", e)); | ||
87 | |||
88 | fn from_text(text: &str) -> ast::Block { | ||
89 | ast_from_text(&format!("fn f() {}", text)) | ||
90 | } | ||
91 | } | ||
92 | |||
93 | pub fn expr_unit() -> ast::Expr { | 85 | pub fn expr_unit() -> ast::Expr { |
94 | expr_from_text("()") | 86 | expr_from_text("()") |
95 | } | 87 | } |
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index ceeb2bde9..d0234cada 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -237,8 +237,7 @@ fn api_walkthrough() { | |||
237 | 237 | ||
238 | // Let's get the `1 + 1` expression! | 238 | // Let's get the `1 + 1` expression! |
239 | let body: ast::BlockExpr = func.body().unwrap(); | 239 | let body: ast::BlockExpr = func.body().unwrap(); |
240 | let block = body.block().unwrap(); | 240 | let expr: ast::Expr = body.expr().unwrap(); |
241 | let expr: ast::Expr = block.expr().unwrap(); | ||
242 | 241 | ||
243 | // Enums are used to group related ast nodes together, and can be used for | 242 | // Enums are used to group related ast nodes together, and can be used for |
244 | // matching. However, because there are no public fields, it's possible to | 243 | // matching. However, because there are no public fields, it's possible to |
@@ -274,8 +273,8 @@ fn api_walkthrough() { | |||
274 | assert_eq!(text.to_string(), "1 + 1"); | 273 | assert_eq!(text.to_string(), "1 + 1"); |
275 | 274 | ||
276 | // There's a bunch of traversal methods on `SyntaxNode`: | 275 | // There's a bunch of traversal methods on `SyntaxNode`: |
277 | assert_eq!(expr_syntax.parent().as_ref(), Some(block.syntax())); | 276 | assert_eq!(expr_syntax.parent().as_ref(), Some(body.syntax())); |
278 | assert_eq!(block.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{'])); | 277 | assert_eq!(body.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{'])); |
279 | assert_eq!( | 278 | assert_eq!( |
280 | expr_syntax.next_sibling_or_token().map(|it| it.kind()), | 279 | expr_syntax.next_sibling_or_token().map(|it| it.kind()), |
281 | Some(SyntaxKind::WHITESPACE) | 280 | Some(SyntaxKind::WHITESPACE) |
diff --git a/crates/ra_syntax/src/parsing/lexer.rs b/crates/ra_syntax/src/parsing/lexer.rs index f450ef4a2..1a5a6dc06 100644 --- a/crates/ra_syntax/src/parsing/lexer.rs +++ b/crates/ra_syntax/src/parsing/lexer.rs | |||
@@ -180,7 +180,7 @@ fn rustc_token_kind_to_syntax_kind( | |||
180 | return (syntax_kind, None); | 180 | return (syntax_kind, None); |
181 | 181 | ||
182 | fn match_literal_kind(kind: &rustc_lexer::LiteralKind) -> (SyntaxKind, Option<&'static str>) { | 182 | fn match_literal_kind(kind: &rustc_lexer::LiteralKind) -> (SyntaxKind, Option<&'static str>) { |
183 | use rustc_lexer::LiteralKind as LK; | 183 | use rustc_lexer::{LexRawStrError, LiteralKind as LK}; |
184 | 184 | ||
185 | #[rustfmt::skip] | 185 | #[rustfmt::skip] |
186 | let syntax_kind = match *kind { | 186 | let syntax_kind = match *kind { |
@@ -215,21 +215,28 @@ fn rustc_token_kind_to_syntax_kind( | |||
215 | return (BYTE_STRING, Some("Missing trailing `\"` symbol to terminate the byte string literal")) | 215 | return (BYTE_STRING, Some("Missing trailing `\"` symbol to terminate the byte string literal")) |
216 | } | 216 | } |
217 | 217 | ||
218 | LK::RawStr { started: true, terminated: true, .. } => RAW_STRING, | 218 | LK::RawStr(str) => match str.validate() { |
219 | LK::RawStr { started: true, terminated: false, .. } => { | 219 | Ok(_) => RAW_STRING, |
220 | return (RAW_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw string literal")) | 220 | Err(LexRawStrError::InvalidStarter) => return (RAW_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw string literal")), |
221 | } | 221 | Err(LexRawStrError::NoTerminator { expected, found, .. }) => if expected == found { |
222 | LK::RawStr { started: false, .. } => { | 222 | return (RAW_STRING, Some("Missing trailing `\"` to terminate the raw string literal")) |
223 | return (RAW_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw string literal")) | 223 | } else { |
224 | } | 224 | return (RAW_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw string literal")) |
225 | |||
226 | }, | ||
227 | Err(LexRawStrError::TooManyDelimiters { .. }) => return (RAW_STRING, Some("Too many `#` symbols: raw strings may be delimited by up to 65535 `#` symbols")), | ||
228 | }, | ||
229 | LK::RawByteStr(str) => match str.validate() { | ||
230 | Ok(_) => RAW_BYTE_STRING, | ||
231 | Err(LexRawStrError::InvalidStarter) => return (RAW_BYTE_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw byte string literal")), | ||
232 | Err(LexRawStrError::NoTerminator { expected, found, .. }) => if expected == found { | ||
233 | return (RAW_BYTE_STRING, Some("Missing trailing `\"` to terminate the raw byte string literal")) | ||
234 | } else { | ||
235 | return (RAW_BYTE_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw byte string literal")) | ||
225 | 236 | ||
226 | LK::RawByteStr { started: true, terminated: true, .. } => RAW_BYTE_STRING, | 237 | }, |
227 | LK::RawByteStr { started: true, terminated: false, .. } => { | 238 | Err(LexRawStrError::TooManyDelimiters { .. }) => return (RAW_BYTE_STRING, Some("Too many `#` symbols: raw byte strings may be delimited by up to 65535 `#` symbols")), |
228 | return (RAW_BYTE_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw byte string literal")) | 239 | }, |
229 | } | ||
230 | LK::RawByteStr { started: false, .. } => { | ||
231 | return (RAW_BYTE_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw byte string literal")) | ||
232 | } | ||
233 | }; | 240 | }; |
234 | 241 | ||
235 | (syntax_kind, None) | 242 | (syntax_kind, None) |
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index f0b3dec63..e075cd801 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -96,7 +96,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { | |||
96 | ast::RecordField(it) => validate_numeric_name(it.name_ref(), &mut errors), | 96 | ast::RecordField(it) => validate_numeric_name(it.name_ref(), &mut errors), |
97 | ast::Visibility(it) => validate_visibility(it, &mut errors), | 97 | ast::Visibility(it) => validate_visibility(it, &mut errors), |
98 | ast::RangeExpr(it) => validate_range_expr(it, &mut errors), | 98 | ast::RangeExpr(it) => validate_range_expr(it, &mut errors), |
99 | ast::PathSegment(it) => validate_crate_keyword_in_path_segment(it, &mut errors), | 99 | ast::PathSegment(it) => validate_path_keywords(it, &mut errors), |
100 | _ => (), | 100 | _ => (), |
101 | } | 101 | } |
102 | } | 102 | } |
@@ -224,59 +224,82 @@ fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec<SyntaxError>) { | |||
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
227 | fn validate_crate_keyword_in_path_segment( | 227 | fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxError>) { |
228 | segment: ast::PathSegment, | 228 | use ast::PathSegmentKind; |
229 | errors: &mut Vec<SyntaxError>, | ||
230 | ) { | ||
231 | const ERR_MSG: &str = "The `crate` keyword is only allowed as the first segment of a path"; | ||
232 | 229 | ||
233 | let crate_token = match segment.crate_token() { | 230 | let path = segment.parent_path(); |
234 | None => return, | 231 | let is_path_start = segment.coloncolon_token().is_none() && path.qualifier().is_none(); |
235 | Some(it) => it, | 232 | |
236 | }; | 233 | if let Some(token) = segment.self_token() { |
234 | if !is_path_start { | ||
235 | errors.push(SyntaxError::new( | ||
236 | "The `self` keyword is only allowed as the first segment of a path", | ||
237 | token.text_range(), | ||
238 | )); | ||
239 | } | ||
240 | } else if let Some(token) = segment.crate_token() { | ||
241 | if !is_path_start || use_prefix(path).is_some() { | ||
242 | errors.push(SyntaxError::new( | ||
243 | "The `crate` keyword is only allowed as the first segment of a path", | ||
244 | token.text_range(), | ||
245 | )); | ||
246 | } | ||
247 | } else if let Some(token) = segment.super_token() { | ||
248 | if !all_supers(&path) { | ||
249 | errors.push(SyntaxError::new( | ||
250 | "The `super` keyword may only be preceded by other `super`s", | ||
251 | token.text_range(), | ||
252 | )); | ||
253 | return; | ||
254 | } | ||
237 | 255 | ||
238 | // Disallow both ::crate and foo::crate | 256 | let mut curr_path = path; |
239 | let mut path = segment.parent_path(); | 257 | while let Some(prefix) = use_prefix(curr_path) { |
240 | if segment.coloncolon_token().is_some() || path.qualifier().is_some() { | 258 | if !all_supers(&prefix) { |
241 | errors.push(SyntaxError::new(ERR_MSG, crate_token.text_range())); | 259 | errors.push(SyntaxError::new( |
242 | return; | 260 | "The `super` keyword may only be preceded by other `super`s", |
261 | token.text_range(), | ||
262 | )); | ||
263 | return; | ||
264 | } | ||
265 | curr_path = prefix; | ||
266 | } | ||
243 | } | 267 | } |
244 | 268 | ||
245 | // For expressions and types, validation is complete, but we still have | 269 | fn use_prefix(mut path: ast::Path) -> Option<ast::Path> { |
246 | // to handle invalid UseItems like this: | 270 | for node in path.syntax().ancestors().skip(1) { |
247 | // | 271 | match_ast! { |
248 | // use foo:{crate::bar::baz}; | 272 | match node { |
249 | // | 273 | ast::UseTree(it) => if let Some(tree_path) = it.path() { |
250 | // To handle this we must inspect the parent `UseItem`s and `UseTree`s | 274 | // Even a top-level path exists within a `UseTree` so we must explicitly |
251 | // but right now we're looking deep inside the nested `Path` nodes because | 275 | // allow our path but disallow anything else |
252 | // `Path`s are left-associative: | 276 | if tree_path != path { |
253 | // | 277 | return Some(tree_path); |
254 | // ((crate)::bar)::baz) | 278 | } |
255 | // ^ current value of path | 279 | }, |
256 | // | 280 | ast::UseTreeList(_it) => continue, |
257 | // So we need to climb to the top | 281 | ast::Path(parent) => path = parent, |
258 | while let Some(parent) = path.parent_path() { | 282 | _ => return None, |
259 | path = parent; | 283 | } |
284 | }; | ||
285 | } | ||
286 | return None; | ||
260 | } | 287 | } |
261 | 288 | ||
262 | // Now that we've found the whole path we need to see if there's a prefix | 289 | fn all_supers(path: &ast::Path) -> bool { |
263 | // somewhere in the UseTree hierarchy. This check is arbitrarily deep | 290 | let segment = match path.segment() { |
264 | // because rust allows arbitrary nesting like so: | 291 | Some(it) => it, |
265 | // | 292 | None => return false, |
266 | // use {foo::{{{{crate::bar::baz}}}}}; | ||
267 | for node in path.syntax().ancestors().skip(1) { | ||
268 | match_ast! { | ||
269 | match node { | ||
270 | ast::UseTree(it) => if let Some(tree_path) = it.path() { | ||
271 | // Even a top-level path exists within a `UseTree` so we must explicitly | ||
272 | // allow our path but disallow anything else | ||
273 | if tree_path != path { | ||
274 | errors.push(SyntaxError::new(ERR_MSG, crate_token.text_range())); | ||
275 | } | ||
276 | }, | ||
277 | ast::UseTreeList(_it) => continue, | ||
278 | _ => return, | ||
279 | } | ||
280 | }; | 293 | }; |
294 | |||
295 | if segment.kind() != Some(PathSegmentKind::SuperKw) { | ||
296 | return false; | ||
297 | } | ||
298 | |||
299 | if let Some(ref subpath) = path.qualifier() { | ||
300 | return all_supers(subpath); | ||
301 | } | ||
302 | |||
303 | return true; | ||
281 | } | 304 | } |
282 | } | 305 | } |
diff --git a/crates/ra_syntax/src/validation/block.rs b/crates/ra_syntax/src/validation/block.rs index 8e962ab5b..2c08f7e6e 100644 --- a/crates/ra_syntax/src/validation/block.rs +++ b/crates/ra_syntax/src/validation/block.rs | |||
@@ -6,19 +6,17 @@ use crate::{ | |||
6 | SyntaxKind::*, | 6 | SyntaxKind::*, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | pub(crate) fn validate_block_expr(expr: ast::BlockExpr, errors: &mut Vec<SyntaxError>) { | 9 | pub(crate) fn validate_block_expr(block: ast::BlockExpr, errors: &mut Vec<SyntaxError>) { |
10 | if let Some(parent) = expr.syntax().parent() { | 10 | if let Some(parent) = block.syntax().parent() { |
11 | match parent.kind() { | 11 | match parent.kind() { |
12 | FN_DEF | EXPR_STMT | BLOCK => return, | 12 | FN_DEF | EXPR_STMT | BLOCK_EXPR => return, |
13 | _ => {} | 13 | _ => {} |
14 | } | 14 | } |
15 | } | 15 | } |
16 | if let Some(block) = expr.block() { | 16 | errors.extend(block.attrs().map(|attr| { |
17 | errors.extend(block.attrs().map(|attr| { | 17 | SyntaxError::new( |
18 | SyntaxError::new( | 18 | "A block in this position cannot accept inner attributes", |
19 | "A block in this position cannot accept inner attributes", | 19 | attr.syntax().text_range(), |
20 | attr.syntax().text_range(), | 20 | ) |
21 | ) | 21 | })) |
22 | })) | ||
23 | } | ||
24 | } | 22 | } |