diff options
Diffstat (limited to 'crates/ra_syntax/src/ast/extensions.rs')
-rw-r--r-- | crates/ra_syntax/src/ast/extensions.rs | 60 |
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 | ||
4 | use std::fmt; | ||
5 | |||
4 | use itertools::Itertools; | 6 | use itertools::Itertools; |
5 | use ra_parser::SyntaxKind; | 7 | use ra_parser::SyntaxKind; |
6 | 8 | ||
@@ -187,6 +189,64 @@ impl ast::StructDef { | |||
187 | } | 189 | } |
188 | } | 190 | } |
189 | 191 | ||
192 | impl 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 | |||
222 | pub enum NameOrNameRef { | ||
223 | Name(ast::Name), | ||
224 | NameRef(ast::NameRef), | ||
225 | } | ||
226 | |||
227 | impl 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 | |||
236 | impl 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 | |||
190 | impl ast::EnumVariant { | 250 | impl ast::EnumVariant { |
191 | pub fn parent_enum(&self) -> ast::EnumDef { | 251 | pub fn parent_enum(&self) -> ast::EnumDef { |
192 | self.syntax() | 252 | self.syntax() |