Skip to content

Conversation

@cormacrelf
Copy link
Contributor

@cormacrelf cormacrelf commented Sep 4, 2024

Recap of recent developments with non-Cargo build systems

  1. We have workspace.discoverConfig, which configures a command to (basically) spit out a rust-project.json on stdout and treats it like you put a rust-project.json file on disk.
  2. JSON projects have a nice section for runnables, but they're currently limited to RunnableKind { Check, Run, TestOne, }. You cannot have the JSON project configure its own flychecks. Which means that configuring a non-Cargo build system is a complicated dance of workspace.discoverConfig + check.overrideCommand + "check.workspace": false.
  3. The {label} substitution (available for runnables) was not usable for the flycheck command. I think because the only users of discoverConfig have been content with $saved_file so far. So we currently have build labels in the JSON project that can't even be used for flychecking.

What this does

This PR adds this functionality:

  1. Allows the discoverConfig to describe how to flycheck crates, using a new runnable kind of "flycheck".
  2. Allows all types of flycheck override commands to use {label}. If you are not using discoverConfig / rust-project.json and therefore don't have build labels attached to crates, then {label} means the cargo canonical name. Previously we only supported $saved_file here.
  3. The flycheck begin notification now includes a pretty-print of the actual command in use (if you're not just letting RA run cargo). Super useful to know that things got configured ok, at the bottom of your VSCode window.

And fixes:

  1. Flychecks were being run on random downstream crates instead of the crate containing the file you saved, which would randomly result in cargo check-ing a bigger downstream dependency, leading to unnecessarily slow flychecks and wasted CPU cycles. See the comments in notification.rs. I noticed this because the buck2 rust-project check command does not give diagnostics for dependencies of the target you ask for. This was fixed in fix: Fix flycheck getting confused which package to check #18845 it seems, although it also appears to have completely disabled flycheck for rust-project.json. I certainly noticed there was no flycheck at all when I tried mainline RA on 2025-12-02. I guess if you don't add tests for behaviour, the behaviour slowly fades away!
Notes for users

For people actually using this, it works well in VSCode if you configure rust-analyzer.workspace.discoverConfig in your settings.json, as per the manual. However, because rust-analyzer.toml support is still in its infancy, to get this going in Neovim, you will need my PR to rustaceanvim to get the settings into the initialization request, and I advise having rustaceanvim autoload settings from a file called rust-analyzer.json.

Tagging: @alibektas @davidbarsky

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 4, 2024
@cormacrelf cormacrelf force-pushed the feature/rust-project-discovery branch from f1dbc97 to 52354dc Compare September 4, 2024 04:08
@cormacrelf cormacrelf changed the title Configure flycheck using discovered using [workspace.discoverConfig] Configure flycheck using workspace.discoverConfig Sep 4, 2024
@cormacrelf cormacrelf force-pushed the feature/rust-project-discovery branch 2 times, most recently from 5bf5e0d to 09ef79a Compare September 5, 2024 04:53
Copy link
Contributor

@davidbarsky davidbarsky left a comment

Choose a reason for hiding this comment

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

some assorted comments. I'll do another pass later.

// Trigger flychecks for the only crate which the target belongs to
Some((_, krate)) => vec![krate],
None => {
tracing::debug!("flycheck scope: {:?}", scope);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
tracing::debug!("flycheck scope: {:?}", scope);
tracing::debug!(?scope);

Comment on lines 663 to 668
PackageToRestart::Package(PackageSpecifier::BuildInfo { label: _ }) => {
// No way to flycheck this single package. All we have is a build label.
// There's no way to really say whether this build label happens to be
// a cargo canonical name, so we won't try.
return None;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

not a review comment, but more resignation: it's unfortunate that it is possible to have a PackageSpecifier::BuildInfo in FlycheckConfig::CargoCommand branch.

Copy link
Contributor Author

@cormacrelf cormacrelf Sep 6, 2024

Choose a reason for hiding this comment

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

We can rename it FlycheckConfig::Automatic. Because it is! In cargo workspaces it does cargo stuff; in json workspaces it does JSON stuff.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed to Automatic, it is a bit clearer.

}

pub(crate) const SAVED_FILE_PLACEHOLDER: &str = "$saved_file";
/// This is stable behaviour. Don't change.
Copy link
Contributor

Choose a reason for hiding this comment

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

fwiw, we can remove $saved_file with a bit of notice.

Copy link
Contributor

Choose a reason for hiding this comment

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

actually, no, I lied we need to keep this for while. the main user of this is Fuchsia and until they're using Bazel, I don't think it's feasible to remove $saved_file.

Copy link
Contributor

Choose a reason for hiding this comment

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

(cc: @P1n3appl3)

Choose a reason for hiding this comment

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

thanks for the ping. We'd actually be ok with removing $saved_file if we could use {label} in the flycheck override. Today we actually do that mapping ourselves (wrapper script checks a global file list to find all labels that include the saved file and runs a check build/clippy on all those in the build system).

I'd be happy to migrate us over to label replacement when this lands.

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'm keeping it because I think it's still useful -- a build system might know that there are multiple crates that use a particular file and compile both. $saved_file is still there but prefer {saved_file} to match all other command interpolations.

@davidbarsky
Copy link
Contributor

Just to confirm my understanding: when you say:

Allows the discoverConfig to describe how to flycheck crates, using a new runnable kind of "flycheck".

The code changes here seem to imply that it'd be relying on the runnables in a rust-project.json; not that you're adding a few field to the configuration object/value. Is that correct? Do you intend to add a new field to discoverConfig...?

@cormacrelf
Copy link
Contributor Author

Correct. However now that I think about it, the runnable templating would be a useful thing to expose to end users to override. They can then have custom test commands, debug commands, etc.

(Noting that Meta's internal test harness has different flags to the OSS one. Would we want to have another configuration layer for rust-project to pick up and change its output? I would hope not!)

@davidbarsky
Copy link
Contributor

Correct.

Sorry, I realized I phrased my question ambiguously: are you planning on adding another field to workspace.discoverConfig for flycheck-specific? If the answer is yes, I'd push back on that and ask for a more wholistic design of flycheck's configuration: it's pretty messy and I don't want to make it worse.

However now that I think about it, the runnable templating would be a useful thing to expose to end users to override. They can then have custom test commands, debug commands, etc.

I agree! I think it's be nice to expose that via the standard rust-analyzer configuration mechanism.

Noting that Meta's internal test harness has different flags to the OSS one.

Oi, I didn't realize that fact, but good to know. Lemme see if I can try and unify the two.

Would we want to have another configuration layer for rust-project to pick up and change its output? I would hope not!

We should probably move this discussion over to the buck2 repo, but I've wanted a rust-project.toml for ages. There a lot of stuff in rust-project that's #[cfg(fbcode)]'d that I'd want to be controlled through configuration. It also means that setting up Buck with rust-analyzer could be as simple as placing a predefined .rust-project.toml and .rust-analyzer.toml at the root of a Buck workspace. Heck, we could even make the buck2 init command do that.

@bors
Copy link
Contributor

bors commented Sep 24, 2024

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

@Veykril
Copy link
Member

Veykril commented May 5, 2025

What is the status of this? (Looking into cleaning up our PR backlog again but I haven't been following this PR)

@cormacrelf
Copy link
Contributor Author

Well, I've been using it with my team pretty comfortably for 8 months. Will soon be upgrading a bunch of systems and will have to rebase this anyway. I will keep this PR updated when I do.

@cormacrelf
Copy link
Contributor Author

@Veykril this is rebased onto master. I actually found during rebasing that a number of the things I did have been done independently in other PRs, just slightly differently. So the diff is a little smaller.

To remind you:

  • Adds a new runnable kind "flycheck" / RunnableKind::Flycheck. Must be distinct from check (check runnable is for human-readable output)
  • Substitutes {label} or $saved_file in it
  • Abstracts over cargo vs projectjson flycheck sources
  • Uses all this to flycheck

This lets your 3rd party build tool configure how RA will flycheck.

@Veykril
Copy link
Member

Veykril commented Dec 2, 2025

I'll try to take a look this week.

@cormacrelf cormacrelf force-pushed the feature/rust-project-discovery branch from b6e93b8 to 57489bb Compare December 2, 2025 08:16
Needed to support flychecking in a later diff
Needed for all_workspace_dependencies_for_package implementation.
This exited the whole loop instead of having continue semantics and
continuing to find workspaces. So wrap in find_map.
You should be able to flycheck a ProjectJson crate based on its build label.
This paves the way for that.

Context: I don't think this has been working for some time. It used to be that
we would use cargo to build ProjectJson crates. Support for ProjectJson seems
to have been somewhat steamrolled in PR 18845 (e4bf6e1).
We need to distinguish from RunnableKind::Check, which is
human-readable.
This adds a substitution helper to get the right behaviour re {label} and $saved_file.
… rust-project.json

This requires us to add $saved_file / {saved_file} interpolation back to restart_for_package.
Otherwise we break existing users of $saved_file. No grand reason why we can't delete saved_file
later, although I would just leave it because sometimes a build system might really know better
which target(s) to build, including multiple targets.
…roject.json runnable

For JSON / override users, pretty-print the custom flycheck command with fewer quote characters

Better debug logging in flycheck
Because (1) it is what we use when there is no relevant config
        (2) we automatically use either rust-project.json's flycheck, or cargo

This also puts check_command config into CargoOptions. It's a cargo option, after all.
It was pretty useless without this.

Previously:

    Parsing target pattern `{label}`

    Caused by:
        Invalid target name `{label}`. (...)
    Build ID: 6dab5942-d81c-4430-83b0-5ba523999050
    Network: Up: 0B  Down: 0B
    Command: run.
    Time elapsed: 0.3s
    BUILD FAILED

     *  The terminal process "buck2 'run', '{label}'" terminated with exit code: 3.
rust-project requires {arg} these days. No good giving people bad information
even if it's not crucial to documenting this.
@cormacrelf cormacrelf force-pushed the feature/rust-project-discovery branch from 57489bb to e484bfc Compare December 3, 2025 08:42
@cormacrelf cormacrelf force-pushed the feature/rust-project-discovery branch from e484bfc to 978412c Compare December 3, 2025 08:44
@cormacrelf
Copy link
Contributor Author

I also added a pretty big docs overhaul for non-cargo build systems. I recommend reviewing this commit-by-commit, as there is a bit of diff noise now due to some renames etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants