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

igorls / context-builder / 22035105478

15 Feb 2026 11:46AM UTC coverage: 59.277% (-2.8%) from 62.112%
22035105478

push

github

igorls
release: v0.8.1

Bug fixes (Deep Think v6 review — 11 confirmed bugs):
- Fixed cache hash desync (4 missing fields)
- Fixed JS/TS arrow function body leak
- Fixed Python decorator erasure + is_method
- Fixed Rust tuple struct erasure
- Fixed C/C++ header prototype extraction
- Fixed C++ class inheritance byte-slicing
- Fixed JS/TS export signatures for lexical_declaration
- Added .jsx extension support

Dependency updates:
- tree-sitter: 0.24 → 0.26
- tree-sitter-rust: 0.23 → 0.24
- tree-sitter-javascript: 0.23 → 0.25
- tree-sitter-python: 0.23 → 0.25
- tree-sitter-go: 0.23 → 0.25
- tree-sitter-c: 0.23 → 0.24

93 of 292 new or added lines in 11 files covered. (31.85%)

29 existing lines in 3 files now uncovered.

1821 of 3072 relevant lines covered (59.28%)

4.07 hits per line

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

38.74
/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 {
×
49
        let tree = match self.parse(source) {
×
50
            Some(t) => t,
×
51
            None => return CodeStructure::default(),
×
52
        };
53

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

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

64
    fn find_truncation_point(&self, source: &str, max_bytes: usize) -> usize {
×
65
        if source.len() <= max_bytes {
×
66
            return source.len();
×
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) {
×
107
                    signatures.push(sig);
×
108
                }
109
            }
110
            "enum_declaration" => {
1✔
111
                if let Some(sig) = self.extract_enum_signature(source, node, visibility) {
×
112
                    signatures.push(sig);
×
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) {
×
130
        match node.kind() {
×
131
            "method_declaration" => structure.functions += 1,
×
132
            "class_declaration" => structure.classes += 1,
×
133
            "interface_declaration" => structure.interfaces += 1,
×
134
            "enum_declaration" => structure.enums += 1,
×
135
            "import_declaration" => {
×
136
                structure.imports.push("import".to_string());
×
137
            }
138
            _ => {}
139
        }
140

141
        let mut cursor = node.walk();
×
142
        for child in node.children(&mut cursor) {
×
143
            self.extract_structure_from_node(&child, structure);
×
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"])
1✔
177
            .unwrap_or_else(|| {
1✔
NEW
178
                let mut sig = String::new();
×
NEW
179
                if vis == Visibility::Public {
×
NEW
180
                    sig.push_str("public ");
×
181
                }
NEW
182
                if let Some(r) = &return_type {
×
NEW
183
                    sig.push_str(r);
×
NEW
184
                    sig.push(' ');
×
185
                }
NEW
186
                sig.push_str(&name);
×
NEW
187
                if let Some(p) = &params {
×
NEW
188
                    sig.push_str(p);
×
189
                } else {
NEW
190
                    sig.push_str("()");
×
191
                }
NEW
192
                sig
×
193
            });
194

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

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

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

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

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

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

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

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

256
        let name = self.find_child_text(node, "identifier", source)?;
×
257

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

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

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

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

291
        let name = self.find_child_text(node, "identifier", source)?;
×
292

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

427
    #[test]
428
    fn test_file_extensions() {
429
        assert!(JavaSupport.supports_extension("java"));
430
        assert!(!JavaSupport.supports_extension("rs"));
431
    }
432
}
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