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

Allow rust-project.json to include arbitrary shell commands for runnables #16840

Merged
merged 1 commit into from
Jun 11, 2024

Conversation

Wilfred
Copy link
Contributor

@Wilfred Wilfred commented Mar 15, 2024

This is a follow-up on #16135, resolving the feedback raised :)

Allow rust-project.json to include shell runnables, of the form:

{
  "build_info": {
    "label": "//project/foo:my-crate",
    "target_kind": "bin",
    "shell_runnables": [
      {
        "kind": "run",
        "program": "buck2",
        "args": ["run", "//project/foo:my-crate"]
      },
      {
        "kind": "test_one",
        "program": "test_runner",
        "args": ["--name=$$TEST_NAME$$"]
      }
    ]
  }
}

If these runnable configs are present for the current crate in rust-project.json, offer them as runnables in VS Code.

This PR required some boring changes to APIs that previously only handled cargo situations. I've split out these changes as commits labelled 'refactor', so it's easy to see the interesting changes.

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 15, 2024
@bors
Copy link
Contributor

bors commented Mar 15, 2024

☔ The latest upstream changes (presumably #16845) made this pull request unmergeable. Please resolve the merge conflicts.

@Wilfred Wilfred force-pushed the shell_runnable branch 5 times, most recently from 65e9be3 to c7bdd91 Compare March 15, 2024 23:14
@Wilfred Wilfred marked this pull request as ready for review March 15, 2024 23:14
@bors
Copy link
Contributor

bors commented Mar 18, 2024

☔ The latest upstream changes (presumably #16868) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented Mar 21, 2024

☔ The latest upstream changes (presumably #16895) made this pull request unmergeable. Please resolve the merge conflicts.

@@ -87,6 +87,21 @@ pub struct Crate {
pub(crate) exclude: Vec<AbsPathBuf>,
pub(crate) is_proc_macro: bool,
pub(crate) repository: Option<String>,
pub build_info: Option<BuildInfo>,
Copy link
Contributor

Choose a reason for hiding this comment

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

i meant to change this in the original PR, but build_info's runnables should be under ProjectJson, not the Crate. label/target_kind should stay under Crate, however.

(that assumes a Bazel/Buck-style labeling system, but even I think for non-Cargo build systems, that's a good enough bar to set.)

Copy link
Contributor

Choose a reason for hiding this comment

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

@davidbarsky If I'm reading this right, you want the runnables to be stored at the root of the project.json. That will require:

  • a substitution mechanism like $label so that the "runnable templates" can be turned into real commands for a specific crate
  • probably RA using the build_info.kind field to figure out which runnables to offer for a given target

I also think we also want custom runnables in build_info for specific crates anyway. Right? Because the build system might simply know better. Substitution is nice because it saves a few MB of JSON. But ultimately you want the ability to add more to specific crates.

Because I believe you're going to want runnables per-crate anyway, and they are completely capable of handling anything substitution can, I think we can merge this PR pretty much as-is. I think the substitution mechanism is more of an optimisation than anything else.

I am happy to put together a PR that allows flycheck to use these.

Copy link
Contributor

Choose a reason for hiding this comment

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

@cormacrelf

a substitution mechanism like $label so that the "runnable templates" can be turned into real commands for a specific crate

Yup: the substitution mechanism is thankfully not too complex: I think it boils down to just a str::replace.

(If you squint, I'd argue that the substitution already exists in rust-analyzer today via Cargo, but the substitution knowledge is pretty implicit...)

probably RA using the build_info.kind field to figure out which runnables to offer for a given target

Will need to repage some context in, but I'm pretty sure the answer is also "yup".

I also think we also want custom runnables in build_info for specific crates anyway. Right? Because the build system might simply know better. Substitution is nice because it saves a few MB of JSON. But ultimately you want the ability to add more to specific crates.

I don't know if I agree: while I'm assuming that while there is a smart build system, I don't think there isn't much surface area for more specialized commands for individual crates. There's also the fact that rust-analyzer is pretty darn fast even compared to buck2, which is the fastest build system I'm aware of—single digit milliseconds versus ~300 milliseconds. There's also the matter of the duplication being somewhat concerning for the Fuschia folks, as their rust-project.json is already pretty large and I'm not really inlined to make things more complicated for them, however slightly.

Because I believe you're going to want runnables per-crate anyway, and they are completely capable of handling anything substitution can, I think we can merge this PR pretty much as-is. I think the substitution mechanism is more of an optimisation than anything else.

You are right it's an optimization, but it's a pretty cheap one. Wilfred and I need to get this over the finish line, but it's genuinely not too much work to implement 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. A good metric for the design is whether rust-project.json can encode all the cargo-related logic. If you set build_info.label to a cargo crate name, and a root level fly check template of cargo check -p $label --message-format=json, then we almost have that mission in the bag. The main missing piece is flycheck for a crate vs for the whole workspace, which is configurable through check.workspace in RA. Having two more runnable kinds, flycheck and flycheckWorkspace, should do 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. A good metric for the design is whether rust-project.json can encode all the cargo-related logic. If you set build_info.label to a cargo crate name, and a root level fly check template of cargo check -p $label --message-format=json, then we almost have that mission in the bag.

Yeah, that's generally the stance I've pursuing.

The main missing piece is flycheck for a crate vs for the whole workspace, which is configurable through check.workspace in RA. Having two more runnable kinds, flycheck and flycheckWorkspace, should do it.

hmm, probably. i don't know if i'd want to set a flycheckWorkspace for rust-project, but I guess it can be a buck2 build 'rdeps(:target, 1)'. at least, i don't know if i'd put it on by default.

(A blessing and a curse of Buck is that there's no clearly delineated "workspace" concept like there is in Cargo.)

Copy link
Contributor

Choose a reason for hiding this comment

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

I wouldn't set it either.


```typescript
{
kind: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

How should the LSP client use the kind field? Does it describe what the runnable does? Then how does it differ then from label field of the parent Runnable?

Also should the "shell" kind have a expectTest field just like the "cargo" kind?

BTW, how should the LSP client interpret the workspaceRoot, expectTest, and overrideCargo fields?

Additionally, I think it would make sense to copy the example from the Pull Request into the lsp-extension.md file, or just reference a user-level documentation describing this feature.

Thanks

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, shouldn't this PR explain the new build_info field of rust-project.json in manual.adoc?

Copy link
Member

Choose a reason for hiding this comment

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

When expectTest is set the client should set the UPDATE_EXPECT env var to 1 when invoking the runnable. ideally there should be a field for arbitrary env var overrides in the payload, then this field could be replaced by the server instructing the client to just set the env var with that general mechanism as we'll need this for other things as well.

overrideCargo I think should just replace the cargo command that is being used by the client.

@Wilfred Wilfred force-pushed the shell_runnable branch 2 times, most recently from 125b58b to b9662e6 Compare March 28, 2024 00:04
@bors
Copy link
Contributor

bors commented Mar 29, 2024

☔ The latest upstream changes (presumably #16971) made this pull request unmergeable. Please resolve the merge conflicts.

@Veykril
Copy link
Member

Veykril commented Apr 18, 2024

This is a follow-up on #16135, resolving the feedback raised :)

So this means #16135 can be closed in favor of this one?

@davidbarsky
Copy link
Contributor

This is a follow-up on #16135, resolving the feedback raised :)

So this means #16135 can be closed in favor of this one?

Yup! Just closed. Wilfred or I will push to this branch as needed.

Copy link
Member

@Veykril Veykril left a comment

Choose a reason for hiding this comment

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

Generally looks good to me (aside from what has been raised already by others)

@Veykril Veykril added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 18, 2024
@davidbarsky davidbarsky force-pushed the shell_runnable branch 5 times, most recently from 0d0ef0a to 660fcbf Compare June 5, 2024 14:22
@bors
Copy link
Contributor

bors commented Jun 6, 2024

✌️ @davidbarsky, you can now approve this pull request!

If @Veykril told you to "r=me" after making some further change, please make that change, then do @bors r=@Veykril

@davidbarsky
Copy link
Contributor

@cormacrelf here's the commit in rust-project: facebook/buck2@7169723.

@petr-tik yes, I think that bazelbuild/rules_rust would be able to take advantage of this feature once this lands.

@bors
Copy link
Contributor

bors commented Jun 7, 2024

☔ The latest upstream changes (presumably #17058) made this pull request unmergeable. Please resolve the merge conflicts.

@davidbarsky davidbarsky force-pushed the shell_runnable branch 2 times, most recently from c062791 to 0dc68a9 Compare June 10, 2024 17:52
/// Additional metadata about a crate, used to configure runnables.
/// Additional, build-specific data about a crate.
///
/// This is primarily used to
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfinished.

/// a check build or a test run.
/// Configuration for commands.
///
/// Examples include a check build or a test run.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd probably explicitly say this is CLI invocations.

/// to offer a 'run' button for library crates.
/// The kind of target.
///
/// Examples (non-exhaustively) include [TargetKind::Lib], [TargetKind::Lib],
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lib twice here.

/// A template for runnables.
///
/// This to create runnables for running/debugging binaries and tests.
/// In the future, it can be used to setup Flycheck.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd focus on what it can do today, rather than future work.

/// "{test_id}",
/// "--print-passing-details"
/// ],
/// "cwd": "/Users/dbarsky/fbsource",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

How about something more generically named here? Buck conventions aren't super useful.

Copy link
Contributor

Choose a reason for hiding this comment

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

whoops, i thought i removed this! I'll make this something like /home/user/repo-root/.

/// "{test_id}",
/// "--print-passing-details"
/// ],
/// "cwd": "/Users/dbarsky/fbsource",
Copy link
Contributor

Choose a reason for hiding this comment

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

whoops, i thought i removed this! I'll make this something like /home/user/repo-root/.

@davidbarsky davidbarsky force-pushed the shell_runnable branch 2 times, most recently from 877c39d to 48a2435 Compare June 10, 2024 23:32
/// The kind of target.
///
/// Examples (non-exhaustively) include [TargetKind::Bin], [TargetKind::Lib],
/// and [TargetKind::Test]. This information is used to determine what sort
Copy link
Member

Choose a reason for hiding this comment

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

what sort of

Copy link
Contributor

@davidbarsky davidbarsky Jun 11, 2024

Choose a reason for hiding this comment

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

thanks!

/// the label might be something like `//ide/rust/rust-analyzer:rust-analyzer`.
///
/// Do not attempt to parse the contents of this string; it is a build system-specific
/// identifier similar to [Crate::display_name].
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Crate::display_name will only show up as monospace in the docs if you wrap it in backquotes.

Copy link
Contributor

Choose a reason for hiding this comment

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

thanks! fixed.

pub label: String,
/// Path corresponding to the build system-specific file defining the crate.
///
/// It is roughly analogous to [ManifestPath], but none of the indexing/loading
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// It is roughly analogous to [ManifestPath], but none of the indexing/loading
/// It is roughly analogous to [`ManifestPath`], but none of the indexing/loading

/// # Example
///
/// Below is an example of a test runnable. `{label}` and `{test_id}`
/// are explained in [Runnable::args]'s documentation.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// are explained in [Runnable::args]'s documentation.
/// are explained in the [`Runnable::args`] documentation.

///
/// For example, this might be `cargo`, `buck`, or `bazel`.
pub program: String,
/// The arguments passed to [Runnable::program].
Copy link
Member

Choose a reason for hiding this comment

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

Since you've changed one..

Suggested change
/// The arguments passed to [Runnable::program].
/// The arguments passed to [`Runnable::program`].

Comment on lines 111 to 112
/// It is roughly analogous to [`ManifestPath`], but none of the indexing/loading
/// operations can be directly applied/used with this file.
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure I can tell what indexing/loading operations are in this context

Copy link
Contributor

@davidbarsky davidbarsky Jun 11, 2024

Choose a reason for hiding this comment

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

it's in reference to ProjectManifest::from_manifest_file. you can't run cargo metadata on a rust-project.json or Starlark-ified TARGETS file.

(Arguably, it should, but that's more of a discussion for #17246. I'll clarify this comment.)

@davidbarsky
Copy link
Contributor

@bors r=@Veykril

@bors
Copy link
Contributor

bors commented Jun 11, 2024

📌 Commit 71a78a9 has been approved by Veykril

It is now in the queue for this repository.

@bors
Copy link
Contributor

bors commented Jun 11, 2024

⌛ Testing commit 71a78a9 with merge 4af21ff...

@bors
Copy link
Contributor

bors commented Jun 11, 2024

☀️ Test successful - checks-actions
Approved by: Veykril
Pushing 4af21ff to master...

@bors bors merged commit 4af21ff into rust-lang:master Jun 11, 2024
11 checks passed
@gvozdvmozgu
Copy link

It seems that after this PR, the tests have stopped running.

 *  Executing task: cargo cargo test --package sqruff-lib --lib -- rules::layout::LT13::tests::test_fail_leading_whitespace_comment --exact --show-output 

error: no such command: `cargo`

        View all installed commands with `cargo --list`
        Find a package to install `cargo` with `cargo search cargo-cargo`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants