Skip to main content

perl_lsp_completion/completion/
test_more.rs

1//! Test::More function completions for Perl
2//!
3//! Provides completion for Test::More functions in test contexts.
4
5use super::{context::CompletionContext, items::CompletionItem};
6
7/// Test::More function completions
8pub const TEST_MORE_EXPORTS: &[(&str, &str, &str)] = &[
9    ("ok", "ok(${1:condition}, ${2:name});", "Test condition is true"),
10    ("is", "is(${1:got}, ${2:expected}, ${3:name});", "Test values are equal"),
11    ("isnt", "isnt(${1:got}, ${2:not_expected}, ${3:name});", "Test values are not equal"),
12    ("like", "like(${1:got}, ${2:qr/.../}, ${3:name});", "Test string matches regex"),
13    ("unlike", "unlike(${1:got}, ${2:qr/.../}, ${3:name});", "Test string doesn't match regex"),
14    ("cmp_ok", "cmp_ok(${1:got}, '${2:op}', ${3:expected}, ${4:name});", "Compare using operator"),
15    ("isa_ok", "isa_ok(${1:ref}, '${2:class}', ${3:name});", "Test object is of class"),
16    ("can_ok", "can_ok(${1:class_or_obj}, ${2:@methods});", "Test object/class can do methods"),
17    ("pass", "pass(${1:name});", "Unconditionally pass test"),
18    ("fail", "fail(${1:name});", "Unconditionally fail test"),
19    ("diag", "diag(${1:message});", "Print diagnostic message"),
20    ("note", "note(${1:message});", "Print note message"),
21    ("explain", "explain(${1:\\$ref});", "Dump data structure"),
22    ("skip", "skip(${1:why}, ${2:how_many});", "Skip tests"),
23    ("todo_skip", "todo_skip(${1:why}, ${2:how_many});", "Mark tests as TODO"),
24    ("BAIL_OUT", "BAIL_OUT(${1:reason});", "Stop all testing"),
25    ("subtest", "subtest '${1:name}' => sub {\n    ${0}\n};", "Run a subtest"),
26    ("done_testing", "done_testing(${1:tests});", "Finish testing"),
27    ("plan", "plan tests => ${1:num};", "Declare test plan"),
28    ("use_ok", "use_ok('${1:Module}');", "Test module loads"),
29    ("require_ok", "require_ok('${1:Module}');", "Test module requires"),
30    (
31        "is_deeply",
32        "is_deeply(${1:\\$got}, ${2:\\$expected}, ${3:name});",
33        "Deep structure comparison",
34    ),
35    ("new_ok", "new_ok('${1:Class}', [${2:args}], ${3:name});", "Test object creation"),
36];
37
38/// Test::More function signatures for hover documentation.
39///
40/// Each entry is `(name, signature, description)`.
41const TEST_MORE_SIGNATURES: &[(&str, &str, &str)] = &[
42    ("ok", "ok($expr, $name)", "Test condition is true"),
43    ("is", "is($got, $expected, $name)", "Test values are equal (string comparison)"),
44    ("isnt", "isnt($got, $not_expected, $name)", "Test values are not equal"),
45    ("like", "like($got, qr/.../, $name)", "Test string matches regex"),
46    ("unlike", "unlike($got, qr/.../, $name)", "Test string does not match regex"),
47    ("cmp_ok", "cmp_ok($got, $op, $expected, $name)", "Compare using an operator"),
48    ("isa_ok", "isa_ok($ref, $class, $name)", "Test object is of the given class"),
49    ("can_ok", "can_ok($class_or_obj, @methods)", "Test object/class can do methods"),
50    ("pass", "pass($name)", "Unconditionally pass a test"),
51    ("fail", "fail($name)", "Unconditionally fail a test"),
52    ("diag", "diag($message)", "Print a diagnostic message to STDERR"),
53    ("note", "note($message)", "Print a note message to STDOUT"),
54    ("explain", "explain($ref)", "Dump a data structure as a string"),
55    ("skip", "skip($why, $how_many)", "Skip tests"),
56    ("todo_skip", "todo_skip($why, $how_many)", "Mark tests as TODO and skip"),
57    ("BAIL_OUT", "BAIL_OUT($reason)", "Stop all testing immediately"),
58    ("subtest", "subtest $name => sub { ... }", "Run a subtest in its own scope"),
59    (
60        "done_testing",
61        "done_testing($tests?)",
62        "Finish testing (optional count; omit to auto-count)",
63    ),
64    ("plan", "plan tests => $num", "Declare the number of tests to run"),
65    ("use_ok", "use_ok($module)", "Test that a module loads successfully"),
66    ("require_ok", "require_ok($module)", "Test that a module requires successfully"),
67    ("is_deeply", "is_deeply($got, $expected, $name)", "Deep structure comparison"),
68    ("new_ok", "new_ok($class, \\@args, $name)", "Test object creation"),
69];
70
71/// Return `(signature, description)` for a Test::More function, or `None` if unknown.
72pub fn get_test_more_documentation(name: &str) -> Option<(&'static str, &'static str)> {
73    TEST_MORE_SIGNATURES.iter().find(|(n, _, _)| *n == name).map(|(_, sig, desc)| (*sig, *desc))
74}
75
76/// Add Test::More completions
77pub fn add_test_more_completions(
78    completions: &mut Vec<CompletionItem>,
79    context: &CompletionContext,
80) {
81    for (name, snippet, doc) in TEST_MORE_EXPORTS {
82        if context.prefix.is_empty() || name.starts_with(&context.prefix) {
83            completions.push(CompletionItem {
84                label: name.to_string(),
85                kind: crate::completion::items::CompletionItemKind::Function,
86                detail: Some("Test::More".to_string()),
87                documentation: Some(doc.to_string()),
88                insert_text: Some(snippet.to_string()),
89                sort_text: Some(format!("2_{}", name)),
90                filter_text: Some(name.to_string()),
91                additional_edits: vec![],
92                text_edit_range: Some((context.prefix_start, context.position)),
93                commit_characters: None,
94            });
95        }
96    }
97}