2019-04-02 10:02:23 +00:00
|
|
|
//! Various traits that are implemented by ast nodes.
|
|
|
|
//!
|
|
|
|
//! The implementations are usually trivial, and live in generated.rs
|
|
|
|
|
2019-04-02 07:03:19 +00:00
|
|
|
use itertools::Itertools;
|
|
|
|
|
|
|
|
use crate::{
|
2019-07-04 20:05:17 +00:00
|
|
|
ast::{self, child_opt, children, AstChildren, AstNode, AstToken},
|
|
|
|
syntax_node::{SyntaxElementChildren, SyntaxNodeChildren},
|
2019-04-02 07:03:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
pub trait TypeAscriptionOwner: AstNode {
|
2019-07-18 16:23:05 +00:00
|
|
|
fn ascribed_type(&self) -> Option<ast::TypeRef> {
|
2019-04-02 07:03:19 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait NameOwner: AstNode {
|
2019-07-18 16:23:05 +00:00
|
|
|
fn name(&self) -> Option<ast::Name> {
|
2019-04-02 07:03:19 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait VisibilityOwner: AstNode {
|
2019-07-18 16:23:05 +00:00
|
|
|
fn visibility(&self) -> Option<ast::Visibility> {
|
2019-04-02 07:03:19 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait LoopBodyOwner: AstNode {
|
2019-07-18 16:23:05 +00:00
|
|
|
fn loop_body(&self) -> Option<ast::Block> {
|
2019-04-02 07:03:19 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-06 11:36:16 +00:00
|
|
|
pub trait TryBlockBodyOwner: AstNode {
|
2019-07-18 16:23:05 +00:00
|
|
|
fn try_body(&self) -> Option<ast::Block> {
|
2019-06-06 11:36:16 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-02 07:03:19 +00:00
|
|
|
pub trait ArgListOwner: AstNode {
|
2019-07-18 16:23:05 +00:00
|
|
|
fn arg_list(&self) -> Option<ast::ArgList> {
|
2019-04-02 07:03:19 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait FnDefOwner: AstNode {
|
|
|
|
fn functions(&self) -> AstChildren<ast::FnDef> {
|
|
|
|
children(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 16:23:05 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub enum ItemOrMacro {
|
|
|
|
Item(ast::ModuleItem),
|
|
|
|
Macro(ast::MacroCall),
|
2019-04-02 07:03:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait ModuleItemOwner: AstNode {
|
|
|
|
fn items(&self) -> AstChildren<ast::ModuleItem> {
|
|
|
|
children(self)
|
|
|
|
}
|
|
|
|
fn items_with_macros(&self) -> ItemOrMacroIter {
|
|
|
|
ItemOrMacroIter(self.syntax().children())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2019-07-18 16:23:05 +00:00
|
|
|
pub struct ItemOrMacroIter(SyntaxNodeChildren);
|
2019-04-02 07:03:19 +00:00
|
|
|
|
2019-07-18 16:23:05 +00:00
|
|
|
impl Iterator for ItemOrMacroIter {
|
|
|
|
type Item = ItemOrMacro;
|
|
|
|
fn next(&mut self) -> Option<ItemOrMacro> {
|
2019-04-02 07:03:19 +00:00
|
|
|
loop {
|
|
|
|
let n = self.0.next()?;
|
2019-07-18 16:23:05 +00:00
|
|
|
if let Some(item) = ast::ModuleItem::cast(n.clone()) {
|
2019-04-02 07:03:19 +00:00
|
|
|
return Some(ItemOrMacro::Item(item));
|
|
|
|
}
|
|
|
|
if let Some(call) = ast::MacroCall::cast(n) {
|
|
|
|
return Some(ItemOrMacro::Macro(call));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait TypeParamsOwner: AstNode {
|
2019-07-18 16:23:05 +00:00
|
|
|
fn type_param_list(&self) -> Option<ast::TypeParamList> {
|
2019-04-02 07:03:19 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
|
2019-07-18 16:23:05 +00:00
|
|
|
fn where_clause(&self) -> Option<ast::WhereClause> {
|
2019-04-02 07:03:19 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait TypeBoundsOwner: AstNode {
|
2019-07-18 16:23:05 +00:00
|
|
|
fn type_bound_list(&self) -> Option<ast::TypeBoundList> {
|
2019-04-02 07:03:19 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait AttrsOwner: AstNode {
|
|
|
|
fn attrs(&self) -> AstChildren<ast::Attr> {
|
|
|
|
children(self)
|
|
|
|
}
|
|
|
|
fn has_atom_attr(&self, atom: &str) -> bool {
|
|
|
|
self.attrs().filter_map(|x| x.as_atom()).any(|x| x == atom)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait DocCommentsOwner: AstNode {
|
|
|
|
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.
|
2019-07-31 17:59:14 +00:00
|
|
|
/// That is, strips leading `///` (+ optional 1 character of whitespace),
|
|
|
|
/// trailing `*/`, trailing whitespace and then joins the lines.
|
2019-04-02 07:34:34 +00:00
|
|
|
fn doc_comment_text(&self) -> Option<String> {
|
|
|
|
let mut has_comments = false;
|
2019-04-02 07:03:19 +00:00
|
|
|
let docs = self
|
|
|
|
.doc_comments()
|
2019-04-02 09:18:52 +00:00
|
|
|
.filter(|comment| comment.kind().doc.is_some())
|
2019-04-02 07:03:19 +00:00
|
|
|
.map(|comment| {
|
2019-04-02 07:34:34 +00:00
|
|
|
has_comments = true;
|
2019-04-02 07:03:19 +00:00
|
|
|
let prefix_len = comment.prefix().len();
|
|
|
|
|
|
|
|
let line = comment.text().as_str();
|
|
|
|
|
|
|
|
// Determine if the prefix or prefix + 1 char is stripped
|
|
|
|
let pos =
|
|
|
|
if line.chars().nth(prefix_len).map(|c| c.is_whitespace()).unwrap_or(false) {
|
|
|
|
prefix_len + 1
|
|
|
|
} else {
|
|
|
|
prefix_len
|
|
|
|
};
|
|
|
|
|
2019-07-31 15:43:00 +00:00
|
|
|
let end = if comment.kind().shape.is_block() && line.ends_with("*/") {
|
2019-07-31 17:59:14 +00:00
|
|
|
line.len() - 2
|
2019-07-31 15:43:00 +00:00
|
|
|
} else {
|
|
|
|
line.len()
|
|
|
|
};
|
|
|
|
|
2019-07-31 17:59:14 +00:00
|
|
|
line[pos..end].trim_end().to_owned()
|
2019-04-02 07:03:19 +00:00
|
|
|
})
|
|
|
|
.join("\n");
|
|
|
|
|
2019-04-02 07:34:34 +00:00
|
|
|
if has_comments {
|
2019-04-02 07:03:19 +00:00
|
|
|
Some(docs)
|
2019-04-02 07:34:34 +00:00
|
|
|
} else {
|
|
|
|
None
|
2019-04-02 07:03:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 16:23:05 +00:00
|
|
|
pub struct CommentIter {
|
|
|
|
iter: SyntaxElementChildren,
|
2019-04-02 07:03:19 +00:00
|
|
|
}
|
|
|
|
|
2019-07-18 16:23:05 +00:00
|
|
|
impl Iterator for CommentIter {
|
|
|
|
type Item = ast::Comment;
|
|
|
|
fn next(&mut self) -> Option<ast::Comment> {
|
2019-07-19 16:05:34 +00:00
|
|
|
self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast))
|
2019-04-02 07:03:19 +00:00
|
|
|
}
|
|
|
|
}
|
2019-05-03 04:18:35 +00:00
|
|
|
|
|
|
|
pub trait DefaultTypeParamOwner: AstNode {
|
2019-07-18 16:23:05 +00:00
|
|
|
fn default_type(&self) -> Option<ast::PathType> {
|
2019-05-03 04:18:35 +00:00
|
|
|
child_opt(self)
|
|
|
|
}
|
|
|
|
}
|