"""Tests for language-specific parsing."""
import pytest
from jcodemunch_mcp.parser import parse_file
JAVASCRIPT_SOURCE = '''
/** Greet a user. */
function greet(name) {
return `Hello, ${name}!`;
}
class Calculator {
/** Add two numbers. */
add(a, b) {
return a + b;
}
}
const MAX_RETRY = 5;
'''
def test_parse_javascript():
"""Test JavaScript parsing."""
symbols = parse_file(JAVASCRIPT_SOURCE, "app.js", "javascript")
# Should have function, class, method, constant
func = next((s for s in symbols if s.name == "greet"), None)
assert func is not None
assert func.kind == "function"
assert "Greet a user" in func.docstring
cls = next((s for s in symbols if s.name == "Calculator"), None)
assert cls is not None
assert cls.kind == "class"
method = next((s for s in symbols if s.name == "add"), None)
assert method is not None
assert method.kind == "method"
TYPESCRIPT_SOURCE = '''
interface User {
name: string;
}
/** Get user by ID. */
function getUser(id: number): User {
return { name: "Test" };
}
class UserService {
private users: User[] = [];
@cache()
findById(id: number): User | undefined {
return this.users.find(u => u.id === id);
}
}
type ID = string | number;
'''
def test_parse_typescript():
"""Test TypeScript parsing."""
symbols = parse_file(TYPESCRIPT_SOURCE, "service.ts", "typescript")
# Should have interface, function, class, method, type alias
func = next((s for s in symbols if s.name == "getUser"), None)
assert func is not None
assert func.kind == "function"
interface = next((s for s in symbols if s.name == "User"), None)
assert interface is not None
assert interface.kind == "type"
GO_SOURCE = '''
package main
import "fmt"
// Person represents a person.
type Person struct {
Name string
}
// Greet prints a greeting.
func (p *Person) Greet() {
fmt.Println("Hello, " + p.Name)
}
// Add adds two numbers.
func Add(a, b int) int {
return a + b
}
const MaxCount = 100
'''
def test_parse_go():
"""Test Go parsing."""
symbols = parse_file(GO_SOURCE, "main.go", "go")
# Should have type, method, function, constant
person = next((s for s in symbols if s.name == "Person"), None)
assert person is not None
assert person.kind == "type"
greet = next((s for s in symbols if s.name == "Greet"), None)
assert greet is not None
assert greet.kind == "method"
RUST_SOURCE = '''
/// A user in the system.
pub struct User {
name: String,
}
impl User {
/// Create a new user.
pub fn new(name: &str) -> Self {
Self { name: name.to_string() }
}
/// Get the user's name.
pub fn name(&self) -> &str {
&self.name
}
}
pub const MAX_USERS: usize = 1000;
'''
def test_parse_rust():
"""Test Rust parsing."""
symbols = parse_file(RUST_SOURCE, "user.rs", "rust")
# Should have struct, impl, methods, constant
user = next((s for s in symbols if s.name == "User"), None)
assert user is not None
assert user.kind == "type"
JAVA_SOURCE = '''
/**
* A simple calculator.
*/
public class Calculator {
public static final int MAX_VALUE = 100;
/**
* Add two numbers.
*/
public int add(int a, int b) {
return a + b;
}
}
interface Operable {
int operate(int a, int b);
}
'''
def test_parse_java():
"""Test Java parsing."""
symbols = parse_file(JAVA_SOURCE, "Calculator.java", "java")
# Should have class, method, interface
calc = next((s for s in symbols if s.name == "Calculator"), None)
assert calc is not None
assert calc.kind == "class"
add = next((s for s in symbols if s.name == "add"), None)
assert add is not None
assert add.kind == "method"