1use cairo_lang_utils::LookupIntern;
2use smol_str::SmolStr;
3
4use super::ast::{
5 self, FunctionDeclaration, FunctionDeclarationGreen, FunctionWithBody, FunctionWithBodyPtr,
6 ImplItem, ItemConstant, ItemEnum, ItemExternFunction, ItemExternFunctionPtr, ItemExternType,
7 ItemImpl, ItemImplAlias, ItemInlineMacro, ItemModule, ItemStruct, ItemTrait, ItemTypeAlias,
8 ItemUse, Member, Modifier, ModuleItem, OptionArgListParenthesized, Statement, StatementBreak,
9 StatementContinue, StatementExpr, StatementLet, StatementReturn, TerminalIdentifier,
10 TerminalIdentifierGreen, TokenIdentifierGreen, TraitItem, TraitItemConstant, TraitItemFunction,
11 TraitItemFunctionPtr, TraitItemImpl, TraitItemType, UsePathLeaf, Variant, WrappedArgList,
12};
13use super::db::SyntaxGroup;
14use super::ids::SyntaxStablePtrId;
15use super::kind::SyntaxKind;
16use super::{SyntaxNode, Terminal, TypedStablePtr, TypedSyntaxNode};
17use crate::node::ast::{Attribute, AttributeList};
18use crate::node::green::GreenNodeDetails;
19
20#[cfg(test)]
21#[path = "helpers_test.rs"]
22mod test;
23
24pub trait GetIdentifier {
25 fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr;
26}
27impl ast::UsePathLeafPtr {
28 pub fn name_green(&self, _syntax_db: &dyn SyntaxGroup) -> Self {
29 *self
30 }
31}
32impl GetIdentifier for ast::UsePathLeafPtr {
33 fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
34 let alias_clause_green = self.alias_clause_green(db).0;
35 let green_node = alias_clause_green.lookup_intern(db);
36 let children = match &green_node.details {
37 GreenNodeDetails::Node { children, width: _ } => children,
38 _ => panic!("Unexpected token"),
39 };
40 if !children.is_empty() {
41 return ast::TerminalIdentifierGreen(children[ast::AliasClause::INDEX_ALIAS])
42 .identifier(db);
43 }
44 let ident_green = self.ident_green(db);
45 ident_green.identifier(db)
46 }
47}
48impl GetIdentifier for ast::PathSegmentGreen {
49 fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
51 let green_node = self.0.lookup_intern(db);
52 let children = match &green_node.details {
53 GreenNodeDetails::Node { children, width: _ } => children,
54 _ => panic!("Unexpected token"),
55 };
56 let identifier = ast::TerminalIdentifierGreen(children[0]);
57 identifier.identifier(db)
58 }
59}
60impl GetIdentifier for ast::ExprPathGreen {
61 fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
63 let green_node = self.0.lookup_intern(db);
64 let children = match &green_node.details {
65 GreenNodeDetails::Node { children, width: _ } => children,
66 _ => panic!("Unexpected token"),
67 };
68 assert_eq!(children.len() & 1, 1, "Expected an odd number of elements in the path.");
69 let segment_green = ast::PathSegmentGreen(*children.last().unwrap());
70 segment_green.identifier(db)
71 }
72}
73impl GetIdentifier for ast::TerminalIdentifierGreen {
74 fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
75 match &self.0.lookup_intern(db).details {
76 GreenNodeDetails::Token(_) => "Unexpected token".into(),
77 GreenNodeDetails::Node { children, width: _ } => {
78 TokenIdentifierGreen(children[1]).text(db)
79 }
80 }
81 }
82}
83impl GetIdentifier for ast::ExprPath {
84 fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
86 self.elements(db).last().cloned().unwrap().identifier(db)
87 }
88}
89
90pub trait PathSegmentEx {
92 fn identifier_ast(&self, db: &dyn SyntaxGroup) -> ast::TerminalIdentifier;
93 fn generic_args(&self, db: &dyn SyntaxGroup) -> Option<Vec<ast::GenericArg>>;
94}
95impl PathSegmentEx for ast::PathSegment {
96 fn identifier_ast(&self, db: &dyn SyntaxGroup) -> ast::TerminalIdentifier {
98 match self {
99 ast::PathSegment::Simple(segment) => segment.ident(db),
100 ast::PathSegment::WithGenericArgs(segment) => segment.ident(db),
101 }
102 }
103 fn generic_args(&self, db: &dyn SyntaxGroup) -> Option<Vec<ast::GenericArg>> {
104 match self {
105 ast::PathSegment::Simple(_) => None,
106 ast::PathSegment::WithGenericArgs(segment) => {
107 Some(segment.generic_args(db).generic_args(db).elements(db))
108 }
109 }
110 }
111}
112impl GetIdentifier for ast::PathSegment {
113 fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
115 self.identifier_ast(db).text(db)
116 }
117}
118impl GetIdentifier for ast::Modifier {
119 fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
120 match self {
121 Modifier::Ref(r) => r.text(db),
122 Modifier::Mut(m) => m.text(db),
123 }
124 }
125}
126
127pub trait NameGreen {
129 fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen;
131}
132
133impl NameGreen for FunctionDeclarationGreen {
134 fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen {
135 TerminalIdentifierGreen(
136 self.0.lookup_intern(db).children()[FunctionDeclaration::INDEX_NAME],
137 )
138 }
139}
140
141impl NameGreen for FunctionWithBodyPtr {
142 fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen {
143 self.declaration_green(db).name_green(db)
144 }
145}
146
147impl NameGreen for ItemExternFunctionPtr {
148 fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen {
149 self.declaration_green(db).name_green(db)
150 }
151}
152
153impl NameGreen for TraitItemFunctionPtr {
154 fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen {
155 self.declaration_green(db).name_green(db)
156 }
157}
158
159pub trait HasName {
161 fn name(&self, db: &dyn SyntaxGroup) -> ast::TerminalIdentifier;
163}
164
165impl HasName for FunctionWithBody {
166 fn name(&self, db: &dyn SyntaxGroup) -> TerminalIdentifier {
167 self.declaration(db).name(db)
168 }
169}
170
171impl HasName for ItemExternFunction {
172 fn name(&self, db: &dyn SyntaxGroup) -> TerminalIdentifier {
173 self.declaration(db).name(db)
174 }
175}
176
177impl HasName for TraitItemFunction {
178 fn name(&self, db: &dyn SyntaxGroup) -> TerminalIdentifier {
179 self.declaration(db).name(db)
180 }
181}
182
183impl HasName for UsePathLeaf {
184 fn name(&self, db: &dyn SyntaxGroup) -> TerminalIdentifier {
185 match self.alias_clause(db) {
186 ast::OptionAliasClause::Empty(_) => self.ident(db).identifier_ast(db),
187 ast::OptionAliasClause::AliasClause(alias) => alias.alias(db),
188 }
189 }
190}
191
192pub trait GenericParamEx {
193 fn name(&self, db: &dyn SyntaxGroup) -> Option<ast::TerminalIdentifier>;
195}
196impl GenericParamEx for ast::GenericParam {
197 fn name(&self, db: &dyn SyntaxGroup) -> Option<ast::TerminalIdentifier> {
198 match self {
199 ast::GenericParam::Type(t) => Some(t.name(db)),
200 ast::GenericParam::Const(c) => Some(c.name(db)),
201 ast::GenericParam::ImplNamed(i) => Some(i.name(db)),
202 ast::GenericParam::ImplAnonymous(_) => None,
203 ast::GenericParam::NegativeImpl(_) => None,
204 }
205 }
206}
207
208pub fn is_single_arg_attr(db: &dyn SyntaxGroup, attr: &Attribute, arg_name: &str) -> bool {
210 match attr.arguments(db) {
211 OptionArgListParenthesized::ArgListParenthesized(args) => {
212 matches!(&args.arguments(db).elements(db)[..],
213 [arg] if arg.as_syntax_node().get_text_without_trivia(db) == arg_name)
214 }
215 OptionArgListParenthesized::Empty(_) => false,
216 }
217}
218
219pub trait QueryAttrs {
221 #[doc(hidden)]
225 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute>;
226
227 fn query_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> Vec<Attribute> {
229 self.attributes_elements(db)
230 .into_iter()
231 .filter(|a| a.attr(db).as_syntax_node().get_text_without_trivia(db) == attr)
232 .collect()
233 }
234
235 fn find_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> Option<Attribute> {
237 self.query_attr(db, attr).into_iter().next()
238 }
239
240 fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
242 self.find_attr(db, attr).is_some()
243 }
244
245 fn has_attr_with_arg(&self, db: &dyn SyntaxGroup, attr_name: &str, arg_name: &str) -> bool {
247 self.query_attr(db, attr_name).iter().any(|attr| is_single_arg_attr(db, attr, arg_name))
248 }
249}
250
251impl QueryAttrs for ItemConstant {
252 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
253 self.attributes(db).elements(db)
254 }
255}
256impl QueryAttrs for ItemModule {
257 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
258 self.attributes(db).elements(db)
259 }
260}
261impl QueryAttrs for FunctionWithBody {
262 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
263 self.attributes(db).elements(db)
264 }
265}
266impl QueryAttrs for ItemUse {
267 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
268 self.attributes(db).elements(db)
269 }
270}
271impl QueryAttrs for ItemExternFunction {
272 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
273 self.attributes(db).elements(db)
274 }
275}
276impl QueryAttrs for ItemExternType {
277 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
278 self.attributes(db).elements(db)
279 }
280}
281impl QueryAttrs for ItemTrait {
282 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
283 self.attributes(db).elements(db)
284 }
285}
286impl QueryAttrs for ItemImpl {
287 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
288 self.attributes(db).elements(db)
289 }
290}
291impl QueryAttrs for ItemImplAlias {
292 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
293 self.attributes(db).elements(db)
294 }
295}
296impl QueryAttrs for ItemStruct {
297 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
298 self.attributes(db).elements(db)
299 }
300}
301impl QueryAttrs for ItemEnum {
302 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
303 self.attributes(db).elements(db)
304 }
305}
306impl QueryAttrs for ItemTypeAlias {
307 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
308 self.attributes(db).elements(db)
309 }
310}
311impl QueryAttrs for TraitItemFunction {
312 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
313 self.attributes(db).elements(db)
314 }
315}
316impl QueryAttrs for TraitItemType {
317 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
318 self.attributes(db).elements(db)
319 }
320}
321impl QueryAttrs for TraitItemConstant {
322 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
323 self.attributes(db).elements(db)
324 }
325}
326impl QueryAttrs for TraitItemImpl {
327 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
328 self.attributes(db).elements(db)
329 }
330}
331impl QueryAttrs for TraitItem {
332 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
333 match self {
334 TraitItem::Function(item) => item.attributes_elements(db),
335 TraitItem::Type(item) => item.attributes_elements(db),
336 TraitItem::Constant(item) => item.attributes_elements(db),
337 TraitItem::Impl(item) => item.attributes_elements(db),
338 TraitItem::Missing(_) => vec![],
339 }
340 }
341}
342
343impl QueryAttrs for ItemInlineMacro {
344 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
345 self.attributes(db).elements(db)
346 }
347}
348
349impl QueryAttrs for ModuleItem {
350 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
351 match self {
352 ModuleItem::Constant(item) => item.attributes_elements(db),
353 ModuleItem::Module(item) => item.attributes_elements(db),
354 ModuleItem::FreeFunction(item) => item.attributes_elements(db),
355 ModuleItem::Use(item) => item.attributes_elements(db),
356 ModuleItem::ExternFunction(item) => item.attributes_elements(db),
357 ModuleItem::ExternType(item) => item.attributes_elements(db),
358 ModuleItem::Trait(item) => item.attributes_elements(db),
359 ModuleItem::Impl(item) => item.attributes_elements(db),
360 ModuleItem::ImplAlias(item) => item.attributes_elements(db),
361 ModuleItem::Struct(item) => item.attributes_elements(db),
362 ModuleItem::Enum(item) => item.attributes_elements(db),
363 ModuleItem::TypeAlias(item) => item.attributes_elements(db),
364 ModuleItem::InlineMacro(item) => item.attributes_elements(db),
365 ModuleItem::Missing(_) => vec![],
366 ModuleItem::HeaderDoc(_) => vec![],
367 }
368 }
369}
370
371impl QueryAttrs for ImplItem {
372 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
373 match self {
374 ImplItem::Function(item) => item.attributes_elements(db),
375 ImplItem::Type(item) => item.attributes_elements(db),
376 ImplItem::Constant(item) => item.attributes_elements(db),
377 ImplItem::Impl(item) => item.attributes_elements(db),
378 ImplItem::Module(item) => item.attributes_elements(db),
379 ImplItem::Use(item) => item.attributes_elements(db),
380 ImplItem::ExternFunction(item) => item.attributes_elements(db),
381 ImplItem::ExternType(item) => item.attributes_elements(db),
382 ImplItem::Trait(item) => item.attributes_elements(db),
383 ImplItem::Struct(item) => item.attributes_elements(db),
384 ImplItem::Enum(item) => item.attributes_elements(db),
385 ImplItem::Missing(_) => vec![],
386 }
387 }
388}
389
390impl QueryAttrs for AttributeList {
391 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
392 self.elements(db)
393 }
394}
395impl QueryAttrs for Member {
396 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
397 self.attributes(db).elements(db)
398 }
399}
400
401impl QueryAttrs for Variant {
402 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
403 self.attributes(db).elements(db)
404 }
405}
406
407impl QueryAttrs for StatementBreak {
408 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
409 self.attributes(db).elements(db)
410 }
411}
412
413impl QueryAttrs for StatementContinue {
414 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
415 self.attributes(db).elements(db)
416 }
417}
418
419impl QueryAttrs for StatementReturn {
420 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
421 self.attributes(db).elements(db)
422 }
423}
424
425impl QueryAttrs for StatementLet {
426 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
427 self.attributes(db).elements(db)
428 }
429}
430
431impl QueryAttrs for StatementExpr {
432 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
433 self.attributes(db).elements(db)
434 }
435}
436
437impl QueryAttrs for SyntaxNode {
440 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
441 match self.kind(db) {
442 SyntaxKind::ItemConstant => {
443 ast::ItemConstant::from_syntax_node(db, self.clone()).attributes_elements(db)
444 }
445 SyntaxKind::ItemModule => {
446 ast::ItemModule::from_syntax_node(db, self.clone()).attributes_elements(db)
447 }
448 SyntaxKind::FunctionWithBody => {
449 ast::FunctionWithBody::from_syntax_node(db, self.clone()).attributes_elements(db)
450 }
451 SyntaxKind::ItemUse => {
452 ast::ItemUse::from_syntax_node(db, self.clone()).attributes_elements(db)
453 }
454 SyntaxKind::ItemExternFunction => {
455 ast::ItemExternFunction::from_syntax_node(db, self.clone()).attributes_elements(db)
456 }
457 SyntaxKind::ItemExternType => {
458 ast::ItemExternType::from_syntax_node(db, self.clone()).attributes_elements(db)
459 }
460 SyntaxKind::ItemTrait => {
461 ast::ItemTrait::from_syntax_node(db, self.clone()).attributes_elements(db)
462 }
463 SyntaxKind::ItemImpl => {
464 ast::ItemImpl::from_syntax_node(db, self.clone()).attributes_elements(db)
465 }
466 SyntaxKind::ItemImplAlias => {
467 ast::ItemImplAlias::from_syntax_node(db, self.clone()).attributes_elements(db)
468 }
469 SyntaxKind::ItemStruct => {
470 ast::ItemStruct::from_syntax_node(db, self.clone()).attributes_elements(db)
471 }
472 SyntaxKind::ItemEnum => {
473 ast::ItemEnum::from_syntax_node(db, self.clone()).attributes_elements(db)
474 }
475 SyntaxKind::ItemTypeAlias => {
476 ast::ItemTypeAlias::from_syntax_node(db, self.clone()).attributes_elements(db)
477 }
478 SyntaxKind::TraitItemFunction => {
479 ast::TraitItemFunction::from_syntax_node(db, self.clone()).attributes_elements(db)
480 }
481 SyntaxKind::ItemInlineMacro => {
482 ast::ItemInlineMacro::from_syntax_node(db, self.clone()).attributes_elements(db)
483 }
484 SyntaxKind::AttributeList => {
485 ast::AttributeList::from_syntax_node(db, self.clone()).attributes_elements(db)
486 }
487 SyntaxKind::Member => {
488 ast::Member::from_syntax_node(db, self.clone()).attributes_elements(db)
489 }
490 SyntaxKind::Variant => {
491 ast::Variant::from_syntax_node(db, self.clone()).attributes_elements(db)
492 }
493 SyntaxKind::StatementBreak => {
494 ast::StatementBreak::from_syntax_node(db, self.clone()).attributes_elements(db)
495 }
496 SyntaxKind::StatementContinue => {
497 ast::StatementContinue::from_syntax_node(db, self.clone()).attributes_elements(db)
498 }
499 SyntaxKind::StatementReturn => {
500 ast::StatementReturn::from_syntax_node(db, self.clone()).attributes_elements(db)
501 }
502 SyntaxKind::StatementLet => {
503 ast::StatementLet::from_syntax_node(db, self.clone()).attributes_elements(db)
504 }
505 SyntaxKind::StatementExpr => {
506 ast::StatementExpr::from_syntax_node(db, self.clone()).attributes_elements(db)
507 }
508 _ => vec![],
509 }
510 }
511}
512
513impl QueryAttrs for Statement {
514 fn attributes_elements(&self, db: &dyn SyntaxGroup) -> Vec<Attribute> {
515 match self {
516 Statement::Break(statement) => statement.attributes_elements(db),
517 Statement::Continue(statement) => statement.attributes_elements(db),
518 Statement::Return(statement) => statement.attributes_elements(db),
519 Statement::Let(statement) => statement.attributes_elements(db),
520 Statement::Expr(statement) => statement.attributes_elements(db),
521 Statement::Item(statement) => statement.item(db).attributes_elements(db),
522 Statement::Missing(_) => vec![],
523 }
524 }
525}
526pub trait WrappedArgListHelper {
527 fn arg_list(&self, db: &dyn SyntaxGroup) -> Option<ast::ArgList>;
529 fn right_bracket_syntax_node(&self, db: &dyn SyntaxGroup) -> SyntaxNode;
531 fn left_bracket_syntax_node(&self, db: &dyn SyntaxGroup) -> SyntaxNode;
533 fn left_bracket_stable_ptr(&self, db: &dyn SyntaxGroup) -> SyntaxStablePtrId;
535}
536impl WrappedArgListHelper for WrappedArgList {
537 fn arg_list(&self, db: &dyn SyntaxGroup) -> Option<ast::ArgList> {
538 match self {
539 WrappedArgList::ParenthesizedArgList(args) => Some(args.arguments(db)),
540 WrappedArgList::BracketedArgList(args) => Some(args.arguments(db)),
541 WrappedArgList::BracedArgList(args) => Some(args.arguments(db)),
542 WrappedArgList::Missing(_) => None,
543 }
544 }
545
546 fn right_bracket_syntax_node(&self, db: &dyn SyntaxGroup) -> SyntaxNode {
547 match self {
548 WrappedArgList::ParenthesizedArgList(args) => args.rparen(db).as_syntax_node(),
549 WrappedArgList::BracketedArgList(args) => args.rbrack(db).as_syntax_node(),
550 WrappedArgList::BracedArgList(args) => args.rbrace(db).as_syntax_node(),
551 WrappedArgList::Missing(_) => self.as_syntax_node(),
552 }
553 }
554
555 fn left_bracket_syntax_node(&self, db: &dyn SyntaxGroup) -> SyntaxNode {
556 match self {
557 WrappedArgList::ParenthesizedArgList(args) => args.lparen(db).as_syntax_node(),
558 WrappedArgList::BracketedArgList(args) => args.lbrack(db).as_syntax_node(),
559 WrappedArgList::BracedArgList(args) => args.lbrace(db).as_syntax_node(),
560 WrappedArgList::Missing(_) => self.as_syntax_node(),
561 }
562 }
563
564 fn left_bracket_stable_ptr(&self, db: &dyn SyntaxGroup) -> SyntaxStablePtrId {
565 match self {
566 WrappedArgList::ParenthesizedArgList(args) => (&args.lparen(db)).into(),
567 WrappedArgList::BracketedArgList(args) => (&args.lbrack(db)).into(),
568 WrappedArgList::BracedArgList(args) => (&args.lbrace(db)).into(),
569 WrappedArgList::Missing(_) => self.into(),
570 }
571 }
572}
573
574pub trait WrappedGenericParamListHelper {
575 fn is_empty(&self, db: &dyn SyntaxGroup) -> bool;
577}
578impl WrappedGenericParamListHelper for ast::WrappedGenericParamList {
579 fn is_empty(&self, db: &dyn SyntaxGroup) -> bool {
580 self.generic_params(db).elements(db).is_empty()
581 }
582}
583
584pub trait OptionWrappedGenericParamListHelper {
585 fn is_empty(&self, db: &dyn SyntaxGroup) -> bool;
588}
589impl OptionWrappedGenericParamListHelper for ast::OptionWrappedGenericParamList {
590 fn is_empty(&self, db: &dyn SyntaxGroup) -> bool {
591 match self {
592 ast::OptionWrappedGenericParamList::Empty(_) => true,
593 ast::OptionWrappedGenericParamList::WrappedGenericParamList(
594 wrapped_generic_param_list,
595 ) => wrapped_generic_param_list.is_empty(db),
596 }
597 }
598}
599
600pub trait BodyItems {
602 type Item;
604 fn items_vec(&self, db: &dyn SyntaxGroup) -> Vec<Self::Item>;
612}
613
614impl BodyItems for ast::ModuleBody {
615 type Item = ModuleItem;
616 fn items_vec(&self, db: &dyn SyntaxGroup) -> Vec<ModuleItem> {
617 self.items(db).elements(db)
618 }
619}
620
621impl BodyItems for ast::TraitBody {
622 type Item = TraitItem;
623 fn items_vec(&self, db: &dyn SyntaxGroup) -> Vec<TraitItem> {
624 self.items(db).elements(db)
625 }
626}
627
628impl BodyItems for ast::ImplBody {
629 type Item = ImplItem;
630 fn items_vec(&self, db: &dyn SyntaxGroup) -> Vec<ImplItem> {
631 self.items(db).elements(db)
632 }
633}
634
635pub trait UsePathEx {
637 fn get_item(&self, db: &dyn SyntaxGroup) -> ast::ItemUse;
639}
640impl UsePathEx for ast::UsePath {
641 fn get_item(&self, db: &dyn SyntaxGroup) -> ast::ItemUse {
642 let mut node = self.as_syntax_node();
643 loop {
644 let Some(parent) = node.parent() else {
645 unreachable!("UsePath is not under an ItemUse.");
646 };
647 match parent.kind(db) {
648 SyntaxKind::ItemUse => {
649 break ast::ItemUse::from_syntax_node(db, parent);
650 }
651 _ => node = parent,
652 }
653 }
654 }
655}
656
657impl UsePathLeaf {
658 pub fn name_stable_ptr(&self, db: &dyn SyntaxGroup) -> SyntaxStablePtrId {
660 match self.alias_clause(db) {
661 ast::OptionAliasClause::Empty(_) => self.ident(db).stable_ptr().untyped(),
662 ast::OptionAliasClause::AliasClause(alias) => alias.alias(db).stable_ptr().untyped(),
663 }
664 }
665}
666
667pub trait IsDependentType {
669 fn is_dependent_type(&self, db: &dyn SyntaxGroup, identifiers: &[&str]) -> bool;
674}
675
676impl IsDependentType for ast::ExprPath {
677 fn is_dependent_type(&self, db: &dyn SyntaxGroup, identifiers: &[&str]) -> bool {
678 let segments = self.elements(db);
679 if let [ast::PathSegment::Simple(arg_segment)] = &segments[..] {
680 identifiers.contains(&arg_segment.ident(db).text(db).as_str())
681 } else {
682 segments.into_iter().any(|segment| {
683 let ast::PathSegment::WithGenericArgs(with_generics) = segment else {
684 return false;
685 };
686 with_generics.generic_args(db).generic_args(db).elements(db).iter().any(|arg| {
687 let generic_arg_value = match arg {
688 ast::GenericArg::Named(named) => named.value(db),
689 ast::GenericArg::Unnamed(unnamed) => unnamed.value(db),
690 };
691 match generic_arg_value {
692 ast::GenericArgValue::Expr(arg_expr) => {
693 arg_expr.expr(db).is_dependent_type(db, identifiers)
694 }
695 ast::GenericArgValue::Underscore(_) => false,
696 }
697 })
698 })
699 }
700 }
701}
702
703impl IsDependentType for ast::Expr {
704 fn is_dependent_type(&self, db: &dyn SyntaxGroup, identifiers: &[&str]) -> bool {
705 match self {
706 ast::Expr::Path(type_path) => type_path.is_dependent_type(db, identifiers),
707 ast::Expr::Unary(unary) => unary.expr(db).is_dependent_type(db, identifiers),
708 ast::Expr::Binary(binary) => {
709 binary.lhs(db).is_dependent_type(db, identifiers)
710 || binary.rhs(db).is_dependent_type(db, identifiers)
711 }
712 ast::Expr::Tuple(tuple) => tuple
713 .expressions(db)
714 .elements(db)
715 .iter()
716 .any(|expr| expr.is_dependent_type(db, identifiers)),
717 ast::Expr::FixedSizeArray(arr) => {
718 arr.exprs(db)
719 .elements(db)
720 .iter()
721 .any(|expr| expr.is_dependent_type(db, identifiers))
722 || match arr.size(db) {
723 ast::OptionFixedSizeArraySize::Empty(_) => false,
724 ast::OptionFixedSizeArraySize::FixedSizeArraySize(size) => {
725 size.size(db).is_dependent_type(db, identifiers)
726 }
727 }
728 }
729 ast::Expr::Literal(_)
730 | ast::Expr::ShortString(_)
731 | ast::Expr::String(_)
732 | ast::Expr::False(_)
733 | ast::Expr::True(_)
734 | ast::Expr::Parenthesized(_)
735 | ast::Expr::FunctionCall(_)
736 | ast::Expr::StructCtorCall(_)
737 | ast::Expr::Block(_)
738 | ast::Expr::Match(_)
739 | ast::Expr::If(_)
740 | ast::Expr::Loop(_)
741 | ast::Expr::While(_)
742 | ast::Expr::For(_)
743 | ast::Expr::Closure(_)
744 | ast::Expr::ErrorPropagate(_)
745 | ast::Expr::FieldInitShorthand(_)
746 | ast::Expr::Indexed(_)
747 | ast::Expr::InlineMacro(_)
748 | ast::Expr::Missing(_) => false,
749 }
750 }
751}