use std::sync::LazyLock;
use regex::Regex;
pub const NODE_KINDS: &[&str] = &[];
static TS_JS_GLOBALS_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(
r"^(describe|it|test|xit|xdescribe|fdescribe|fit|context|beforeEach|afterEach|beforeAll|afterAll|expect)\(",
)
.expect("testing TS/JS globals regex is valid")
});
static TS_JS_FRAMEWORK_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^(jest|vi)\.(fn|mock|spyOn|clearAllMocks|resetAllMocks|useFakeTimers)\(")
.expect("testing TS/JS framework regex is valid")
});
static GO_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(
r"\bt\.(Run|Error|Errorf|Fatal|Fatalf|Helper|Skip|Skipf|Log|Logf|Cleanup|Parallel)\(",
)
.expect("testing Go regex is valid")
});
static PYTHON_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"\bself\.assert[A-Z]\w*\(").expect("testing Python regex is valid")
});
pub fn matches_callee(text: &str, language: &str) -> bool {
match language {
"typescript" | "javascript" => {
TS_JS_GLOBALS_RE.is_match(text) || TS_JS_FRAMEWORK_RE.is_match(text)
}
"go" => GO_RE.is_match(text),
"python" => PYTHON_RE.is_match(text),
_ => false,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn describe_matches_ts() {
assert!(matches_callee("describe('suite', fn)", "typescript"));
}
#[test]
fn it_matches_js() {
assert!(matches_callee("it('does something', fn)", "javascript"));
}
#[test]
fn test_matches_ts() {
assert!(matches_callee("test('is truthy', () => {})", "typescript"));
}
#[test]
fn expect_matches_js() {
assert!(matches_callee("expect(x).toBe(1)", "javascript"));
}
#[test]
fn before_each_matches() {
assert!(matches_callee("beforeEach(() => {})", "typescript"));
}
#[test]
fn after_all_matches() {
assert!(matches_callee("afterAll(() => {})", "javascript"));
}
#[test]
fn xit_matches() {
assert!(matches_callee("xit('skipped', fn)", "typescript"));
}
#[test]
fn context_matches() {
assert!(matches_callee("context('ctx', fn)", "javascript"));
}
#[test]
fn jest_mock_matches() {
assert!(matches_callee("jest.mock('./module')", "typescript"));
}
#[test]
fn jest_fn_matches() {
assert!(matches_callee("jest.fn()", "typescript"));
}
#[test]
fn jest_spy_on_matches() {
assert!(matches_callee("jest.spyOn(obj, 'method')", "typescript"));
}
#[test]
fn vi_fn_matches() {
assert!(matches_callee("vi.fn()", "javascript"));
}
#[test]
fn vi_mock_matches() {
assert!(matches_callee("vi.mock('./mod')", "typescript"));
}
#[test]
fn console_log_does_not_match() {
assert!(!matches_callee("console.log(x)", "typescript"));
}
#[test]
fn use_effect_does_not_match() {
assert!(!matches_callee("useEffect(fn, [])", "typescript"));
}
#[test]
fn t_run_matches_go() {
assert!(matches_callee("t.Run(\"sub\", fn)", "go"));
}
#[test]
fn t_fatal_matches_go() {
assert!(matches_callee("t.Fatal(err)", "go"));
}
#[test]
fn t_parallel_matches_go() {
assert!(matches_callee("t.Parallel()", "go"));
}
#[test]
fn go_st_run_does_not_match() {
assert!(!matches_callee("st.Run(\"sub\", fn)", "go"));
}
#[test]
fn self_assert_equal_matches() {
assert!(matches_callee("self.assertEqual(a, b)", "python"));
}
#[test]
fn self_assert_true_matches() {
assert!(matches_callee("self.assertTrue(x)", "python"));
}
#[test]
fn self_method_does_not_match() {
assert!(!matches_callee("self.method()", "python"));
}
#[test]
fn self_assert_snake_does_not_match() {
assert!(!matches_callee("self.assert_something()", "python"));
}
#[test]
fn rust_returns_false() {
assert!(!matches_callee("describe('s', fn)", "rust"));
}
#[test]
fn node_kinds_is_empty() {
#[allow(clippy::const_is_empty)]
let empty = NODE_KINDS.is_empty();
assert!(empty);
}
}