diff --git a/crates/languages/src/go.rs b/crates/languages/src/go.rs index 60c6d98d21f9b3273f3afdaeb2cbe544af15efe9..52bd93523c2a9e0257249bd2c4464a589d41f286 100644 --- a/crates/languages/src/go.rs +++ b/crates/languages/src/go.rs @@ -479,6 +479,8 @@ const GO_SUBTEST_NAME_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("GO_SUBTEST_NAME")); const GO_TABLE_TEST_CASE_NAME_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("GO_TABLE_TEST_CASE_NAME")); +const GO_SUITE_NAME_TASK_VARIABLE: VariableName = + VariableName::Custom(Cow::Borrowed("GO_SUITE_NAME")); impl ContextProvider for GoContextProvider { fn build_context( @@ -537,19 +539,26 @@ impl ContextProvider for GoContextProvider { let go_subtest_variable = extract_subtest_name(_subtest_name.unwrap_or("")) .map(|subtest_name| (GO_SUBTEST_NAME_TASK_VARIABLE.clone(), subtest_name)); - let table_test_case_name = variables.get(&VariableName::Custom(Cow::Borrowed( + let _table_test_case_name = variables.get(&VariableName::Custom(Cow::Borrowed( "_table_test_case_name", ))); - let go_table_test_case_variable = table_test_case_name + let go_table_test_case_variable = _table_test_case_name .and_then(extract_subtest_name) .map(|case_name| (GO_TABLE_TEST_CASE_NAME_TASK_VARIABLE.clone(), case_name)); + let _suite_name = variables.get(&VariableName::Custom(Cow::Borrowed("_suite_name"))); + + let go_suite_variable = _suite_name + .and_then(extract_subtest_name) + .map(|suite_name| (GO_SUITE_NAME_TASK_VARIABLE.clone(), suite_name)); + Task::ready(Ok(TaskVariables::from_iter( [ go_package_variable, go_subtest_variable, go_table_test_case_variable, + go_suite_variable, go_module_root_variable, ] .into_iter() @@ -566,6 +575,28 @@ impl ContextProvider for GoContextProvider { let module_cwd = Some(GO_MODULE_ROOT_TASK_VARIABLE.template_value()); Task::ready(Some(TaskTemplates(vec![ + TaskTemplate { + label: format!( + "go test {} -v -run Test{}/{}", + GO_PACKAGE_TASK_VARIABLE.template_value(), + GO_SUITE_NAME_TASK_VARIABLE.template_value(), + VariableName::Symbol.template_value(), + ), + command: "go".into(), + args: vec![ + "test".into(), + "-v".into(), + "-run".into(), + format!( + "\\^Test{}\\$/\\^{}\\$", + GO_SUITE_NAME_TASK_VARIABLE.template_value(), + VariableName::Symbol.template_value(), + ), + ], + cwd: package_cwd.clone(), + tags: vec!["go-testify-suite".to_owned()], + ..TaskTemplate::default() + }, TaskTemplate { label: format!( "go test {} -v -run {}/{}", @@ -819,6 +850,59 @@ mod tests { ); } + #[gpui::test] + fn test_testify_suite_detection(cx: &mut TestAppContext) { + let language = language("go", tree_sitter_go::LANGUAGE.into()); + + let testify_suite = r#" + package main + + import ( + "testing" + + "github.com/stretchr/testify/suite" + ) + + type ExampleSuite struct { + suite.Suite + } + + func TestExampleSuite(t *testing.T) { + suite.Run(t, new(ExampleSuite)) + } + + func (s *ExampleSuite) TestSomething_Success() { + // test code + } + "#; + + let buffer = cx + .new(|cx| crate::Buffer::local(testify_suite, cx).with_language(language.clone(), cx)); + cx.executor().run_until_parked(); + + let runnables: Vec<_> = buffer.update(cx, |buffer, _| { + let snapshot = buffer.snapshot(); + snapshot.runnable_ranges(0..testify_suite.len()).collect() + }); + + let tag_strings: Vec = runnables + .iter() + .flat_map(|r| &r.runnable.tags) + .map(|tag| tag.0.to_string()) + .collect(); + + assert!( + tag_strings.contains(&"go-test".to_string()), + "Should find go-test tag, found: {:?}", + tag_strings + ); + assert!( + tag_strings.contains(&"go-testify-suite".to_string()), + "Should find go-testify-suite tag, found: {:?}", + tag_strings + ); + } + #[gpui::test] fn test_go_runnable_detection(cx: &mut TestAppContext) { let language = language("go", tree_sitter_go::LANGUAGE.into()); diff --git a/crates/languages/src/go/runnables.scm b/crates/languages/src/go/runnables.scm index f56262f799c3d73c8eaadd03665565f75add27ba..90b29f7cbca2f46786c092f3450edc65e04939f1 100644 --- a/crates/languages/src/go/runnables.scm +++ b/crates/languages/src/go/runnables.scm @@ -1,22 +1,28 @@ ; Functions names start with `Test` ( - [ + ( (function_declaration name: (_) @run (#match? @run "^Test.*")) + ) @_ + (#set! tag go-test) +) + +; Suite test methods (testify/suite) +( (method_declaration receiver: (parameter_list (parameter_declaration - name: (identifier) @_receiver_name - type: [ - (pointer_type (type_identifier) @_receiver_type) - (type_identifier) @_receiver_type - ] + type: [ + (pointer_type (type_identifier) @_suite_name) + (type_identifier) @_suite_name + ] ) ) - name: (field_identifier) @run @_method_name - (#match? @_method_name "^Test.*")) - ] @_ - (#set! tag go-test) + name: (field_identifier) @run @_subtest_name + (#match? @_subtest_name "^Test.*") + (#match? @_suite_name ".*Suite") + ) @_ + (#set! tag go-testify-suite) ) ; `go:generate` comments