rust-analyzer/crates/ra_syntax/src/ast/traits.rs

137 lines
3.6 KiB
Rust
Raw Normal View History

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::{
ast::{self, child_opt, children, AstChildren, AstNode, AstToken},
2020-03-26 15:10:01 +00:00
syntax_node::SyntaxElementChildren,
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-09-02 18:23:19 +00:00
fn loop_body(&self) -> Option<ast::BlockExpr> {
2019-04-02 07:03:19 +00:00
child_opt(self)
}
}
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)
}
}
pub trait ModuleItemOwner: AstNode {
fn items(&self) -> AstChildren<ast::ModuleItem> {
children(self)
}
}
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 {
2019-09-29 21:15:03 +00:00
self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom)
2019-04-02 07:03:19 +00:00
}
}
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.
/// 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: &str = comment.text().as_str();
2019-04-02 07:03:19 +00:00
// Determine if the prefix or prefix + 1 char is stripped
let pos =
if let Some(ws) = line.chars().nth(prefix_len).filter(|c| c.is_whitespace()) {
prefix_len + ws.len_utf8()
2019-04-02 07:03:19 +00:00
} else {
prefix_len
};
2019-07-31 15:43:00 +00:00
let end = if comment.kind().shape.is_block() && line.ends_with("*/") {
line.len() - 2
2019-07-31 15:43:00 +00:00
} else {
line.len()
};
// Note that we do not trim the end of the line here
// since whitespace can have special meaning at the end
// of a line in markdown.
line[pos..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
}
}