mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Remove code duplication
This commit is contained in:
parent
33df20868d
commit
e07d3c94de
5 changed files with 49 additions and 60 deletions
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue