Skip to content
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
14 changes: 12 additions & 2 deletions crates/flycheck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub enum FlycheckConfig {
features: Vec<String>,
extra_args: Vec<String>,
extra_env: FxHashMap<String, String>,
ansi_color_output: bool,
},
CustomCommand {
command: String,
Expand Down Expand Up @@ -293,12 +294,21 @@ impl FlycheckActor {
extra_args,
features,
extra_env,
ansi_color_output,
} => {
let mut cmd = Command::new(toolchain::cargo());
cmd.arg(command);
cmd.current_dir(&self.root);
cmd.args(["--workspace", "--message-format=json", "--manifest-path"])
.arg(self.root.join("Cargo.toml").as_os_str());
cmd.arg("--workspace");

cmd.arg(if *ansi_color_output {
"--message-format=json-diagnostic-rendered-ansi"
} else {
"--message-format=json"
});

cmd.arg("--manifest-path");
cmd.arg(self.root.join("Cargo.toml").as_os_str());

for target in target_triples {
cmd.args(["--target", target.as_str()]);
Expand Down
10 changes: 9 additions & 1 deletion crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ config_data! {
check_noDefaultFeatures | checkOnSave_noDefaultFeatures: Option<bool> = "null",
/// Override the command rust-analyzer uses instead of `cargo check` for
/// diagnostics on save. The command is required to output json and
/// should therefore include `--message-format=json` or a similar option.
/// should therefore include `--message-format=json` or a similar option
/// (if your client supports the `colorDiagnosticOutput` experimental
/// capability, you can use `--message-format=json-diagnostic-rendered-ansi`).
///
/// If you're changing this because you're using some tool wrapping
/// Cargo, you might also want to change
Expand Down Expand Up @@ -1006,6 +1008,11 @@ impl Config {
self.experimental("serverStatusNotification")
}

/// Whether the client supports colored output for full diagnostics from `checkOnSave`.
pub fn color_diagnostic_output(&self) -> bool {
self.experimental("colorDiagnosticOutput")
}

pub fn publish_diagnostics(&self) -> bool {
self.data.diagnostics_enable
}
Expand Down Expand Up @@ -1204,6 +1211,7 @@ impl Config {
},
extra_args: self.data.check_extraArgs.clone(),
extra_env: self.check_on_save_extra_env(),
ansi_color_output: self.color_diagnostic_output(),
},
}
}
Expand Down
26 changes: 26 additions & 0 deletions docs/dev/lsp-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -792,3 +792,29 @@ export interface ClientCommandOptions {
commands: string[];
}
```

## Colored Diagnostic Output

**Experimental Client Capability:** `{ "colorDiagnosticOutput": boolean }`

If this capability is set, the "full compiler diagnostics" provided by `checkOnSave`
will include ANSI color and style codes to render the diagnostic in a similar manner
as `cargo`. This is translated into `--message-format=json-diagnostic-rendered-ansi`
when flycheck is run, instead of the default `--message-format=json`.

The full compiler rendered diagnostics are included in the server response
regardless of this capability:

```typescript
// https://microsoft.github.io/language-server-protocol/specifications/specification-current#diagnostic
export interface Diagnostic {
...
data?: {
/**
* The human-readable compiler output as it would be printed to a terminal.
* Includes ANSI color and style codes if the client has set the experimental
* `colorDiagnosticOutput` capability.
*/
rendered?: string;
};
}
4 changes: 3 additions & 1 deletion docs/user/generated_config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ Whether to pass `--no-default-features` to Cargo. Defaults to
--
Override the command rust-analyzer uses instead of `cargo check` for
diagnostics on save. The command is required to output json and
should therefore include `--message-format=json` or a similar option.
should therefore include `--message-format=json` or a similar option
(if your client supports the `colorDiagnosticOutput` experimental
capability, you can use `--message-format=json-diagnostic-rendered-ansi`).

If you're changing this because you're using some tool wrapping
Cargo, you might also want to change
Expand Down
11 changes: 11 additions & 0 deletions editors/code/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"test": "cross-env TEST_VARIABLE=test node ./out/tests/runTests.js"
},
"dependencies": {
"anser": "^2.1.1",
"d3": "^7.6.1",
"d3-graphviz": "^5.0.2",
"vscode-languageclient": "^8.0.2"
Expand Down Expand Up @@ -643,7 +644,7 @@
]
},
"rust-analyzer.check.overrideCommand": {
"markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefore include `--message-format=json` or a similar option.\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects, this command is invoked for\neach of them, with the working directory being the project root\n(i.e., the folder containing the `Cargo.toml`).\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.",
"markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefore include `--message-format=json` or a similar option\n(if your client supports the `colorDiagnosticOutput` experimental\ncapability, you can use `--message-format=json-diagnostic-rendered-ansi`).\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects, this command is invoked for\neach of them, with the working directory being the project root\n(i.e., the folder containing the `Cargo.toml`).\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.",
"default": null,
"type": [
"null",
Expand Down
18 changes: 11 additions & 7 deletions editors/code/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as anser from "anser";
import * as lc from "vscode-languageclient/node";
import * as vscode from "vscode";
import * as ra from "../src/lsp_ext";
import * as Is from "vscode-languageclient/lib/common/utils/is";
import { assert } from "./util";
import * as diagnostics from "./diagnostics";
import { WorkspaceEdit } from "vscode";
import { Config, substituteVSCodeVariables } from "./config";
import { randomUUID } from "crypto";
Expand Down Expand Up @@ -120,12 +122,12 @@ export async function createClient(
},
async handleDiagnostics(
uri: vscode.Uri,
diagnostics: vscode.Diagnostic[],
diagnosticList: vscode.Diagnostic[],
next: lc.HandleDiagnosticsSignature
) {
const preview = config.previewRustcOutput;
const errorCode = config.useRustcErrorCode;
diagnostics.forEach((diag, idx) => {
diagnosticList.forEach((diag, idx) => {
// Abuse the fact that VSCode leaks the LSP diagnostics data field through the
// Diagnostic class, if they ever break this we are out of luck and have to go
// back to the worst diagnostics experience ever:)
Expand All @@ -138,9 +140,10 @@ export async function createClient(
?.rendered;
if (rendered) {
if (preview) {
const decolorized = anser.ansiToText(rendered);
const index =
rendered.match(/^(note|help):/m)?.index || rendered.length;
diag.message = rendered
decolorized.match(/^(note|help):/m)?.index || rendered.length;
diag.message = decolorized
.substring(0, index)
.replace(/^ -->[^\n]+\n/m, "");
}
Expand All @@ -154,16 +157,16 @@ export async function createClient(
}
diag.code = {
target: vscode.Uri.from({
scheme: "rust-analyzer-diagnostics-view",
path: "/diagnostic message",
scheme: diagnostics.URI_SCHEME,
path: `/diagnostic message [${idx.toString()}]`,
fragment: uri.toString(),
query: idx.toString(),
}),
value: value ?? "Click for full compiler diagnostic",
};
}
});
return next(uri, diagnostics);
return next(uri, diagnosticList);
},
async provideHover(
document: vscode.TextDocument,
Expand Down Expand Up @@ -330,6 +333,7 @@ class ExperimentalFeatures implements lc.StaticFeature {
caps.codeActionGroup = true;
caps.hoverActions = true;
caps.serverStatusNotification = true;
caps.colorDiagnosticOutput = true;
caps.commands = {
commands: [
"rust-analyzer.runSingle",
Expand Down
Loading