Make config.rs a single source of truth for configuration.

Configuration is editor-independent. For this reason, we pick
JSON-schema as the repr of the source of truth. We do specify it using
rust-macros and some quick&dirty hackery though.

The idea for syncing truth with package.json is to just do that
manually, but there's a test to check that they are actually synced.

There's CLI to print config's json schema:

    $ rust-analyzer --print-config-schema

We go with a CLI rather than LSP request/response to make it easier to
incorporate the thing into extension's static config. This is roughtly
how we put the thing in package.json.
This commit is contained in:
Aleksey Kladov 2020-12-02 17:31:24 +03:00
parent e2e6b709e6
commit 2544abbf86
7 changed files with 674 additions and 447 deletions

1
Cargo.lock generated
View File

@ -1550,6 +1550,7 @@ version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
dependencies = [
"indexmap",
"itoa",
"ryu",
"serde",

View File

@ -27,7 +27,7 @@ pico-args = "0.3.1"
oorandom = "11.1.2"
rustc-hash = "1.1.0"
serde = { version = "1.0.106", features = ["derive"] }
serde_json = "1.0.48"
serde_json = { version = "1.0.48", features = ["preserve_order"] }
threadpool = "1.7.1"
rayon = "1.5"
mimalloc = { version = "0.1.19", default-features = false, optional = true }

View File

@ -28,6 +28,7 @@ pub(crate) enum Command {
StructuredSearch { debug_snippet: Option<String>, patterns: Vec<SsrPattern> },
ProcMacro,
RunServer,
PrintConfigSchema,
Version,
Help,
}
@ -135,6 +136,10 @@ impl Args {
return Ok(Args { verbosity, log_file: None, command: Command::Help });
}
if matches.contains("--print-config-schema") {
return Ok(Args { verbosity, log_file, command: Command::PrintConfigSchema });
}
let subcommand = match matches.subcommand()? {
Some(it) => it,
None => {

View File

@ -31,6 +31,9 @@ fn try_main() -> Result<()> {
setup_logging(args.log_file)?;
match args.command {
args::Command::RunServer => run_server()?,
args::Command::PrintConfigSchema => {
println!("{:#}", Config::json_schema());
}
args::Command::ProcMacro => proc_macro_srv::cli::run()?,
args::Command::Parse { no_dump } => cli::parse(no_dump)?,

View File

@ -13,14 +13,166 @@ use flycheck::FlycheckConfig;
use hir::PrefixKind;
use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig};
use ide_db::helpers::insert_use::MergeBehaviour;
use itertools::Itertools;
use lsp_types::{ClientCapabilities, MarkupKind};
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
use rustc_hash::FxHashSet;
use serde::Deserialize;
use serde::{de::DeserializeOwned, Deserialize};
use vfs::AbsPathBuf;
use crate::{caps::enabled_completions_resolve_capabilities, diagnostics::DiagnosticsMapConfig};
config_data! {
struct ConfigData {
/// The strategy to use when inserting new imports or merging imports.
assist_importMergeBehaviour: MergeBehaviourDef = "\"full\"",
/// The path structure for newly inserted paths to use.
assist_importPrefix: ImportPrefixDef = "\"plain\"",
/// Show function name and docs in parameter hints.
callInfo_full: bool = "true",
/// Automatically refresh project info via `cargo metadata` on
/// Cargo.toml changes.
cargo_autoreload: bool = "true",
/// Activate all available features.
cargo_allFeatures: bool = "false",
/// List of features to activate.
cargo_features: Vec<String> = "[]",
/// Run `cargo check` on startup to get the correct value for package
/// OUT_DIRs.
cargo_loadOutDirsFromCheck: bool = "false",
/// Do not activate the `default` feature.
cargo_noDefaultFeatures: bool = "false",
/// Compilation target (target triple).
cargo_target: Option<String> = "null",
/// Internal config for debugging, disables loading of sysroot crates.
cargo_noSysroot: bool = "false",
/// Run specified `cargo check` command for diagnostics on save.
checkOnSave_enable: bool = "true",
/// Check with all features (will be passed as `--all-features`).
/// Defaults to `rust-analyzer.cargo.allFeatures`.
checkOnSave_allFeatures: Option<bool> = "null",
/// Check all targets and tests (will be passed as `--all-targets`).
checkOnSave_allTargets: bool = "true",
/// Cargo command to use for `cargo check`.
checkOnSave_command: String = "\"check\"",
/// Do not activate the `default` feature.
checkOnSave_noDefaultFeatures: Option<bool> = "null",
/// Check for a specific target. Defaults to
/// `rust-analyzer.cargo.target`.
checkOnSave_target: Option<String> = "null",
/// Extra arguments for `cargo check`.
checkOnSave_extraArgs: Vec<String> = "[]",
/// List of features to activate. Defaults to
/// `rust-analyzer.cargo.features`.
checkOnSave_features: Option<Vec<String>> = "null",
/// Advanced option, fully override the command rust-analyzer uses for
/// checking. The command should include `--message-format=json` or
/// similar option.
checkOnSave_overrideCommand: Option<Vec<String>> = "null",
/// Whether to add argument snippets when completing functions.
completion_addCallArgumentSnippets: bool = "true",
/// Whether to add parenthesis when completing functions.
completion_addCallParenthesis: bool = "true",
/// Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
completion_postfix_enable: bool = "true",
/// Toggles the additional completions that automatically add imports when completed.
/// Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
completion_autoimport_enable: bool = "true",
/// Whether to show native rust-analyzer diagnostics.
diagnostics_enable: bool = "true",
/// Whether to show experimental rust-analyzer diagnostics that might
/// have more false positives than usual.
diagnostics_enableExperimental: bool = "true",
/// List of rust-analyzer diagnostics to disable.
diagnostics_disabled: FxHashSet<String> = "[]",
/// List of warnings that should be displayed with info severity.\nThe
/// warnings will be indicated by a blue squiggly underline in code and
/// a blue icon in the problems panel.
diagnostics_warningsAsHint: Vec<String> = "[]",
/// List of warnings that should be displayed with hint severity.\nThe
/// warnings will be indicated by faded text or three dots in code and
/// will not show up in the problems panel.
diagnostics_warningsAsInfo: Vec<String> = "[]",
/// Controls file watching implementation.
files_watcher: String = "\"client\"",
/// Whether to show `Debug` action. Only applies when
/// `#rust-analyzer.hoverActions.enable#` is set.
hoverActions_debug: bool = "true",
/// Whether to show HoverActions in Rust files.
hoverActions_enable: bool = "true",
/// Whether to show `Go to Type Definition` action. Only applies when
/// `#rust-analyzer.hoverActions.enable#` is set.
hoverActions_gotoTypeDef: bool = "true",
/// Whether to show `Implementations` action. Only applies when
/// `#rust-analyzer.hoverActions.enable#` is set.
hoverActions_implementations: bool = "true",
/// Whether to show `Run` action. Only applies when
/// `#rust-analyzer.hoverActions.enable#` is set.
hoverActions_run: bool = "true",
/// Use markdown syntax for links in hover.
hoverActions_linksInHover: bool = "true",
/// Whether to show inlay type hints for method chains.
inlayHints_chainingHints: bool = "true",
/// Maximum length for inlay hints.
inlayHints_maxLength: Option<usize> = "null",
/// Whether to show function parameter name inlay hints at the call
/// site.
inlayHints_parameterHints: bool = "true",
/// Whether to show inlay type hints for variables.
inlayHints_typeHints: bool = "true",
/// Whether to show `Debug` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_debug: bool = "true",
/// Whether to show CodeLens in Rust files.
lens_enable: bool = "true",
/// Whether to show `Implementations` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_implementations: bool = "true",
/// Whether to show `Run` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_run: bool = "true",
/// Whether to show `Method References` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_methodReferences: bool = "false",
/// Disable project auto-discovery in favor of explicitly specified set
/// of projects. \nElements must be paths pointing to Cargo.toml,
/// rust-project.json, or JSON objects in rust-project.json format.
linkedProjects: Vec<ManifestOrProjectJson> = "[]",
/// Number of syntax trees rust-analyzer keeps in memory.
lruCapacity: Option<usize> = "null",
/// Whether to show `can't find Cargo.toml` error message.
notifications_cargoTomlNotFound: bool = "true",
/// Enable Proc macro support, cargo.loadOutDirsFromCheck must be
/// enabled.
procMacro_enable: bool = "false",
/// Command to be executed instead of 'cargo' for runnables.
runnables_overrideCargo: Option<String> = "null",
/// Additional arguments to be passed to cargo for runnables such as
/// tests or binaries.\nFor example, it may be '--release'.
runnables_cargoExtraArgs: Vec<String> = "[]",
/// Path to the rust compiler sources, for usage in rustc_private projects.
rustcSource : Option<String> = "null",
/// Additional arguments to rustfmt.
rustfmt_extraArgs: Vec<String> = "[]",
/// Advanced option, fully override the command rust-analyzer uses for
/// formatting.
rustfmt_overrideCommand: Option<Vec<String>> = "null",
}
}
#[derive(Debug, Clone)]
pub struct Config {
pub client_caps: ClientCapsConfig,
@ -149,25 +301,27 @@ pub struct ClientCapsConfig {
impl Config {
pub fn new(root_path: AbsPathBuf) -> Self {
Config {
// Defaults here don't matter, we'll immediately re-write them with
// ConfigData.
let mut res = Config {
client_caps: ClientCapsConfig::default(),
publish_diagnostics: true,
publish_diagnostics: false,
diagnostics: DiagnosticsConfig::default(),
diagnostics_map: DiagnosticsMapConfig::default(),
lru_capacity: None,
proc_macro_srv: None,
files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() },
notifications: NotificationsConfig { cargo_toml_not_found: true },
notifications: NotificationsConfig { cargo_toml_not_found: false },
cargo_autoreload: true,
cargo_autoreload: false,
cargo: CargoConfig::default(),
rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() },
flycheck: Some(FlycheckConfig::CargoCommand {
command: "check".to_string(),
command: String::new(),
target_triple: None,
no_default_features: false,
all_targets: true,
all_targets: false,
all_features: false,
extra_args: Vec::new(),
features: Vec::new(),
@ -175,35 +329,32 @@ impl Config {
runnables: RunnablesConfig::default(),
inlay_hints: InlayHintsConfig {
type_hints: true,
parameter_hints: true,
chaining_hints: true,
type_hints: false,
parameter_hints: false,
chaining_hints: false,
max_length: None,
},
completion: CompletionConfig {
enable_postfix_completions: true,
enable_autoimport_completions: true,
add_call_parenthesis: true,
add_call_argument_snippets: true,
..CompletionConfig::default()
},
completion: CompletionConfig::default(),
assist: AssistConfig::default(),
call_info_full: true,
call_info_full: false,
lens: LensConfig::default(),
hover: HoverConfig::default(),
semantic_tokens_refresh: false,
linked_projects: Vec::new(),
root_path,
}
};
res.do_update(serde_json::json!({}));
res
}
pub fn update(&mut self, json: serde_json::Value) {
log::info!("Config::update({:#})", json);
if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) {
return;
}
self.do_update(json);
log::info!("Config::update() = {:#?}", self);
}
fn do_update(&mut self, json: serde_json::Value) {
let data = ConfigData::from_json(json);
self.publish_diagnostics = data.diagnostics_enable;
@ -349,8 +500,6 @@ impl Config {
links_in_hover: data.hoverActions_linksInHover,
markdown: true,
};
log::info!("Config::update() = {:#?}", self);
}
pub fn update_caps(&mut self, caps: &ClientCapabilities) {
@ -434,6 +583,10 @@ impl Config {
}
}
}
pub fn json_schema() -> serde_json::Value {
ConfigData::json_schema()
}
}
#[derive(Deserialize)]
@ -459,94 +612,167 @@ enum ImportPrefixDef {
ByCrate,
}
macro_rules! config_data {
(struct $name:ident { $($field:ident: $ty:ty = $default:expr,)*}) => {
macro_rules! _config_data {
(struct $name:ident {
$(
$(#[doc=$doc:literal])*
$field:ident: $ty:ty = $default:expr,
)*
}) => {
#[allow(non_snake_case)]
struct $name { $($field: $ty,)* }
impl $name {
fn from_json(mut json: serde_json::Value) -> $name {
$name {$(
$field: {
let pointer = stringify!($field).replace('_', "/");
let pointer = format!("/{}", pointer);
json.pointer_mut(&pointer)
.and_then(|it| serde_json::from_value(it.take()).ok())
.unwrap_or($default)
},
$field: get_field(&mut json, stringify!($field), $default),
)*}
}
}
fn json_schema() -> serde_json::Value {
schema(&[
$({
let field = stringify!($field);
let ty = stringify!($ty);
(field, ty, &[$($doc),*], $default)
},)*
])
}
}
};
}
use _config_data as config_data;
config_data! {
struct ConfigData {
assist_importMergeBehaviour: MergeBehaviourDef = MergeBehaviourDef::Full,
assist_importPrefix: ImportPrefixDef = ImportPrefixDef::Plain,
fn get_field<T: DeserializeOwned>(
json: &mut serde_json::Value,
field: &'static str,
default: &str,
) -> T {
let default = serde_json::from_str(default).unwrap();
callInfo_full: bool = true,
cargo_autoreload: bool = true,
cargo_allFeatures: bool = false,
cargo_features: Vec<String> = Vec::new(),
cargo_loadOutDirsFromCheck: bool = false,
cargo_noDefaultFeatures: bool = false,
cargo_target: Option<String> = None,
cargo_noSysroot: bool = false,
checkOnSave_enable: bool = true,
checkOnSave_allFeatures: Option<bool> = None,
checkOnSave_allTargets: bool = true,
checkOnSave_command: String = "check".into(),
checkOnSave_noDefaultFeatures: Option<bool> = None,
checkOnSave_target: Option<String> = None,
checkOnSave_extraArgs: Vec<String> = Vec::new(),
checkOnSave_features: Option<Vec<String>> = None,
checkOnSave_overrideCommand: Option<Vec<String>> = None,
completion_addCallArgumentSnippets: bool = true,
completion_addCallParenthesis: bool = true,
completion_postfix_enable: bool = true,
completion_autoimport_enable: bool = true,
diagnostics_enable: bool = true,
diagnostics_enableExperimental: bool = true,
diagnostics_disabled: FxHashSet<String> = FxHashSet::default(),
diagnostics_warningsAsHint: Vec<String> = Vec::new(),
diagnostics_warningsAsInfo: Vec<String> = Vec::new(),
files_watcher: String = "client".into(),
hoverActions_debug: bool = true,
hoverActions_enable: bool = true,
hoverActions_gotoTypeDef: bool = true,
hoverActions_implementations: bool = true,
hoverActions_run: bool = true,
hoverActions_linksInHover: bool = true,
inlayHints_chainingHints: bool = true,
inlayHints_maxLength: Option<usize> = None,
inlayHints_parameterHints: bool = true,
inlayHints_typeHints: bool = true,
lens_debug: bool = true,
lens_enable: bool = true,
lens_implementations: bool = true,
lens_run: bool = true,
lens_methodReferences: bool = false,
linkedProjects: Vec<ManifestOrProjectJson> = Vec::new(),
lruCapacity: Option<usize> = None,
notifications_cargoTomlNotFound: bool = true,
procMacro_enable: bool = false,
runnables_overrideCargo: Option<String> = None,
runnables_cargoExtraArgs: Vec<String> = Vec::new(),
rustfmt_extraArgs: Vec<String> = Vec::new(),
rustfmt_overrideCommand: Option<Vec<String>> = None,
rustcSource : Option<String> = None,
}
let mut pointer = field.replace('_', "/");
pointer.insert(0, '/');
json.pointer_mut(&pointer)
.and_then(|it| serde_json::from_value(it.take()).ok())
.unwrap_or(default)
}
fn schema(fields: &[(&'static str, &'static str, &[&str], &str)]) -> serde_json::Value {
for ((f1, ..), (f2, ..)) in fields.iter().zip(&fields[1..]) {
fn key(f: &str) -> &str {
f.splitn(2, "_").next().unwrap()
};
assert!(key(f1) <= key(f2), "wrong field order: {:?} {:?}", f1, f2);
}
let map = fields
.iter()
.map(|(field, ty, doc, default)| {
let name = field.replace("_", ".");
let name = format!("rust-analyzer.{}", name);
let props = field_props(field, ty, doc, default);
(name, props)
})
.collect::<serde_json::Map<_, _>>();
map.into()
}
fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json::Value {
let doc = doc.iter().map(|it| it.trim()).join(" ");
assert!(
doc.ends_with('.') && doc.starts_with(char::is_uppercase),
"bad docs for {}: {:?}",
field,
doc
);
let default = default.parse::<serde_json::Value>().unwrap();
let mut map = serde_json::Map::default();
macro_rules! set {
($($key:literal: $value:tt),*$(,)?) => {{$(
map.insert($key.into(), serde_json::json!($value));
)*}};
}
set!("markdownDescription": doc);
set!("default": default);
match ty {
"bool" => set!("type": "boolean"),
"String" => set!("type": "string"),
"Vec<String>" => set! {
"type": "array",
"items": { "type": "string" },
},
"FxHashSet<String>" => set! {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true,
},
"Option<usize>" => set! {
"type": ["null", "integer"],
"minimum": 0,
},
"Option<String>" => set! {
"type": ["null", "string"],
},
"Option<bool>" => set! {
"type": ["null", "boolean"],
},
"Option<Vec<String>>" => set! {
"type": ["null", "array"],
"items": { "type": "string" },
},
"MergeBehaviourDef" => set! {
"type": "string",
"enum": ["none", "full", "last"],
"enumDescriptions": [
"No merging",
"Merge all layers of the import trees",
"Only merge the last layer of the import trees"
],
},
"ImportPrefixDef" => set! {
"type": "string",
"enum": [
"plain",
"by_self",
"by_crate"
],
"enumDescriptions": [
"Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.",
"Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name",
"Force import paths to be absolute by always starting them with `crate` or the crate name they refer to."
],
},
"Vec<ManifestOrProjectJson>" => set! {
"type": "array",
"items": { "type": ["string", "object"] },
},
_ => panic!("{}: {}", ty, default),
}
map.into()
}
#[test]
fn schema_in_sync_with_package_json() {
fn remove_ws(text: &str) -> String {
text.replace(char::is_whitespace, "")
}
let s = Config::json_schema();
let schema = format!("{:#}", s);
let schema = schema.trim_start_matches('{').trim_end_matches('}');
let package_json = std::env::current_dir()
.unwrap()
.ancestors()
.nth(2)
.unwrap()
.join("editors/code/package.json");
let package_json = std::fs::read_to_string(&package_json).unwrap();
let p = remove_ws(&package_json);
let s = remove_ws(&schema);
assert!(p.contains(&s), "update config in package.json. New config:\n{:#}", schema);
}

View File

@ -321,12 +321,11 @@ fn lines_match_works() {
/// as paths). You can use a `"{...}"` string literal as a wildcard for
/// arbitrary nested JSON. Arrays are sorted before comparison.
pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a Value, &'a Value)> {
use serde_json::Value::*;
match (expected, actual) {
(&Number(ref l), &Number(ref r)) if l == r => None,
(&Bool(l), &Bool(r)) if l == r => None,
(&String(ref l), &String(ref r)) if lines_match(l, r) => None,
(&Array(ref l), &Array(ref r)) => {
(Value::Number(l), Value::Number(r)) if l == r => None,
(Value::Bool(l), Value::Bool(r)) if l == r => None,
(Value::String(l), Value::String(r)) if lines_match(l, r) => None,
(Value::Array(l), Value::Array(r)) => {
if l.len() != r.len() {
return Some((expected, actual));
}
@ -350,17 +349,26 @@ pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a
None
}
}
(&Object(ref l), &Object(ref r)) => {
(Value::Object(l), Value::Object(r)) => {
fn sorted_values(obj: &serde_json::Map<String, Value>) -> Vec<&Value> {
let mut entries = obj.iter().collect::<Vec<_>>();
entries.sort_by_key(|it| it.0);
entries.into_iter().map(|(_k, v)| v).collect::<Vec<_>>()
}
let same_keys = l.len() == r.len() && l.keys().all(|k| r.contains_key(k));
if !same_keys {
return Some((expected, actual));
}
l.values().zip(r.values()).filter_map(|(l, r)| find_mismatch(l, r)).next()
let l = sorted_values(l);
let r = sorted_values(r);
l.into_iter().zip(r).filter_map(|(l, r)| find_mismatch(l, r)).next()
}
(&Null, &Null) => None,
(Value::Null, Value::Null) => None,
// magic string literal "{...}" acts as wildcard for any sub-JSON
(&String(ref l), _) if l == "{...}" => None,
(Value::String(l), _) if l == "{...}" => None,
_ => Some((expected, actual)),
}
}

View File

@ -215,169 +215,6 @@
"type": "object",
"title": "Rust Analyzer",
"properties": {
"rust-analyzer.lruCapacity": {
"type": [
"null",
"integer"
],
"default": null,
"minimum": 0,
"exclusiveMinimum": true,
"description": "Number of syntax trees rust-analyzer keeps in memory."
},
"rust-analyzer.files.watcher": {
"type": "string",
"enum": [
"client",
"notify"
],
"default": "client",
"description": "Controls file watching implementation."
},
"rust-analyzer.files.exclude": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"description": "Paths to exclude from analysis."
},
"rust-analyzer.notifications.cargoTomlNotFound": {
"type": "boolean",
"default": true,
"markdownDescription": "Whether to show `can't find Cargo.toml` error message"
},
"rust-analyzer.cargo.autoreload": {
"type": "boolean",
"default": true,
"markdownDescription": "Automatically refresh project info via `cargo metadata` on Cargo.toml changes"
},
"rust-analyzer.cargo.noDefaultFeatures": {
"type": "boolean",
"default": false,
"markdownDescription": "Do not activate the `default` feature"
},
"rust-analyzer.cargo.allFeatures": {
"type": "boolean",
"default": false,
"description": "Activate all available features"
},
"rust-analyzer.cargo.features": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"description": "List of features to activate"
},
"rust-analyzer.cargo.loadOutDirsFromCheck": {
"type": "boolean",
"default": false,
"markdownDescription": "Run `cargo check` on startup to get the correct value for package OUT_DIRs"
},
"rust-analyzer.cargo.target": {
"type": [
"null",
"string"
],
"default": null,
"description": "Specify the compilation target"
},
"rust-analyzer.noSysroot": {
"markdownDescription": "Internal config for debugging, disables loading of sysroot crates",
"type": "boolean",
"default": false
},
"rust-analyzer.rustfmt.extraArgs": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"description": "Additional arguments to rustfmt"
},
"rust-analyzer.rustfmt.overrideCommand": {
"type": [
"null",
"array"
],
"items": {
"type": "string",
"minItems": 1
},
"default": null,
"markdownDescription": "Advanced option, fully override the command rust-analyzer uses for formatting."
},
"rust-analyzer.checkOnSave.enable": {
"type": "boolean",
"default": true,
"markdownDescription": "Run specified `cargo check` command for diagnostics on save"
},
"rust-analyzer.checkOnSave.extraArgs": {
"type": "array",
"items": {
"type": "string"
},
"markdownDescription": "Extra arguments for `cargo check`",
"default": []
},
"rust-analyzer.checkOnSave.command": {
"type": "string",
"default": "check",
"markdownDescription": "Cargo command to use for `cargo check`"
},
"rust-analyzer.checkOnSave.overrideCommand": {
"type": [
"null",
"array"
],
"items": {
"type": "string",
"minItems": 1
},
"default": null,
"markdownDescription": "Advanced option, fully override the command rust-analyzer uses for checking. The command should include `--message-format=json` or similar option."
},
"rust-analyzer.checkOnSave.allTargets": {
"type": "boolean",
"default": true,
"markdownDescription": "Check all targets and tests (will be passed as `--all-targets`)"
},
"rust-analyzer.checkOnSave.noDefaultFeatures": {
"type": [
"null",
"boolean"
],
"default": null,
"markdownDescription": "Do not activate the `default` feature"
},
"rust-analyzer.checkOnSave.allFeatures": {
"type": [
"null",
"boolean"
],
"default": null,
"markdownDescription": "Check with all features (will be passed as `--all-features`). Defaults to `rust-analyzer.cargo.allFeatures`."
},
"rust-analyzer.checkOnSave.features": {
"type": [
"null",
"array"
],
"items": {
"type": "string"
},
"default": null,
"description": "List of features to activate. Defaults to `rust-analyzer.cargo.features`."
},
"rust-analyzer.checkOnSave.target": {
"type": [
"null",
"string"
],
"default": null,
"description": "Check for a specific target. Defaults to `rust-analyzer.cargo.target`."
},
"rust-analyzer.cargoRunner": {
"type": [
"null",
@ -420,59 +257,6 @@
"default": true,
"description": "Whether to show inlay hints"
},
"rust-analyzer.inlayHints.typeHints": {
"type": "boolean",
"default": true,
"description": "Whether to show inlay type hints for variables."
},
"rust-analyzer.inlayHints.chainingHints": {
"type": "boolean",
"default": true,
"description": "Whether to show inlay type hints for method chains."
},
"rust-analyzer.inlayHints.parameterHints": {
"type": "boolean",
"default": true,
"description": "Whether to show function parameter name inlay hints at the call site."
},
"rust-analyzer.inlayHints.maxLength": {
"type": [
"null",
"integer"
],
"default": 20,
"minimum": 0,
"exclusiveMinimum": true,
"description": "Maximum length for inlay hints"
},
"rust-analyzer.completion.addCallParenthesis": {
"type": "boolean",
"default": true,
"description": "Whether to add parenthesis when completing functions"
},
"rust-analyzer.completion.addCallArgumentSnippets": {
"type": "boolean",
"default": true,
"description": "Whether to add argument snippets when completing functions"
},
"rust-analyzer.completion.postfix.enable": {
"type": "boolean",
"default": true,
"markdownDescription": "Whether to show postfix snippets like `dbg`, `if`, `not`, etc."
},
"rust-analyzer.completion.autoimport.enable": {
"type": "boolean",
"default": true,
"markdownDescription": [
"Toggles the additional completions that automatically add imports when completed.",
"Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled"
]
},
"rust-analyzer.callInfo.full": {
"type": "boolean",
"default": true,
"description": "Show function name and docs in parameter hints"
},
"rust-analyzer.updates.channel": {
"type": "string",
"enum": [
@ -520,11 +304,6 @@
"type": "boolean",
"default": false
},
"rust-analyzer.procMacro.enable": {
"description": "Enable Proc macro support, cargo.loadOutDirsFromCheck must be enabled.",
"type": "boolean",
"default": false
},
"rust-analyzer.debug.engine": {
"type": "string",
"enum": [
@ -557,105 +336,9 @@
"default": {},
"description": "Optional settings passed to the debug engine. Example:\n{ \"lldb\": { \"terminal\":\"external\"} }"
},
"rust-analyzer.lens.enable": {
"description": "Whether to show CodeLens in Rust files.",
"type": "boolean",
"default": true
},
"rust-analyzer.lens.run": {
"markdownDescription": "Whether to show `Run` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
"type": "boolean",
"default": true
},
"rust-analyzer.lens.debug": {
"markdownDescription": "Whether to show `Debug` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
"type": "boolean",
"default": true
},
"rust-analyzer.lens.implementations": {
"markdownDescription": "Whether to show `Implementations` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
"type": "boolean",
"default": true
},
"rust-analyzer.lens.methodReferences": {
"markdownDescription": "Whether to show `Method References` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
"type": "boolean",
"default": false
},
"rust-analyzer.hoverActions.enable": {
"description": "Whether to show HoverActions in Rust files.",
"type": "boolean",
"default": true
},
"rust-analyzer.hoverActions.implementations": {
"markdownDescription": "Whether to show `Implementations` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
"type": "boolean",
"default": true
},
"rust-analyzer.hoverActions.run": {
"markdownDescription": "Whether to show `Run` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
"type": "boolean",
"default": true
},
"rust-analyzer.hoverActions.debug": {
"markdownDescription": "Whether to show `Debug` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
"type": "boolean",
"default": true
},
"rust-analyzer.hoverActions.gotoTypeDef": {
"markdownDescription": "Whether to show `Go to Type Definition` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
"type": "boolean",
"default": true
},
"rust-analyzer.linkedProjects": {
"markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects. \nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format",
"type": "array",
"items": {
"type": [
"string",
"object"
]
},
"default": null
},
"rust-analyzer.diagnostics.enable": {
"type": "boolean",
"default": true,
"markdownDescription": "Whether to show native rust-analyzer diagnostics."
},
"rust-analyzer.diagnostics.enableExperimental": {
"type": "boolean",
"default": true,
"markdownDescription": "Whether to show experimental rust-analyzer diagnostics that might have more false positives than usual."
},
"rust-analyzer.diagnostics.disabled": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
},
"description": "List of rust-analyzer diagnostics to disable",
"default": []
},
"rust-analyzer.diagnostics.warningsAsInfo": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
},
"description": "List of warnings that should be displayed with info severity.\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the problems panel.",
"default": []
},
"rust-analyzer.diagnostics.warningsAsHint": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
},
"description": "List of warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.",
"default": []
},
"rust-analyzer.assist.importMergeBehaviour": {
"markdownDescription": "The strategy to use when inserting new imports or merging imports.",
"default": "full",
"type": "string",
"enum": [
"none",
@ -666,11 +349,11 @@
"No merging",
"Merge all layers of the import trees",
"Only merge the last layer of the import trees"
],
"default": "full",
"description": "The strategy to use when inserting new imports or merging imports."
]
},
"rust-analyzer.assist.importPrefix": {
"markdownDescription": "The path structure for newly inserted paths to use.",
"default": "plain",
"type": "string",
"enum": [
"plain",
@ -681,33 +364,334 @@
"Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.",
"Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name",
"Force import paths to be absolute by always starting them with `crate` or the crate name they refer to."
],
"default": "plain",
"description": "The path structure for newly inserted paths to use."
]
},
"rust-analyzer.runnables.overrideCargo": {
"rust-analyzer.callInfo.full": {
"markdownDescription": "Show function name and docs in parameter hints.",
"default": true,
"type": "boolean"
},
"rust-analyzer.cargo.autoreload": {
"markdownDescription": "Automatically refresh project info via `cargo metadata` on Cargo.toml changes.",
"default": true,
"type": "boolean"
},
"rust-analyzer.cargo.allFeatures": {
"markdownDescription": "Activate all available features.",
"default": false,
"type": "boolean"
},
"rust-analyzer.cargo.features": {
"markdownDescription": "List of features to activate.",
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"rust-analyzer.cargo.loadOutDirsFromCheck": {
"markdownDescription": "Run `cargo check` on startup to get the correct value for package OUT_DIRs.",
"default": false,
"type": "boolean"
},
"rust-analyzer.cargo.noDefaultFeatures": {
"markdownDescription": "Do not activate the `default` feature.",
"default": false,
"type": "boolean"
},
"rust-analyzer.cargo.target": {
"markdownDescription": "Compilation target (target triple).",
"default": null,
"type": [
"null",
"string"
],
"default": null,
"description": "Command to be executed instead of 'cargo' for runnables."
]
},
"rust-analyzer.runnables.cargoExtraArgs": {
"rust-analyzer.cargo.noSysroot": {
"markdownDescription": "Internal config for debugging, disables loading of sysroot crates.",
"default": false,
"type": "boolean"
},
"rust-analyzer.checkOnSave.enable": {
"markdownDescription": "Run specified `cargo check` command for diagnostics on save.",
"default": true,
"type": "boolean"
},
"rust-analyzer.checkOnSave.allFeatures": {
"markdownDescription": "Check with all features (will be passed as `--all-features`). Defaults to `rust-analyzer.cargo.allFeatures`.",
"default": null,
"type": [
"null",
"boolean"
]
},
"rust-analyzer.checkOnSave.allTargets": {
"markdownDescription": "Check all targets and tests (will be passed as `--all-targets`).",
"default": true,
"type": "boolean"
},
"rust-analyzer.checkOnSave.command": {
"markdownDescription": "Cargo command to use for `cargo check`.",
"default": "check",
"type": "string"
},
"rust-analyzer.checkOnSave.noDefaultFeatures": {
"markdownDescription": "Do not activate the `default` feature.",
"default": null,
"type": [
"null",
"boolean"
]
},
"rust-analyzer.checkOnSave.target": {
"markdownDescription": "Check for a specific target. Defaults to `rust-analyzer.cargo.target`.",
"default": null,
"type": [
"null",
"string"
]
},
"rust-analyzer.checkOnSave.extraArgs": {
"markdownDescription": "Extra arguments for `cargo check`.",
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"rust-analyzer.checkOnSave.features": {
"markdownDescription": "List of features to activate. Defaults to `rust-analyzer.cargo.features`.",
"default": null,
"type": [
"null",
"array"
],
"items": {
"type": "string"
}
},
"rust-analyzer.checkOnSave.overrideCommand": {
"markdownDescription": "Advanced option, fully override the command rust-analyzer uses for checking. The command should include `--message-format=json` or similar option.",
"default": null,
"type": [
"null",
"array"
],
"items": {
"type": "string"
}
},
"rust-analyzer.completion.addCallArgumentSnippets": {
"markdownDescription": "Whether to add argument snippets when completing functions.",
"default": true,
"type": "boolean"
},
"rust-analyzer.completion.addCallParenthesis": {
"markdownDescription": "Whether to add parenthesis when completing functions.",
"default": true,
"type": "boolean"
},
"rust-analyzer.completion.postfix.enable": {
"markdownDescription": "Whether to show postfix snippets like `dbg`, `if`, `not`, etc.",
"default": true,
"type": "boolean"
},
"rust-analyzer.completion.autoimport.enable": {
"markdownDescription": "Toggles the additional completions that automatically add imports when completed. Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.",
"default": true,
"type": "boolean"
},
"rust-analyzer.diagnostics.enable": {
"markdownDescription": "Whether to show native rust-analyzer diagnostics.",
"default": true,
"type": "boolean"
},
"rust-analyzer.diagnostics.enableExperimental": {
"markdownDescription": "Whether to show experimental rust-analyzer diagnostics that might have more false positives than usual.",
"default": true,
"type": "boolean"
},
"rust-analyzer.diagnostics.disabled": {
"markdownDescription": "List of rust-analyzer diagnostics to disable.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": [],
"description": "Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be '--release'"
"uniqueItems": true
},
"rust-analyzer.rustcSource": {
"rust-analyzer.diagnostics.warningsAsHint": {
"markdownDescription": "List of warnings that should be displayed with info severity.\\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the problems panel.",
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"rust-analyzer.diagnostics.warningsAsInfo": {
"markdownDescription": "List of warnings that should be displayed with hint severity.\\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.",
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"rust-analyzer.files.watcher": {
"markdownDescription": "Controls file watching implementation.",
"default": "client",
"type": "string"
},
"rust-analyzer.hoverActions.debug": {
"markdownDescription": "Whether to show `Debug` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
"default": true,
"type": "boolean"
},
"rust-analyzer.hoverActions.enable": {
"markdownDescription": "Whether to show HoverActions in Rust files.",
"default": true,
"type": "boolean"
},
"rust-analyzer.hoverActions.gotoTypeDef": {
"markdownDescription": "Whether to show `Go to Type Definition` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
"default": true,
"type": "boolean"
},
"rust-analyzer.hoverActions.implementations": {
"markdownDescription": "Whether to show `Implementations` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
"default": true,
"type": "boolean"
},
"rust-analyzer.hoverActions.run": {
"markdownDescription": "Whether to show `Run` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
"default": true,
"type": "boolean"
},
"rust-analyzer.hoverActions.linksInHover": {
"markdownDescription": "Use markdown syntax for links in hover.",
"default": true,
"type": "boolean"
},
"rust-analyzer.inlayHints.chainingHints": {
"markdownDescription": "Whether to show inlay type hints for method chains.",
"default": true,
"type": "boolean"
},
"rust-analyzer.inlayHints.maxLength": {
"markdownDescription": "Maximum length for inlay hints.",
"default": null,
"type": [
"null",
"integer"
],
"minimum": 0
},
"rust-analyzer.inlayHints.parameterHints": {
"markdownDescription": "Whether to show function parameter name inlay hints at the call site.",
"default": true,
"type": "boolean"
},
"rust-analyzer.inlayHints.typeHints": {
"markdownDescription": "Whether to show inlay type hints for variables.",
"default": true,
"type": "boolean"
},
"rust-analyzer.lens.debug": {
"markdownDescription": "Whether to show `Debug` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
"default": true,
"type": "boolean"
},
"rust-analyzer.lens.enable": {
"markdownDescription": "Whether to show CodeLens in Rust files.",
"default": true,
"type": "boolean"
},
"rust-analyzer.lens.implementations": {
"markdownDescription": "Whether to show `Implementations` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
"default": true,
"type": "boolean"
},
"rust-analyzer.lens.run": {
"markdownDescription": "Whether to show `Run` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
"default": true,
"type": "boolean"
},
"rust-analyzer.lens.methodReferences": {
"markdownDescription": "Whether to show `Method References` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
"default": false,
"type": "boolean"
},
"rust-analyzer.linkedProjects": {
"markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects. \\nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format.",
"default": [],
"type": "array",
"items": {
"type": [
"string",
"object"
]
}
},
"rust-analyzer.lruCapacity": {
"markdownDescription": "Number of syntax trees rust-analyzer keeps in memory.",
"default": null,
"type": [
"null",
"integer"
],
"minimum": 0
},
"rust-analyzer.notifications.cargoTomlNotFound": {
"markdownDescription": "Whether to show `can't find Cargo.toml` error message.",
"default": true,
"type": "boolean"
},
"rust-analyzer.procMacro.enable": {
"markdownDescription": "Enable Proc macro support, cargo.loadOutDirsFromCheck must be enabled.",
"default": false,
"type": "boolean"
},
"rust-analyzer.runnables.overrideCargo": {
"markdownDescription": "Command to be executed instead of 'cargo' for runnables.",
"default": null,
"type": [
"null",
"string"
],
]
},
"rust-analyzer.runnables.cargoExtraArgs": {
"markdownDescription": "Additional arguments to be passed to cargo for runnables such as tests or binaries.\\nFor example, it may be '--release'.",
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"rust-analyzer.rustcSource": {
"markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects.",
"default": null,
"description": "Path to the rust compiler sources, for usage in rustc_private projects."
"type": [
"null",
"string"
]
},
"rust-analyzer.rustfmt.extraArgs": {
"markdownDescription": "Additional arguments to rustfmt.",
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"rust-analyzer.rustfmt.overrideCommand": {
"markdownDescription": "Advanced option, fully override the command rust-analyzer uses for formatting.",
"default": null,
"type": [
"null",
"array"
],
"items": {
"type": "string"
}
}
}
},