Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/rust-analyzer/src/command.rs4
-rw-r--r--crates/rust-analyzer/src/config.rs9
-rw-r--r--crates/rust-analyzer/src/discover.rs5
-rw-r--r--crates/rust-analyzer/src/flycheck.rs14
-rw-r--r--crates/rust-analyzer/src/test_runner.rs7
-rw-r--r--docs/book/src/configuration_generated.md9
-rw-r--r--docs/book/src/non_cargo_based_projects.md4
-rw-r--r--editors/code/package.json2
8 files changed, 42 insertions, 12 deletions
diff --git a/crates/rust-analyzer/src/command.rs b/crates/rust-analyzer/src/command.rs
index ff2e21c865..bc3fa21c66 100644
--- a/crates/rust-analyzer/src/command.rs
+++ b/crates/rust-analyzer/src/command.rs
@@ -23,6 +23,7 @@ use stdx::process::streaming_output;
/// well as custom discover commands.
pub(crate) trait JsonLinesParser<T>: Send + 'static {
fn from_line(&self, line: &str, error: &mut String) -> Option<T>;
+ fn from_stderr_line(&self, line: &str, error: &mut String) -> Option<T>;
fn from_eof(&self) -> Option<T>;
}
@@ -95,7 +96,8 @@ impl<T: Sized + Send + 'static> CommandActor<T> {
_ = stderr.write_all(line.as_bytes());
_ = stderr.write_all(b"\n");
}
- if process_line(line, &mut stderr_errors) {
+ if let Some(t) = self.parser.from_stderr_line(line, &mut stderr_errors) {
+ self.sender.send(t).unwrap();
read_at_least_one_stderr_message = true;
}
},
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 649ed44aac..5b6215c41f 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -562,9 +562,9 @@ config_data! {
///
/// **Warning**: This format is provisional and subject to change.
///
- /// The discover command should output JSON objects, one per
- /// line (JSONL format). These objects should correspond to
- /// this Rust data type:
+ /// The discover command should output JSON objects to stdout,
+ /// one per line (JSONL format). These objects should correspond
+ /// to this Rust data type:
///
/// ```norun
/// #[derive(Debug, Clone, Deserialize, Serialize)]
@@ -604,6 +604,9 @@ config_data! {
/// Only the finished event is required, but the other
/// variants are encouraged to give users more feedback about
/// progress or errors.
+ ///
+ /// Stderr is not parsed as JSONL. It is treated as command log
+ /// output and forwarded to rust-analyzer's own logs.
workspace_discoverConfig: Option<DiscoverWorkspaceConfig> = None,
}
}
diff --git a/crates/rust-analyzer/src/discover.rs b/crates/rust-analyzer/src/discover.rs
index 098b6a4d98..04d0cedb3e 100644
--- a/crates/rust-analyzer/src/discover.rs
+++ b/crates/rust-analyzer/src/discover.rs
@@ -136,6 +136,11 @@ impl JsonLinesParser<DiscoverProjectMessage> for DiscoverProjectParser {
fn from_eof(&self) -> Option<DiscoverProjectMessage> {
None
}
+
+ fn from_stderr_line(&self, line: &str, _error: &mut String) -> Option<DiscoverProjectMessage> {
+ tracing::info!(%line, "discover command stderr");
+ None
+ }
}
#[test]
diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs
index f73ffb24ee..b927a11604 100644
--- a/crates/rust-analyzer/src/flycheck.rs
+++ b/crates/rust-analyzer/src/flycheck.rs
@@ -1011,8 +1011,8 @@ enum CheckMessage {
struct CheckParser;
-impl JsonLinesParser<CheckMessage> for CheckParser {
- fn from_line(&self, line: &str, error: &mut String) -> Option<CheckMessage> {
+impl CheckParser {
+ fn parse_line(&self, line: &str, error: &mut String) -> Option<CheckMessage> {
let mut deserializer = serde_json::Deserializer::from_str(line);
deserializer.disable_recursion_limit();
if let Ok(message) = JsonMessage::deserialize(&mut deserializer) {
@@ -1042,6 +1042,16 @@ impl JsonLinesParser<CheckMessage> for CheckParser {
error.push('\n');
None
}
+}
+
+impl JsonLinesParser<CheckMessage> for CheckParser {
+ fn from_line(&self, line: &str, error: &mut String) -> Option<CheckMessage> {
+ self.parse_line(line, error)
+ }
+
+ fn from_stderr_line(&self, line: &str, error: &mut String) -> Option<CheckMessage> {
+ self.parse_line(line, error)
+ }
fn from_eof(&self) -> Option<CheckMessage> {
None
diff --git a/crates/rust-analyzer/src/test_runner.rs b/crates/rust-analyzer/src/test_runner.rs
index 31f35df5c7..c6f8a7c799 100644
--- a/crates/rust-analyzer/src/test_runner.rs
+++ b/crates/rust-analyzer/src/test_runner.rs
@@ -72,6 +72,13 @@ impl JsonLinesParser<CargoTestMessage> for CargoTestOutputParser {
})
}
+ fn from_stderr_line(&self, line: &str, _error: &mut String) -> Option<CargoTestMessage> {
+ Some(CargoTestMessage {
+ target: self.target.clone(),
+ output: CargoTestOutput::Custom { text: line.to_owned() },
+ })
+ }
+
fn from_eof(&self) -> Option<CargoTestMessage> {
Some(CargoTestMessage { target: self.target.clone(), output: CargoTestOutput::Finished })
}
diff --git a/docs/book/src/configuration_generated.md b/docs/book/src/configuration_generated.md
index fd377616d9..4df17d77ed 100644
--- a/docs/book/src/configuration_generated.md
+++ b/docs/book/src/configuration_generated.md
@@ -1769,9 +1769,9 @@ will likely be useful:
**Warning**: This format is provisional and subject to change.
-The discover command should output JSON objects, one per
-line (JSONL format). These objects should correspond to
-this Rust data type:
+The discover command should output JSON objects to stdout,
+one per line (JSONL format). These objects should correspond
+to this Rust data type:
```norun
#[derive(Debug, Clone, Deserialize, Serialize)]
@@ -1812,6 +1812,9 @@ Only the finished event is required, but the other
variants are encouraged to give users more feedback about
progress or errors.
+Stderr is not parsed as JSONL. It is treated as command log
+output and forwarded to rust-analyzer's own logs.
+
## rust-analyzer.workspace.symbol.search.excludeImports {#workspace.symbol.search.excludeImports}
diff --git a/docs/book/src/non_cargo_based_projects.md b/docs/book/src/non_cargo_based_projects.md
index 9cc3292444..75e7fc900f 100644
--- a/docs/book/src/non_cargo_based_projects.md
+++ b/docs/book/src/non_cargo_based_projects.md
@@ -237,8 +237,8 @@ There are four ways to feed `rust-project.json` to rust-analyzer:
- Use
[`"rust-analyzer.workspace.discoverConfig": … }`](./configuration.md#workspace.discoverConfig)
to specify a workspace discovery command to generate project descriptions
- on-the-fly. Please note that the command output is message-oriented and must
- output JSONL [as described in the configuration docs](./configuration.md#workspace.discoverConfig).
+ on-the-fly. Please note that the command's stdout is message-oriented and
+ must output JSONL [as described in the configuration docs](./configuration.md#workspace.discoverConfig).
- Place `rust-project.json` file at the root of the project, and
rust-analyzer will discover it.
diff --git a/editors/code/package.json b/editors/code/package.json
index 61bc4cb29d..d152cfb586 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -3258,7 +3258,7 @@
"title": "Workspace",
"properties": {
"rust-analyzer.workspace.discoverConfig": {
- "markdownDescription": "Configure a command that rust-analyzer can invoke to\nobtain configuration.\n\nThis is an alternative to manually generating\n`rust-project.json`: it enables rust-analyzer to generate\nrust-project.json on the fly, and regenerate it when\nswitching or modifying projects.\n\nThis is an object with three fields:\n\n* `command`: the shell command to invoke\n\n* `filesToWatch`: which build system-specific files should\nbe watched to trigger regenerating the configuration\n\n* `progressLabel`: the name of the command, used in\nprogress indicators in the IDE\n\nHere's an example of a valid configuration:\n\n```json\n\"rust-analyzer.workspace.discoverConfig\": {\n \"command\": [\n \"rust-project\",\n \"develop-json\",\n \"{arg}\"\n ],\n \"progressLabel\": \"buck2/rust-project\",\n \"filesToWatch\": [\n \"BUCK\"\n ]\n}\n```\n\n## Argument Substitutions\n\nIf `command` includes the argument `{arg}`, that argument will be substituted\nwith the JSON-serialized form of the following enum:\n\n```norun\n#[derive(PartialEq, Clone, Debug, Serialize)]\n#[serde(rename_all = \"camelCase\")]\npub enum DiscoverArgument {\n Path(AbsPathBuf),\n Buildfile(AbsPathBuf),\n}\n```\n\nrust-analyzer will use the path invocation to find and\ngenerate a `rust-project.json` and therefore a\nworkspace. Example:\n\n\n```norun\nrust-project develop-json '{ \"path\": \"myproject/src/main.rs\" }'\n```\n\nrust-analyzer will use build file invocations to update an\nexisting workspace. Example:\n\nOr with a build file and the configuration above:\n\n```norun\nrust-project develop-json '{ \"buildfile\": \"myproject/BUCK\" }'\n```\n\nAs a reference for implementors, buck2's `rust-project`\nwill likely be useful:\n<https://github.com/facebook/buck2/tree/main/integrations/rust-project>.\n\n## Discover Command Output\n\n**Warning**: This format is provisional and subject to change.\n\nThe discover command should output JSON objects, one per\nline (JSONL format). These objects should correspond to\nthis Rust data type:\n\n```norun\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(tag = \"kind\")]\n#[serde(rename_all = \"snake_case\")]\nenum DiscoverProjectData {\n Finished { buildfile: Utf8PathBuf, project: ProjectJsonData },\n Error { error: String, source: Option<String> },\n Progress { message: String },\n}\n```\n\nFor example, a progress event:\n\n```json\n{\"kind\":\"progress\",\"message\":\"generating rust-project.json\"}\n```\n\nA finished event can look like this (expanded and\ncommented for readability):\n\n```json\n{\n // the internally-tagged representation of the enum.\n \"kind\": \"finished\",\n // the file used by a non-Cargo build system to define\n // a package or target.\n \"buildfile\": \"rust-analyzer/BUCK\",\n // the contents of a rust-project.json, elided for brevity\n \"project\": {\n \"sysroot\": \"foo\",\n \"crates\": []\n }\n}\n```\n\nOnly the finished event is required, but the other\nvariants are encouraged to give users more feedback about\nprogress or errors.",
+ "markdownDescription": "Configure a command that rust-analyzer can invoke to\nobtain configuration.\n\nThis is an alternative to manually generating\n`rust-project.json`: it enables rust-analyzer to generate\nrust-project.json on the fly, and regenerate it when\nswitching or modifying projects.\n\nThis is an object with three fields:\n\n* `command`: the shell command to invoke\n\n* `filesToWatch`: which build system-specific files should\nbe watched to trigger regenerating the configuration\n\n* `progressLabel`: the name of the command, used in\nprogress indicators in the IDE\n\nHere's an example of a valid configuration:\n\n```json\n\"rust-analyzer.workspace.discoverConfig\": {\n \"command\": [\n \"rust-project\",\n \"develop-json\",\n \"{arg}\"\n ],\n \"progressLabel\": \"buck2/rust-project\",\n \"filesToWatch\": [\n \"BUCK\"\n ]\n}\n```\n\n## Argument Substitutions\n\nIf `command` includes the argument `{arg}`, that argument will be substituted\nwith the JSON-serialized form of the following enum:\n\n```norun\n#[derive(PartialEq, Clone, Debug, Serialize)]\n#[serde(rename_all = \"camelCase\")]\npub enum DiscoverArgument {\n Path(AbsPathBuf),\n Buildfile(AbsPathBuf),\n}\n```\n\nrust-analyzer will use the path invocation to find and\ngenerate a `rust-project.json` and therefore a\nworkspace. Example:\n\n\n```norun\nrust-project develop-json '{ \"path\": \"myproject/src/main.rs\" }'\n```\n\nrust-analyzer will use build file invocations to update an\nexisting workspace. Example:\n\nOr with a build file and the configuration above:\n\n```norun\nrust-project develop-json '{ \"buildfile\": \"myproject/BUCK\" }'\n```\n\nAs a reference for implementors, buck2's `rust-project`\nwill likely be useful:\n<https://github.com/facebook/buck2/tree/main/integrations/rust-project>.\n\n## Discover Command Output\n\n**Warning**: This format is provisional and subject to change.\n\nThe discover command should output JSON objects to stdout,\none per line (JSONL format). These objects should correspond\nto this Rust data type:\n\n```norun\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(tag = \"kind\")]\n#[serde(rename_all = \"snake_case\")]\nenum DiscoverProjectData {\n Finished { buildfile: Utf8PathBuf, project: ProjectJsonData },\n Error { error: String, source: Option<String> },\n Progress { message: String },\n}\n```\n\nFor example, a progress event:\n\n```json\n{\"kind\":\"progress\",\"message\":\"generating rust-project.json\"}\n```\n\nA finished event can look like this (expanded and\ncommented for readability):\n\n```json\n{\n // the internally-tagged representation of the enum.\n \"kind\": \"finished\",\n // the file used by a non-Cargo build system to define\n // a package or target.\n \"buildfile\": \"rust-analyzer/BUCK\",\n // the contents of a rust-project.json, elided for brevity\n \"project\": {\n \"sysroot\": \"foo\",\n \"crates\": []\n }\n}\n```\n\nOnly the finished event is required, but the other\nvariants are encouraged to give users more feedback about\nprogress or errors.\n\nStderr is not parsed as JSONL. It is treated as command log\noutput and forwarded to rust-analyzer's own logs.",
"default": null,
"anyOf": [
{