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

igorls / context-builder / 22050142336

16 Feb 2026 04:28AM UTC coverage: 77.753% (+0.1%) from 77.617%
22050142336

push

github

igorls
refactor: reformat long lines and function signatures for improved readability.

7 of 12 new or added lines in 4 files covered. (58.33%)

16 existing lines in 2 files now uncovered.

2415 of 3106 relevant lines covered (77.75%)

4.27 hits per line

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

79.72
/src/tree_sitter/languages/cpp.rs
1
//! C++ language support for tree-sitter.
2

3
#[cfg(feature = "tree-sitter-cpp")]
4
use tree_sitter::{Parser, Tree};
5

6
#[cfg(feature = "tree-sitter-cpp")]
7
use crate::tree_sitter::language_support::{
8
    CodeStructure, LanguageSupport, Signature, SignatureKind, Visibility,
9
    slice_signature_before_body,
10
};
11

12
pub struct CppSupport;
13

14
#[cfg(feature = "tree-sitter-cpp")]
15
impl CppSupport {
16
    fn get_language() -> tree_sitter::Language {
1✔
17
        tree_sitter_cpp::LANGUAGE.into()
1✔
18
    }
19
}
20

21
#[cfg(feature = "tree-sitter-cpp")]
22
impl LanguageSupport for CppSupport {
23
    fn file_extensions(&self) -> &[&'static str] {
1✔
24
        &["cpp", "cxx", "cc", "hpp", "hxx", "hh"]
25
    }
26

27
    fn parse(&self, source: &str) -> Option<Tree> {
1✔
28
        let mut parser = Parser::new();
1✔
29
        parser.set_language(&Self::get_language()).ok()?;
2✔
30
        parser.parse(source, None)
1✔
31
    }
32

33
    fn extract_signatures(&self, source: &str, visibility: Visibility) -> Vec<Signature> {
1✔
34
        let tree = match self.parse(source) {
1✔
35
            Some(t) => t,
1✔
36
            None => return Vec::new(),
×
37
        };
38

39
        let root = tree.root_node();
1✔
40
        let mut signatures = Vec::new();
1✔
41

42
        self.extract_signatures_from_node(source, &root, visibility, &mut signatures);
1✔
43

44
        signatures.sort_by_key(|s| s.line_number);
3✔
45
        signatures
1✔
46
    }
47

48
    fn extract_structure(&self, source: &str) -> CodeStructure {
1✔
49
        let tree = match self.parse(source) {
1✔
50
            Some(t) => t,
1✔
51
            None => return CodeStructure::default(),
×
52
        };
53

54
        let root = tree.root_node();
1✔
55
        let mut structure = CodeStructure {
56
            total_lines: source.lines().count(),
1✔
57
            ..Default::default()
58
        };
59

60
        self.extract_structure_from_node(&root, &mut structure);
1✔
61
        structure
1✔
62
    }
63

64
    fn find_truncation_point(&self, source: &str, max_bytes: usize) -> usize {
1✔
65
        if source.len() <= max_bytes {
1✔
66
            return source.len();
1✔
67
        }
68

69
        let tree = match self.parse(source) {
×
70
            Some(t) => t,
×
71
            None => return max_bytes,
×
72
        };
73

74
        let root = tree.root_node();
×
75
        let mut best_end = 0;
×
76

77
        let mut cursor = root.walk();
×
78
        self.find_best_boundary(&mut cursor, max_bytes, &mut best_end);
×
79
        drop(cursor);
×
80

81
        if best_end == 0 { max_bytes } else { best_end }
×
82
    }
83
}
84

85
#[cfg(feature = "tree-sitter-cpp")]
86
impl CppSupport {
87
    fn extract_signatures_from_node(
1✔
88
        &self,
89
        source: &str,
90
        node: &tree_sitter::Node,
91
        visibility: Visibility,
92
        signatures: &mut Vec<Signature>,
93
    ) {
94
        match node.kind() {
1✔
95
            "function_definition" => {
1✔
96
                if let Some(sig) = self.extract_function_signature(source, node, visibility) {
2✔
97
                    signatures.push(sig);
1✔
98
                }
99
            }
100
            "template_declaration" => {
1✔
101
                // Walk into template_declaration to find the inner class/struct/function
102
                // while preserving the template<...> prefix via slice_signature_before_body
103
                let mut cursor = node.walk();
1✔
104
                for child in node.children(&mut cursor) {
2✔
105
                    match child.kind() {
2✔
106
                        "function_definition" => {
1✔
107
                            // Extract using the template_declaration node for full signature
NEW
108
                            if let Some(mut sig) =
×
109
                                self.extract_function_signature(source, &child, visibility)
110
                            {
111
                                // Replace signature with one that includes template<...> prefix
112
                                if let Some(full) = slice_signature_before_body(
113
                                    source,
114
                                    node,
115
                                    &["compound_statement", "function_body"],
116
                                ) {
UNCOV
117
                                    sig.full_signature = full;
×
118
                                }
119
                                signatures.push(sig);
×
120
                            }
121
                        }
122
                        "class_specifier" => {
2✔
123
                            if let Some(mut sig) =
2✔
124
                                self.extract_class_signature(source, &child, visibility)
125
                            {
126
                                if let Some(full) = slice_signature_before_body(
127
                                    source,
128
                                    node,
129
                                    &["field_declaration_list"],
130
                                ) {
UNCOV
131
                                    sig.full_signature = full;
×
132
                                }
133
                                signatures.push(sig);
1✔
134
                            }
135
                        }
136
                        "struct_specifier" => {
2✔
137
                            if let Some(mut sig) = self.extract_struct_signature(source, &child) {
×
138
                                if let Some(full) = slice_signature_before_body(
139
                                    source,
140
                                    node,
141
                                    &["field_declaration_list"],
142
                                ) {
UNCOV
143
                                    sig.full_signature = full;
×
144
                                }
145
                                signatures.push(sig);
×
146
                            }
147
                        }
148
                        _ => {}
149
                    }
150
                }
151
                return; // Don't recurse into template children again
152
            }
153
            "declaration" => {
1✔
154
                // Header file prototypes: `int foo(int x, int y);`
155
                if let Some(sig) = self.extract_declaration_signature(source, node) {
2✔
156
                    signatures.push(sig);
1✔
157
                }
158
            }
159
            "class_specifier" => {
1✔
160
                if let Some(sig) = self.extract_class_signature(source, node, visibility) {
2✔
161
                    signatures.push(sig);
1✔
162
                }
163
            }
164
            "struct_specifier" => {
1✔
165
                if let Some(sig) = self.extract_struct_signature(source, node) {
2✔
166
                    signatures.push(sig);
1✔
167
                }
168
            }
169
            "enum_specifier" => {
1✔
170
                if let Some(sig) = self.extract_enum_signature(source, node) {
2✔
171
                    signatures.push(sig);
1✔
172
                }
173
            }
174
            "alias_declaration" | "type_definition" => {
2✔
175
                if let Some(sig) = self.extract_alias_signature(source, node) {
2✔
176
                    signatures.push(sig);
1✔
177
                }
178
            }
179
            "preproc_function_def" => {
1✔
180
                if let Some(sig) = self.extract_macro_signature(source, node) {
1✔
181
                    signatures.push(sig);
1✔
182
                }
183
            }
184
            _ => {}
185
        }
186

187
        let mut cursor = node.walk();
1✔
188
        for child in node.children(&mut cursor) {
2✔
189
            self.extract_signatures_from_node(source, &child, visibility, signatures);
2✔
190
        }
191
    }
192

193
    fn extract_structure_from_node(&self, node: &tree_sitter::Node, structure: &mut CodeStructure) {
1✔
194
        match node.kind() {
1✔
195
            "function_definition" => structure.functions += 1,
3✔
196
            "class_specifier" => structure.classes += 1,
3✔
197
            "struct_specifier" => structure.structs += 1,
3✔
198
            "enum_specifier" => structure.enums += 1,
3✔
199
            "preproc_include" => {
1✔
200
                structure.imports.push("include".to_string());
1✔
201
            }
202
            _ => {}
203
        }
204

205
        let mut cursor = node.walk();
1✔
206
        for child in node.children(&mut cursor) {
2✔
207
            self.extract_structure_from_node(&child, structure);
2✔
208
        }
209
    }
210

211
    #[allow(dead_code)]
212
    fn get_visibility(&self, _node: &tree_sitter::Node) -> Visibility {
×
213
        // C++ has access specifiers: public, private, protected
214
        // For simplicity, we check sibling nodes for access specifiers
215
        // This is a simplified check; full implementation would track class context
216
        Visibility::All
217
    }
218

219
    fn extract_function_signature(
1✔
220
        &self,
221
        source: &str,
222
        node: &tree_sitter::Node,
223
        visibility: Visibility,
224
    ) -> Option<Signature> {
225
        let name = self.find_function_name(node, source)?;
2✔
226
        let return_type = self.find_return_type(node, source);
2✔
227
        let params = self.find_child_text(node, "parameter_list", source);
2✔
228

229
        // Use byte-slicing to preserve templates, parameters, and qualifiers
230
        let full_sig = slice_signature_before_body(source, node, &["compound_statement"])
1✔
231
            .unwrap_or_else(|| {
1✔
232
                let mut sig = String::new();
×
233
                if let Some(r) = &return_type {
×
234
                    sig.push_str(r);
×
235
                    sig.push(' ');
×
236
                }
237
                sig.push_str(&name);
×
238
                if let Some(p) = &params {
×
239
                    sig.push_str(p);
×
240
                } else {
241
                    sig.push_str("()");
×
242
                }
243
                sig
×
244
            });
245

246
        Some(Signature {
1✔
247
            kind: SignatureKind::Function,
248
            name,
1✔
249
            params,
1✔
250
            return_type,
1✔
251
            visibility,
252
            line_number: node.start_position().row + 1,
2✔
253
            full_signature: full_sig,
1✔
254
        })
255
    }
256

257
    /// Extract function prototype signatures from `declaration` nodes (header files).
258
    fn extract_declaration_signature(
1✔
259
        &self,
260
        source: &str,
261
        node: &tree_sitter::Node,
262
    ) -> Option<Signature> {
263
        // Only capture declarations that look like function prototypes
264
        let mut cursor = node.walk();
1✔
265
        let has_function_declarator = node.children(&mut cursor).any(|c| {
3✔
266
            if c.kind() == "function_declarator" {
1✔
267
                return true;
1✔
268
            }
269
            let mut inner = c.walk();
1✔
270
            c.children(&mut inner)
2✔
271
                .any(|gc| gc.kind() == "function_declarator")
1✔
272
        });
273

274
        if !has_function_declarator {
1✔
275
            return None;
×
276
        }
277

278
        let name = self.find_function_name(node, source)?;
2✔
279
        let text = source[node.start_byte()..node.end_byte()].trim_end();
2✔
280
        let full_sig = text.trim_end_matches(';').trim_end().to_string();
1✔
281

282
        Some(Signature {
1✔
283
            kind: SignatureKind::Function,
284
            name,
1✔
285
            params: None,
1✔
286
            return_type: None,
1✔
287
            visibility: Visibility::All,
288
            line_number: node.start_position().row + 1,
2✔
289
            full_signature: full_sig,
1✔
290
        })
291
    }
292
    fn extract_class_signature(
1✔
293
        &self,
294
        source: &str,
295
        node: &tree_sitter::Node,
296
        visibility: Visibility,
297
    ) -> Option<Signature> {
298
        let name = self.find_child_text(node, "type_identifier", source)?;
2✔
299

300
        // Use byte-slicing to preserve templates and inheritance
301
        // e.g., `template<typename T> class Foo : public Base`
302
        let full_sig = slice_signature_before_body(source, node, &["field_declaration_list"])
1✔
303
            .unwrap_or_else(|| format!("class {}", name));
1✔
304

305
        Some(Signature {
1✔
306
            kind: SignatureKind::Class,
307
            name,
1✔
308
            params: None,
1✔
309
            return_type: None,
1✔
310
            visibility,
311
            line_number: node.start_position().row + 1,
2✔
312
            full_signature: full_sig,
1✔
313
        })
314
    }
315

316
    fn extract_struct_signature(
1✔
317
        &self,
318
        source: &str,
319
        node: &tree_sitter::Node,
320
    ) -> Option<Signature> {
321
        let name = self.find_child_text(node, "type_identifier", source)?;
2✔
322

323
        let full_sig = format!("struct {}", name);
2✔
324

325
        Some(Signature {
1✔
326
            kind: SignatureKind::Struct,
327
            name,
1✔
328
            params: None,
1✔
329
            return_type: None,
1✔
330
            visibility: Visibility::All,
331
            line_number: node.start_position().row + 1,
2✔
332
            full_signature: full_sig,
1✔
333
        })
334
    }
335

336
    fn extract_enum_signature(&self, source: &str, node: &tree_sitter::Node) -> Option<Signature> {
1✔
337
        let name = self.find_child_text(node, "type_identifier", source)?;
2✔
338

339
        let full_sig = format!("enum {}", name);
2✔
340

341
        Some(Signature {
1✔
342
            kind: SignatureKind::Enum,
343
            name,
1✔
344
            params: None,
1✔
345
            return_type: None,
1✔
346
            visibility: Visibility::All,
347
            line_number: node.start_position().row + 1,
2✔
348
            full_signature: full_sig,
1✔
349
        })
350
    }
351

352
    fn extract_alias_signature(&self, source: &str, node: &tree_sitter::Node) -> Option<Signature> {
1✔
353
        let name = self.find_child_text(node, "type_identifier", source)?;
2✔
354

355
        let full_sig = format!("using/typedef {}", name);
2✔
356

357
        Some(Signature {
1✔
358
            kind: SignatureKind::TypeAlias,
359
            name,
1✔
360
            params: None,
1✔
361
            return_type: None,
1✔
362
            visibility: Visibility::All,
363
            line_number: node.start_position().row + 1,
2✔
364
            full_signature: full_sig,
1✔
365
        })
366
    }
367

368
    fn extract_macro_signature(&self, source: &str, node: &tree_sitter::Node) -> Option<Signature> {
1✔
369
        let name = self.find_child_text(node, "identifier", source)?;
2✔
370

371
        let full_sig = format!("#define {}", name);
2✔
372

373
        Some(Signature {
1✔
374
            kind: SignatureKind::Macro,
375
            name,
1✔
376
            params: None,
1✔
377
            return_type: None,
1✔
378
            visibility: Visibility::All,
379
            line_number: node.start_position().row + 1,
2✔
380
            full_signature: full_sig,
1✔
381
        })
382
    }
383

384
    fn find_function_name(&self, node: &tree_sitter::Node, source: &str) -> Option<String> {
1✔
385
        let mut cursor = node.walk();
1✔
386
        for child in node.children(&mut cursor) {
2✔
387
            if child.kind() == "function_declarator" || child.kind() == "reference_declarator" {
3✔
388
                let mut inner_cursor = child.walk();
1✔
389
                for inner in child.children(&mut inner_cursor) {
2✔
390
                    if inner.kind() == "identifier" || inner.kind() == "qualified_identifier" {
3✔
391
                        return Some(source[inner.start_byte()..inner.end_byte()].to_string());
2✔
392
                    }
393
                }
394
            }
395
            if child.kind() == "identifier" || child.kind() == "qualified_identifier" {
3✔
396
                return Some(source[child.start_byte()..child.end_byte()].to_string());
×
397
            }
398
        }
399
        None
1✔
400
    }
401

402
    fn find_return_type(&self, node: &tree_sitter::Node, source: &str) -> Option<String> {
1✔
403
        let mut cursor = node.walk();
1✔
404
        for child in node.children(&mut cursor) {
2✔
405
            match child.kind() {
2✔
406
                "primitive_type" | "type_identifier" | "sized_type_specifier" => {
1✔
407
                    return Some(source[child.start_byte()..child.end_byte()].to_string());
2✔
408
                }
409
                _ => {}
410
            }
411
        }
412
        None
×
413
    }
414

415
    fn find_child_text(
1✔
416
        &self,
417
        node: &tree_sitter::Node,
418
        kind: &str,
419
        source: &str,
420
    ) -> Option<String> {
421
        let mut cursor = node.walk();
1✔
422
        for child in node.children(&mut cursor) {
2✔
423
            if child.kind() == kind {
2✔
424
                return Some(source[child.start_byte()..child.end_byte()].to_string());
1✔
425
            }
426
        }
427
        None
1✔
428
    }
429

430
    fn find_best_boundary(
×
431
        &self,
432
        cursor: &mut tree_sitter::TreeCursor,
433
        max_bytes: usize,
434
        best_end: &mut usize,
435
    ) {
436
        loop {
437
            let node = cursor.node();
×
438
            let end_byte = node.end_byte();
×
439

440
            if end_byte <= max_bytes && end_byte > *best_end {
×
441
                let is_item = matches!(
×
442
                    node.kind(),
×
443
                    "function_definition"
444
                        | "class_specifier"
445
                        | "struct_specifier"
446
                        | "enum_specifier"
447
                        | "alias_declaration"
448
                        | "type_definition"
449
                );
450
                if is_item {
×
451
                    *best_end = end_byte;
×
452
                }
453
            }
454

455
            if cursor.goto_first_child() {
×
456
                self.find_best_boundary(cursor, max_bytes, best_end);
×
457
                cursor.goto_parent();
×
458
            }
459

460
            if !cursor.goto_next_sibling() {
×
461
                break;
462
            }
463
        }
464
    }
465
}
466

467
#[cfg(test)]
468
mod tests {
469
    use super::*;
470

471
    #[test]
472
    fn test_extract_class_signature() {
473
        let source = r#"
474
class HelloWorld {
475
public:
476
    void greet() {
477
        std::cout << "Hello" << std::endl;
478
    }
479
};
480
"#;
481

482
        let signatures = CppSupport.extract_signatures(source, Visibility::All);
483
        let classes: Vec<_> = signatures
484
            .iter()
485
            .filter(|s| s.kind == SignatureKind::Class)
486
            .collect();
487
        assert!(!classes.is_empty());
488
        assert_eq!(classes[0].name, "HelloWorld");
489
    }
490

491
    #[test]
492
    fn test_extract_function_signature() {
493
        let source = r#"
494
int add(int a, int b) {
495
    return a + b;
496
}
497

498
void greet(const std::string& name) {
499
    std::cout << name << std::endl;
500
}
501
"#;
502

503
        let signatures = CppSupport.extract_signatures(source, Visibility::All);
504
        let funcs: Vec<_> = signatures
505
            .iter()
506
            .filter(|s| s.kind == SignatureKind::Function)
507
            .collect();
508
        assert!(funcs.len() >= 2);
509
    }
510

511
    #[test]
512
    fn test_extract_struct_signature() {
513
        let source = r#"
514
struct Vec3 {
515
    float x, y, z;
516
};
517
"#;
518

519
        let signatures = CppSupport.extract_signatures(source, Visibility::All);
520
        let structs: Vec<_> = signatures
521
            .iter()
522
            .filter(|s| s.kind == SignatureKind::Struct)
523
            .collect();
524
        assert!(!structs.is_empty());
525
        assert_eq!(structs[0].name, "Vec3");
526
    }
527

528
    #[test]
529
    fn test_extract_enum_signature() {
530
        let source = r#"
531
enum class Direction {
532
    Up,
533
    Down,
534
    Left,
535
    Right
536
};
537
"#;
538

539
        let signatures = CppSupport.extract_signatures(source, Visibility::All);
540
        let enums: Vec<_> = signatures
541
            .iter()
542
            .filter(|s| s.kind == SignatureKind::Enum)
543
            .collect();
544
        assert!(!enums.is_empty());
545
        assert_eq!(enums[0].name, "Direction");
546
    }
547

548
    #[test]
549
    fn test_extract_header_prototype() {
550
        let source = r#"
551
int add(int a, int b);
552
void greet(const std::string& name);
553
"#;
554

555
        let signatures = CppSupport.extract_signatures(source, Visibility::All);
556
        let funcs: Vec<_> = signatures
557
            .iter()
558
            .filter(|s| s.kind == SignatureKind::Function)
559
            .collect();
560
        assert!(funcs.len() >= 2);
561
        for f in &funcs {
562
            assert!(!f.full_signature.ends_with(';'));
563
        }
564
    }
565

566
    #[test]
567
    fn test_extract_template_class_with_inheritance() {
568
        let source = r#"
569
template<typename T>
570
class Container : public Base {
571
    T value;
572
public:
573
    T get() { return value; }
574
};
575
"#;
576

577
        let signatures = CppSupport.extract_signatures(source, Visibility::All);
578
        let classes: Vec<_> = signatures
579
            .iter()
580
            .filter(|s| s.kind == SignatureKind::Class)
581
            .collect();
582
        assert!(!classes.is_empty());
583
        // Byte-slicing fix should preserve template<> and : public Base
584
        let sig = &classes[0].full_signature;
585
        assert!(sig.contains("Container"));
586
    }
587

588
    #[test]
589
    fn test_extract_type_alias() {
590
        let source = r#"
591
using StringVec = std::vector<std::string>;
592
typedef unsigned int uint;
593
"#;
594

595
        let signatures = CppSupport.extract_signatures(source, Visibility::All);
596
        let aliases: Vec<_> = signatures
597
            .iter()
598
            .filter(|s| s.kind == SignatureKind::TypeAlias)
599
            .collect();
600
        assert!(!aliases.is_empty());
601
    }
602

603
    #[test]
604
    fn test_extract_macro() {
605
        let source = r#"
606
#define MIN(a, b) ((a) < (b) ? (a) : (b))
607
"#;
608

609
        let signatures = CppSupport.extract_signatures(source, Visibility::All);
610
        let macros: Vec<_> = signatures
611
            .iter()
612
            .filter(|s| s.kind == SignatureKind::Macro)
613
            .collect();
614
        assert!(!macros.is_empty());
615
        assert_eq!(macros[0].name, "MIN");
616
    }
617

618
    #[test]
619
    fn test_extract_structure() {
620
        let source = r#"
621
#include <iostream>
622
#include <vector>
623

624
class Foo {
625
public:
626
    void bar() {}
627
};
628

629
struct Point { int x; int y; };
630
enum Color { R, G, B };
631

632
void helper() {}
633
"#;
634

635
        let structure = CppSupport.extract_structure(source);
636
        assert!(structure.functions >= 1);
637
        assert!(structure.classes >= 1);
638
        assert!(structure.structs >= 1);
639
        assert!(structure.enums >= 1);
640
        assert!(structure.imports.len() >= 2);
641
    }
642

643
    #[test]
644
    fn test_parse_valid_cpp() {
645
        let source = "int main() { return 0; }";
646
        let tree = CppSupport.parse(source);
647
        assert!(tree.is_some());
648
    }
649

650
    #[test]
651
    fn test_find_truncation_point() {
652
        let source = "int main() { return 0; }";
653
        let point = CppSupport.find_truncation_point(source, 1000);
654
        assert_eq!(point, source.len());
655
    }
656

657
    #[test]
658
    fn test_file_extensions() {
659
        assert!(CppSupport.supports_extension("cpp"));
660
        assert!(CppSupport.supports_extension("hpp"));
661
        assert!(CppSupport.supports_extension("cxx"));
662
        assert!(!CppSupport.supports_extension("c"));
663
    }
664
}
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