mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
Scale back to only two traits
This commit is contained in:
parent
60f4d7bd8c
commit
689661c959
8 changed files with 2020 additions and 228 deletions
|
@ -1,5 +1,5 @@
|
|||
use ra_syntax::{
|
||||
ast::{self, AstElement, AstNode},
|
||||
ast::{self, AstNode},
|
||||
SyntaxKind::{
|
||||
BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR,
|
||||
WHITESPACE,
|
||||
|
@ -124,7 +124,7 @@ fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
|
|||
}
|
||||
}
|
||||
|
||||
if ast::Stmt::cast_element(node.clone().into()).is_some() {
|
||||
if ast::Stmt::cast(node.clone().into()).is_some() {
|
||||
return Some((node, false));
|
||||
}
|
||||
|
||||
|
|
|
@ -492,7 +492,6 @@ impl ExprCollector<'_> {
|
|||
ast::Stmt::ExprStmt(stmt) => {
|
||||
Some(Statement::Expr(self.collect_expr_opt(stmt.expr())))
|
||||
}
|
||||
ast::Stmt::ModuleItem(_) => None,
|
||||
})
|
||||
.collect();
|
||||
let tail = block.expr().map(|e| self.collect_expr(e));
|
||||
|
|
|
@ -64,6 +64,22 @@ pub trait AstToken {
|
|||
}
|
||||
}
|
||||
|
||||
mod support {
|
||||
use super::{AstChildren, AstNode, AstToken, SyntaxNode};
|
||||
|
||||
pub(super) fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {
|
||||
parent.children().find_map(N::cast)
|
||||
}
|
||||
|
||||
pub(super) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {
|
||||
AstChildren::new(parent)
|
||||
}
|
||||
|
||||
pub(super) fn token<T: AstToken>(parent: &SyntaxNode) -> Option<T> {
|
||||
parent.children_with_tokens().filter_map(|it| it.into_token()).find_map(T::cast)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over `SyntaxNode` children of a particular AST type.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AstChildren<N> {
|
||||
|
|
|
@ -5,8 +5,7 @@ use itertools::Itertools;
|
|||
|
||||
use crate::{
|
||||
ast::{
|
||||
self, child_opt, child_token_opt, children, AstElement, AstNode, AstToken, AttrInput,
|
||||
NameOwner, SyntaxNode,
|
||||
self, child_opt, children, support, AstNode, AstToken, AttrInput, NameOwner, SyntaxNode,
|
||||
},
|
||||
SmolStr, SyntaxElement,
|
||||
SyntaxKind::*,
|
||||
|
@ -437,7 +436,7 @@ impl ast::TypeBound {
|
|||
.skip_while(|it| it.kind() != T![const])
|
||||
.find_map(ast::Question::cast)
|
||||
} else {
|
||||
child_token_opt(self)
|
||||
support::token(&self.syntax)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +508,7 @@ impl ast::RangePat {
|
|||
pub fn start(&self) -> Option<ast::Pat> {
|
||||
self.syntax()
|
||||
.children_with_tokens()
|
||||
.take_while(|it| !ast::RangeSeparator::can_cast_element(it.kind()))
|
||||
.take_while(|it| !ast::RangeSeparator::can_cast(it.kind()))
|
||||
.filter_map(|it| it.into_node())
|
||||
.find_map(ast::Pat::cast)
|
||||
}
|
||||
|
@ -517,7 +516,7 @@ impl ast::RangePat {
|
|||
pub fn end(&self) -> Option<ast::Pat> {
|
||||
self.syntax()
|
||||
.children_with_tokens()
|
||||
.skip_while(|it| !ast::RangeSeparator::can_cast_element(it.kind()))
|
||||
.skip_while(|it| !ast::RangeSeparator::can_cast(it.kind()))
|
||||
.filter_map(|it| it.into_node())
|
||||
.find_map(ast::Pat::cast)
|
||||
}
|
||||
|
@ -525,10 +524,10 @@ impl ast::RangePat {
|
|||
|
||||
impl ast::TokenTree {
|
||||
pub fn left_delimiter(&self) -> Option<ast::LeftDelimiter> {
|
||||
self.syntax().first_child_or_token().and_then(ast::LeftDelimiter::cast_element)
|
||||
self.syntax().first_child_or_token()?.into_token().and_then(ast::LeftDelimiter::cast)
|
||||
}
|
||||
|
||||
pub fn right_delimiter(&self) -> Option<ast::RightDelimiter> {
|
||||
self.syntax().last_child_or_token().and_then(ast::RightDelimiter::cast_element)
|
||||
self.syntax().last_child_or_token()?.into_token().and_then(ast::RightDelimiter::cast)
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,9 +4,9 @@
|
|||
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::ast::{
|
||||
self, child_elements, child_opt, child_token_opt, child_tokens, children, AstChildElements,
|
||||
AstChildTokens, AstChildren, AstNode, AstToken,
|
||||
use crate::{
|
||||
ast::{self, child_opt, children, support, AstChildren, AstNode, AstToken},
|
||||
syntax_node::SyntaxElementChildren,
|
||||
};
|
||||
|
||||
pub trait TypeAscriptionOwner: AstNode {
|
||||
|
@ -71,7 +71,7 @@ pub trait TypeBoundsOwner: AstNode {
|
|||
}
|
||||
|
||||
fn colon(&self) -> Option<ast::Colon> {
|
||||
child_token_opt(self)
|
||||
support::token(self.syntax())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,14 +82,11 @@ pub trait AttrsOwner: AstNode {
|
|||
fn has_atom_attr(&self, atom: &str) -> bool {
|
||||
self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom)
|
||||
}
|
||||
fn attr_or_comments(&self) -> AstChildElements<ast::AttrOrComment> {
|
||||
child_elements(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DocCommentsOwner: AstNode {
|
||||
fn doc_comments(&self) -> AstChildTokens<ast::Comment> {
|
||||
child_tokens(self)
|
||||
fn doc_comments(&self) -> CommentIter {
|
||||
CommentIter { iter: self.syntax().children_with_tokens() }
|
||||
}
|
||||
|
||||
/// Returns the textual content of a doc comment block as a single string.
|
||||
|
@ -134,3 +131,14 @@ pub trait DocCommentsOwner: AstNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CommentIter {
|
||||
iter: SyntaxElementChildren,
|
||||
}
|
||||
|
||||
impl Iterator for CommentIter {
|
||||
type Item = ast::Comment;
|
||||
fn next(&mut self) -> Option<ast::Comment> {
|
||||
self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -549,7 +549,6 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
struct Block: AttrsOwner, ModuleItemOwner {
|
||||
LCurly,
|
||||
statements: [Stmt],
|
||||
statements_or_semi: [StmtOrSemi],
|
||||
Expr,
|
||||
RCurly,
|
||||
}
|
||||
|
@ -749,12 +748,10 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
|
||||
enum AttrInput { Literal, TokenTree }
|
||||
enum Stmt {
|
||||
ModuleItem,
|
||||
LetStmt,
|
||||
ExprStmt,
|
||||
// macro calls are parsed as expression statements */
|
||||
}
|
||||
enum StmtOrSemi {Stmt, Semi}
|
||||
|
||||
enum LeftDelimiter { LParen, LBrack, LCurly }
|
||||
enum RightDelimiter { RParen, RBrack, RCurly }
|
||||
|
@ -825,10 +822,5 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
RecordFieldDefList,
|
||||
TupleFieldDefList,
|
||||
}
|
||||
|
||||
enum AttrOrComment {
|
||||
Attr,
|
||||
Comment
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -146,14 +146,23 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
FieldSrc::Many(_) => {
|
||||
quote! {
|
||||
pub fn #method_name(&self) -> AstChildren<#ty> {
|
||||
AstChildren::new(&self.syntax)
|
||||
support::children(&self.syntax)
|
||||
}
|
||||
}
|
||||
}
|
||||
FieldSrc::Optional(_) | FieldSrc::Shorthand => {
|
||||
quote! {
|
||||
pub fn #method_name(&self) -> Option<#ty> {
|
||||
AstChildren::new(&self.syntax).next()
|
||||
let is_token = element_kinds_map[&ty.to_string()].has_tokens;
|
||||
if is_token {
|
||||
quote! {
|
||||
pub fn #method_name(&self) -> Option<#ty> {
|
||||
support::token(&self.syntax)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
pub fn #method_name(&self) -> Option<#ty> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,6 +214,48 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
quote!(impl ast::#trait_name for #name {})
|
||||
});
|
||||
|
||||
let element_kinds = &element_kinds_map[&en.name.to_string()];
|
||||
assert!(
|
||||
element_kinds.has_nodes ^ element_kinds.has_tokens,
|
||||
"{}: {:#?}",
|
||||
name,
|
||||
element_kinds
|
||||
);
|
||||
let specific_ast_trait = {
|
||||
let (ast_trait, syntax_type) = if element_kinds.has_tokens {
|
||||
(quote!(AstToken), quote!(SyntaxToken))
|
||||
} else {
|
||||
(quote!(AstNode), quote!(SyntaxNode))
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl #ast_trait for #name {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
#(#kinds)|* => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn cast(syntax: #syntax_type) -> Option<Self> {
|
||||
let res = match syntax.kind() {
|
||||
#(
|
||||
#kinds => #name::#variants(#variants { syntax }),
|
||||
)*
|
||||
_ => return None,
|
||||
};
|
||||
Some(res)
|
||||
}
|
||||
fn syntax(&self) -> &#syntax_type {
|
||||
match self {
|
||||
#(
|
||||
#name::#variants(it) => &it.syntax,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum #name {
|
||||
|
@ -225,30 +276,8 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
}
|
||||
}
|
||||
|
||||
impl AstNode for #name {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
#(#kinds)|* => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
let res = match syntax.kind() {
|
||||
#(
|
||||
#kinds => #name::#variants(#variants { syntax }),
|
||||
)*
|
||||
_ => return None,
|
||||
};
|
||||
Some(res)
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
match self {
|
||||
#(
|
||||
#name::#variants(it) => &it.syntax,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
#specific_ast_trait
|
||||
|
||||
#(#traits)*
|
||||
}
|
||||
});
|
||||
|
@ -268,7 +297,7 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
#[allow(unused_imports)]
|
||||
use crate::{
|
||||
SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *},
|
||||
ast::{self, AstNode, AstToken, AstChildren},
|
||||
ast::{self, AstNode, AstToken, AstChildren, support},
|
||||
};
|
||||
|
||||
#(#tokens)*
|
||||
|
|
Loading…
Reference in a new issue