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