diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/syntax')
9 files changed, 168 insertions, 28 deletions
diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 8fc493a23..305cf2d39 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -14,6 +14,7 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" +either = "1.7.0" itertools = "0.10.5" rowan = "0.15.10" rustc_lexer = { version = "727.0.0", package = "rustc-ap-rustc_lexer" } diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index 36ad5fddf..548b5ba8b 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -97,6 +97,7 @@ Item = | Static | Struct | Trait +| TraitAlias | TypeAlias | Union | Use @@ -240,10 +241,11 @@ Trait = Attr* Visibility? 'unsafe'? 'auto'? 'trait' Name GenericParamList? - ( - (':' TypeBoundList?)? WhereClause? AssocItemList - | '=' TypeBoundList? WhereClause? ';' - ) + (':' TypeBoundList?)? WhereClause? AssocItemList + +TraitAlias = + Attr* Visibility? + 'trait' Name GenericParamList? '=' TypeBoundList? WhereClause? ';' AssocItemList = '{' Attr* AssocItem* '}' diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast.rs b/src/tools/rust-analyzer/crates/syntax/src/ast.rs index 385a4e0a3..1e691beff 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast.rs @@ -13,7 +13,7 @@ pub mod prec; use std::marker::PhantomData; -use itertools::Either; +use either::Either; use crate::{ syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken}, @@ -25,7 +25,8 @@ pub use self::{ generated::{nodes::*, tokens::*}, node_ext::{ AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind, - SlicePatComponents, StructKind, TypeBoundKind, TypeOrConstParam, VisibilityKind, + SlicePatComponents, StructKind, TraitOrAlias, TypeBoundKind, TypeOrConstParam, + VisibilityKind, }, operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp}, token_ext::{CommentKind, CommentPlacement, CommentShape, IsString, QuoteOffsets, Radix}, @@ -128,6 +129,13 @@ where } } +impl<L, R> HasAttrs for Either<L, R> +where + L: HasAttrs, + R: HasAttrs, +{ +} + mod support { use super::{AstChildren, AstNode, SyntaxKind, SyntaxNode, SyntaxToken}; diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs index db66d08a7..c43d0830b 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs @@ -48,23 +48,30 @@ impl From<ast::IfExpr> for ElseBranch { } impl ast::IfExpr { - pub fn then_branch(&self) -> Option<ast::BlockExpr> { - self.children_after_condition().next() + pub fn condition(&self) -> Option<ast::Expr> { + // If the condition is a BlockExpr, check if the then body is missing. + // If it is assume the condition is the expression that is missing instead. + let mut exprs = support::children(self.syntax()); + let first = exprs.next(); + match first { + Some(ast::Expr::BlockExpr(_)) => exprs.next().and(first), + first => first, + } } - pub fn else_branch(&self) -> Option<ElseBranch> { - let res = match self.children_after_condition().nth(1) { - Some(block) => ElseBranch::Block(block), - None => { - let elif = self.children_after_condition().next()?; - ElseBranch::IfExpr(elif) - } - }; - Some(res) + pub fn then_branch(&self) -> Option<ast::BlockExpr> { + match support::children(self.syntax()).nth(1)? { + ast::Expr::BlockExpr(block) => Some(block), + _ => None, + } } - fn children_after_condition<N: AstNode>(&self) -> impl Iterator<Item = N> { - self.syntax().children().skip(1).filter_map(N::cast) + pub fn else_branch(&self) -> Option<ElseBranch> { + match support::children(self.syntax()).nth(2)? { + ast::Expr::BlockExpr(block) => Some(ElseBranch::Block(block)), + ast::Expr::IfExpr(elif) => Some(ElseBranch::IfExpr(elif)), + _ => None, + } } } @@ -356,7 +363,15 @@ impl ast::BlockExpr { Some(it) => it, None => return true, }; - !matches!(parent.kind(), FN | IF_EXPR | WHILE_EXPR | LOOP_EXPR) + match parent.kind() { + FOR_EXPR | IF_EXPR => parent + .children() + .filter(|it| ast::Expr::can_cast(it.kind())) + .next() + .map_or(true, |it| it == *self.syntax()), + LET_ELSE | FN | WHILE_EXPR | LOOP_EXPR | CONST_BLOCK_PAT => false, + _ => true, + } } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index 642a3bfc3..fe3248453 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -407,7 +407,21 @@ impl Trait { pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) } pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) } pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TraitAlias { + pub(crate) syntax: SyntaxNode, +} +impl ast::HasAttrs for TraitAlias {} +impl ast::HasName for TraitAlias {} +impl ast::HasVisibility for TraitAlias {} +impl ast::HasGenericParams for TraitAlias {} +impl ast::HasDocComments for TraitAlias {} +impl TraitAlias { + pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) } pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } + pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) } pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } } @@ -1573,6 +1587,7 @@ pub enum Item { Static(Static), Struct(Struct), Trait(Trait), + TraitAlias(TraitAlias), TypeAlias(TypeAlias), Union(Union), Use(Use), @@ -2058,6 +2073,17 @@ impl AstNode for Trait { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for TraitAlias { + fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT_ALIAS } + 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 TypeAlias { fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS } fn cast(syntax: SyntaxNode) -> Option<Self> { @@ -3570,6 +3596,9 @@ impl From<Struct> for Item { impl From<Trait> for Item { fn from(node: Trait) -> Item { Item::Trait(node) } } +impl From<TraitAlias> for Item { + fn from(node: TraitAlias) -> Item { Item::TraitAlias(node) } +} impl From<TypeAlias> for Item { fn from(node: TypeAlias) -> Item { Item::TypeAlias(node) } } @@ -3596,6 +3625,7 @@ impl AstNode for Item { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | USE @@ -3616,6 +3646,7 @@ impl AstNode for Item { STATIC => Item::Static(Static { syntax }), STRUCT => Item::Struct(Struct { syntax }), TRAIT => Item::Trait(Trait { syntax }), + TRAIT_ALIAS => Item::TraitAlias(TraitAlias { syntax }), TYPE_ALIAS => Item::TypeAlias(TypeAlias { syntax }), UNION => Item::Union(Union { syntax }), USE => Item::Use(Use { syntax }), @@ -3638,6 +3669,7 @@ impl AstNode for Item { Item::Static(it) => &it.syntax, Item::Struct(it) => &it.syntax, Item::Trait(it) => &it.syntax, + Item::TraitAlias(it) => &it.syntax, Item::TypeAlias(it) => &it.syntax, Item::Union(it) => &it.syntax, Item::Use(it) => &it.syntax, @@ -3950,6 +3982,7 @@ impl AstNode for AnyHasAttrs { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | USE @@ -4035,6 +4068,7 @@ impl AstNode for AnyHasDocComments { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | USE @@ -4056,7 +4090,7 @@ impl AnyHasGenericParams { } impl AstNode for AnyHasGenericParams { fn can_cast(kind: SyntaxKind) -> bool { - matches!(kind, ENUM | FN | IMPL | STRUCT | TRAIT | TYPE_ALIAS | UNION) + matches!(kind, ENUM | FN | IMPL | STRUCT | TRAIT | TRAIT_ALIAS | TYPE_ALIAS | UNION) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then_some(AnyHasGenericParams { syntax }) @@ -4108,6 +4142,7 @@ impl AstNode for AnyHasName { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | RENAME @@ -4163,6 +4198,7 @@ impl AstNode for AnyHasVisibility { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | USE @@ -4391,6 +4427,11 @@ impl std::fmt::Display for Trait { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for TraitAlias { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for TypeAlias { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs index fe82aa907..3308077da 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs @@ -680,6 +680,81 @@ impl TypeOrConstParam { } } +impl AstNode for TypeOrConstParam { + fn can_cast(kind: SyntaxKind) -> bool + where + Self: Sized, + { + matches!(kind, SyntaxKind::TYPE_PARAM | SyntaxKind::CONST_PARAM) + } + + fn cast(syntax: SyntaxNode) -> Option<Self> + where + Self: Sized, + { + let res = match syntax.kind() { + SyntaxKind::TYPE_PARAM => TypeOrConstParam::Type(ast::TypeParam { syntax }), + SyntaxKind::CONST_PARAM => TypeOrConstParam::Const(ast::ConstParam { syntax }), + _ => return None, + }; + Some(res) + } + + fn syntax(&self) -> &SyntaxNode { + match self { + TypeOrConstParam::Type(it) => it.syntax(), + TypeOrConstParam::Const(it) => it.syntax(), + } + } +} + +impl HasAttrs for TypeOrConstParam {} + +#[derive(Debug, Clone)] +pub enum TraitOrAlias { + Trait(ast::Trait), + TraitAlias(ast::TraitAlias), +} + +impl TraitOrAlias { + pub fn name(&self) -> Option<ast::Name> { + match self { + TraitOrAlias::Trait(x) => x.name(), + TraitOrAlias::TraitAlias(x) => x.name(), + } + } +} + +impl AstNode for TraitOrAlias { + fn can_cast(kind: SyntaxKind) -> bool + where + Self: Sized, + { + matches!(kind, SyntaxKind::TRAIT | SyntaxKind::TRAIT_ALIAS) + } + + fn cast(syntax: SyntaxNode) -> Option<Self> + where + Self: Sized, + { + let res = match syntax.kind() { + SyntaxKind::TRAIT => TraitOrAlias::Trait(ast::Trait { syntax }), + SyntaxKind::TRAIT_ALIAS => TraitOrAlias::TraitAlias(ast::TraitAlias { syntax }), + _ => return None, + }; + Some(res) + } + + fn syntax(&self) -> &SyntaxNode { + match self { + TraitOrAlias::Trait(it) => it.syntax(), + TraitOrAlias::TraitAlias(it) => it.syntax(), + } + } +} + +impl HasAttrs for TraitOrAlias {} + pub enum VisibilityKind { In(ast::Path), PubCrate, @@ -862,12 +937,6 @@ impl From<ast::Adt> for ast::Item { } } -impl ast::IfExpr { - pub fn condition(&self) -> Option<ast::Expr> { - support::child(&self.syntax) - } -} - impl ast::MatchGuard { pub fn condition(&self) -> Option<ast::Expr> { support::child(&self.syntax) diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/traits.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/traits.rs index aa2b7ed5c..3e43df2d0 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/traits.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/traits.rs @@ -1,7 +1,7 @@ //! Various traits that are implemented by ast nodes. //! //! The implementations are usually trivial, and live in generated.rs -use itertools::Either; +use either::Either; use crate::{ ast::{self, support, AstChildren, AstNode, AstToken}, @@ -134,3 +134,5 @@ impl Iterator for AttrDocCommentIter { }) } } + +impl<A: HasName, B: HasName> HasName for Either<A, B> {} diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests/ast_src.rs b/src/tools/rust-analyzer/crates/syntax/src/tests/ast_src.rs index 3ff6e0300..ccce71966 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/tests/ast_src.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/tests/ast_src.rs @@ -86,6 +86,7 @@ pub(crate) const KINDS_SRC: KindsSrc<'_> = KindsSrc { "STATIC", "CONST", "TRAIT", + "TRAIT_ALIAS", "IMPL", "TYPE_ALIAS", "MACRO_CALL", diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs b/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs index 03aa2c451..e954b5825 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs @@ -783,6 +783,7 @@ fn extract_struct_traits(ast: &mut AstSrc) { "Enum", "Variant", "Trait", + "TraitAlias", "Module", "Static", "Const", |