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

igorls / context-builder / 22042957845

15 Feb 2026 08:59PM UTC coverage: 79.739% (+0.05%) from 79.688%
22042957845

push

github

igorls
style: cargo fmt

39 of 74 new or added lines in 10 files covered. (52.7%)

2 existing lines in 2 files now uncovered.

2448 of 3070 relevant lines covered (79.74%)

4.39 hits per line

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

72.63
/src/tree_sitter/languages/java.rs
1
//! Java language support for tree-sitter.
2

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

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

12
pub struct JavaSupport;
13

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

21
#[cfg(feature = "tree-sitter-java")]
22
impl LanguageSupport for JavaSupport {
23
    fn file_extensions(&self) -> &[&'static str] {
1✔
24
        &["java"]
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-java")]
86
impl JavaSupport {
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
            "method_declaration" => {
1✔
96
                if let Some(sig) = self.extract_method_signature(source, node, visibility) {
2✔
97
                    signatures.push(sig);
1✔
98
                }
99
            }
100
            "class_declaration" => {
1✔
101
                if let Some(sig) = self.extract_class_signature(source, node, visibility) {
2✔
102
                    signatures.push(sig);
1✔
103
                }
104
            }
105
            "interface_declaration" => {
1✔
106
                if let Some(sig) = self.extract_interface_signature(source, node, visibility) {
2✔
107
                    signatures.push(sig);
1✔
108
                }
109
            }
110
            "enum_declaration" => {
1✔
111
                if let Some(sig) = self.extract_enum_signature(source, node, visibility) {
2✔
112
                    signatures.push(sig);
1✔
113
                }
114
            }
115
            "field_declaration" => {
1✔
116
                if let Some(sig) = self.extract_field_signature(source, node, visibility) {
×
117
                    signatures.push(sig);
×
118
                }
119
            }
120
            _ => {}
121
        }
122

123
        let mut cursor = node.walk();
1✔
124
        for child in node.children(&mut cursor) {
2✔
125
            self.extract_signatures_from_node(source, &child, visibility, signatures);
2✔
126
        }
127
    }
128

129
    fn extract_structure_from_node(&self, node: &tree_sitter::Node, structure: &mut CodeStructure) {
1✔
130
        match node.kind() {
1✔
131
            "method_declaration" => structure.functions += 1,
3✔
132
            "class_declaration" => structure.classes += 1,
3✔
133
            "interface_declaration" => structure.interfaces += 1,
3✔
134
            "enum_declaration" => structure.enums += 1,
3✔
135
            "import_declaration" => {
1✔
136
                structure.imports.push("import".to_string());
1✔
137
            }
138
            _ => {}
139
        }
140

141
        let mut cursor = node.walk();
1✔
142
        for child in node.children(&mut cursor) {
2✔
143
            self.extract_structure_from_node(&child, structure);
2✔
144
        }
145
    }
146

147
    #[allow(dead_code)]
148
    fn get_visibility(&self, _node: &tree_sitter::Node) -> Visibility {
1✔
149
        // Java visibility is determined by modifiers
150
        // Simplified: check for public/private/protected keywords in AST modifiers
151
        Visibility::All
152
    }
153

154
    fn extract_method_signature(
1✔
155
        &self,
156
        source: &str,
157
        node: &tree_sitter::Node,
158
        visibility: Visibility,
159
    ) -> Option<Signature> {
160
        let vis = self.get_visibility(node);
1✔
161

162
        if visibility == Visibility::Public && vis != Visibility::Public {
1✔
163
            return None;
×
164
        }
165
        if visibility == Visibility::Private && vis == Visibility::Public {
1✔
166
            return None;
×
167
        }
168

169
        let name = self.find_child_text(node, "identifier", source)?;
2✔
170
        let params = self.find_child_text(node, "formal_parameters", source);
2✔
171
        let return_type = self
172
            .find_child_text(node, "type_identifier", source)
1✔
173
            .or_else(|| self.find_child_text_for_type(node, source));
3✔
174

175
        // Use byte-slicing to preserve annotations, generics, throws, and modifiers
176
        let full_sig = slice_signature_before_body(source, node, &["block"]).unwrap_or_else(|| {
3✔
177
            let mut sig = String::new();
1✔
178
            if vis == Visibility::Public {
2✔
NEW
179
                sig.push_str("public ");
×
180
            }
181
            if let Some(r) = &return_type {
2✔
182
                sig.push_str(r);
2✔
183
                sig.push(' ');
1✔
184
            }
185
            sig.push_str(&name);
2✔
186
            if let Some(p) = &params {
1✔
187
                sig.push_str(p);
2✔
188
            } else {
NEW
189
                sig.push_str("()");
×
190
            }
191
            sig
1✔
192
        });
193

194
        Some(Signature {
1✔
195
            kind: SignatureKind::Method,
196
            name,
1✔
197
            params,
1✔
198
            return_type,
1✔
199
            visibility: vis,
200
            line_number: node.start_position().row + 1,
2✔
201
            full_signature: full_sig,
1✔
202
        })
203
    }
204

205
    fn extract_class_signature(
1✔
206
        &self,
207
        source: &str,
208
        node: &tree_sitter::Node,
209
        visibility: Visibility,
210
    ) -> Option<Signature> {
211
        let vis = self.get_visibility(node);
1✔
212

213
        if visibility == Visibility::Public && vis != Visibility::Public {
1✔
214
            return None;
×
215
        }
216
        if visibility == Visibility::Private && vis == Visibility::Public {
1✔
217
            return None;
×
218
        }
219

220
        let name = self.find_child_text(node, "identifier", source)?;
2✔
221

222
        let mut full_sig = String::new();
1✔
223
        if vis == Visibility::Public {
2✔
224
            full_sig.push_str("public ");
×
225
        }
226
        full_sig.push_str("class ");
1✔
227
        full_sig.push_str(&name);
1✔
228

229
        Some(Signature {
1✔
230
            kind: SignatureKind::Class,
231
            name,
1✔
232
            params: None,
1✔
233
            return_type: None,
1✔
234
            visibility: vis,
235
            line_number: node.start_position().row + 1,
2✔
236
            full_signature: full_sig,
1✔
237
        })
238
    }
239

240
    fn extract_interface_signature(
1✔
241
        &self,
242
        source: &str,
243
        node: &tree_sitter::Node,
244
        visibility: Visibility,
245
    ) -> Option<Signature> {
246
        let vis = self.get_visibility(node);
1✔
247

248
        if visibility == Visibility::Public && vis != Visibility::Public {
1✔
249
            return None;
×
250
        }
251
        if visibility == Visibility::Private && vis == Visibility::Public {
1✔
252
            return None;
×
253
        }
254

255
        let name = self.find_child_text(node, "identifier", source)?;
2✔
256

257
        let mut full_sig = String::new();
1✔
258
        if vis == Visibility::Public {
2✔
259
            full_sig.push_str("public ");
×
260
        }
261
        full_sig.push_str("interface ");
1✔
262
        full_sig.push_str(&name);
1✔
263

264
        Some(Signature {
1✔
265
            kind: SignatureKind::Interface,
266
            name,
1✔
267
            params: None,
1✔
268
            return_type: None,
1✔
269
            visibility: vis,
270
            line_number: node.start_position().row + 1,
2✔
271
            full_signature: full_sig,
1✔
272
        })
273
    }
274

275
    fn extract_enum_signature(
1✔
276
        &self,
277
        source: &str,
278
        node: &tree_sitter::Node,
279
        visibility: Visibility,
280
    ) -> Option<Signature> {
281
        let vis = self.get_visibility(node);
1✔
282

283
        if visibility == Visibility::Public && vis != Visibility::Public {
1✔
284
            return None;
×
285
        }
286
        if visibility == Visibility::Private && vis == Visibility::Public {
1✔
287
            return None;
×
288
        }
289

290
        let name = self.find_child_text(node, "identifier", source)?;
2✔
291

292
        let mut full_sig = String::new();
1✔
293
        if vis == Visibility::Public {
2✔
294
            full_sig.push_str("public ");
×
295
        }
296
        full_sig.push_str("enum ");
1✔
297
        full_sig.push_str(&name);
1✔
298

299
        Some(Signature {
1✔
300
            kind: SignatureKind::Enum,
301
            name,
1✔
302
            params: None,
1✔
303
            return_type: None,
1✔
304
            visibility: vis,
305
            line_number: node.start_position().row + 1,
2✔
306
            full_signature: full_sig,
1✔
307
        })
308
    }
309

310
    fn extract_field_signature(
×
311
        &self,
312
        source: &str,
313
        node: &tree_sitter::Node,
314
        visibility: Visibility,
315
    ) -> Option<Signature> {
316
        let vis = self.get_visibility(node);
×
317

318
        if visibility == Visibility::Public && vis != Visibility::Public {
×
319
            return None;
×
320
        }
321
        if visibility == Visibility::Private && vis == Visibility::Public {
×
322
            return None;
×
323
        }
324

325
        let name = self.find_child_text(node, "identifier", source)?;
×
326
        let full_signature = format!("field {}", &name);
×
327

328
        Some(Signature {
×
329
            kind: SignatureKind::Constant,
330
            name,
×
331
            params: None,
×
332
            return_type: None,
×
333
            visibility: vis,
334
            line_number: node.start_position().row + 1,
×
335
            full_signature,
×
336
        })
337
    }
338

339
    fn find_child_text(
1✔
340
        &self,
341
        node: &tree_sitter::Node,
342
        kind: &str,
343
        source: &str,
344
    ) -> Option<String> {
345
        let mut cursor = node.walk();
1✔
346
        for child in node.children(&mut cursor) {
2✔
347
            if child.kind() == kind {
2✔
348
                return Some(source[child.start_byte()..child.end_byte()].to_string());
1✔
349
            }
350
        }
351
        None
1✔
352
    }
353

354
    fn find_child_text_for_type(&self, node: &tree_sitter::Node, source: &str) -> Option<String> {
1✔
355
        let mut cursor = node.walk();
1✔
356
        for child in node.children(&mut cursor) {
2✔
357
            if child.kind() == "void_type"
2✔
358
                || child.kind() == "integral_type"
2✔
359
                || child.kind() == "boolean_type"
1✔
360
            {
361
                return Some(source[child.start_byte()..child.end_byte()].to_string());
2✔
362
            }
363
        }
364
        None
1✔
365
    }
366

367
    fn find_best_boundary(
×
368
        &self,
369
        cursor: &mut tree_sitter::TreeCursor,
370
        max_bytes: usize,
371
        best_end: &mut usize,
372
    ) {
373
        loop {
374
            let node = cursor.node();
×
375
            let end_byte = node.end_byte();
×
376

377
            if end_byte <= max_bytes && end_byte > *best_end {
×
378
                let is_item = matches!(
×
379
                    node.kind(),
×
380
                    "method_declaration"
381
                        | "class_declaration"
382
                        | "interface_declaration"
383
                        | "enum_declaration"
384
                );
385
                if is_item {
×
386
                    *best_end = end_byte;
×
387
                }
388
            }
389

390
            if cursor.goto_first_child() {
×
391
                self.find_best_boundary(cursor, max_bytes, best_end);
×
392
                cursor.goto_parent();
×
393
            }
394

395
            if !cursor.goto_next_sibling() {
×
396
                break;
397
            }
398
        }
399
    }
400
}
401

402
#[cfg(test)]
403
mod tests {
404
    use super::*;
405

406
    #[test]
407
    fn test_extract_class_signature() {
408
        let source = r#"
409
public class HelloWorld {
410
    public static void main(String[] args) {
411
        System.out.println("Hello");
412
    }
413
}
414
}
415
"#;
416

417
        let signatures = JavaSupport.extract_signatures(source, Visibility::All);
418
        let classes: Vec<_> = signatures
419
            .iter()
420
            .filter(|s| s.kind == SignatureKind::Class)
421
            .collect();
422
        assert!(!classes.is_empty());
423
        assert_eq!(classes[0].name, "HelloWorld");
424
    }
425

426
    #[test]
427
    fn test_extract_method_signature() {
428
        let source = r#"
429
public class Calculator {
430
    public int add(int a, int b) {
431
        return a + b;
432
    }
433

434
    private double multiply(double x, double y) {
435
        return x * y;
436
    }
437
}
438
"#;
439

440
        let signatures = JavaSupport.extract_signatures(source, Visibility::All);
441
        let methods: Vec<_> = signatures
442
            .iter()
443
            .filter(|s| s.kind == SignatureKind::Method || s.kind == SignatureKind::Function)
444
            .collect();
445
        assert!(methods.len() >= 2);
446
    }
447

448
    #[test]
449
    fn test_extract_interface_signature() {
450
        let source = r#"
451
public interface Printable {
452
    void print();
453
    String format(String template);
454
}
455
"#;
456

457
        let signatures = JavaSupport.extract_signatures(source, Visibility::All);
458
        let interfaces: Vec<_> = signatures
459
            .iter()
460
            .filter(|s| s.kind == SignatureKind::Interface)
461
            .collect();
462
        assert!(!interfaces.is_empty());
463
        assert_eq!(interfaces[0].name, "Printable");
464
    }
465

466
    #[test]
467
    fn test_extract_enum_signature() {
468
        let source = r#"
469
public enum Color {
470
    RED, GREEN, BLUE;
471
}
472
"#;
473

474
        let signatures = JavaSupport.extract_signatures(source, Visibility::All);
475
        let enums: Vec<_> = signatures
476
            .iter()
477
            .filter(|s| s.kind == SignatureKind::Enum)
478
            .collect();
479
        assert!(!enums.is_empty());
480
        assert_eq!(enums[0].name, "Color");
481
    }
482

483
    #[test]
484
    fn test_extract_class_with_inheritance() {
485
        let source = r#"
486
public class Dog extends Animal implements Runnable {
487
    public void run() {}
488
}
489
"#;
490

491
        let signatures = JavaSupport.extract_signatures(source, Visibility::All);
492
        let classes: Vec<_> = signatures
493
            .iter()
494
            .filter(|s| s.kind == SignatureKind::Class)
495
            .collect();
496
        assert!(!classes.is_empty());
497
        assert_eq!(classes[0].name, "Dog");
498
    }
499

500
    #[test]
501
    fn test_extract_structure() {
502
        let source = r#"
503
import java.util.List;
504
import java.util.Map;
505

506
public class App {
507
    public void doStuff() {}
508
    private void helper() {}
509
}
510

511
interface Printable {
512
    void print();
513
}
514

515
enum Status { ACTIVE, INACTIVE }
516
"#;
517

518
        let structure = JavaSupport.extract_structure(source);
519
        assert!(structure.functions >= 2);
520
        assert!(structure.classes >= 1);
521
        assert!(structure.interfaces >= 1);
522
        assert!(structure.enums >= 1);
523
        assert!(structure.imports.len() >= 2);
524
    }
525

526
    #[test]
527
    fn test_parse_valid_java() {
528
        let source = "public class Main { public static void main(String[] args) {} }";
529
        let tree = JavaSupport.parse(source);
530
        assert!(tree.is_some());
531
    }
532

533
    #[test]
534
    fn test_find_truncation_point() {
535
        let source = "public class Main { public static void main(String[] args) {} }";
536
        let point = JavaSupport.find_truncation_point(source, 1000);
537
        assert_eq!(point, source.len());
538
    }
539

540
    #[test]
541
    fn test_file_extensions() {
542
        assert!(JavaSupport.supports_extension("java"));
543
        assert!(!JavaSupport.supports_extension("rs"));
544
    }
545
}
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