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
+17 -25
View File
@@ -42,11 +42,6 @@ fn cast(syntax: SyntaxNode) -> Option<Self>
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 @@ fn text(&self) -> &SmolStr {
}
}
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 @@ fn next(&mut self) -> Option<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]
+1 -2
View File
@@ -6,7 +6,7 @@
use arrayvec::ArrayVec;
use crate::{
algo,
algo::{self, neighbor, SyntaxRewriter},
ast::{
self,
make::{self, tokens},
@@ -16,7 +16,6 @@
SyntaxKind::{ATTR, COMMENT, WHITESPACE},
SyntaxNode, SyntaxToken, T,
};
use algo::{neighbor, SyntaxRewriter};
impl ast::BinExpr {
#[must_use]
+11 -11
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 @@ pub fn else_branch(&self) -> Option<ElseBranch> {
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 @@ pub fn else_branch(&self) -> Option<ElseBranch> {
}
fn blocks(&self) -> AstChildren<ast::BlockExpr> {
children(self)
support::children(self.syntax())
}
}
@@ -212,15 +212,15 @@ pub fn op_token(&self) -> Option<SyntaxToken> {
}
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 @@ pub fn end(&self) -> Option<ast::Expr> {
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()))
}
}
+7 -9
View File
@@ -5,9 +5,7 @@
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 @@ pub fn target_trait(&self) -> Option<ast::TypeRef> {
}
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
+13 -13
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 @@ fn colon(&self) -> Option<ast::Colon> {
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)