• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

perf-toolbox / tir / 12097958782

30 Nov 2024 04:42PM UTC coverage: 86.283% (-1.0%) from 87.302%
12097958782

Pull #118

github

web-flow
Merge 063db9841 into f95be4d3a
Pull Request #118: feat: generate register description with TMDL

1044 of 1118 new or added lines in 10 files covered. (93.38%)

2 existing lines in 1 file now uncovered.

6334 of 7341 relevant lines covered (86.28%)

7323.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.84
/tmdl/src/ast.rs
1
use core::fmt;
2

3
use lpl::{syntax::NodeOrToken, Span};
4

5
use crate::{SyntaxElement, SyntaxKind, SyntaxNode};
6

7
macro_rules! ast_with_doc {
8
    ($name: ident) => {
9
        impl $name {
10
            pub fn doc(&self) -> Option<String> {
176✔
11
                let all: Vec<_> = self
176✔
12
                    .syntax()
176✔
13
                    .children()
176✔
14
                    .filter_map(|c| match c {
608✔
15
                        NodeOrToken::Token(t) if t.kind() == SyntaxKind::LocalDocComment => {
440✔
16
                            Some(t.text().to_string())
24✔
17
                        }
18
                        _ => None,
584✔
19
                    })
608✔
20
                    .collect();
176✔
21

176✔
22
                if all.is_empty() {
176✔
23
                    None
164✔
24
                } else {
25
                    Some(all.join("\n"))
12✔
26
                }
27
            }
176✔
28
        }
29
    };
30
}
31

32
macro_rules! trivial_ast_node {
33
    ($name: ident, $kind:expr) => {
34
        #[repr(transparent)]
35
        #[derive(Clone)]
36
        pub struct $name(SyntaxNode);
37

38
        impl $name {
39
            pub fn new(root: SyntaxNode) -> Option<Self> {
1,032✔
40
                if root.kind() != $kind {
1,032✔
NEW
41
                    return None;
×
42
                }
1,032✔
43

1,032✔
44
                Some(Self(root))
1,032✔
45
            }
1,032✔
46
        }
47

48
        impl ASTNode for $name {
49
            fn syntax(&self) -> &SyntaxNode {
2,306✔
50
                &self.0
2,306✔
51
            }
2,306✔
52
        }
53
    };
54

55
    ($name: ident, $kind:expr, with_doc) => {
56
        trivial_ast_node!($name, $kind);
57
        ast_with_doc!($name);
58
    };
59
}
60

61
macro_rules! ast_printer {
62
    ($name: ident, $($field:ident),+) => {
63
        impl fmt::Debug for $name {
64
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172✔
65
                f.debug_struct(stringify!($name))
172✔
66
                    $(
172✔
67
                    .field(stringify!($field), &self.$field())
172✔
68
                    )*
172✔
69
                    .finish()
172✔
70
            }
172✔
71
        }
72
    }
73
}
74

75
pub trait ASTNode {
76
    fn syntax(&self) -> &SyntaxNode;
NEW
77
    fn span(&self) -> Span {
×
NEW
78
        self.syntax().span()
×
NEW
79
    }
×
80
}
81

82
pub trait ExprNode {
83
    fn ty(&self) -> &Type;
84
}
85

86
pub trait AttrListOwner: ASTNode {
87
    fn attr_list(&self) -> Option<AttrList> {
304✔
88
        self.syntax()
304✔
89
            .children()
304✔
90
            .find(|c| match c {
304✔
91
                NodeOrToken::Node(n) => n.kind() == SyntaxKind::AttrList,
304✔
NEW
92
                _ => false,
×
93
            })
304✔
94
            .and_then(|c| AttrList::new(c.as_node().clone()))
304✔
95
    }
304✔
96
}
97

98
#[derive(Clone)]
99
pub enum Type {
100
    Bits(u16),
101
    String,
102
    Integer,
103
    Unresolved(SyntaxElement),
104
    Void,
105
}
106

107
trivial_ast_node!(AttrList, SyntaxKind::AttrList);
108
trivial_ast_node!(Attr, SyntaxKind::Attr);
109

110
#[derive(Clone)]
111
pub enum Item {
112
    InstrTemplateDecl(InstrTemplateDecl),
113
    InstrDecl(InstrDecl),
114
    EncodingDecl(EncodingDecl),
115
    AsmDecl(AsmDecl),
116
    EnumDecl(EnumDecl),
117
    ImplDecl(ImplDecl),
118
    FlagDecl(FlagDecl),
119
    FnDecl(FnDecl),
120
}
121

122
#[derive(Clone)]
123
pub struct SourceFile {
124
    syntax: SyntaxNode,
125
    items: Vec<Item>,
126
}
127

128
#[derive(Clone)]
129
pub struct InstrTemplateDecl {
130
    syntax: SyntaxNode,
131
    params: Vec<InstrTemplateParameterDecl>,
132
    fields: Vec<StructFieldDecl>,
133
    parent_template: Option<SyntaxNode>,
134
    parent_template_args: Vec<InstrTemplateArg>,
135
}
136

137
trivial_ast_node!(
138
    InstrTemplateParameterDecl,
139
    SyntaxKind::InstrTemplateSingleParam
140
);
141

142
#[derive(Clone)]
143
pub struct InstrDecl {
144
    syntax: SyntaxNode,
145
    template_args: Vec<InstrTemplateArg>,
146
}
147

148
trivial_ast_node!(InstrTemplateArg, SyntaxKind::InstrParentTemplateArg);
149

150
#[derive(Clone)]
151
pub struct EncodingDecl {
152
    #[allow(dead_code)]
153
    syntax: SyntaxNode,
154
    body: BlockExpr,
155
}
156

157
#[derive(Clone)]
158
pub struct AsmDecl {
159
    #[allow(dead_code)]
160
    syntax: SyntaxNode,
161
    body: BlockExpr,
162
}
163

164
trivial_ast_node!(ImplDecl, SyntaxKind::ImplDecl);
165
ast_printer!(ImplDecl, trait_name, target_name);
166

167
trivial_ast_node!(StructFieldDecl, SyntaxKind::StructField);
168
ast_printer!(StructFieldDecl, name, ty);
169

170
#[derive(Clone)]
171
pub struct EnumDecl {
172
    syntax: SyntaxNode,
173
    variants: Vec<EnumVariantDecl>,
174
}
175
ast_with_doc!(EnumDecl);
176

177
trivial_ast_node!(EnumVariantDecl, SyntaxKind::EnumVariantDecl, with_doc);
178
trivial_ast_node!(FlagDecl, SyntaxKind::FlagDecl, with_doc);
179
ast_printer!(FlagDecl, name, doc);
180

181
#[derive(Clone)]
182
pub enum Expr {
183
    Literal(LiteralExpr),
184
    Block(BlockExpr),
185
    List(ListExpr),
186
    BinOp(BinOpExpr),
187
}
188

189
#[derive(Clone)]
190
pub struct LiteralExpr {
191
    #[allow(dead_code)]
192
    syntax: SyntaxNode,
193
    ty: Type,
194
}
195

196
#[derive(Clone)]
197
pub struct BlockExpr {
198
    #[allow(dead_code)]
199
    syntax: SyntaxNode,
200
    stmts: Vec<Expr>,
201
    ty: Type,
202
}
203

204
#[derive(Clone)]
205
pub struct ListExpr {
206
    #[allow(dead_code)]
207
    syntax: SyntaxNode,
208
    elements: Vec<Expr>,
209
    ty: Type,
210
}
211

212
#[derive(Clone, Debug)]
213
pub enum BinOpKind {
214
    BitConcat,
215
}
216

217
#[derive(Clone)]
218
pub struct BinOpExpr {
219
    #[allow(dead_code)]
220
    syntax: SyntaxNode,
221
    kind: BinOpKind,
222
    left: Box<Expr>,
223
    right: Box<Expr>,
224
}
225

226
trivial_ast_node!(FnDecl, SyntaxKind::FnDecl);
227
ast_printer!(FnDecl, signature, body);
228
trivial_ast_node!(FnSignature, SyntaxKind::FnSignature);
229
trivial_ast_node!(FnParam, SyntaxKind::FnParam);
230

231
impl Type {
232
    pub fn new(syntax: SyntaxNode) -> Option<Type> {
46✔
233
        if syntax.kind() != SyntaxKind::Type {
46✔
234
            return None;
×
235
        }
46✔
236

237
        let ident = syntax
46✔
238
            .children()
46✔
239
            .find(|c| {
94✔
240
                if let NodeOrToken::Token(token) = c {
94✔
241
                    token.kind() == SyntaxKind::Identifier
94✔
242
                } else {
243
                    false
×
244
                }
245
            })?
94✔
246
            .as_token()
46✔
247
            .text()
46✔
248
            .to_string();
46✔
249

46✔
250
        match ident.as_ref() {
46✔
251
            "str" => Some(Type::String),
46✔
252
            "bits" => {
38✔
253
                let param = syntax
26✔
254
                    .children()
26✔
255
                    .find_map(|c| match c {
78✔
256
                        NodeOrToken::Node(node) if node.kind() == SyntaxKind::TypeParams => {
26✔
257
                            Some(node)
26✔
258
                        }
259
                        _ => None,
52✔
260
                    })
78✔
261
                    .iter()
26✔
262
                    .flat_map(|n| n.children())
26✔
263
                    .find_map(|c| match c {
52✔
264
                        NodeOrToken::Node(node) if node.kind() == SyntaxKind::LiteralExpr => {
26✔
265
                            Some(node)
26✔
266
                        }
267
                        _ => None,
26✔
268
                    })
52✔
269
                    .iter()
26✔
270
                    .flat_map(|n| n.children())
26✔
271
                    .find_map(|c| match c {
26✔
272
                        NodeOrToken::Token(token) if token.kind() == SyntaxKind::IntegerLiteral => {
26✔
273
                            Some(token.text().to_string())
26✔
274
                        }
275
                        _ => None,
×
276
                    })?;
26✔
277

278
                let num_bits = param.parse::<u16>().ok()?;
26✔
279

280
                Some(Type::Bits(num_bits))
26✔
281
            }
282
            _ => Some(Type::Unresolved(NodeOrToken::Node(syntax))),
12✔
283
        }
284
    }
46✔
285
}
286

287
impl fmt::Debug for Type {
288
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122✔
289
        match self {
122✔
290
            Type::Unresolved(_) => write!(f, "<unresolved>"),
38✔
291
            Type::String => write!(f, "str"),
48✔
292
            Type::Bits(num) => write!(f, "bits<{}>", num),
26✔
293
            Type::Integer => write!(f, "int"),
10✔
NEW
294
            Type::Void => write!(f, "()"),
×
295
        }
296
    }
122✔
297
}
298

299
impl Item {
300
    pub fn name(&self) -> String {
42✔
301
        match self {
42✔
302
            Item::InstrDecl(instr) => instr.name(),
20✔
303
            Item::InstrTemplateDecl(instr) => instr.name(),
8✔
304
            Item::EnumDecl(instr) => instr.name(),
6✔
305
            Item::FnDecl(fn_) => fn_.signature().name(),
2✔
306
            _ => "unknown".to_owned(),
6✔
307
        }
308
    }
42✔
309
}
310

311
impl fmt::Debug for Item {
312
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44✔
313
        match self {
44✔
314
            Item::InstrTemplateDecl(i) => i.fmt(f),
8✔
315
            Item::InstrDecl(i) => i.fmt(f),
20✔
316
            Item::EncodingDecl(i) => i.fmt(f),
4✔
317
            Item::AsmDecl(i) => i.fmt(f),
4✔
318
            Item::EnumDecl(i) => i.fmt(f),
2✔
319
            Item::ImplDecl(i) => i.fmt(f),
2✔
320
            Item::FlagDecl(i) => i.fmt(f),
2✔
321
            Item::FnDecl(i) => i.fmt(f),
2✔
322
        }
323
    }
44✔
324
}
325

326
impl From<InstrTemplateDecl> for Item {
327
    fn from(i: InstrTemplateDecl) -> Self {
16✔
328
        Item::InstrTemplateDecl(i)
16✔
329
    }
16✔
330
}
331

332
impl From<InstrDecl> for Item {
333
    fn from(i: InstrDecl) -> Self {
40✔
334
        Item::InstrDecl(i)
40✔
335
    }
40✔
336
}
337

338
impl From<EncodingDecl> for Item {
339
    fn from(i: EncodingDecl) -> Self {
8✔
340
        Item::EncodingDecl(i)
8✔
341
    }
8✔
342
}
343

344
impl From<AsmDecl> for Item {
345
    fn from(i: AsmDecl) -> Self {
8✔
346
        Item::AsmDecl(i)
8✔
347
    }
8✔
348
}
349

350
impl From<EnumDecl> for Item {
351
    fn from(i: EnumDecl) -> Self {
8✔
352
        Item::EnumDecl(i)
8✔
353
    }
8✔
354
}
355

356
impl From<ImplDecl> for Item {
357
    fn from(i: ImplDecl) -> Self {
8✔
358
        Item::ImplDecl(i)
8✔
359
    }
8✔
360
}
361

362
impl From<FlagDecl> for Item {
363
    fn from(i: FlagDecl) -> Self {
8✔
364
        Item::FlagDecl(i)
8✔
365
    }
8✔
366
}
367

368
impl From<FnDecl> for Item {
369
    fn from(i: FnDecl) -> Self {
4✔
370
        Item::FnDecl(i)
4✔
371
    }
4✔
372
}
373

374
impl SourceFile {
375
    pub fn new(root: SyntaxNode) -> Option<SourceFile> {
8✔
376
        if root.kind() != SyntaxKind::TranslationUnit {
8✔
377
            return None;
×
378
        }
8✔
379

8✔
380
        let items = root
8✔
381
            .children()
8✔
382
            .filter_map(|child| match child {
188✔
383
                NodeOrToken::Node(node) => match node.kind() {
100✔
384
                    SyntaxKind::InstrTemplateDecl => {
385
                        InstrTemplateDecl::new(node.clone()).map(|t| t.into())
16✔
386
                    }
387
                    SyntaxKind::InstrDecl => InstrDecl::new(node.clone()).map(|t| t.into()),
40✔
388
                    SyntaxKind::EncodingDecl => EncodingDecl::new(node.clone()).map(|t| t.into()),
8✔
389
                    SyntaxKind::AsmDecl => AsmDecl::new(node.clone()).map(|t| t.into()),
8✔
390
                    SyntaxKind::EnumDecl => EnumDecl::new(node.clone()).map(|t| t.into()),
8✔
391
                    SyntaxKind::ImplDecl => ImplDecl::new(node.clone()).map(|t| t.into()),
8✔
392
                    SyntaxKind::FlagDecl => FlagDecl::new(node.clone()).map(|t| t.into()),
8✔
393
                    SyntaxKind::FnDecl => FnDecl::new(node.clone()).map(|t| t.into()),
4✔
UNCOV
394
                    _ => None,
×
395
                },
396
                _ => None,
88✔
397
            })
188✔
398
            .collect();
8✔
399

8✔
400
        Some(SourceFile {
8✔
401
            syntax: root,
8✔
402
            items,
8✔
403
        })
8✔
404
    }
8✔
405

406
    pub fn items(&self) -> std::slice::Iter<'_, Item> {
14✔
407
        self.items.iter()
14✔
408
    }
14✔
409
}
410

411
impl ASTNode for SourceFile {
412
    fn syntax(&self) -> &SyntaxNode {
×
413
        &self.syntax
×
414
    }
×
415

416
    fn span(&self) -> Span {
×
417
        self.syntax().span()
×
418
    }
×
419
}
420

421
ast_printer!(SourceFile, items);
422

423
impl InstrTemplateDecl {
424
    pub fn new(syntax: SyntaxNode) -> Option<InstrTemplateDecl> {
16✔
425
        if syntax.kind() != SyntaxKind::InstrTemplateDecl {
16✔
426
            return None;
×
427
        }
16✔
428

16✔
429
        let params = syntax
16✔
430
            .children()
16✔
431
            .find_map(|c| match c {
72✔
432
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrTemplateParams => {
32✔
433
                    Some(node)
16✔
434
                }
435
                _ => None,
56✔
436
            })
72✔
437
            .iter()
16✔
438
            .flat_map(|n| n.children())
16✔
439
            .filter_map(|c| match c {
144✔
440
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrTemplateSingleParam => {
64✔
441
                    InstrTemplateParameterDecl::new(node)
64✔
442
                }
443
                _ => None,
80✔
444
            })
144✔
445
            .collect::<Vec<_>>();
16✔
446

16✔
447
        let fields = syntax
16✔
448
            .children()
16✔
449
            .find_map(|c| match c {
128✔
450
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::StructBody => Some(node),
56✔
451
                _ => None,
112✔
452
            })
128✔
453
            .iter()
16✔
454
            .flat_map(|n| n.children())
16✔
455
            .filter_map(|c| match c {
88✔
456
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::StructField => {
24✔
457
                    StructFieldDecl::new(node)
24✔
458
                }
459
                _ => None,
64✔
460
            })
88✔
461
            .collect::<Vec<_>>();
16✔
462

16✔
463
        let parent_template = syntax.children().find_map(|c| match c {
112✔
464
            NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrParentTemplate => Some(node),
48✔
465
            _ => None,
104✔
466
        });
112✔
467
        let parent_template_args = syntax
16✔
468
            .children()
16✔
469
            .find_map(|c| match c {
112✔
470
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrParentTemplate => {
48✔
471
                    Some(node)
8✔
472
                }
473
                _ => None,
104✔
474
            })
112✔
475
            .iter()
16✔
476
            .flat_map(|n| n.children())
16✔
477
            .filter_map(|c| match c {
88✔
478
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrParentTemplateArg => {
40✔
479
                    InstrTemplateArg::new(node)
32✔
480
                }
481
                _ => None,
56✔
482
            })
88✔
483
            .collect::<Vec<_>>();
16✔
484

16✔
485
        Some(Self {
16✔
486
            syntax,
16✔
487
            params,
16✔
488
            fields,
16✔
489
            parent_template,
16✔
490
            parent_template_args,
16✔
491
        })
16✔
492
    }
16✔
493

494
    pub fn name(&self) -> String {
16✔
495
        self.syntax
16✔
496
            .children()
16✔
497
            .find_map(|child| match child {
56✔
498
                NodeOrToken::Node(node) => {
16✔
499
                    if node.kind() == SyntaxKind::InstrTemplateName {
16✔
500
                        Some(node)
16✔
501
                    } else {
502
                        None
×
503
                    }
504
                }
505
                _ => None,
40✔
506
            })
56✔
507
            .iter()
16✔
508
            .flat_map(|node| node.children())
16✔
509
            .find_map(|child| match child {
16✔
510
                crate::SyntaxElement::Token(token) => {
16✔
511
                    if token.kind() == SyntaxKind::Identifier {
16✔
512
                        Some(token.text().to_string())
16✔
513
                    } else {
514
                        None
×
515
                    }
516
                }
517
                _ => None,
×
518
            })
16✔
519
            .unwrap_or("unknown".to_string())
16✔
520
    }
16✔
521

522
    pub fn parameters(&self) -> &[InstrTemplateParameterDecl] {
8✔
523
        &self.params
8✔
524
    }
8✔
525

526
    pub fn fields(&self) -> &[StructFieldDecl] {
48✔
527
        &self.fields
48✔
528
    }
48✔
529

530
    pub fn has_parent_template(&self) -> bool {
×
531
        self.parent_template.is_some()
×
532
    }
×
533

534
    pub fn parent_template_name(&self) -> Option<String> {
48✔
535
        self.parent_template
48✔
536
            .iter()
48✔
537
            .flat_map(|c| c.children())
48✔
538
            .find_map(|child| match child {
48✔
539
                NodeOrToken::Node(node) => {
24✔
540
                    if node.kind() == SyntaxKind::InstrParentTemplateName {
24✔
541
                        Some(node)
24✔
542
                    } else {
543
                        None
×
544
                    }
545
                }
546
                _ => None,
24✔
547
            })
48✔
548
            .iter()
48✔
549
            .flat_map(|node| node.children())
48✔
550
            .find_map(|child| match child {
48✔
551
                crate::SyntaxElement::Token(token) => {
24✔
552
                    if token.kind() == SyntaxKind::Identifier {
24✔
553
                        Some(token.text().to_string())
24✔
554
                    } else {
555
                        None
×
556
                    }
557
                }
558
                _ => None,
×
559
            })
48✔
560
    }
48✔
561

562
    pub fn parent_template_args(&self) -> std::slice::Iter<'_, InstrTemplateArg> {
8✔
563
        self.parent_template_args.iter()
8✔
564
    }
8✔
565
}
566

567
ast_printer!(
568
    InstrTemplateDecl,
569
    name,
570
    parameters,
571
    fields,
572
    parent_template_name,
573
    parent_template_args
574
);
575

576
impl InstrTemplateParameterDecl {
577
    pub fn name(&self) -> String {
32✔
578
        self.syntax()
32✔
579
            .children()
32✔
580
            .find_map(|child| match child {
56✔
581
                NodeOrToken::Node(node)
32✔
582
                    if node.kind() == SyntaxKind::InstrTemplateSingleParamName =>
32✔
583
                {
32✔
584
                    Some(node)
32✔
585
                }
586
                _ => None,
24✔
587
            })
56✔
588
            .iter()
32✔
589
            .flat_map(|node| node.children())
32✔
590
            .find_map(|child| match child {
32✔
591
                crate::SyntaxElement::Token(token) if token.kind() == SyntaxKind::Identifier => {
32✔
592
                    Some(token.text().to_string())
32✔
593
                }
594
                _ => None,
×
595
            })
32✔
596
            .unwrap_or("unknown".to_string())
32✔
597
    }
32✔
598

599
    pub fn ty(&self) -> Type {
32✔
600
        let ty = self
32✔
601
            .syntax()
32✔
602
            .children()
32✔
603
            .find_map(|child| match child {
120✔
604
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::Type => Some(node),
64✔
605
                _ => None,
88✔
606
            })
120✔
607
            .unwrap();
32✔
608

32✔
609
        Type::new(ty).unwrap()
32✔
610
    }
32✔
611
}
612

613
ast_printer!(InstrTemplateParameterDecl, name, ty);
614

615
impl InstrDecl {
616
    pub fn new(syntax: SyntaxNode) -> Option<Self> {
40✔
617
        if syntax.kind() != SyntaxKind::InstrDecl {
40✔
618
            return None;
×
619
        }
40✔
620

40✔
621
        let template_args = syntax
40✔
622
            .children()
40✔
623
            .find_map(|c| match c {
240✔
624
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrParentTemplate => {
80✔
625
                    Some(node)
40✔
626
                }
627
                _ => None,
200✔
628
            })
240✔
629
            .iter()
40✔
630
            .flat_map(|n| n.children())
40✔
631
            .filter_map(|c| match c {
360✔
632
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrParentTemplateArg => {
160✔
633
                    InstrTemplateArg::new(node)
120✔
634
                }
635
                _ => None,
240✔
636
            })
360✔
637
            .collect::<Vec<_>>();
40✔
638

40✔
639
        Some(Self {
40✔
640
            syntax,
40✔
641
            template_args,
40✔
642
        })
40✔
643
    }
40✔
644

645
    pub fn name(&self) -> String {
80✔
646
        self.syntax
80✔
647
            .children()
80✔
648
            .find_map(|c| match c {
240✔
649
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrName => Some(node),
80✔
650
                _ => None,
160✔
651
            })
240✔
652
            .iter()
80✔
653
            .flat_map(|n| n.children())
80✔
654
            .find_map(|c| match c {
80✔
655
                NodeOrToken::Token(token) if token.kind() == SyntaxKind::Identifier => {
80✔
656
                    Some(token.text().to_string())
80✔
657
                }
658
                _ => None,
×
659
            })
80✔
660
            .unwrap_or("unknown".to_string())
80✔
661
    }
80✔
662

663
    pub fn template_name(&self) -> String {
40✔
664
        self.syntax
40✔
665
            .children()
40✔
666
            .find_map(|c| match c {
240✔
667
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrParentTemplate => {
80✔
668
                    Some(node)
40✔
669
                }
670
                _ => None,
200✔
671
            })
240✔
672
            .iter()
40✔
673
            .flat_map(|n| n.children())
40✔
674
            .find_map(|c| match c {
80✔
675
                NodeOrToken::Node(node) if node.kind() == SyntaxKind::InstrParentTemplateName => {
40✔
676
                    Some(node)
40✔
677
                }
678
                _ => None,
40✔
679
            })
80✔
680
            .iter()
40✔
681
            .flat_map(|n| n.children())
40✔
682
            .find_map(|c| match c {
40✔
683
                NodeOrToken::Token(token) if token.kind() == SyntaxKind::Identifier => {
40✔
684
                    Some(token.text().to_string())
40✔
685
                }
686
                _ => None,
×
687
            })
40✔
688
            .unwrap_or("unknown".to_string())
40✔
689
    }
40✔
690

691
    pub fn template_args(&self) -> &[InstrTemplateArg] {
20✔
692
        &self.template_args
20✔
693
    }
20✔
694
}
695

696
ast_printer!(InstrDecl, name, template_name, template_args);
697

698
// FIXME remove this
699
impl fmt::Debug for InstrTemplateArg {
700
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76✔
701
        f.debug_struct("InstrTemplateArg").finish()
76✔
702
    }
76✔
703
}
704

705
impl EncodingDecl {
706
    pub fn new(syntax: SyntaxNode) -> Option<Self> {
8✔
707
        if syntax.kind() != SyntaxKind::EncodingDecl {
8✔
708
            return None;
×
709
        }
8✔
710

711
        let body = syntax.children().find_map(|c| match c {
56✔
712
            NodeOrToken::Node(n) if n.kind() == SyntaxKind::BlockExpr => BlockExpr::new(n),
16✔
713
            _ => None,
48✔
714
        })?;
56✔
715

716
        Some(Self { syntax, body })
8✔
717
    }
8✔
718

719
    pub fn target_name(&self) -> String {
8✔
720
        self.syntax
8✔
721
            .children()
8✔
722
            .find_map(|child| match child {
40✔
723
                NodeOrToken::Node(node) => {
8✔
724
                    if node.kind() == SyntaxKind::ImplTargetName {
8✔
725
                        Some(node)
8✔
726
                    } else {
727
                        None
×
728
                    }
729
                }
730
                _ => None,
32✔
731
            })
40✔
732
            .iter()
8✔
733
            .flat_map(|node| node.children())
8✔
734
            .find_map(|child| match child {
8✔
735
                crate::SyntaxElement::Token(token) => {
8✔
736
                    if token.kind() == SyntaxKind::Identifier {
8✔
737
                        Some(token.text().to_string())
8✔
738
                    } else {
739
                        None
×
740
                    }
741
                }
742
                _ => None,
×
743
            })
8✔
744
            .unwrap_or("unknown".to_string())
8✔
745
    }
8✔
746

747
    pub fn body(&self) -> &BlockExpr {
4✔
748
        &self.body
4✔
749
    }
4✔
750
}
751

752
ast_printer!(EncodingDecl, target_name, body);
753

754
impl AsmDecl {
755
    pub fn new(syntax: SyntaxNode) -> Option<Self> {
8✔
756
        if syntax.kind() != SyntaxKind::AsmDecl {
8✔
757
            return None;
×
758
        }
8✔
759

760
        let body = syntax.children().find_map(|c| match c {
56✔
761
            NodeOrToken::Node(n) if n.kind() == SyntaxKind::BlockExpr => BlockExpr::new(n),
16✔
762
            _ => None,
48✔
763
        })?;
56✔
764

765
        Some(Self { syntax, body })
8✔
766
    }
8✔
767

768
    pub fn target_name(&self) -> String {
8✔
769
        self.syntax
8✔
770
            .children()
8✔
771
            .find_map(|child| match child {
40✔
772
                NodeOrToken::Node(node) => {
8✔
773
                    if node.kind() == SyntaxKind::ImplTargetName {
8✔
774
                        Some(node)
8✔
775
                    } else {
776
                        None
×
777
                    }
778
                }
779
                _ => None,
32✔
780
            })
40✔
781
            .iter()
8✔
782
            .flat_map(|node| node.children())
8✔
783
            .find_map(|child| match child {
8✔
784
                crate::SyntaxElement::Token(token) => {
8✔
785
                    if token.kind() == SyntaxKind::Identifier {
8✔
786
                        Some(token.text().to_string())
8✔
787
                    } else {
788
                        None
×
789
                    }
790
                }
791
                _ => None,
×
792
            })
8✔
793
            .unwrap_or("unknown".to_string())
8✔
794
    }
8✔
795

796
    pub fn body(&self) -> &BlockExpr {
4✔
797
        &self.body
4✔
798
    }
4✔
799
}
800

801
ast_printer!(AsmDecl, target_name, body);
802

803
impl ImplDecl {
804
    pub fn target_name(&self) -> String {
8✔
805
        self.syntax()
8✔
806
            .children()
8✔
807
            .find_map(|child| match child {
64✔
808
                NodeOrToken::Node(node) => {
16✔
809
                    if node.kind() == SyntaxKind::ImplTargetName {
16✔
810
                        Some(node)
8✔
811
                    } else {
812
                        None
8✔
813
                    }
814
                }
815
                _ => None,
48✔
816
            })
64✔
817
            .iter()
8✔
818
            .flat_map(|node| node.children())
8✔
819
            .find_map(|child| match child {
8✔
820
                crate::SyntaxElement::Token(token) => {
8✔
821
                    if token.kind() == SyntaxKind::Identifier {
8✔
822
                        Some(token.text().to_string())
8✔
823
                    } else {
824
                        None
×
825
                    }
826
                }
827
                _ => None,
×
828
            })
8✔
829
            .unwrap_or("unknown".to_string())
8✔
830
    }
8✔
831

832
    pub fn trait_name(&self) -> String {
8✔
833
        self.syntax()
8✔
834
            .children()
8✔
835
            .find_map(|child| match child {
32✔
836
                NodeOrToken::Node(node) => {
8✔
837
                    if node.kind() == SyntaxKind::ImplTraitName {
8✔
838
                        Some(node)
8✔
839
                    } else {
840
                        None
×
841
                    }
842
                }
843
                _ => None,
24✔
844
            })
32✔
845
            .iter()
8✔
846
            .flat_map(|node| node.children())
8✔
847
            .find_map(|child| match child {
8✔
848
                crate::SyntaxElement::Token(token) => {
8✔
849
                    if token.kind() == SyntaxKind::Identifier {
8✔
850
                        Some(token.text().to_string())
8✔
851
                    } else {
852
                        None
×
853
                    }
854
                }
855
                _ => None,
×
856
            })
8✔
857
            .unwrap_or("unknown".to_string())
8✔
858
    }
8✔
859
}
860

861
impl StructFieldDecl {
862
    pub fn name(&self) -> String {
72✔
863
        self.syntax()
72✔
864
            .children()
72✔
865
            .find_map(|c| match c {
144✔
866
                NodeOrToken::Token(t) if t.kind() == SyntaxKind::Identifier => {
144✔
867
                    Some(t.text().to_string())
72✔
868
                }
869
                _ => None,
72✔
870
            })
144✔
871
            .unwrap_or("unknown".to_string())
72✔
872
    }
72✔
873

874
    pub fn ty(&self) -> Type {
12✔
875
        self.syntax()
12✔
876
            .children()
12✔
877
            .find_map(|c| match c {
48✔
878
                NodeOrToken::Node(n) if n.kind() == SyntaxKind::Type => Type::new(n),
12✔
879
                _ => None,
36✔
880
            })
48✔
881
            .unwrap()
12✔
882
    }
12✔
883
}
884

885
ast_printer!(EnumDecl, name, doc, variants);
886

887
impl ASTNode for EnumDecl {
888
    fn syntax(&self) -> &SyntaxNode {
28✔
889
        &self.syntax
28✔
890
    }
28✔
891
}
892

893
impl EnumDecl {
894
    pub fn new(syntax: SyntaxNode) -> Option<Self> {
8✔
895
        if syntax.kind() != SyntaxKind::EnumDecl {
8✔
896
            return None;
×
897
        }
8✔
898

8✔
899
        let variants = syntax
8✔
900
            .children()
8✔
901
            .find_map(|c| match c {
64✔
902
                NodeOrToken::Node(n) if n.kind() == SyntaxKind::EnumBody => Some(n),
8✔
903
                _ => None,
56✔
904
            })
64✔
905
            .iter()
8✔
906
            .flat_map(|n| n.children())
8✔
907
            .filter_map(|c| match c {
336✔
908
                NodeOrToken::Node(n) if n.kind() == SyntaxKind::EnumVariantDecl => {
160✔
909
                    EnumVariantDecl::new(n)
160✔
910
                }
911
                _ => None,
176✔
912
            })
336✔
913
            .collect::<Vec<_>>();
8✔
914

8✔
915
        Some(Self { syntax, variants })
8✔
916
    }
8✔
917

918
    pub fn name(&self) -> String {
20✔
919
        self.syntax()
20✔
920
            .children()
20✔
921
            .find_map(|c| match c {
148✔
922
                NodeOrToken::Token(t) if t.kind() == SyntaxKind::Identifier => {
148✔
923
                    Some(t.text().to_string())
20✔
924
                }
925
                _ => None,
128✔
926
            })
148✔
927
            .unwrap_or("unknown".to_string())
20✔
928
    }
20✔
929

930
    pub fn variants(&self) -> &[EnumVariantDecl] {
32✔
931
        &self.variants
32✔
932
    }
32✔
933
}
934

935
impl EnumVariantDecl {
936
    pub fn name(&self) -> String {
736✔
937
        self.syntax()
736✔
938
            .children()
736✔
939
            .find_map(|c| match c {
2,208✔
940
                NodeOrToken::Token(t) if t.kind() == SyntaxKind::Identifier => {
1,472✔
941
                    Some(t.text().to_string())
736✔
942
                }
943
                _ => None,
1,472✔
944
            })
2,208✔
945
            .unwrap_or("unknown".to_string())
736✔
946
    }
736✔
947
}
948

949
impl AttrListOwner for EnumVariantDecl {}
950

951
ast_printer!(EnumVariantDecl, name, doc, attr_list);
952

953
impl FlagDecl {
954
    pub fn name(&self) -> String {
8✔
955
        self.syntax()
8✔
956
            .children()
8✔
957
            .find_map(|c| match c {
48✔
958
                NodeOrToken::Token(t) if t.kind() == SyntaxKind::Identifier => {
48✔
959
                    Some(t.text().to_string())
8✔
960
                }
961
                _ => None,
40✔
962
            })
48✔
963
            .unwrap_or("unknown".to_string())
8✔
964
    }
8✔
965
}
966

967
impl From<LiteralExpr> for Expr {
968
    fn from(value: LiteralExpr) -> Self {
676✔
969
        Expr::Literal(value)
676✔
970
    }
676✔
971
}
972

973
impl From<BlockExpr> for Expr {
974
    fn from(value: BlockExpr) -> Self {
×
975
        Expr::Block(value)
×
976
    }
×
977
}
978

979
impl From<ListExpr> for Expr {
980
    fn from(value: ListExpr) -> Self {
306✔
981
        Expr::List(value)
306✔
982
    }
306✔
983
}
984

985
impl From<BinOpExpr> for Expr {
986
    fn from(value: BinOpExpr) -> Self {
36✔
987
        Expr::BinOp(value)
36✔
988
    }
36✔
989
}
990

991
impl Expr {
992
    pub fn as_list(&self) -> ListExpr {
288✔
993
        match &self {
288✔
994
            Expr::List(list) => list.clone(),
288✔
NEW
995
            _ => unreachable!("Not a List!"),
×
996
        }
997
    }
288✔
998

999
    pub fn as_literal(&self) -> LiteralExpr {
584✔
1000
        match &self {
584✔
1001
            Expr::Literal(literal) => literal.clone(),
584✔
NEW
1002
            _ => unreachable!("Not a Literal!"),
×
1003
        }
1004
    }
584✔
1005
}
1006

1007
impl ExprNode for Expr {
1008
    fn ty(&self) -> &Type {
360✔
1009
        match self {
360✔
1010
            Expr::Literal(l) => l.ty(),
322✔
1011
            Expr::Block(b) => b.ty(),
×
1012
            Expr::BinOp(b) => b.ty(),
36✔
1013
            Expr::List(l) => l.ty(),
2✔
1014
        }
1015
    }
360✔
1016
}
1017

1018
impl fmt::Debug for Expr {
1019
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102✔
1020
        match self {
102✔
1021
            Expr::Literal(l) => l.fmt(f),
66✔
1022
            Expr::Block(b) => b.fmt(f),
×
1023
            Expr::BinOp(b) => b.fmt(f),
18✔
1024
            Expr::List(l) => l.fmt(f),
18✔
1025
        }
1026
    }
102✔
1027
}
1028

1029
impl LiteralExpr {
1030
    pub fn new(syntax: SyntaxNode) -> Option<Self> {
676✔
1031
        if syntax.kind() != SyntaxKind::LiteralExpr {
676✔
1032
            return None;
×
1033
        }
676✔
1034

1035
        let ty = syntax.children().find_map(|c| match c {
1,034✔
1036
            NodeOrToken::Token(token) => {
1,022✔
1037
                if token.kind() == SyntaxKind::IntegerLiteral {
1,022✔
1038
                    Some(Type::Integer)
8✔
1039
                } else if token.kind() == SyntaxKind::StringLiteral {
1,014✔
1040
                    Some(Type::String)
624✔
1041
                } else if token.kind() == SyntaxKind::BitLiteral {
390✔
1042
                    Some(Type::Bits((token.text_len() - 2) as u16))
×
1043
                } else if token.kind() == SyntaxKind::Identifier {
390✔
1044
                    Some(Type::Unresolved(NodeOrToken::Token(token)))
32✔
1045
                } else {
1046
                    None
358✔
1047
                }
1048
            }
1049
            NodeOrToken::Node(node) if node.kind() == SyntaxKind::FieldExpr => {
12✔
1050
                Some(Type::Unresolved(NodeOrToken::Node(node)))
12✔
1051
            }
1052
            _ => None,
×
1053
        })?;
1,034✔
1054

1055
        Some(Self { syntax, ty })
676✔
1056
    }
676✔
1057

1058
    pub fn text(&self) -> String {
584✔
1059
        self.syntax
584✔
1060
            .children()
584✔
1061
            .find_map(|c| match c {
880✔
1062
                NodeOrToken::Token(t) if t.kind() == SyntaxKind::StringLiteral => {
880✔
1063
                    Some(t.text().to_string())
584✔
1064
                }
1065
                _ => None,
296✔
1066
            })
880✔
1067
            .unwrap()
584✔
1068
    }
584✔
1069
}
1070

1071
impl ExprNode for LiteralExpr {
1072
    fn ty(&self) -> &Type {
388✔
1073
        &self.ty
388✔
1074
    }
388✔
1075
}
1076

1077
ast_printer!(LiteralExpr, ty);
1078

1079
impl ExprNode for BlockExpr {
1080
    fn ty(&self) -> &Type {
×
1081
        &self.ty
×
1082
    }
×
1083
}
1084

1085
impl BlockExpr {
1086
    pub fn new(syntax: SyntaxNode) -> Option<Self> {
18✔
1087
        if syntax.kind() != SyntaxKind::BlockExpr {
18✔
1088
            return None;
×
1089
        }
18✔
1090

18✔
1091
        let stmts = syntax
18✔
1092
            .children()
18✔
1093
            .filter_map(map_expr)
18✔
1094
            .collect::<Vec<Expr>>();
18✔
1095

18✔
1096
        let ty = stmts.last().map(|e| e.ty()).cloned().unwrap_or(Type::Void);
18✔
1097

18✔
1098
        Some(Self { syntax, stmts, ty })
18✔
1099
    }
18✔
1100
}
1101

1102
impl fmt::Debug for BlockExpr {
1103
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10✔
1104
        f.debug_struct("BlockExpr")
10✔
1105
            .field("type", &self.ty)
10✔
1106
            .field("stmts", &self.stmts)
10✔
1107
            .finish()
10✔
1108
    }
10✔
1109
}
1110

1111
impl ExprNode for ListExpr {
1112
    fn ty(&self) -> &Type {
2✔
1113
        &self.ty
2✔
1114
    }
2✔
1115
}
1116

1117
impl ListExpr {
1118
    pub fn new(syntax: SyntaxNode) -> Option<Self> {
306✔
1119
        if syntax.kind() != SyntaxKind::ListExpr {
306✔
NEW
1120
            return None;
×
1121
        }
306✔
1122

306✔
1123
        let elements = syntax
306✔
1124
            .children()
306✔
1125
            .filter_map(map_expr)
306✔
1126
            .collect::<Vec<Expr>>();
306✔
1127

1128
        let ty = elements.last().map(|e| e.ty()).cloned()?;
306✔
1129

1130
        Some(Self {
306✔
1131
            syntax,
306✔
1132
            elements,
306✔
1133
            ty,
306✔
1134
        })
306✔
1135
    }
306✔
1136

1137
    pub fn elements(&self) -> &[Expr] {
288✔
1138
        &self.elements
288✔
1139
    }
288✔
1140
}
1141

1142
impl fmt::Debug for ListExpr {
1143
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18✔
1144
        f.debug_list().entries(&self.elements).finish()
18✔
1145
    }
18✔
1146
}
1147

1148
impl BinOpExpr {
1149
    pub fn new(syntax: SyntaxNode) -> Option<Self> {
36✔
1150
        if syntax.kind() != SyntaxKind::BinOpExpr {
36✔
1151
            return None;
×
1152
        }
36✔
1153

36✔
1154
        let left: Box<Expr> = syntax
36✔
1155
            .children()
36✔
1156
            .find_map(|c| match c {
36✔
1157
                NodeOrToken::Node(n) if n.kind() == SyntaxKind::BinOpExprLeft => Some(n),
36✔
1158
                _ => None,
×
1159
            })
36✔
1160
            .iter()
36✔
1161
            .flat_map(|n| n.children())
36✔
1162
            .find_map(map_expr)
36✔
1163
            .map(Box::new)
36✔
1164
            .unwrap();
36✔
1165
        let kind: BinOpKind = syntax
36✔
1166
            .children()
36✔
1167
            .find_map(|c| match c {
108✔
1168
                NodeOrToken::Node(n) if n.kind() == SyntaxKind::BinOpExprOp => Some(n),
72✔
1169
                _ => None,
72✔
1170
            })
108✔
1171
            .iter()
36✔
1172
            .flat_map(|n| n.children())
36✔
1173
            .find_map(|c| match c {
36✔
1174
                NodeOrToken::Token(token) => match token.kind() {
36✔
1175
                    SyntaxKind::At => Some(BinOpKind::BitConcat),
36✔
1176
                    _ => None,
×
1177
                },
1178
                _ => None,
×
1179
            })?;
36✔
1180
        let right: Box<Expr> = syntax
36✔
1181
            .children()
36✔
1182
            .find_map(|c| match c {
144✔
1183
                NodeOrToken::Node(n) if n.kind() == SyntaxKind::BinOpExprRight => Some(n),
108✔
1184
                _ => None,
108✔
1185
            })
144✔
1186
            .iter()
36✔
1187
            .flat_map(|n| n.children())
36✔
1188
            .find_map(map_expr)
36✔
1189
            .map(Box::new)?;
36✔
1190

1191
        Some(Self {
36✔
1192
            syntax,
36✔
1193
            kind,
36✔
1194
            left,
36✔
1195
            right,
36✔
1196
        })
36✔
1197
    }
36✔
1198
}
1199

1200
impl fmt::Debug for BinOpExpr {
1201
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18✔
1202
        f.debug_struct("BinOpExpr")
18✔
1203
            .field("kind", &self.kind)
18✔
1204
            .field("left", &*self.left)
18✔
1205
            .field("right", &*self.right)
18✔
1206
            .finish()
18✔
1207
    }
18✔
1208
}
1209

1210
impl ExprNode for BinOpExpr {
1211
    fn ty(&self) -> &Type {
36✔
1212
        self.left.ty()
36✔
1213
    }
36✔
1214
}
1215

1216
fn map_expr(element: SyntaxElement) -> Option<Expr> {
2,628✔
1217
    match element {
2,628✔
1218
        NodeOrToken::Node(node) => match node.kind() {
1,018✔
1219
            SyntaxKind::LiteralExpr => LiteralExpr::new(node).map(|e| e.into()),
676✔
1220
            SyntaxKind::BlockExpr => BlockExpr::new(node).map(|e| e.into()),
×
1221
            SyntaxKind::BinOpExpr => BinOpExpr::new(node).map(|e| e.into()),
36✔
1222
            SyntaxKind::ListExpr => ListExpr::new(node).map(|e| e.into()),
306✔
UNCOV
1223
            _ => None,
×
1224
        },
1225
        _ => None,
1,610✔
1226
    }
1227
}
2,628✔
1228

1229
impl AttrList {
1230
    pub fn attributes(&self) -> impl Iterator<Item = Attr> + use<'_> {
304✔
1231
        self.syntax().children().filter_map(|c| match c {
1,424✔
1232
            NodeOrToken::Node(n) => Attr::new(n.clone()),
304✔
1233
            _ => None,
1,120✔
1234
        })
1,424✔
1235
    }
304✔
1236
}
1237

1238
impl fmt::Debug for AttrList {
1239
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16✔
1240
        f.debug_list().entries(self.attributes()).finish()
16✔
1241
    }
16✔
1242
}
1243

1244
impl Attr {
1245
    pub fn name(&self) -> String {
304✔
1246
        self.syntax()
304✔
1247
            .children()
304✔
1248
            .find_map(|child| match child {
304✔
1249
                NodeOrToken::Token(t) => {
304✔
1250
                    if t.kind() == SyntaxKind::Identifier {
304✔
1251
                        Some(t.text().to_string())
304✔
1252
                    } else {
NEW
1253
                        None
×
1254
                    }
1255
                }
NEW
1256
                _ => None,
×
1257
            })
304✔
1258
            .unwrap()
304✔
1259
    }
304✔
1260

1261
    pub fn exprs(&self) -> impl Iterator<Item = Expr> + use<'_> {
304✔
1262
        self.syntax().children().filter_map(map_expr)
304✔
1263
    }
304✔
1264
}
1265

1266
impl fmt::Debug for Attr {
1267
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16✔
1268
        let exprs = self.exprs().collect::<Vec<_>>();
16✔
1269
        f.debug_struct("Attr")
16✔
1270
            .field("name", &self.name())
16✔
1271
            .field("values", &exprs)
16✔
1272
            .finish()
16✔
1273
    }
16✔
1274
}
1275

1276
impl FnDecl {
1277
    pub fn signature(&self) -> FnSignature {
4✔
1278
        self.syntax()
4✔
1279
            .children()
4✔
1280
            .find_map(|c| match c {
4✔
1281
                NodeOrToken::Node(n) if n.kind() == SyntaxKind::FnSignature => {
4✔
1282
                    FnSignature::new(n.clone())
4✔
1283
                }
NEW
1284
                _ => None,
×
1285
            })
4✔
1286
            .unwrap()
4✔
1287
    }
4✔
1288

1289
    pub fn body(&self) -> BlockExpr {
2✔
1290
        self.syntax()
2✔
1291
            .children()
2✔
1292
            .find_map(|c| match c {
6✔
1293
                NodeOrToken::Node(n) if n.kind() == SyntaxKind::BlockExpr => {
4✔
1294
                    BlockExpr::new(n.clone())
2✔
1295
                }
1296
                _ => None,
4✔
1297
            })
6✔
1298
            .unwrap()
2✔
1299
    }
2✔
1300
}
1301

1302
impl FnSignature {
1303
    pub fn name(&self) -> String {
4✔
1304
        self.syntax()
4✔
1305
            .children()
4✔
1306
            .find_map(|c| match c {
16✔
1307
                NodeOrToken::Token(t) if t.kind() == SyntaxKind::Identifier => {
16✔
1308
                    Some(t.text().to_string())
4✔
1309
                }
1310
                _ => None,
12✔
1311
            })
16✔
1312
            .unwrap()
4✔
1313
    }
4✔
1314

1315
    pub fn params(&self) -> impl Iterator<Item = FnParam> + use<'_> {
2✔
1316
        self.syntax()
2✔
1317
            .children()
2✔
1318
            .find(|c| match c {
18✔
1319
                NodeOrToken::Node(n) => n.kind() == SyntaxKind::FnParamList,
4✔
1320
                _ => false,
14✔
1321
            })
18✔
1322
            .map(|list| {
2✔
NEW
1323
                list.as_node()
×
NEW
1324
                    .children()
×
NEW
1325
                    .filter_map(|c| match c {
×
NEW
1326
                        NodeOrToken::Node(n) if n.kind() == SyntaxKind::FnParam => {
×
NEW
1327
                            FnParam::new(n.clone())
×
1328
                        }
NEW
1329
                        _ => None,
×
NEW
1330
                    })
×
NEW
1331
                    .collect::<Vec<_>>()
×
1332
            })
2✔
1333
            .into_iter()
2✔
1334
            .flatten()
2✔
1335
    }
2✔
1336

1337
    pub fn ret_ty(&self) -> Option<Type> {
2✔
1338
        self.syntax()
2✔
1339
            .children()
2✔
1340
            .find_map(|c| match c {
18✔
1341
                NodeOrToken::Node(n) if n.kind() == SyntaxKind::FnRetType => Some(n.clone()),
4✔
1342
                _ => None,
16✔
1343
            })
18✔
1344
            .and_then(|node| {
2✔
1345
                node.children().find_map(|c| match c {
4✔
1346
                    NodeOrToken::Node(c) if c.kind() == SyntaxKind::Type => Type::new(c),
2✔
1347
                    _ => None,
2✔
1348
                })
4✔
1349
            })
2✔
1350
    }
2✔
1351
}
1352

1353
impl fmt::Debug for FnSignature {
1354
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2✔
1355
        let params = self.params().collect::<Vec<_>>();
2✔
1356
        f.debug_struct("FnSignature")
2✔
1357
            .field("name", &self.name())
2✔
1358
            .field("parameters", &params)
2✔
1359
            .field("return_type", &self.ret_ty())
2✔
1360
            .finish()
2✔
1361
    }
2✔
1362
}
1363

1364
impl fmt::Debug for FnParam {
NEW
1365
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
NEW
1366
        f.debug_tuple("FnParam").field(&self.0).finish()
×
NEW
1367
    }
×
1368
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc