Remove code duplication

This commit is contained in:
Aleksey Kladov 2020-04-09 22:22:58 +02:00
parent 33df20868d
commit e07d3c94de
5 changed files with 49 additions and 60 deletions

View file

@ -42,11 +42,6 @@ pub trait AstNode {
fn syntax(&self) -> &SyntaxNode;
}
#[test]
fn assert_ast_is_object_safe() {
fn _f(_: &dyn AstNode, _: &dyn NameOwner) {}
}
/// Like `AstNode`, but wraps tokens rather than interior nodes.
pub trait AstToken {
fn can_cast(token: SyntaxKind) -> bool
@ -64,22 +59,6 @@ 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> {
@ -100,12 +79,25 @@ impl<N: AstNode> Iterator for AstChildren<N> {
}
}
fn child_opt<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> Option<C> {
children(parent).next()
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)
}
}
fn children<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> AstChildren<C> {
AstChildren::new(parent.syntax())
#[test]
fn assert_ast_is_object_safe() {
fn _f(_: &dyn AstNode, _: &dyn NameOwner) {}
}
#[test]

View file

@ -6,7 +6,7 @@ use std::{iter, ops::RangeInclusive};
use arrayvec::ArrayVec;
use crate::{
algo,
algo::{self, neighbor, SyntaxRewriter},
ast::{
self,
make::{self, tokens},
@ -16,7 +16,6 @@ use crate::{
SyntaxKind::{ATTR, COMMENT, WHITESPACE},
SyntaxNode, SyntaxToken, T,
};
use algo::{neighbor, SyntaxRewriter};
impl ast::BinExpr {
#[must_use]

View file

@ -1,7 +1,7 @@
//! Various extension methods to ast Expr Nodes, which are hard to code-generate.
use crate::{
ast::{self, child_opt, children, AstChildren, AstNode},
ast::{self, support, AstChildren, AstNode},
SmolStr,
SyntaxKind::*,
SyntaxToken, T,
@ -36,7 +36,7 @@ impl ast::IfExpr {
let res = match self.blocks().nth(1) {
Some(block) => ElseBranch::Block(block),
None => {
let elif: ast::IfExpr = child_opt(self)?;
let elif: ast::IfExpr = support::child(self.syntax())?;
ElseBranch::IfExpr(elif)
}
};
@ -44,7 +44,7 @@ impl ast::IfExpr {
}
fn blocks(&self) -> AstChildren<ast::BlockExpr> {
children(self)
support::children(self.syntax())
}
}
@ -212,15 +212,15 @@ impl ast::BinExpr {
}
pub fn lhs(&self) -> Option<ast::Expr> {
children(self).next()
support::children(self.syntax()).next()
}
pub fn rhs(&self) -> Option<ast::Expr> {
children(self).nth(1)
support::children(self.syntax()).nth(1)
}
pub fn sub_exprs(&self) -> (Option<ast::Expr>, Option<ast::Expr>) {
let mut children = children(self);
let mut children = support::children(self.syntax());
let first = children.next();
let second = children.next();
(first, second)
@ -275,10 +275,10 @@ impl ast::RangeExpr {
impl ast::IndexExpr {
pub fn base(&self) -> Option<ast::Expr> {
children(self).next()
support::children(self.syntax()).next()
}
pub fn index(&self) -> Option<ast::Expr> {
children(self).nth(1)
support::children(self.syntax()).nth(1)
}
}
@ -291,11 +291,11 @@ impl ast::ArrayExpr {
pub fn kind(&self) -> ArrayExprKind {
if self.is_repeat() {
ArrayExprKind::Repeat {
initializer: children(self).next(),
repeat: children(self).nth(1),
initializer: support::children(self.syntax()).next(),
repeat: support::children(self.syntax()).nth(1),
}
} else {
ArrayExprKind::ElementList(children(self))
ArrayExprKind::ElementList(support::children(self.syntax()))
}
}

View file

@ -5,9 +5,7 @@ use itertools::Itertools;
use ra_parser::SyntaxKind;
use crate::{
ast::{
self, child_opt, children, support, AstNode, AstToken, AttrInput, NameOwner, SyntaxNode,
},
ast::{self, support, AstNode, AstToken, AttrInput, NameOwner, SyntaxNode},
SmolStr, SyntaxElement, SyntaxToken, T,
};
@ -161,7 +159,7 @@ impl ast::ImplDef {
}
fn target(&self) -> (Option<ast::TypeRef>, Option<ast::TypeRef>) {
let mut types = children(self);
let mut types = support::children(self.syntax());
let first = types.next();
let second = types.next();
(first, second)
@ -177,9 +175,9 @@ pub enum StructKind {
impl StructKind {
fn from_node<N: AstNode>(node: &N) -> StructKind {
if let Some(nfdl) = child_opt::<_, ast::RecordFieldDefList>(node) {
if let Some(nfdl) = support::child::<ast::RecordFieldDefList>(node.syntax()) {
StructKind::Record(nfdl)
} else if let Some(pfl) = child_opt::<_, ast::TupleFieldDefList>(node) {
} else if let Some(pfl) = support::child::<ast::TupleFieldDefList>(node.syntax()) {
StructKind::Tuple(pfl)
} else {
StructKind::Unit
@ -322,9 +320,9 @@ pub enum TypeBoundKind {
impl ast::TypeBound {
pub fn kind(&self) -> TypeBoundKind {
if let Some(path_type) = children(self).next() {
if let Some(path_type) = support::children(self.syntax()).next() {
TypeBoundKind::PathType(path_type)
} else if let Some(for_type) = children(self).next() {
} else if let Some(for_type) = support::children(self.syntax()).next() {
TypeBoundKind::ForType(for_type)
} else if let Some(lifetime) = self.lifetime_token() {
TypeBoundKind::Lifetime(lifetime)
@ -364,7 +362,7 @@ pub enum VisibilityKind {
impl ast::Visibility {
pub fn kind(&self) -> VisibilityKind {
if let Some(path) = children(self).next() {
if let Some(path) = support::children(self.syntax()).next() {
VisibilityKind::In(path)
} else if self.crate_kw_token().is_some() {
VisibilityKind::PubCrate

View file

@ -5,69 +5,69 @@
use itertools::Itertools;
use crate::{
ast::{self, child_opt, children, support, AstChildren, AstNode, AstToken},
ast::{self, support, AstChildren, AstNode, AstToken},
syntax_node::SyntaxElementChildren,
};
pub trait TypeAscriptionOwner: AstNode {
fn ascribed_type(&self) -> Option<ast::TypeRef> {
child_opt(self)
support::child(self.syntax())
}
}
pub trait NameOwner: AstNode {
fn name(&self) -> Option<ast::Name> {
child_opt(self)
support::child(self.syntax())
}
}
pub trait VisibilityOwner: AstNode {
fn visibility(&self) -> Option<ast::Visibility> {
child_opt(self)
support::child(self.syntax())
}
}
pub trait LoopBodyOwner: AstNode {
fn loop_body(&self) -> Option<ast::BlockExpr> {
child_opt(self)
support::child(self.syntax())
}
fn label(&self) -> Option<ast::Label> {
child_opt(self)
support::child(self.syntax())
}
}
pub trait ArgListOwner: AstNode {
fn arg_list(&self) -> Option<ast::ArgList> {
child_opt(self)
support::child(self.syntax())
}
}
pub trait FnDefOwner: AstNode {
fn functions(&self) -> AstChildren<ast::FnDef> {
children(self)
support::children(self.syntax())
}
}
pub trait ModuleItemOwner: AstNode {
fn items(&self) -> AstChildren<ast::ModuleItem> {
children(self)
support::children(self.syntax())
}
}
pub trait TypeParamsOwner: AstNode {
fn type_param_list(&self) -> Option<ast::TypeParamList> {
child_opt(self)
support::child(self.syntax())
}
fn where_clause(&self) -> Option<ast::WhereClause> {
child_opt(self)
support::child(self.syntax())
}
}
pub trait TypeBoundsOwner: AstNode {
fn type_bound_list(&self) -> Option<ast::TypeBoundList> {
child_opt(self)
support::child(self.syntax())
}
fn colon(&self) -> Option<ast::Colon> {
@ -77,7 +77,7 @@ pub trait TypeBoundsOwner: AstNode {
pub trait AttrsOwner: AstNode {
fn attrs(&self) -> AstChildren<ast::Attr> {
children(self)
support::children(self.syntax())
}
fn has_atom_attr(&self, atom: &str) -> bool {
self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom)