mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +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::{
|
use ra_syntax::{
|
||||||
ast::{self, AstElement, AstNode},
|
ast::{self, AstNode},
|
||||||
SyntaxKind::{
|
SyntaxKind::{
|
||||||
BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR,
|
BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR,
|
||||||
WHITESPACE,
|
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));
|
return Some((node, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -492,7 +492,6 @@ impl ExprCollector<'_> {
|
||||||
ast::Stmt::ExprStmt(stmt) => {
|
ast::Stmt::ExprStmt(stmt) => {
|
||||||
Some(Statement::Expr(self.collect_expr_opt(stmt.expr())))
|
Some(Statement::Expr(self.collect_expr_opt(stmt.expr())))
|
||||||
}
|
}
|
||||||
ast::Stmt::ModuleItem(_) => None,
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let tail = block.expr().map(|e| self.collect_expr(e));
|
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.
|
/// An iterator over `SyntaxNode` children of a particular AST type.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AstChildren<N> {
|
pub struct AstChildren<N> {
|
||||||
|
|
|
@ -5,8 +5,7 @@ use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
self, child_opt, child_token_opt, children, AstElement, AstNode, AstToken, AttrInput,
|
self, child_opt, children, support, AstNode, AstToken, AttrInput, NameOwner, SyntaxNode,
|
||||||
NameOwner, SyntaxNode,
|
|
||||||
},
|
},
|
||||||
SmolStr, SyntaxElement,
|
SmolStr, SyntaxElement,
|
||||||
SyntaxKind::*,
|
SyntaxKind::*,
|
||||||
|
@ -437,7 +436,7 @@ impl ast::TypeBound {
|
||||||
.skip_while(|it| it.kind() != T![const])
|
.skip_while(|it| it.kind() != T![const])
|
||||||
.find_map(ast::Question::cast)
|
.find_map(ast::Question::cast)
|
||||||
} else {
|
} else {
|
||||||
child_token_opt(self)
|
support::token(&self.syntax)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,7 +508,7 @@ impl ast::RangePat {
|
||||||
pub fn start(&self) -> Option<ast::Pat> {
|
pub fn start(&self) -> Option<ast::Pat> {
|
||||||
self.syntax()
|
self.syntax()
|
||||||
.children_with_tokens()
|
.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())
|
.filter_map(|it| it.into_node())
|
||||||
.find_map(ast::Pat::cast)
|
.find_map(ast::Pat::cast)
|
||||||
}
|
}
|
||||||
|
@ -517,7 +516,7 @@ impl ast::RangePat {
|
||||||
pub fn end(&self) -> Option<ast::Pat> {
|
pub fn end(&self) -> Option<ast::Pat> {
|
||||||
self.syntax()
|
self.syntax()
|
||||||
.children_with_tokens()
|
.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())
|
.filter_map(|it| it.into_node())
|
||||||
.find_map(ast::Pat::cast)
|
.find_map(ast::Pat::cast)
|
||||||
}
|
}
|
||||||
|
@ -525,10 +524,10 @@ impl ast::RangePat {
|
||||||
|
|
||||||
impl ast::TokenTree {
|
impl ast::TokenTree {
|
||||||
pub fn left_delimiter(&self) -> Option<ast::LeftDelimiter> {
|
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> {
|
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 itertools::Itertools;
|
||||||
|
|
||||||
use crate::ast::{
|
use crate::{
|
||||||
self, child_elements, child_opt, child_token_opt, child_tokens, children, AstChildElements,
|
ast::{self, child_opt, children, support, AstChildren, AstNode, AstToken},
|
||||||
AstChildTokens, AstChildren, AstNode, AstToken,
|
syntax_node::SyntaxElementChildren,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait TypeAscriptionOwner: AstNode {
|
pub trait TypeAscriptionOwner: AstNode {
|
||||||
|
@ -71,7 +71,7 @@ pub trait TypeBoundsOwner: AstNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn colon(&self) -> Option<ast::Colon> {
|
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 {
|
fn has_atom_attr(&self, atom: &str) -> bool {
|
||||||
self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom)
|
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 {
|
pub trait DocCommentsOwner: AstNode {
|
||||||
fn doc_comments(&self) -> AstChildTokens<ast::Comment> {
|
fn doc_comments(&self) -> CommentIter {
|
||||||
child_tokens(self)
|
CommentIter { iter: self.syntax().children_with_tokens() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the textual content of a doc comment block as a single string.
|
/// 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 {
|
struct Block: AttrsOwner, ModuleItemOwner {
|
||||||
LCurly,
|
LCurly,
|
||||||
statements: [Stmt],
|
statements: [Stmt],
|
||||||
statements_or_semi: [StmtOrSemi],
|
|
||||||
Expr,
|
Expr,
|
||||||
RCurly,
|
RCurly,
|
||||||
}
|
}
|
||||||
|
@ -749,12 +748,10 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
|
|
||||||
enum AttrInput { Literal, TokenTree }
|
enum AttrInput { Literal, TokenTree }
|
||||||
enum Stmt {
|
enum Stmt {
|
||||||
ModuleItem,
|
|
||||||
LetStmt,
|
LetStmt,
|
||||||
ExprStmt,
|
ExprStmt,
|
||||||
// macro calls are parsed as expression statements */
|
// macro calls are parsed as expression statements */
|
||||||
}
|
}
|
||||||
enum StmtOrSemi {Stmt, Semi}
|
|
||||||
|
|
||||||
enum LeftDelimiter { LParen, LBrack, LCurly }
|
enum LeftDelimiter { LParen, LBrack, LCurly }
|
||||||
enum RightDelimiter { RParen, RBrack, RCurly }
|
enum RightDelimiter { RParen, RBrack, RCurly }
|
||||||
|
@ -825,10 +822,5 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
RecordFieldDefList,
|
RecordFieldDefList,
|
||||||
TupleFieldDefList,
|
TupleFieldDefList,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AttrOrComment {
|
|
||||||
Attr,
|
|
||||||
Comment
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -146,14 +146,23 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
FieldSrc::Many(_) => {
|
FieldSrc::Many(_) => {
|
||||||
quote! {
|
quote! {
|
||||||
pub fn #method_name(&self) -> AstChildren<#ty> {
|
pub fn #method_name(&self) -> AstChildren<#ty> {
|
||||||
AstChildren::new(&self.syntax)
|
support::children(&self.syntax)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FieldSrc::Optional(_) | FieldSrc::Shorthand => {
|
FieldSrc::Optional(_) | FieldSrc::Shorthand => {
|
||||||
|
let is_token = element_kinds_map[&ty.to_string()].has_tokens;
|
||||||
|
if is_token {
|
||||||
quote! {
|
quote! {
|
||||||
pub fn #method_name(&self) -> Option<#ty> {
|
pub fn #method_name(&self) -> Option<#ty> {
|
||||||
AstChildren::new(&self.syntax).next()
|
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 {})
|
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! {
|
quote! {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum #name {
|
pub enum #name {
|
||||||
|
@ -225,30 +276,8 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AstNode for #name {
|
#specific_ast_trait
|
||||||
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,
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#(#traits)*
|
#(#traits)*
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -268,7 +297,7 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::{
|
use crate::{
|
||||||
SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *},
|
SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *},
|
||||||
ast::{self, AstNode, AstToken, AstChildren},
|
ast::{self, AstNode, AstToken, AstChildren, support},
|
||||||
};
|
};
|
||||||
|
|
||||||
#(#tokens)*
|
#(#tokens)*
|
||||||
|
|
Loading…
Reference in a new issue