Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

go: Add runnables for Go #12003

Merged
merged 16 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 74 additions & 13 deletions crates/languages/src/go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ impl GoLspAdapter {

lazy_static! {
static ref GOPLS_VERSION_REGEX: Regex = Regex::new(r"\d+\.\d+\.\d+").unwrap();
static ref GO_EXTRACT_SUBTEST_NAME_REGEX: Regex =
Regex::new(r#".*t\.Run\("([^"]*)".*"#).unwrap();
static ref GO_ESCAPE_SUBTEST_NAME_REGEX: Regex = Regex::new(r#"[.*+?^${}()|\[\]\\]"#).unwrap();
}

#[async_trait(?Send)]
Expand Down Expand Up @@ -443,6 +446,8 @@ fn adjust_runs(
pub(crate) struct GoContextProvider;

const GO_PACKAGE_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("GO_PACKAGE"));
const GO_SUBTEST_NAME_TASK_VARIABLE: VariableName =
VariableName::Custom(Cow::Borrowed("GO_SUBTEST_NAME"));

impl ContextProvider for GoContextProvider {
fn build_context(
Expand All @@ -457,11 +462,10 @@ impl ContextProvider for GoContextProvider {
.file()
.and_then(|file| Some(file.as_local()?.abs_path(cx)));

Ok(
if let Some(buffer_dir) = local_abs_path
.as_deref()
.and_then(|local_abs_path| local_abs_path.parent())
{
let go_package_variable = local_abs_path
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we should add something like ZED_FILE_DIR so that you don't have to do this. I'll take care of it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, we'll have ZED_DIRNAME on main real soon: #12245 ; you won't have to set that variable then.

.as_deref()
.and_then(|local_abs_path| local_abs_path.parent())
.map(|buffer_dir| {
// Prefer the relative form `./my-nested-package/is-here` over
// absolute path, because it's more readable in the modal, but
// the absolute path also works.
Expand All @@ -477,14 +481,19 @@ impl ContextProvider for GoContextProvider {
})
.unwrap_or_else(|| format!("{}", buffer_dir.to_string_lossy()));

TaskVariables::from_iter(Some((
GO_PACKAGE_TASK_VARIABLE.clone(),
package_name.to_string(),
)))
} else {
TaskVariables::default()
},
)
(GO_PACKAGE_TASK_VARIABLE.clone(), package_name.to_string())
});

let _subtest_name = variables.get(&VariableName::Custom(Cow::Borrowed("_subtest_name")));

let go_subtest_variable = extract_subtest_name(_subtest_name.unwrap_or(""))
.map(|subtest_name| (GO_SUBTEST_NAME_TASK_VARIABLE.clone(), subtest_name));

Ok(TaskVariables::from_iter(
[go_package_variable, go_subtest_variable]
.into_iter()
.flatten(),
))
}

fn associated_tasks(&self) -> Option<TaskTemplates> {
Expand Down Expand Up @@ -517,6 +526,46 @@ impl ContextProvider for GoContextProvider {
args: vec!["test".into(), "./...".into()],
..TaskTemplate::default()
},
TaskTemplate {
label: format!(
"go test {} -run {}/{}",
GO_PACKAGE_TASK_VARIABLE.template_value(),
VariableName::Symbol.template_value(),
GO_SUBTEST_NAME_TASK_VARIABLE.template_value(),
),
command: "go".into(),
args: vec![
"test".into(),
GO_PACKAGE_TASK_VARIABLE.template_value(),
"-v".into(),
"-run".into(),
format!(
"^{}$/^{}$",
VariableName::Symbol.template_value(),
GO_SUBTEST_NAME_TASK_VARIABLE.template_value(),
),
],
tags: vec!["go-subtest".to_owned()],
..TaskTemplate::default()
},
TaskTemplate {
label: format!(
"go test {} -bench {}",
GO_PACKAGE_TASK_VARIABLE.template_value(),
VariableName::Symbol.template_value()
),
command: "go".into(),
args: vec![
"test".into(),
GO_PACKAGE_TASK_VARIABLE.template_value(),
"-benchmem".into(),
"-run=^$".into(),
"-bench".into(),
format!("^{}$", VariableName::Symbol.template_value()),
],
tags: vec!["go-benchmark".to_owned()],
..TaskTemplate::default()
},
TaskTemplate {
label: format!("go run {}", GO_PACKAGE_TASK_VARIABLE.template_value(),),
command: "go".into(),
Expand All @@ -528,6 +577,18 @@ impl ContextProvider for GoContextProvider {
}
}

fn extract_subtest_name(input: &str) -> Option<String> {
let replaced_spaces = input.trim_matches('"').replace(' ', "_");

Some(
GO_ESCAPE_SUBTEST_NAME_REGEX
.replace_all(&replaced_spaces, |caps: &regex::Captures| {
format!("\\{}", &caps[0])
})
.to_string(),
)
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
67 changes: 57 additions & 10 deletions crates/languages/src/go/runnables.scm
Original file line number Diff line number Diff line change
@@ -1,15 +1,62 @@
; Functions names start with `Test`
(
(
(function_declaration name: (_) @run
(#match? @run "^Test.*"))
) @_
(#set! tag go-test)
(
(function_declaration name: (_) @run
(#match? @run "^Test.*"))
) @_
(#set! tag go-test)
)

; `t.Run`
(
(
(function_declaration name: (_) @run
(#eq? @run "main"))
) @_
(#set! tag go-main)
(
(call_expression
function: (
selector_expression
field: _ @run @_name
(#eq? @_name "Run")
)
arguments: (
argument_list
.
(interpreted_string_literal) @_subtest_name
.
(func_literal
parameters: (
parameter_list
(parameter_declaration
name: (identifier) @_param_name
type: (pointer_type
(qualified_type
package: (package_identifier) @_pkg
name: (type_identifier) @_type
(#eq? @_pkg "testing")
(#eq? @_type "T")
)
)
)
)
) @_second_argument
)
)
) @_
(#set! tag go-subtest)
)

; Functions names start with `Benchmark`
(
(
(function_declaration name: (_) @run @_name
(#match? @_name "^Benchmark.+"))
) @_
(#set! tag go-benchmark)
)

; go run
(
(
(function_declaration name: (_) @run
(#eq? @run "main"))
) @_
(#set! tag go-main)
)
1 change: 1 addition & 0 deletions crates/languages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ pub fn init(
vec![Arc::new(go::GoLspAdapter)],
GoContextProvider
);

language!(
"json",
vec![Arc::new(json::JsonLspAdapter::new(
Expand Down
23 changes: 23 additions & 0 deletions crates/task/src/task_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,4 +679,27 @@ mod tests {
expected.sort_by_key(|var| var.to_string());
assert_eq!(resolved_variables, expected)
}

#[test]
fn substitute_funky_labels() {
let faulty_go_test = TaskTemplate {
label: format!(
"go test {}/{}",
VariableName::Symbol.template_value(),
VariableName::Symbol.template_value(),
),
command: "go".into(),
args: vec![format!(
"^{}$/^{}$",
VariableName::Symbol.template_value(),
VariableName::Symbol.template_value()
)],
..TaskTemplate::default()
};
let mut context = TaskContext::default();
context
.task_variables
.insert(VariableName::Symbol, "my-symbol".to_string());
assert!(faulty_go_test.resolve_task("base", &context).is_some());
}
}
Loading