aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast/extensions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/ast/extensions.rs')
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs60
1 files changed, 60 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 76b7655e6..f2ea5088e 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -1,6 +1,8 @@
1//! Various extension methods to ast Nodes, which are hard to code-generate. 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. 2//! Extensions for various expressions live in a sibling `expr_extensions` module.
3 3
4use std::fmt;
5
4use itertools::Itertools; 6use itertools::Itertools;
5use ra_parser::SyntaxKind; 7use ra_parser::SyntaxKind;
6 8
@@ -187,6 +189,64 @@ impl ast::StructDef {
187 } 189 }
188} 190}
189 191
192impl ast::RecordField {
193 pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordField> {
194 let candidate =
195 field_name.syntax().parent().and_then(ast::RecordField::cast).or_else(|| {
196 field_name.syntax().ancestors().nth(4).and_then(ast::RecordField::cast)
197 })?;
198 if candidate.field_name().as_ref() == Some(field_name) {
199 Some(candidate)
200 } else {
201 None
202 }
203 }
204
205 /// Deals with field init shorthand
206 pub fn field_name(&self) -> Option<ast::NameRef> {
207 if let Some(name_ref) = self.name_ref() {
208 return Some(name_ref);
209 }
210 if let Some(ast::Expr::PathExpr(expr)) = self.expr() {
211 let path = expr.path()?;
212 let segment = path.segment()?;
213 let name_ref = segment.name_ref()?;
214 if path.qualifier().is_none() {
215 return Some(name_ref);
216 }
217 }
218 None
219 }
220}
221
222pub enum NameOrNameRef {
223 Name(ast::Name),
224 NameRef(ast::NameRef),
225}
226
227impl fmt::Display for NameOrNameRef {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 match self {
230 NameOrNameRef::Name(it) => fmt::Display::fmt(it, f),
231 NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f),
232 }
233 }
234}
235
236impl ast::RecordFieldPat {
237 /// Deals with field init shorthand
238 pub fn field_name(&self) -> Option<NameOrNameRef> {
239 if let Some(name_ref) = self.name_ref() {
240 return Some(NameOrNameRef::NameRef(name_ref));
241 }
242 if let Some(ast::Pat::BindPat(pat)) = self.pat() {
243 let name = pat.name()?;
244 return Some(NameOrNameRef::Name(name));
245 }
246 None
247 }
248}
249
190impl ast::EnumVariant { 250impl ast::EnumVariant {
191 pub fn parent_enum(&self) -> ast::EnumDef { 251 pub fn parent_enum(&self) -> ast::EnumDef {
192 self.syntax() 252 self.syntax()