1 //! Various extension methods to ast Nodes, which are hard to code-generate.
2 //! Extensions for various expressions live in a sibling `expr_extensions` module.
4 use itertools::Itertools;
7 ast::{self, child_opt, children, AstNode, SyntaxNode},
8 SmolStr, SyntaxElement,
12 use ra_parser::SyntaxKind;
15 pub fn text(&self) -> &SmolStr {
16 text_of_first_token(self.syntax())
21 pub fn text(&self) -> &SmolStr {
22 text_of_first_token(self.syntax())
26 fn text_of_first_token(node: &SyntaxNode) -> &SmolStr {
27 node.green().children().first().and_then(|it| it.as_token()).unwrap().text()
31 pub fn is_inner(&self) -> bool {
32 let tt = match self.value() {
37 let prev = match tt.syntax().prev_sibling() {
45 pub fn as_atom(&self) -> Option<SmolStr> {
46 let tt = self.value()?;
47 let (_bra, attr, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
48 if attr.kind() == IDENT {
49 Some(attr.as_token()?.text().clone())
55 pub fn as_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
56 let tt = self.value()?;
57 let (_bra, attr, args, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
58 let args = ast::TokenTree::cast(args.as_node()?.clone())?;
59 if attr.kind() == IDENT {
60 Some((attr.as_token()?.text().clone(), args))
66 pub fn as_named(&self) -> Option<SmolStr> {
67 let tt = self.value()?;
68 let attr = tt.syntax().children_with_tokens().nth(1)?;
69 if attr.kind() == IDENT {
70 Some(attr.as_token()?.text().clone())
76 pub fn as_key_value(&self) -> Option<(SmolStr, SmolStr)> {
77 let tt = self.value()?;
78 let tt_node = tt.syntax();
79 let attr = tt_node.children_with_tokens().nth(1)?;
80 if attr.kind() == IDENT {
81 let key = attr.as_token()?.text().clone();
82 let val_node = tt_node.children_with_tokens().find(|t| t.kind() == STRING)?;
83 let val = val_node.as_token()?.text().trim_start_matches('"').trim_end_matches('"');
84 Some((key, SmolStr::new(val)))
91 #[derive(Debug, Clone, PartialEq, Eq)]
92 pub enum PathSegmentKind {
99 impl ast::PathSegment {
100 pub fn parent_path(&self) -> ast::Path {
103 .and_then(ast::Path::cast)
104 .expect("segments are always nested in paths")
107 pub fn kind(&self) -> Option<PathSegmentKind> {
108 let res = if let Some(name_ref) = self.name_ref() {
109 PathSegmentKind::Name(name_ref)
111 match self.syntax().first_child_or_token()?.kind() {
112 T![self] => PathSegmentKind::SelfKw,
113 T![super] => PathSegmentKind::SuperKw,
114 T![crate] => PathSegmentKind::CrateKw,
121 pub fn has_colon_colon(&self) -> bool {
122 match self.syntax.first_child_or_token().map(|s| s.kind()) {
123 Some(T![::]) => true,
130 pub fn parent_path(&self) -> Option<ast::Path> {
131 self.syntax().parent().and_then(ast::Path::cast)
136 pub fn has_semi(&self) -> bool {
137 match self.syntax().last_child_or_token() {
139 Some(node) => node.kind() == T![;],
145 pub fn has_star(&self) -> bool {
146 self.syntax().children_with_tokens().any(|it| it.kind() == T![*])
150 impl ast::UseTreeList {
151 pub fn parent_use_tree(&self) -> ast::UseTree {
154 .and_then(ast::UseTree::cast)
155 .expect("UseTreeLists are always nested in UseTrees")
159 impl ast::ImplBlock {
160 pub fn target_type(&self) -> Option<ast::TypeRef> {
161 match self.target() {
162 (Some(t), None) | (_, Some(t)) => Some(t),
167 pub fn target_trait(&self) -> Option<ast::TypeRef> {
168 match self.target() {
169 (Some(t), Some(_)) => Some(t),
174 fn target(&self) -> (Option<ast::TypeRef>, Option<ast::TypeRef>) {
175 let mut types = children(self);
176 let first = types.next();
177 let second = types.next();
181 pub fn is_negative(&self) -> bool {
182 self.syntax().children_with_tokens().any(|t| t.kind() == T![!])
186 #[derive(Debug, Clone, PartialEq, Eq)]
187 pub enum StructKind {
188 Tuple(ast::PosFieldDefList),
189 Named(ast::NamedFieldDefList),
194 fn from_node<N: AstNode>(node: &N) -> StructKind {
195 if let Some(nfdl) = child_opt::<_, ast::NamedFieldDefList>(node) {
196 StructKind::Named(nfdl)
197 } else if let Some(pfl) = child_opt::<_, ast::PosFieldDefList>(node) {
198 StructKind::Tuple(pfl)
205 impl ast::StructDef {
206 pub fn is_union(&self) -> bool {
207 for child in self.syntax().children_with_tokens() {
209 T![struct] => return false,
210 T![union] => return true,
217 pub fn kind(&self) -> StructKind {
218 StructKind::from_node(self)
222 impl ast::EnumVariant {
223 pub fn parent_enum(&self) -> ast::EnumDef {
226 .and_then(|it| it.parent())
227 .and_then(ast::EnumDef::cast)
228 .expect("EnumVariants are always nested in Enums")
230 pub fn kind(&self) -> StructKind {
231 StructKind::from_node(self)
236 pub fn semicolon_token(&self) -> Option<SyntaxToken> {
238 .last_child_or_token()
239 .and_then(|it| it.into_token())
240 .filter(|it| it.kind() == T![;])
245 pub fn has_semi(&self) -> bool {
246 match self.syntax().last_child_or_token() {
248 Some(node) => node.kind() == T![;],
254 pub fn has_semi(&self) -> bool {
255 match self.syntax().last_child_or_token() {
257 Some(node) => node.kind() == T![;],
262 #[derive(Debug, Clone, PartialEq, Eq)]
268 impl ast::FieldExpr {
269 pub fn index_token(&self) -> Option<SyntaxToken> {
271 .children_with_tokens()
272 // FIXME: Accepting floats here to reject them in validation later
273 .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER)
275 .and_then(SyntaxElement::as_token)
279 pub fn field_access(&self) -> Option<FieldKind> {
280 if let Some(nr) = self.name_ref() {
281 Some(FieldKind::Name(nr))
282 } else if let Some(tok) = self.index_token() {
283 Some(FieldKind::Index(tok))
291 pub fn is_mut(&self) -> bool {
292 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
297 pub fn is_mutable(&self) -> bool {
298 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
301 pub fn is_ref(&self) -> bool {
302 self.syntax().children_with_tokens().any(|n| n.kind() == T![ref])
306 impl ast::PointerType {
307 pub fn is_mut(&self) -> bool {
308 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
312 impl ast::ReferenceType {
313 pub fn is_mut(&self) -> bool {
314 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
318 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
319 pub enum SelfParamKind {
328 impl ast::SelfParam {
329 pub fn self_kw_token(&self) -> SyntaxToken {
331 .children_with_tokens()
332 .filter_map(|it| it.into_token())
333 .find(|it| it.kind() == T![self])
334 .expect("invalid tree: self param must have self")
337 pub fn kind(&self) -> SelfParamKind {
338 let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == T![&]);
340 // check for a `mut` coming after the & -- `mut &self` != `&mut self`
343 .children_with_tokens()
344 .skip_while(|n| n.kind() != T![&])
345 .any(|n| n.kind() == T![mut])
347 SelfParamKind::MutRef
357 impl ast::LifetimeParam {
358 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
360 .children_with_tokens()
361 .filter_map(|it| it.into_token())
362 .find(|it| it.kind() == LIFETIME)
366 impl ast::WherePred {
367 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
369 .children_with_tokens()
370 .filter_map(|it| it.into_token())
371 .find(|it| it.kind() == LIFETIME)
376 pub fn is_auto(&self) -> bool {
377 self.syntax().children_with_tokens().any(|t| t.kind() == T![auto])