-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
go: Add runnables for Go #12003
Conversation
We require contributors to sign our Contributor License Agreement, and we don't have @anilsenay on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
@cla-bot check |
The cla-bot has been summoned, and re-checked this pull request! |
crates/languages/src/go.rs
Outdated
let snapshot = location.buffer.read(cx).snapshot(); | ||
let point_range = location.range.to_point(&snapshot); | ||
let end = Point::new(point_range.start.row + 1, 0); | ||
let line = snapshot.text_for_range(point_range.start..end).peek(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would make sense for build_context
function to get access to context built up so far; that way, it could inspect variables set by the captures and you wouldn't have to extract function name from current line, which in my opinion isn't ideal. You really had no better tool at your disposal though.
Tomorrow I'll wire through the changes that will allow us to simplify that function a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@osiewicz Unfortunately, I haven't found a better way to get the line. As you said, It would be better if I could just access viabuild_context
more easily. I would appreciate your assistance 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries at all! It's not like there was a better way either.
I've opened a PR in #12134; once that lands,
you'll be able to capture the first parameter (that's a string) as a hidden variable, process it (stripping "Run" prefix) and then save it as the SUBTASK_NAME
.
Woops, sorry! Didn't see this one here, I'll try to help with the rebase. |
Ahaha its okey 🙏 I haven't rebase it to avoid overlap your code. You may review my code and change as you like while doing rebase. |
Alright, I rebased and combined the code. Clicking on subtests works, but there's something fishy going on that stops them from showing up in the modal. They only show up when on first character of the line that contains |
Thank you @mrnugget 🎉 Alright, he would also look for a better way to get the selected line. Then I'll leave it to him. I'll also look at what I can do. |
Yeah, I also pushed a commit to use the whole line. |
crates/languages/src/go.rs
Outdated
let line = snapshot.text_for_range(start..end).peek(); | ||
|
||
let go_subtest_variable = extract_subtest_name(line.unwrap_or("")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think peek()
does not return the whole line. I debugged line
and it has not contain all line content. I tried to use collect
and then got the whole line. Could you take a look for this issue?
let line = snapshot.text_for_range(start..end).collect::<String>();
let go_subtest_variable = extract_subtest_name(line.as_str())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does for me.
[crates/languages/src/go.rs:492:9] &line = Some(
"\tt.Run(\"Foobar\", func(t *testing.T) {\n",
)
[crates/languages/src/go.rs:492:9] &line = Some(
"\t\tfmt.Println(\"subtest\")\n",
)
Got it, thank you for explanation 🙏 |
Oh right, our way to set
for example, in a working directory
I guess vscode-go extension doing similar like this. In addition, module names are listed in the Testing tab. So getting module name of a go file may be useful for us even later.
I agree that configurable test args could be helpful. For example I changed test timeout argument in vscode. I can be done by injecting user's custom arg list to task's args list maybe. Do you have any opinion or future plans for this suggestion @mrnugget @osiewicz ? |
First off, if the user has a task in their |
In #12003 we found ourselves in need for precise region tracking in which a given runnable has an effect in order to grab variables from it. This PR makes it so that in task modal all task variables from queries overlapping current cursor position. However, in the process of working on that I've found that we cannot always use a top-level capture to represent the full match range of runnable (which has been my assumption up to this point). Tree-sitter captures cannot capture sibling groups; we did just that in Rust queries. Thankfully, none of the extensions are affected as in them, a capture is always attached to single node. This PR adds annotations to them nonetheless; we'll be able to get rid of top-level captures in extension runnables.scm once this PR is in stable version of Zed.
In #12003 we found ourselves in need for precise region tracking in which a given runnable has an effect in order to grab variables from it. This PR makes it so that in task modal all task variables from queries overlapping current cursor position. However, in the process of working on that I've found that we cannot always use a top-level capture to represent the full match range of runnable (which has been my assumption up to this point). Tree-sitter captures cannot capture sibling groups; we did just that in Rust queries. Thankfully, none of the extensions are affected as in them, a capture is always attached to single node. This PR adds annotations to them nonetheless; we'll be able to get rid of top-level captures in extension runnables.scm once this PR is in stable version of Zed.
(#eq? @run "main")) | ||
) @go-main | ||
(call_expression function: (_) @run @_name | ||
(#match? @_name "^t.Run.*")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it safe to assume that the variable we're calling Run
on is always going to be called t
? I get that it's a convention, but is there some precedent in Go community for breaking it sometimes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think we can rework this pattern altogether to simplify it a bit:
With the following query:
; `t.Run`
(
(call_expression
function: (
selector_expression
field: _ @run @_name
(#eq? @_name "Run")
)
arguments: (
argument_list
.
(interpreted_string_literal) @_subtest_name
)
)
(#set! tag go-subtest)
)
In build_context
the task_variables argument is gonna have the value of first argument (string literal) in _subtest_name
key. You won't have to parse the line then.
So, tl;dr: in build_context you can get the value of this capture with:
variables.get(&VariableName::Custom(Cow::Borrowed("_subtest_name")));
You still need to escape the subtest name (I guess?) and set it in the context being returned from build_context (captures with _ prefix are removed after a call to build_context so that end users can't reference it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, its a convention and actually I did not want to cover an edge case for now 😄
It seems logical; I'm gonna try your new suggestion when I am free or maybe you gonna try it already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Chipping in to say it's a fairly strong convention and good starting point. I've seen some codebases use test helpers that break the t.Run
pattern but VSCode and GoLand don't match those subtests either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that's fair. With that other query (#12003 (comment)) we don't even need to match on variable name though, as we'll capture just the name of the function being called; so the whole dispute about whether we should match t.
is kinda moot. ;p
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would your example above match an unrelated Run()
call like
client.Run(ctx) // should not match
t.Run("client returns OK", func(t testing.T) {...}) // should match
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it would not. We also expect the first argument to be a string literal. We could perhaps constrain it further to also require a second parameter that's (I guess?) an anonymous function taking a single param of type testing T
Co-authored-by: Piotr Osiewicz <[email protected]>
Co-authored-by: Piotr Osiewicz <[email protected]>
If you talked about submodule issue, I will open an issue for that not to be forgotten after this PR merged. |
…odal (#12237) In #12003 we found ourselves in need for precise region tracking in which a given runnable has an effect in order to grab variables from it. This PR makes it so that in task modal all task variables from queries overlapping current cursor position. However, in the process of working on that I've found that we cannot always use a top-level capture to represent the full match range of runnable (which has been my assumption up to this point). Tree-sitter captures cannot capture sibling groups; we did just that in Rust queries. Thankfully, none of the extensions are affected as in them, a capture is always attached to single node. This PR adds annotations to them nonetheless; we'll be able to get rid of top-level captures in extension runnables.scm once this PR is in stable version of Zed. Release Notes: - N/A
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM :)
Hide @second_argument from user Co-authored-by: Piotr Osiewicz <[email protected]>
…odal (zed-industries/zed#12237) In zed-industries/zed#12003 we found ourselves in need for precise region tracking in which a given runnable has an effect in order to grab variables from it. This PR makes it so that in task modal all task variables from queries overlapping current cursor position. However, in the process of working on that I've found that we cannot always use a top-level capture to represent the full match range of runnable (which has been my assumption up to this point). Tree-sitter captures cannot capture sibling groups; we did just that in Rust queries. Thankfully, none of the extensions are affected as in them, a capture is always attached to single node. This PR adds annotations to them nonetheless; we'll be able to get rid of top-level captures in extension runnables.scm once this PR is in stable version of Zed. Release Notes: - N/A
Implemented runnables for specially for running tests for Go.
I'm grateful for your feedback because this is my first experience with Rust and Zed codebase.
Release Notes:
Screen.Recording.2024-05-21.at.23.16.15.mov