Skip to content

Commit 4952997

Browse files
committed
test(languages): verify parent scope extraction across 7 languages
1 parent 6e547c2 commit 4952997

1 file changed

Lines changed: 177 additions & 0 deletions

File tree

tests/languages.rs

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,183 @@ fn make_file_change(path: &str, diff: &str, additions: usize, deletions: usize)
9595
}
9696
}
9797

98+
/// Helper: parse source code with the given file extension and return extracted symbols.
99+
/// Creates a synthetic FileChange covering all lines, so all symbols are captured.
100+
#[cfg(any(
101+
feature = "lang-rust",
102+
feature = "lang-typescript",
103+
feature = "lang-python",
104+
feature = "lang-go",
105+
feature = "lang-java",
106+
feature = "lang-c",
107+
feature = "lang-cpp",
108+
feature = "lang-ruby",
109+
feature = "lang-csharp"
110+
))]
111+
fn extract_symbols_from_source(source: &str, ext: &str) -> Vec<commitbee::domain::CodeSymbol> {
112+
let line_count = source.lines().count();
113+
let path = format!("src/test_file.{ext}");
114+
let diff = format!("@@ -0,0 +1,{line_count} @@\n+placeholder\n");
115+
let change = make_file_change(&path, &diff, line_count, 0);
116+
let staged_map = HashMap::from([(PathBuf::from(&path), source.to_string())]);
117+
let head_map = HashMap::new();
118+
let analyzer = AnalyzerService::new().expect("AnalyzerService::new() should succeed");
119+
analyzer.extract_symbols(&[change], &staged_map, &head_map)
120+
}
121+
122+
// ─── Parent scope extraction ─────────────────────────────────────────────────
123+
124+
#[cfg(feature = "lang-rust")]
125+
mod rust_parent_scope {
126+
use super::*;
127+
128+
#[test]
129+
fn rust_impl_method_has_parent_scope() {
130+
let source = r#"impl CommitValidator {
131+
pub fn validate(&self, input: &str) -> bool {
132+
true
133+
}
134+
}"#;
135+
let symbols = extract_symbols_from_source(source, "rs");
136+
let method = symbols
137+
.iter()
138+
.find(|s| s.name == "validate")
139+
.expect("should find validate");
140+
assert_eq!(method.parent_scope.as_deref(), Some("CommitValidator"));
141+
}
142+
143+
#[test]
144+
fn rust_top_level_function_has_no_parent_scope() {
145+
let source = "pub fn standalone() -> bool {\n true\n}\n";
146+
let symbols = extract_symbols_from_source(source, "rs");
147+
let func = symbols
148+
.iter()
149+
.find(|s| s.name == "standalone")
150+
.expect("should find standalone");
151+
assert_eq!(func.parent_scope, None);
152+
}
153+
154+
#[test]
155+
fn rust_trait_method_has_parent_scope() {
156+
let source = r#"trait Validator {
157+
fn validate(&self) -> bool;
158+
}"#;
159+
let symbols = extract_symbols_from_source(source, "rs");
160+
// Trait methods may or may not be captured depending on the .scm query
161+
if let Some(method) = symbols.iter().find(|s| s.name == "validate") {
162+
assert_eq!(method.parent_scope.as_deref(), Some("Validator"));
163+
}
164+
}
165+
}
166+
167+
#[cfg(feature = "lang-python")]
168+
mod python_parent_scope {
169+
use super::*;
170+
171+
#[test]
172+
fn python_class_method_has_parent_scope() {
173+
let source = "class MyService:\n def process(self, data):\n return data\n";
174+
let symbols = extract_symbols_from_source(source, "py");
175+
if let Some(method) = symbols.iter().find(|s| s.name == "process") {
176+
assert_eq!(method.parent_scope.as_deref(), Some("MyService"));
177+
}
178+
}
179+
180+
#[test]
181+
fn python_top_level_function_has_no_parent_scope() {
182+
let source = "def standalone(x):\n return x\n";
183+
let symbols = extract_symbols_from_source(source, "py");
184+
let func = symbols
185+
.iter()
186+
.find(|s| s.name == "standalone")
187+
.expect("should find standalone");
188+
assert_eq!(func.parent_scope, None);
189+
}
190+
}
191+
192+
#[cfg(feature = "lang-typescript")]
193+
mod typescript_parent_scope {
194+
use super::*;
195+
196+
#[test]
197+
fn typescript_class_method_has_parent_scope() {
198+
let source = "class UserService {\n getName(): string {\n return 'test';\n }\n}\n";
199+
let symbols = extract_symbols_from_source(source, "ts");
200+
if let Some(method) = symbols.iter().find(|s| s.name == "getName") {
201+
assert_eq!(method.parent_scope.as_deref(), Some("UserService"));
202+
}
203+
}
204+
205+
#[test]
206+
fn typescript_top_level_function_has_no_parent_scope() {
207+
let source = "function standalone(): void {\n return;\n}\n";
208+
let symbols = extract_symbols_from_source(source, "ts");
209+
let func = symbols
210+
.iter()
211+
.find(|s| s.name == "standalone")
212+
.expect("should find standalone");
213+
assert_eq!(func.parent_scope, None);
214+
}
215+
}
216+
217+
#[cfg(feature = "lang-java")]
218+
mod java_parent_scope {
219+
use super::*;
220+
221+
#[test]
222+
fn java_class_method_has_parent_scope() {
223+
let source = "public class Calculator {\n public int add(int a, int b) {\n return a + b;\n }\n}\n";
224+
let symbols = extract_symbols_from_source(source, "java");
225+
if let Some(method) = symbols.iter().find(|s| s.name == "add") {
226+
assert_eq!(method.parent_scope.as_deref(), Some("Calculator"));
227+
}
228+
}
229+
}
230+
231+
#[cfg(feature = "lang-go")]
232+
mod go_parent_scope {
233+
use super::*;
234+
235+
#[test]
236+
fn go_top_level_function_has_no_parent_scope() {
237+
let source = "func ParseConfig(path string) error {\n\treturn nil\n}\n";
238+
let symbols = extract_symbols_from_source(source, "go");
239+
let func = symbols
240+
.iter()
241+
.find(|s| s.name == "ParseConfig")
242+
.expect("should find ParseConfig");
243+
assert_eq!(func.parent_scope, None);
244+
}
245+
}
246+
247+
#[cfg(feature = "lang-ruby")]
248+
mod ruby_parent_scope {
249+
use super::*;
250+
251+
#[test]
252+
fn ruby_class_method_has_parent_scope() {
253+
let source = "class Calculator\n def add(a, b)\n a + b\n end\nend\n";
254+
let symbols = extract_symbols_from_source(source, "rb");
255+
if let Some(method) = symbols.iter().find(|s| s.name == "add") {
256+
assert_eq!(method.parent_scope.as_deref(), Some("Calculator"));
257+
}
258+
}
259+
}
260+
261+
#[cfg(feature = "lang-csharp")]
262+
mod csharp_parent_scope {
263+
use super::*;
264+
265+
#[test]
266+
fn csharp_class_method_has_parent_scope() {
267+
let source = "public class Calculator {\n public int Add(int a, int b) {\n return a + b;\n }\n}\n";
268+
let symbols = extract_symbols_from_source(source, "cs");
269+
if let Some(method) = symbols.iter().find(|s| s.name == "Add") {
270+
assert_eq!(method.parent_scope.as_deref(), Some("Calculator"));
271+
}
272+
}
273+
}
274+
98275
// ─── Java ────────────────────────────────────────────────────────────────────
99276

100277
#[cfg(feature = "lang-java")]

0 commit comments

Comments
 (0)