diff options
Diffstat (limited to 'src/tools/rust-analyzer/editors/code')
21 files changed, 2631 insertions, 1704 deletions
diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json index bd8b0e9c4e0..7de75763177 100644 --- a/src/tools/rust-analyzer/editors/code/package-lock.json +++ b/src/tools/rust-analyzer/editors/code/package-lock.json @@ -1087,12 +1087,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2243,9 +2243,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 6e4fedd992c..db2a989106f 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -300,6 +300,11 @@ "command": "rust-analyzer.toggleCheckOnSave", "title": "Toggle Check on Save", "category": "rust-analyzer" + }, + { + "command": "rust-analyzer.toggleLSPLogs", + "title": "Toggle LSP Logs", + "category": "rust-analyzer" } ], "keybindings": [ @@ -314,1440 +319,2281 @@ "when": "editorTextFocus && editorLangId == rust" } ], - "configuration": { - "type": "object", - "title": "rust-analyzer", - "properties": { - "rust-analyzer.cargoRunner": { - "type": [ - "null", - "string" - ], - "default": null, - "description": "Custom cargo runner extension ID." - }, - "rust-analyzer.runnables.extraEnv": { - "anyOf": [ - { - "type": "null" - }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "platform": { - "type": [ - "null", - "string", - "array" - ], - "default": null, - "markdownDescription": "Platform(s) filter like \"win32\" or [\"linux\", \"win32\"]. See [process.platform](https://nodejs.org/api/process.html#processplatform) values." - }, - "mask": { - "type": "string", - "description": "Runnable name mask" - }, - "env": { - "type": "object", - "description": "Variables in form of { \"key\": \"value\"}" + "configuration": [ + { + "title": "general", + "properties": { + "rust-analyzer.cargoRunner": { + "type": [ + "null", + "string" + ], + "default": null, + "description": "Custom cargo runner extension ID." + }, + "rust-analyzer.restartServerOnConfigChange": { + "markdownDescription": "Whether to restart the server automatically when certain settings that require a restart are changed.", + "default": false, + "type": "boolean" + }, + "rust-analyzer.discoverProjectRunner": { + "markdownDescription": "Sets the extension responsible for determining which extension the rust-analyzer extension uses to generate `rust-project.json` files. This should should only be used\n if a build system like Buck or Bazel is also in use.", + "default": null, + "type": [ + "null", + "string" + ] + }, + "rust-analyzer.showUnlinkedFileNotification": { + "markdownDescription": "Whether to show a notification for unlinked files asking the user to add the corresponding Cargo.toml to the linked projects setting.", + "default": true, + "type": "boolean" + }, + "rust-analyzer.showRequestFailedErrorNotification": { + "markdownDescription": "Whether to show error notifications for failing requests.", + "default": true, + "type": "boolean" + }, + "rust-analyzer.showDependenciesExplorer": { + "markdownDescription": "Whether to show the dependencies view.", + "default": true, + "type": "boolean" + }, + "rust-analyzer.testExplorer": { + "markdownDescription": "Whether to show the test explorer.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "runnables", + "properties": { + "rust-analyzer.runnables.extraEnv": { + "anyOf": [ + { + "type": "null" + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "platform": { + "type": [ + "null", + "string", + "array" + ], + "default": null, + "markdownDescription": "Platform(s) filter like \"win32\" or [\"linux\", \"win32\"]. See [process.platform](https://nodejs.org/api/process.html#processplatform) values." + }, + "mask": { + "type": "string", + "description": "Runnable name mask" + }, + "env": { + "type": "object", + "description": "Variables in form of { \"key\": \"value\"}" + } } } + }, + { + "type": "object", + "description": "Variables in form of { \"key\": \"value\"}" } + ], + "default": null, + "markdownDescription": "Environment variables passed to the runnable launched using `Test` or `Debug` lens or `rust-analyzer.run` command." + }, + "rust-analyzer.runnables.problemMatcher": { + "type": "array", + "items": { + "type": "string" }, - { - "type": "object", - "description": "Variables in form of { \"key\": \"value\"}" - } - ], - "default": null, - "markdownDescription": "Environment variables passed to the runnable launched using `Test` or `Debug` lens or `rust-analyzer.run` command." - }, - "rust-analyzer.runnables.problemMatcher": { - "type": "array", - "items": { - "type": "string" + "default": [ + "$rustc" + ], + "markdownDescription": "Problem matchers to use for `rust-analyzer.run` command, eg `[\"$rustc\", \"$rust-panic\"]`." + } + } + }, + { + "title": "statusBar", + "properties": { + "rust-analyzer.statusBar.clickAction": { + "type": "string", + "enum": [ + "stopServer", + "openLogs" + ], + "enumDescriptions": [ + "Stop Server", + "Open Logs" + ], + "default": "openLogs", + "markdownDescription": "Action to run when clicking the extension status bar item." + } + } + }, + { + "title": "server", + "properties": { + "rust-analyzer.server.path": { + "type": [ + "null", + "string" + ], + "scope": "machine-overridable", + "default": null, + "markdownDescription": "Path to rust-analyzer executable (points to bundled binary by default)." }, - "default": [ - "$rustc" - ], - "markdownDescription": "Problem matchers to use for `rust-analyzer.run` command, eg `[\"$rustc\", \"$rust-panic\"]`." - }, - "rust-analyzer.statusBar.clickAction": { - "type": "string", - "enum": [ - "stopServer", - "openLogs" - ], - "enumDescriptions": [ - "Stop Server", - "Open Logs" - ], - "default": "openLogs", - "markdownDescription": "Action to run when clicking the extension status bar item." - }, - "rust-analyzer.server.path": { - "type": [ - "null", - "string" - ], - "scope": "machine-overridable", - "default": null, - "markdownDescription": "Path to rust-analyzer executable (points to bundled binary by default)." - }, - "rust-analyzer.server.extraEnv": { - "type": [ - "null", - "object" - ], - "additionalProperties": { + "rust-analyzer.server.extraEnv": { "type": [ - "string", - "number" + "null", + "object" + ], + "additionalProperties": { + "type": [ + "string", + "number" + ] + }, + "default": null, + "markdownDescription": "Extra environment variables that will be passed to the rust-analyzer executable. Useful for passing e.g. `RA_LOG` for debugging." + } + } + }, + { + "title": "trace", + "properties": { + "rust-analyzer.trace.server": { + "type": "string", + "scope": "window", + "enum": [ + "off", + "messages", + "verbose" + ], + "enumDescriptions": [ + "No traces", + "Error only", + "Full log" + ], + "default": "off", + "description": "Trace requests to the rust-analyzer (this is usually overly verbose and not recommended for regular users)." + }, + "rust-analyzer.trace.extension": { + "description": "Enable logging of VS Code extensions itself.", + "type": "boolean", + "default": false + } + } + }, + { + "title": "debug", + "properties": { + "rust-analyzer.debug.engine": { + "type": "string", + "enum": [ + "auto", + "vadimcn.vscode-lldb", + "ms-vscode.cpptools" + ], + "default": "auto", + "description": "Preferred debug engine.", + "markdownEnumDescriptions": [ + "First try to use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb), if it's not installed try to use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools).", + "Use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)", + "Use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)" ] }, - "default": null, - "markdownDescription": "Extra environment variables that will be passed to the rust-analyzer executable. Useful for passing e.g. `RA_LOG` for debugging." - }, - "rust-analyzer.trace.server": { - "type": "string", - "scope": "window", - "enum": [ - "off", - "messages", - "verbose" - ], - "enumDescriptions": [ - "No traces", - "Error only", - "Full log" - ], - "default": "off", - "description": "Trace requests to the rust-analyzer (this is usually overly verbose and not recommended for regular users)." - }, - "rust-analyzer.trace.extension": { - "description": "Enable logging of VS Code extensions itself.", - "type": "boolean", - "default": false - }, - "rust-analyzer.debug.engine": { - "type": "string", - "enum": [ - "auto", - "vadimcn.vscode-lldb", - "ms-vscode.cpptools" - ], - "default": "auto", - "description": "Preferred debug engine.", - "markdownEnumDescriptions": [ - "First try to use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb), if it's not installed try to use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools).", - "Use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)", - "Use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)" - ] - }, - "rust-analyzer.debug.sourceFileMap": { - "type": [ - "object", - "string" - ], - "const": "auto", - "description": "Optional source file mappings passed to the debug engine.", - "default": { - "/rustc/<id>": "${env:USERPROFILE}/.rustup/toolchains/<toolchain-id>/lib/rustlib/src/rust" + "rust-analyzer.debug.sourceFileMap": { + "type": [ + "object", + "string" + ], + "const": "auto", + "description": "Optional source file mappings passed to the debug engine.", + "default": { + "/rustc/<id>": "${env:USERPROFILE}/.rustup/toolchains/<toolchain-id>/lib/rustlib/src/rust" + } + }, + "rust-analyzer.debug.openDebugPane": { + "markdownDescription": "Whether to open up the `Debug Panel` on debugging start.", + "type": "boolean", + "default": false + }, + "rust-analyzer.debug.engineSettings": { + "type": "object", + "default": {}, + "markdownDescription": "Optional settings passed to the debug engine. Example: `{ \"lldb\": { \"terminal\":\"external\"} }`" } - }, - "rust-analyzer.debug.openDebugPane": { - "markdownDescription": "Whether to open up the `Debug Panel` on debugging start.", - "type": "boolean", - "default": false - }, - "rust-analyzer.debug.engineSettings": { - "type": "object", - "default": {}, - "markdownDescription": "Optional settings passed to the debug engine. Example: `{ \"lldb\": { \"terminal\":\"external\"} }`" - }, - "rust-analyzer.restartServerOnConfigChange": { - "markdownDescription": "Whether to restart the server automatically when certain settings that require a restart are changed.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.typing.continueCommentsOnNewline": { - "markdownDescription": "Whether to prefix newlines after comments with the corresponding comment prefix.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.diagnostics.previewRustcOutput": { - "markdownDescription": "Whether to show the main part of the rendered rustc output of a diagnostic message.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.diagnostics.useRustcErrorCode": { - "markdownDescription": "Whether to show diagnostics using the original rustc error code. If this is false, all rustc diagnostics will have the code 'rustc(Click for full compiler diagnostics)'", - "default": false, - "type": "boolean" - }, - "rust-analyzer.discoverProjectRunner": { - "markdownDescription": "Sets the extension responsible for determining which extension the rust-analyzer extension uses to generate `rust-project.json` files. This should should only be used\n if a build system like Buck or Bazel is also in use.", - "default": null, - "type": [ - "null", - "string" - ] - }, - "rust-analyzer.showUnlinkedFileNotification": { - "markdownDescription": "Whether to show a notification for unlinked files asking the user to add the corresponding Cargo.toml to the linked projects setting.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.showRequestFailedErrorNotification": { - "markdownDescription": "Whether to show error notifications for failing requests.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.showDependenciesExplorer": { - "markdownDescription": "Whether to show the dependencies view.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.testExplorer": { - "markdownDescription": "Whether to show the test explorer.", - "default": false, - "type": "boolean" - }, - "$generated-start": {}, - "rust-analyzer.assist.emitMustUse": { - "markdownDescription": "Whether to insert #[must_use] when generating `as_` methods\nfor enum variants.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.assist.expressionFillDefault": { - "markdownDescription": "Placeholder expression to use for missing expressions in assists.", - "default": "todo", - "type": "string", - "enum": [ - "todo", - "default" - ], - "enumDescriptions": [ - "Fill missing expressions with the `todo` macro", - "Fill missing expressions with reasonable defaults, `new` or `default` constructors." - ] - }, - "rust-analyzer.assist.termSearch.fuel": { - "markdownDescription": "Term search fuel in \"units of work\" for assists (Defaults to 400).", - "default": 400, - "type": "integer", - "minimum": 0 - }, - "rust-analyzer.cachePriming.enable": { - "markdownDescription": "Warm up caches on project load.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.cachePriming.numThreads": { - "markdownDescription": "How many worker threads to handle priming caches. The default `0` means to pick automatically.", - "default": 0, - "type": "number", - "minimum": 0, - "maximum": 255 - }, - "rust-analyzer.cargo.allTargets": { - "markdownDescription": "Pass `--all-targets` to cargo invocation.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.cargo.autoreload": { - "markdownDescription": "Automatically refresh project info via `cargo metadata` on\n`Cargo.toml` or `.cargo/config.toml` changes.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.cargo.buildScripts.enable": { - "markdownDescription": "Run build scripts (`build.rs`) for more precise code analysis.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.cargo.buildScripts.invocationLocation": { - "markdownDescription": "Specifies the working directory for running build scripts.\n- \"workspace\": run build scripts for a workspace in the workspace's root directory.\n This is incompatible with `#rust-analyzer.cargo.buildScripts.invocationStrategy#` set to `once`.\n- \"root\": run build scripts in the project's root directory.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", - "default": "workspace", - "type": "string", - "enum": [ - "workspace", - "root" - ], - "enumDescriptions": [ - "The command will be executed in the corresponding workspace root.", - "The command will be executed in the project root." - ] - }, - "rust-analyzer.cargo.buildScripts.invocationStrategy": { - "markdownDescription": "Specifies the invocation strategy to use when running the build scripts command.\nIf `per_workspace` is set, the command will be executed for each workspace.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", - "default": "per_workspace", - "type": "string", - "enum": [ - "per_workspace", - "once" - ], - "enumDescriptions": [ - "The command will be executed for each workspace.", - "The command will be executed once." - ] - }, - "rust-analyzer.cargo.buildScripts.overrideCommand": { - "markdownDescription": "Override the command rust-analyzer uses to run build scripts and\nbuild procedural macros. The command is required to output json\nand should therefore include `--message-format=json` or a similar\noption.\n\nIf there are multiple linked projects/workspaces, this command is invoked for\neach of them, with the working directory being the workspace root\n(i.e., the folder containing the `Cargo.toml`). This can be overwritten\nby changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and\n`#rust-analyzer.cargo.buildScripts.invocationLocation#`.\n\nBy default, a cargo invocation will be constructed for the configured\ntargets and features, with the following base command line:\n\n```bash\ncargo check --quiet --workspace --message-format=json --all-targets\n```\n.", - "default": null, - "type": [ - "null", - "array" - ], - "items": { - "type": "string" + } + }, + { + "title": "typing", + "properties": { + "rust-analyzer.typing.continueCommentsOnNewline": { + "markdownDescription": "Whether to prefix newlines after comments with the corresponding comment prefix.", + "default": true, + "type": "boolean" } - }, - "rust-analyzer.cargo.buildScripts.rebuildOnSave": { - "markdownDescription": "Rerun proc-macros building/build-scripts running when proc-macro\nor build-script sources change and are saved.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.cargo.buildScripts.useRustcWrapper": { - "markdownDescription": "Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to\navoid checking unnecessary things.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.cargo.cfgs": { - "markdownDescription": "List of cfg options to enable with the given values.", - "default": { - "debug_assertions": null, - "miri": null + } + }, + { + "title": "diagnostics", + "properties": { + "rust-analyzer.diagnostics.previewRustcOutput": { + "markdownDescription": "Whether to show the main part of the rendered rustc output of a diagnostic message.", + "default": false, + "type": "boolean" }, - "type": "object" - }, - "rust-analyzer.cargo.extraArgs": { - "markdownDescription": "Extra arguments that are passed to every cargo invocation.", - "default": [], - "type": "array", - "items": { - "type": "string" + "rust-analyzer.diagnostics.useRustcErrorCode": { + "markdownDescription": "Whether to show diagnostics using the original rustc error code. If this is false, all rustc diagnostics will have the code 'rustc(Click for full compiler diagnostics)'", + "default": false, + "type": "boolean" } - }, - "rust-analyzer.cargo.extraEnv": { - "markdownDescription": "Extra environment variables that will be set when running cargo, rustc\nor other commands within the workspace. Useful for setting RUSTFLAGS.", - "default": {}, - "type": "object" - }, - "rust-analyzer.cargo.features": { - "markdownDescription": "List of features to activate.\n\nSet this to `\"all\"` to pass `--all-features` to cargo.", - "default": [], - "anyOf": [ - { - "type": "string", - "enum": [ - "all" - ], - "enumDescriptions": [ - "Pass `--all-features` to cargo" - ] - }, - { - "type": "array", - "items": { - "type": "string" + } + }, + { + "title": "$generated-start" + }, + { + "title": "assist", + "properties": { + "rust-analyzer.assist.emitMustUse": { + "markdownDescription": "Whether to insert #[must_use] when generating `as_` methods\nfor enum variants.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "assist", + "properties": { + "rust-analyzer.assist.expressionFillDefault": { + "markdownDescription": "Placeholder expression to use for missing expressions in assists.", + "default": "todo", + "type": "string", + "enum": [ + "todo", + "default" + ], + "enumDescriptions": [ + "Fill missing expressions with the `todo` macro", + "Fill missing expressions with reasonable defaults, `new` or `default` constructors." + ] + } + } + }, + { + "title": "assist", + "properties": { + "rust-analyzer.assist.termSearch.fuel": { + "markdownDescription": "Term search fuel in \"units of work\" for assists (Defaults to 400).", + "default": 400, + "type": "integer", + "minimum": 0 + } + } + }, + { + "title": "cachePriming", + "properties": { + "rust-analyzer.cachePriming.enable": { + "markdownDescription": "Warm up caches on project load.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "cachePriming", + "properties": { + "rust-analyzer.cachePriming.numThreads": { + "markdownDescription": "How many worker threads to handle priming caches. The default `0` means to pick automatically.", + "default": "physical", + "anyOf": [ + { + "type": "number", + "minimum": 0, + "maximum": 255 + }, + { + "type": "string", + "enum": [ + "physical", + "logical" + ], + "enumDescriptions": [ + "Use the number of physical cores", + "Use the number of logical cores" + ] } + ] + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.allTargets": { + "markdownDescription": "Pass `--all-targets` to cargo invocation.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.autoreload": { + "markdownDescription": "Automatically refresh project info via `cargo metadata` on\n`Cargo.toml` or `.cargo/config.toml` changes.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.buildScripts.enable": { + "markdownDescription": "Run build scripts (`build.rs`) for more precise code analysis.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.buildScripts.invocationLocation": { + "markdownDescription": "Specifies the working directory for running build scripts.\n- \"workspace\": run build scripts for a workspace in the workspace's root directory.\n This is incompatible with `#rust-analyzer.cargo.buildScripts.invocationStrategy#` set to `once`.\n- \"root\": run build scripts in the project's root directory.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", + "default": "workspace", + "type": "string", + "enum": [ + "workspace", + "root" + ], + "enumDescriptions": [ + "The command will be executed in the corresponding workspace root.", + "The command will be executed in the project root." + ] + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.buildScripts.invocationStrategy": { + "markdownDescription": "Specifies the invocation strategy to use when running the build scripts command.\nIf `per_workspace` is set, the command will be executed for each workspace.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.", + "default": "per_workspace", + "type": "string", + "enum": [ + "per_workspace", + "once" + ], + "enumDescriptions": [ + "The command will be executed for each workspace.", + "The command will be executed once." + ] + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.buildScripts.overrideCommand": { + "markdownDescription": "Override the command rust-analyzer uses to run build scripts and\nbuild procedural macros. The command is required to output json\nand should therefore include `--message-format=json` or a similar\noption.\n\nIf there are multiple linked projects/workspaces, this command is invoked for\neach of them, with the working directory being the workspace root\n(i.e., the folder containing the `Cargo.toml`). This can be overwritten\nby changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and\n`#rust-analyzer.cargo.buildScripts.invocationLocation#`.\n\nBy default, a cargo invocation will be constructed for the configured\ntargets and features, with the following base command line:\n\n```bash\ncargo check --quiet --workspace --message-format=json --all-targets\n```\n.", + "default": null, + "type": [ + "null", + "array" + ], + "items": { + "type": "string" } - ] - }, - "rust-analyzer.cargo.noDefaultFeatures": { - "markdownDescription": "Whether to pass `--no-default-features` to cargo.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.cargo.sysroot": { - "markdownDescription": "Relative path to the sysroot, or \"discover\" to try to automatically find it via\n\"rustc --print sysroot\".\n\nUnsetting this disables sysroot loading.\n\nThis option does not take effect until rust-analyzer is restarted.", - "default": "discover", - "type": [ - "null", - "string" - ] - }, - "rust-analyzer.cargo.sysrootQueryMetadata": { - "markdownDescription": "Whether to run cargo metadata on the sysroot library allowing rust-analyzer to analyze\nthird-party dependencies of the standard libraries.\n\nThis will cause `cargo` to create a lockfile in your sysroot directory. rust-analyzer\nwill attempt to clean up afterwards, but nevertheless requires the location to be\nwritable to.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.cargo.sysrootSrc": { - "markdownDescription": "Relative path to the sysroot library sources. If left unset, this will default to\n`{cargo.sysroot}/lib/rustlib/src/rust/library`.\n\nThis option does not take effect until rust-analyzer is restarted.", - "default": null, - "type": [ - "null", - "string" - ] - }, - "rust-analyzer.cargo.target": { - "markdownDescription": "Compilation target override (target triple).", - "default": null, - "type": [ - "null", - "string" - ] - }, - "rust-analyzer.cargo.targetDir": { - "markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis prevents rust-analyzer's `cargo check` and initial build-script and proc-macro\nbuilding from locking the `Cargo.lock` at the expense of duplicating build artifacts.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path relative to the workspace to use that path.", - "default": null, - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.buildScripts.rebuildOnSave": { + "markdownDescription": "Rerun proc-macros building/build-scripts running when proc-macro\nor build-script sources change and are saved.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.buildScripts.useRustcWrapper": { + "markdownDescription": "Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to\navoid checking unnecessary things.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.cfgs": { + "markdownDescription": "List of cfg options to enable with the given values.", + "default": { + "debug_assertions": null, + "miri": null }, - { + "type": "object" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.extraArgs": { + "markdownDescription": "Extra arguments that are passed to every cargo invocation.", + "default": [], + "type": "array", + "items": { "type": "string" } - ] - }, - "rust-analyzer.checkOnSave": { - "markdownDescription": "Run the check command for diagnostics on save.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.check.allTargets": { - "markdownDescription": "Check all targets and tests (`--all-targets`). Defaults to\n`#rust-analyzer.cargo.allTargets#`.", - "default": null, - "type": [ - "null", - "boolean" - ] - }, - "rust-analyzer.check.command": { - "markdownDescription": "Cargo command to use for `cargo check`.", - "default": "check", - "type": "string" - }, - "rust-analyzer.check.extraArgs": { - "markdownDescription": "Extra arguments for `cargo check`.", - "default": [], - "type": "array", - "items": { - "type": "string" } - }, - "rust-analyzer.check.extraEnv": { - "markdownDescription": "Extra environment variables that will be set when running `cargo check`.\nExtends `#rust-analyzer.cargo.extraEnv#`.", - "default": {}, - "type": "object" - }, - "rust-analyzer.check.features": { - "markdownDescription": "List of features to activate. Defaults to\n`#rust-analyzer.cargo.features#`.\n\nSet to `\"all\"` to pass `--all-features` to Cargo.", - "default": null, - "anyOf": [ - { - "type": "string", - "enum": [ - "all" - ], - "enumDescriptions": [ - "Pass `--all-features` to cargo" - ] - }, - { - "type": "array", - "items": { + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.extraEnv": { + "markdownDescription": "Extra environment variables that will be set when running cargo, rustc\nor other commands within the workspace. Useful for setting RUSTFLAGS.", + "default": {}, + "type": "object" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.features": { + "markdownDescription": "List of features to activate.\n\nSet this to `\"all\"` to pass `--all-features` to cargo.", + "default": [], + "anyOf": [ + { + "type": "string", + "enum": [ + "all" + ], + "enumDescriptions": [ + "Pass `--all-features` to cargo" + ] + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.noDefaultFeatures": { + "markdownDescription": "Whether to pass `--no-default-features` to cargo.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.sysroot": { + "markdownDescription": "Relative path to the sysroot, or \"discover\" to try to automatically find it via\n\"rustc --print sysroot\".\n\nUnsetting this disables sysroot loading.\n\nThis option does not take effect until rust-analyzer is restarted.", + "default": "discover", + "type": [ + "null", + "string" + ] + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.sysrootQueryMetadata": { + "markdownDescription": "Whether to run cargo metadata on the sysroot library allowing rust-analyzer to analyze\nthird-party dependencies of the standard libraries.\n\nThis will cause `cargo` to create a lockfile in your sysroot directory. rust-analyzer\nwill attempt to clean up afterwards, but nevertheless requires the location to be\nwritable to.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.sysrootSrc": { + "markdownDescription": "Relative path to the sysroot library sources. If left unset, this will default to\n`{cargo.sysroot}/lib/rustlib/src/rust/library`.\n\nThis option does not take effect until rust-analyzer is restarted.", + "default": null, + "type": [ + "null", + "string" + ] + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.target": { + "markdownDescription": "Compilation target override (target triple).", + "default": null, + "type": [ + "null", + "string" + ] + } + } + }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.targetDir": { + "markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis prevents rust-analyzer's `cargo check` and initial build-script and proc-macro\nbuilding from locking the `Cargo.lock` at the expense of duplicating build artifacts.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path relative to the workspace to use that path.", + "default": null, + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { "type": "string" } - }, - { - "type": "null" - } - ] - }, - "rust-analyzer.check.ignore": { - "markdownDescription": "List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore.\n\nFor example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,...", - "default": [], - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - }, - "rust-analyzer.check.invocationLocation": { - "markdownDescription": "Specifies the working directory for running checks.\n- \"workspace\": run checks for workspaces in the corresponding workspaces' root directories.\n This falls back to \"root\" if `#rust-analyzer.check.invocationStrategy#` is set to `once`.\n- \"root\": run checks in the project's root directory.\nThis config only has an effect when `#rust-analyzer.check.overrideCommand#`\nis set.", - "default": "workspace", - "type": "string", - "enum": [ - "workspace", - "root" - ], - "enumDescriptions": [ - "The command will be executed in the corresponding workspace root.", - "The command will be executed in the project root." - ] - }, - "rust-analyzer.check.invocationStrategy": { - "markdownDescription": "Specifies the invocation strategy to use when running the check command.\nIf `per_workspace` is set, the command will be executed for each workspace.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.check.overrideCommand#`\nis set.", - "default": "per_workspace", - "type": "string", - "enum": [ - "per_workspace", - "once" - ], - "enumDescriptions": [ - "The command will be executed for each workspace.", - "The command will be executed once." - ] - }, - "rust-analyzer.check.noDefaultFeatures": { - "markdownDescription": "Whether to pass `--no-default-features` to Cargo. Defaults to\n`#rust-analyzer.cargo.noDefaultFeatures#`.", - "default": null, - "type": [ - "null", - "boolean" - ] - }, - "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(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/workspaces, this command is invoked for\neach of them, with the working directory being the workspace root\n(i.e., the folder containing the `Cargo.toml`). This can be overwritten\nby changing `#rust-analyzer.check.invocationStrategy#` and\n`#rust-analyzer.check.invocationLocation#`.\n\nIf `$saved_file` is part of the command, rust-analyzer will pass\nthe absolute path of the saved file to the provided command. This is\nintended to be used with non-Cargo build systems.\nNote that `$saved_file` is experimental and may be removed in the future.\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.", - "default": null, - "type": [ - "null", - "array" - ], - "items": { + ] + } + } + }, + { + "title": "general", + "properties": { + "rust-analyzer.checkOnSave": { + "markdownDescription": "Run the check command for diagnostics on save.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.allTargets": { + "markdownDescription": "Check all targets and tests (`--all-targets`). Defaults to\n`#rust-analyzer.cargo.allTargets#`.", + "default": null, + "type": [ + "null", + "boolean" + ] + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.command": { + "markdownDescription": "Cargo command to use for `cargo check`.", + "default": "check", "type": "string" } - }, - "rust-analyzer.check.targets": { - "markdownDescription": "Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.\n\nCan be a single target, e.g. `\"x86_64-unknown-linux-gnu\"` or a list of targets, e.g.\n`[\"aarch64-apple-darwin\", \"x86_64-apple-darwin\"]`.\n\nAliased as `\"checkOnSave.targets\"`.", - "default": null, - "anyOf": [ - { - "type": "null" - }, - { + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.extraArgs": { + "markdownDescription": "Extra arguments for `cargo check`.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.extraEnv": { + "markdownDescription": "Extra environment variables that will be set when running `cargo check`.\nExtends `#rust-analyzer.cargo.extraEnv#`.", + "default": {}, + "type": "object" + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.features": { + "markdownDescription": "List of features to activate. Defaults to\n`#rust-analyzer.cargo.features#`.\n\nSet to `\"all\"` to pass `--all-features` to Cargo.", + "default": null, + "anyOf": [ + { + "type": "string", + "enum": [ + "all" + ], + "enumDescriptions": [ + "Pass `--all-features` to cargo" + ] + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.ignore": { + "markdownDescription": "List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore.\n\nFor example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,...", + "default": [], + "type": "array", + "items": { "type": "string" }, - { - "type": "array", - "items": { + "uniqueItems": true + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.invocationLocation": { + "markdownDescription": "Specifies the working directory for running checks.\n- \"workspace\": run checks for workspaces in the corresponding workspaces' root directories.\n This falls back to \"root\" if `#rust-analyzer.check.invocationStrategy#` is set to `once`.\n- \"root\": run checks in the project's root directory.\nThis config only has an effect when `#rust-analyzer.check.overrideCommand#`\nis set.", + "default": "workspace", + "type": "string", + "enum": [ + "workspace", + "root" + ], + "enumDescriptions": [ + "The command will be executed in the corresponding workspace root.", + "The command will be executed in the project root." + ] + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.invocationStrategy": { + "markdownDescription": "Specifies the invocation strategy to use when running the check command.\nIf `per_workspace` is set, the command will be executed for each workspace.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.check.overrideCommand#`\nis set.", + "default": "per_workspace", + "type": "string", + "enum": [ + "per_workspace", + "once" + ], + "enumDescriptions": [ + "The command will be executed for each workspace.", + "The command will be executed once." + ] + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.noDefaultFeatures": { + "markdownDescription": "Whether to pass `--no-default-features` to Cargo. Defaults to\n`#rust-analyzer.cargo.noDefaultFeatures#`.", + "default": null, + "type": [ + "null", + "boolean" + ] + } + } + }, + { + "title": "check", + "properties": { + "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(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/workspaces, this command is invoked for\neach of them, with the working directory being the workspace root\n(i.e., the folder containing the `Cargo.toml`). This can be overwritten\nby changing `#rust-analyzer.check.invocationStrategy#` and\n`#rust-analyzer.check.invocationLocation#`.\n\nIf `$saved_file` is part of the command, rust-analyzer will pass\nthe absolute path of the saved file to the provided command. This is\nintended to be used with non-Cargo build systems.\nNote that `$saved_file` is experimental and may be removed in the future.\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.", + "default": null, + "type": [ + "null", + "array" + ], + "items": { + "type": "string" + } + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.targets": { + "markdownDescription": "Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.\n\nCan be a single target, e.g. `\"x86_64-unknown-linux-gnu\"` or a list of targets, e.g.\n`[\"aarch64-apple-darwin\", \"x86_64-apple-darwin\"]`.\n\nAliased as `\"checkOnSave.targets\"`.", + "default": null, + "anyOf": [ + { + "type": "null" + }, + { "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + }, + { + "title": "check", + "properties": { + "rust-analyzer.check.workspace": { + "markdownDescription": "Whether `--workspace` should be passed to `cargo check`.\nIf false, `-p <package>` will be passed instead.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.autoimport.enable": { + "markdownDescription": "Toggles the additional completions that automatically add imports when completed.\nNote that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.autoself.enable": { + "markdownDescription": "Toggles the additional completions that automatically show method calls and field accesses\nwith `self` prefixed to them when inside a method.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.callable.snippets": { + "markdownDescription": "Whether to add parenthesis and argument snippets when completing function.", + "default": "fill_arguments", + "type": "string", + "enum": [ + "fill_arguments", + "add_parentheses", + "none" + ], + "enumDescriptions": [ + "Add call parentheses and pre-fill arguments.", + "Add call parentheses.", + "Do no snippet completions for callables." + ] + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.fullFunctionSignatures.enable": { + "markdownDescription": "Whether to show full function/method signatures in completion docs.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.limit": { + "markdownDescription": "Maximum number of completions to return. If `None`, the limit is infinite.", + "default": null, + "type": [ + "null", + "integer" + ], + "minimum": 0 + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.postfix.enable": { + "markdownDescription": "Whether to show postfix snippets like `dbg`, `if`, `not`, etc.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.privateEditable.enable": { + "markdownDescription": "Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.snippets.custom": { + "markdownDescription": "Custom completion snippets.", + "default": { + "Arc::new": { + "postfix": "arc", + "body": "Arc::new(${receiver})", + "requires": "std::sync::Arc", + "description": "Put the expression into an `Arc`", + "scope": "expr" + }, + "Rc::new": { + "postfix": "rc", + "body": "Rc::new(${receiver})", + "requires": "std::rc::Rc", + "description": "Put the expression into an `Rc`", + "scope": "expr" + }, + "Box::pin": { + "postfix": "pinbox", + "body": "Box::pin(${receiver})", + "requires": "std::boxed::Box", + "description": "Put the expression into a pinned `Box`", + "scope": "expr" + }, + "Ok": { + "postfix": "ok", + "body": "Ok(${receiver})", + "description": "Wrap the expression in a `Result::Ok`", + "scope": "expr" + }, + "Err": { + "postfix": "err", + "body": "Err(${receiver})", + "description": "Wrap the expression in a `Result::Err`", + "scope": "expr" + }, + "Some": { + "postfix": "some", + "body": "Some(${receiver})", + "description": "Wrap the expression in an `Option::Some`", + "scope": "expr" } - } - ] - }, - "rust-analyzer.check.workspace": { - "markdownDescription": "Whether `--workspace` should be passed to `cargo check`.\nIf false, `-p <package>` will be passed instead.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.completion.autoimport.enable": { - "markdownDescription": "Toggles the additional completions that automatically add imports when completed.\nNote that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.completion.autoself.enable": { - "markdownDescription": "Toggles the additional completions that automatically show method calls and field accesses\nwith `self` prefixed to them when inside a method.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.completion.callable.snippets": { - "markdownDescription": "Whether to add parenthesis and argument snippets when completing function.", - "default": "fill_arguments", - "type": "string", - "enum": [ - "fill_arguments", - "add_parentheses", - "none" - ], - "enumDescriptions": [ - "Add call parentheses and pre-fill arguments.", - "Add call parentheses.", - "Do no snippet completions for callables." - ] - }, - "rust-analyzer.completion.fullFunctionSignatures.enable": { - "markdownDescription": "Whether to show full function/method signatures in completion docs.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.completion.limit": { - "markdownDescription": "Maximum number of completions to return. If `None`, the limit is infinite.", - "default": null, - "type": [ - "null", - "integer" - ], - "minimum": 0 - }, - "rust-analyzer.completion.postfix.enable": { - "markdownDescription": "Whether to show postfix snippets like `dbg`, `if`, `not`, etc.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.completion.privateEditable.enable": { - "markdownDescription": "Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.completion.snippets.custom": { - "markdownDescription": "Custom completion snippets.", - "default": { - "Arc::new": { - "postfix": "arc", - "body": "Arc::new(${receiver})", - "requires": "std::sync::Arc", - "description": "Put the expression into an `Arc`", - "scope": "expr" - }, - "Rc::new": { - "postfix": "rc", - "body": "Rc::new(${receiver})", - "requires": "std::rc::Rc", - "description": "Put the expression into an `Rc`", - "scope": "expr" - }, - "Box::pin": { - "postfix": "pinbox", - "body": "Box::pin(${receiver})", - "requires": "std::boxed::Box", - "description": "Put the expression into a pinned `Box`", - "scope": "expr" - }, - "Ok": { - "postfix": "ok", - "body": "Ok(${receiver})", - "description": "Wrap the expression in a `Result::Ok`", - "scope": "expr" }, - "Err": { - "postfix": "err", - "body": "Err(${receiver})", - "description": "Wrap the expression in a `Result::Err`", - "scope": "expr" + "type": "object" + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.termSearch.enable": { + "markdownDescription": "Whether to enable term search based snippets like `Some(foo.bar().baz())`.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.termSearch.fuel": { + "markdownDescription": "Term search fuel in \"units of work\" for autocompletion (Defaults to 200).", + "default": 200, + "type": "integer", + "minimum": 0 + } + } + }, + { + "title": "diagnostics", + "properties": { + "rust-analyzer.diagnostics.disabled": { + "markdownDescription": "List of rust-analyzer diagnostics to disable.", + "default": [], + "type": "array", + "items": { + "type": "string" }, - "Some": { - "postfix": "some", - "body": "Some(${receiver})", - "description": "Wrap the expression in an `Option::Some`", - "scope": "expr" + "uniqueItems": true + } + } + }, + { + "title": "diagnostics", + "properties": { + "rust-analyzer.diagnostics.enable": { + "markdownDescription": "Whether to show native rust-analyzer diagnostics.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "diagnostics", + "properties": { + "rust-analyzer.diagnostics.experimental.enable": { + "markdownDescription": "Whether to show experimental rust-analyzer diagnostics that might\nhave more false positives than usual.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "diagnostics", + "properties": { + "rust-analyzer.diagnostics.remapPrefix": { + "markdownDescription": "Map of prefixes to be substituted when parsing diagnostic file paths.\nThis should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`.", + "default": {}, + "type": "object" + } + } + }, + { + "title": "diagnostics", + "properties": { + "rust-analyzer.diagnostics.styleLints.enable": { + "markdownDescription": "Whether to run additional style lints.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "diagnostics", + "properties": { + "rust-analyzer.diagnostics.warningsAsHint": { + "markdownDescription": "List of warnings that should be displayed with hint severity.\n\nThe warnings will be indicated by faded text or three dots in code\nand will not show up in the `Problems Panel`.", + "default": [], + "type": "array", + "items": { + "type": "string" } - }, - "type": "object" - }, - "rust-analyzer.completion.termSearch.enable": { - "markdownDescription": "Whether to enable term search based snippets like `Some(foo.bar().baz())`.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.completion.termSearch.fuel": { - "markdownDescription": "Term search fuel in \"units of work\" for autocompletion (Defaults to 200).", - "default": 200, - "type": "integer", - "minimum": 0 - }, - "rust-analyzer.diagnostics.disabled": { - "markdownDescription": "List of rust-analyzer diagnostics to disable.", - "default": [], - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - }, - "rust-analyzer.diagnostics.enable": { - "markdownDescription": "Whether to show native rust-analyzer diagnostics.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.diagnostics.experimental.enable": { - "markdownDescription": "Whether to show experimental rust-analyzer diagnostics that might\nhave more false positives than usual.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.diagnostics.remapPrefix": { - "markdownDescription": "Map of prefixes to be substituted when parsing diagnostic file paths.\nThis should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`.", - "default": {}, - "type": "object" - }, - "rust-analyzer.diagnostics.styleLints.enable": { - "markdownDescription": "Whether to run additional style lints.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.diagnostics.warningsAsHint": { - "markdownDescription": "List of warnings that should be displayed with hint severity.\n\nThe warnings will be indicated by faded text or three dots in code\nand will not show up in the `Problems Panel`.", - "default": [], - "type": "array", - "items": { - "type": "string" } - }, - "rust-analyzer.diagnostics.warningsAsInfo": { - "markdownDescription": "List of warnings that should be displayed with info severity.\n\nThe warnings will be indicated by a blue squiggly underline in code\nand a blue icon in the `Problems Panel`.", - "default": [], - "type": "array", - "items": { - "type": "string" + } + }, + { + "title": "diagnostics", + "properties": { + "rust-analyzer.diagnostics.warningsAsInfo": { + "markdownDescription": "List of warnings that should be displayed with info severity.\n\nThe warnings will be indicated by a blue squiggly underline in code\nand a blue icon in the `Problems Panel`.", + "default": [], + "type": "array", + "items": { + "type": "string" + } } - }, - "rust-analyzer.files.excludeDirs": { - "markdownDescription": "These directories will be ignored by rust-analyzer. They are\nrelative to the workspace root, and globs are not supported. You may\nalso need to add the folders to Code's `files.watcherExclude`.", - "default": [], - "type": "array", - "items": { - "type": "string" + } + }, + { + "title": "files", + "properties": { + "rust-analyzer.files.excludeDirs": { + "markdownDescription": "These directories will be ignored by rust-analyzer. They are\nrelative to the workspace root, and globs are not supported. You may\nalso need to add the folders to Code's `files.watcherExclude`.", + "default": [], + "type": "array", + "items": { + "type": "string" + } } - }, - "rust-analyzer.files.watcher": { - "markdownDescription": "Controls file watching implementation.", - "default": "client", - "type": "string", - "enum": [ - "client", - "server" - ], - "enumDescriptions": [ - "Use the client (editor) to watch files for changes", - "Use server-side file watching" - ] - }, - "rust-analyzer.highlightRelated.breakPoints.enable": { - "markdownDescription": "Enables highlighting of related references while the cursor is on `break`, `loop`, `while`, or `for` keywords.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.highlightRelated.closureCaptures.enable": { - "markdownDescription": "Enables highlighting of all captures of a closure while the cursor is on the `|` or move keyword of a closure.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.highlightRelated.exitPoints.enable": { - "markdownDescription": "Enables highlighting of all exit points while the cursor is on any `return`, `?`, `fn`, or return type arrow (`->`).", - "default": true, - "type": "boolean" - }, - "rust-analyzer.highlightRelated.references.enable": { - "markdownDescription": "Enables highlighting of related references while the cursor is on any identifier.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.highlightRelated.yieldPoints.enable": { - "markdownDescription": "Enables highlighting of all break points for a loop or block context while the cursor is on any `async` or `await` keywords.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.actions.debug.enable": { - "markdownDescription": "Whether to show `Debug` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.actions.enable": { - "markdownDescription": "Whether to show HoverActions in Rust files.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.actions.gotoTypeDef.enable": { - "markdownDescription": "Whether to show `Go to Type Definition` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.actions.implementations.enable": { - "markdownDescription": "Whether to show `Implementations` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.actions.references.enable": { - "markdownDescription": "Whether to show `References` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.hover.actions.run.enable": { - "markdownDescription": "Whether to show `Run` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.documentation.enable": { - "markdownDescription": "Whether to show documentation on hover.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.documentation.keywords.enable": { - "markdownDescription": "Whether to show keyword hover popups. Only applies when\n`#rust-analyzer.hover.documentation.enable#` is set.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.links.enable": { - "markdownDescription": "Use markdown syntax for links on hover.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.memoryLayout.alignment": { - "markdownDescription": "How to render the align information in a memory layout hover.", - "default": "hexadecimal", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string", - "enum": [ - "both", - "decimal", - "hexadecimal" - ], - "enumDescriptions": [ - "Render as 12 (0xC)", - "Render as 12", - "Render as 0xC" + } + }, + { + "title": "files", + "properties": { + "rust-analyzer.files.watcher": { + "markdownDescription": "Controls file watching implementation.", + "default": "client", + "type": "string", + "enum": [ + "client", + "server" + ], + "enumDescriptions": [ + "Use the client (editor) to watch files for changes", + "Use server-side file watching" + ] + } + } + }, + { + "title": "highlightRelated", + "properties": { + "rust-analyzer.highlightRelated.breakPoints.enable": { + "markdownDescription": "Enables highlighting of related references while the cursor is on `break`, `loop`, `while`, or `for` keywords.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "highlightRelated", + "properties": { + "rust-analyzer.highlightRelated.closureCaptures.enable": { + "markdownDescription": "Enables highlighting of all captures of a closure while the cursor is on the `|` or move keyword of a closure.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "highlightRelated", + "properties": { + "rust-analyzer.highlightRelated.exitPoints.enable": { + "markdownDescription": "Enables highlighting of all exit points while the cursor is on any `return`, `?`, `fn`, or return type arrow (`->`).", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "highlightRelated", + "properties": { + "rust-analyzer.highlightRelated.references.enable": { + "markdownDescription": "Enables highlighting of related references while the cursor is on any identifier.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "highlightRelated", + "properties": { + "rust-analyzer.highlightRelated.yieldPoints.enable": { + "markdownDescription": "Enables highlighting of all break points for a loop or block context while the cursor is on any `async` or `await` keywords.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.actions.debug.enable": { + "markdownDescription": "Whether to show `Debug` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.actions.enable": { + "markdownDescription": "Whether to show HoverActions in Rust files.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.actions.gotoTypeDef.enable": { + "markdownDescription": "Whether to show `Go to Type Definition` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.actions.implementations.enable": { + "markdownDescription": "Whether to show `Implementations` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.actions.references.enable": { + "markdownDescription": "Whether to show `References` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.actions.run.enable": { + "markdownDescription": "Whether to show `Run` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` is set.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.documentation.enable": { + "markdownDescription": "Whether to show documentation on hover.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.documentation.keywords.enable": { + "markdownDescription": "Whether to show keyword hover popups. Only applies when\n`#rust-analyzer.hover.documentation.enable#` is set.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.links.enable": { + "markdownDescription": "Use markdown syntax for links on hover.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.memoryLayout.alignment": { + "markdownDescription": "How to render the align information in a memory layout hover.", + "default": "hexadecimal", + "anyOf": [ + { + "type": "null" + }, + { + "type": "string", + "enum": [ + "both", + "decimal", + "hexadecimal" + ], + "enumDescriptions": [ + "Render as 12 (0xC)", + "Render as 12", + "Render as 0xC" + ] + } + ] + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.memoryLayout.enable": { + "markdownDescription": "Whether to show memory layout data on hover.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.memoryLayout.niches": { + "markdownDescription": "How to render the niche information in a memory layout hover.", + "default": false, + "type": [ + "null", + "boolean" + ] + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.memoryLayout.offset": { + "markdownDescription": "How to render the offset information in a memory layout hover.", + "default": "hexadecimal", + "anyOf": [ + { + "type": "null" + }, + { + "type": "string", + "enum": [ + "both", + "decimal", + "hexadecimal" + ], + "enumDescriptions": [ + "Render as 12 (0xC)", + "Render as 12", + "Render as 0xC" + ] + } + ] + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.memoryLayout.size": { + "markdownDescription": "How to render the size information in a memory layout hover.", + "default": "both", + "anyOf": [ + { + "type": "null" + }, + { + "type": "string", + "enum": [ + "both", + "decimal", + "hexadecimal" + ], + "enumDescriptions": [ + "Render as 12 (0xC)", + "Render as 12", + "Render as 0xC" + ] + } + ] + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.show.enumVariants": { + "markdownDescription": "How many variants of an enum to display when hovering on. Show none if empty.", + "default": 5, + "type": [ + "null", + "integer" + ], + "minimum": 0 + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.show.fields": { + "markdownDescription": "How many fields of a struct, variant or union to display when hovering on. Show none if empty.", + "default": 5, + "type": [ + "null", + "integer" + ], + "minimum": 0 + } + } + }, + { + "title": "hover", + "properties": { + "rust-analyzer.hover.show.traitAssocItems": { + "markdownDescription": "How many associated items of a trait to display when hovering a trait.", + "default": null, + "type": [ + "null", + "integer" + ], + "minimum": 0 + } + } + }, + { + "title": "imports", + "properties": { + "rust-analyzer.imports.granularity.enforce": { + "markdownDescription": "Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "imports", + "properties": { + "rust-analyzer.imports.granularity.group": { + "markdownDescription": "How imports should be grouped into use statements.", + "default": "crate", + "type": "string", + "enum": [ + "preserve", + "crate", + "module", + "item", + "one" + ], + "enumDescriptions": [ + "Do not change the granularity of any imports and preserve the original structure written by the developer.", + "Merge imports from the same crate into a single use statement. Conversely, imports from different crates are split into separate statements.", + "Merge imports from the same module into a single use statement. Conversely, imports from different modules are split into separate statements.", + "Flatten imports so that each has its own use statement.", + "Merge all imports into a single use statement as long as they have the same visibility and attributes." + ] + } + } + }, + { + "title": "imports", + "properties": { + "rust-analyzer.imports.group.enable": { + "markdownDescription": "Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "imports", + "properties": { + "rust-analyzer.imports.merge.glob": { + "markdownDescription": "Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "imports", + "properties": { + "rust-analyzer.imports.preferNoStd": { + "markdownDescription": "Prefer to unconditionally use imports of the core and alloc crate, over the std crate.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "imports", + "properties": { + "rust-analyzer.imports.preferPrelude": { + "markdownDescription": "Whether to prefer import paths containing a `prelude` module.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "imports", + "properties": { + "rust-analyzer.imports.prefix": { + "markdownDescription": "The path structure for newly inserted paths to use.", + "default": "plain", + "type": "string", + "enum": [ + "plain", + "self", + "crate" + ], + "enumDescriptions": [ + "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.", + "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item. Prefixes `self` in front of the path if it starts with a module.", + "Force import paths to be absolute by always starting them with `crate` or the extern crate name they come from." + ] + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.bindingModeHints.enable": { + "markdownDescription": "Whether to show inlay type hints for binding modes.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.chainingHints.enable": { + "markdownDescription": "Whether to show inlay type hints for method chains.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.closingBraceHints.enable": { + "markdownDescription": "Whether to show inlay hints after a closing `}` to indicate what item it belongs to.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.closingBraceHints.minLines": { + "markdownDescription": "Minimum number of lines required before the `}` until the hint is shown (set to 0 or 1\nto always show them).", + "default": 25, + "type": "integer", + "minimum": 0 + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.closureCaptureHints.enable": { + "markdownDescription": "Whether to show inlay hints for closure captures.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.closureReturnTypeHints.enable": { + "markdownDescription": "Whether to show inlay type hints for return types of closures.", + "default": "never", + "type": "string", + "enum": [ + "always", + "never", + "with_block" + ], + "enumDescriptions": [ + "Always show type hints for return types of closures.", + "Never show type hints for return types of closures.", + "Only show type hints for return types of closures with blocks." + ] + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.closureStyle": { + "markdownDescription": "Closure notation in type and chaining inlay hints.", + "default": "impl_fn", + "type": "string", + "enum": [ + "impl_fn", + "rust_analyzer", + "with_id", + "hide" + ], + "enumDescriptions": [ + "`impl_fn`: `impl FnMut(i32, u64) -> i8`", + "`rust_analyzer`: `|i32, u64| -> i8`", + "`with_id`: `{closure#14352}`, where that id is the unique number of the closure in r-a internals", + "`hide`: Shows `...` for every closure type" + ] + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.discriminantHints.enable": { + "markdownDescription": "Whether to show enum variant discriminant hints.", + "default": "never", + "type": "string", + "enum": [ + "always", + "never", + "fieldless" + ], + "enumDescriptions": [ + "Always show all discriminant hints.", + "Never show discriminant hints.", + "Only show discriminant hints on fieldless enum variants." + ] + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.expressionAdjustmentHints.enable": { + "markdownDescription": "Whether to show inlay hints for type adjustments.", + "default": "never", + "type": "string", + "enum": [ + "always", + "never", + "reborrow" + ], + "enumDescriptions": [ + "Always show all adjustment hints.", + "Never show adjustment hints.", + "Only show auto borrow and dereference adjustment hints." + ] + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.expressionAdjustmentHints.hideOutsideUnsafe": { + "markdownDescription": "Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.expressionAdjustmentHints.mode": { + "markdownDescription": "Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).", + "default": "prefix", + "type": "string", + "enum": [ + "prefix", + "postfix", + "prefer_prefix", + "prefer_postfix" + ], + "enumDescriptions": [ + "Always show adjustment hints as prefix (`*expr`).", + "Always show adjustment hints as postfix (`expr.*`).", + "Show prefix or postfix depending on which uses less parenthesis, preferring prefix.", + "Show prefix or postfix depending on which uses less parenthesis, preferring postfix." + ] + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.implicitDrops.enable": { + "markdownDescription": "Whether to show implicit drop hints.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.lifetimeElisionHints.enable": { + "markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.", + "default": "never", + "type": "string", + "enum": [ + "always", + "never", + "skip_trivial" + ], + "enumDescriptions": [ + "Always show lifetime elision hints.", + "Never show lifetime elision hints.", + "Only show lifetime elision hints if a return type is involved." + ] + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.lifetimeElisionHints.useParameterNames": { + "markdownDescription": "Whether to prefer using parameter names as the name for elided lifetime hints if possible.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.maxLength": { + "markdownDescription": "Maximum length for inlay hints. Set to null to have an unlimited length.", + "default": 25, + "type": [ + "null", + "integer" + ], + "minimum": 0 + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.parameterHints.enable": { + "markdownDescription": "Whether to show function parameter name inlay hints at the call\nsite.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.rangeExclusiveHints.enable": { + "markdownDescription": "Whether to show exclusive range inlay hints.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.reborrowHints.enable": { + "markdownDescription": "Whether to show inlay hints for compiler inserted reborrows.\nThis setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#.", + "default": "never", + "type": "string", + "enum": [ + "always", + "never", + "mutable" + ], + "enumDescriptions": [ + "Always show reborrow hints.", + "Never show reborrow hints.", + "Only show mutable reborrow hints." + ] + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.renderColons": { + "markdownDescription": "Whether to render leading colons for type hints, and trailing colons for parameter hints.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.typeHints.enable": { + "markdownDescription": "Whether to show inlay type hints for variables.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.typeHints.hideClosureInitialization": { + "markdownDescription": "Whether to hide inlay type hints for `let` statements that initialize to a closure.\nOnly applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { + "rust-analyzer.inlayHints.typeHints.hideNamedConstructor": { + "markdownDescription": "Whether to hide inlay type hints for constructors.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "interpret", + "properties": { + "rust-analyzer.interpret.tests": { + "markdownDescription": "Enables the experimental support for interpreting tests.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "joinLines", + "properties": { + "rust-analyzer.joinLines.joinAssignments": { + "markdownDescription": "Join lines merges consecutive declaration and initialization of an assignment.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "joinLines", + "properties": { + "rust-analyzer.joinLines.joinElseIf": { + "markdownDescription": "Join lines inserts else between consecutive ifs.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "joinLines", + "properties": { + "rust-analyzer.joinLines.removeTrailingComma": { + "markdownDescription": "Join lines removes trailing commas.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "joinLines", + "properties": { + "rust-analyzer.joinLines.unwrapTrivialBlock": { + "markdownDescription": "Join lines unwraps trivial blocks.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.debug.enable": { + "markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.enable": { + "markdownDescription": "Whether to show CodeLens in Rust files.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.forceCustomCommands": { + "markdownDescription": "Internal config: use custom client-side commands even when the\nclient doesn't set the corresponding capability.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.implementations.enable": { + "markdownDescription": "Whether to show `Implementations` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.location": { + "markdownDescription": "Where to render annotations.", + "default": "above_name", + "type": "string", + "enum": [ + "above_name", + "above_whole_item" + ], + "enumDescriptions": [ + "Render annotations above the name of the item.", + "Render annotations above the whole item, including documentation comments and attributes." + ] + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.references.adt.enable": { + "markdownDescription": "Whether to show `References` lens for Struct, Enum, and Union.\nOnly applies when `#rust-analyzer.lens.enable#` is set.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.references.enumVariant.enable": { + "markdownDescription": "Whether to show `References` lens for Enum Variants.\nOnly applies when `#rust-analyzer.lens.enable#` is set.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.references.method.enable": { + "markdownDescription": "Whether to show `Method References` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.references.trait.enable": { + "markdownDescription": "Whether to show `References` lens for Trait.\nOnly applies when `#rust-analyzer.lens.enable#` is set.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "lens", + "properties": { + "rust-analyzer.lens.run.enable": { + "markdownDescription": "Whether to show `Run` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "general", + "properties": { + "rust-analyzer.linkedProjects": { + "markdownDescription": "Disable project auto-discovery in favor of explicitly specified set\nof projects.\n\nElements must be paths pointing to `Cargo.toml`,\n`rust-project.json`, `.rs` files (which will be treated as standalone files) or JSON\nobjects in `rust-project.json` format.", + "default": [], + "type": "array", + "items": { + "type": [ + "string", + "object" ] } - ] - }, - "rust-analyzer.hover.memoryLayout.enable": { - "markdownDescription": "Whether to show memory layout data on hover.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.hover.memoryLayout.niches": { - "markdownDescription": "How to render the niche information in a memory layout hover.", - "default": false, - "type": [ - "null", - "boolean" - ] - }, - "rust-analyzer.hover.memoryLayout.offset": { - "markdownDescription": "How to render the offset information in a memory layout hover.", - "default": "hexadecimal", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string", - "enum": [ - "both", - "decimal", - "hexadecimal" - ], - "enumDescriptions": [ - "Render as 12 (0xC)", - "Render as 12", - "Render as 0xC" - ] + } + } + }, + { + "title": "lru", + "properties": { + "rust-analyzer.lru.capacity": { + "markdownDescription": "Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.", + "default": null, + "type": [ + "null", + "integer" + ], + "minimum": 0 + } + } + }, + { + "title": "lru", + "properties": { + "rust-analyzer.lru.query.capacities": { + "markdownDescription": "Sets the LRU capacity of the specified queries.", + "default": {}, + "type": "object" + } + } + }, + { + "title": "notifications", + "properties": { + "rust-analyzer.notifications.cargoTomlNotFound": { + "markdownDescription": "Whether to show `can't find Cargo.toml` error message.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "notifications", + "properties": { + "rust-analyzer.notifications.unindexedProject": { + "markdownDescription": "Whether to send an UnindexedProject notification to the client.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "general", + "properties": { + "rust-analyzer.numThreads": { + "markdownDescription": "How many worker threads in the main loop. The default `null` means to pick automatically.", + "default": null, + "anyOf": [ + { + "type": "null" + }, + { + "type": "number", + "minimum": 0, + "maximum": 255 + }, + { + "type": "string", + "enum": [ + "physical", + "logical" + ], + "enumDescriptions": [ + "Use the number of physical cores", + "Use the number of logical cores" + ] + } + ] + } + } + }, + { + "title": "procMacro", + "properties": { + "rust-analyzer.procMacro.attributes.enable": { + "markdownDescription": "Expand attribute macros. Requires `#rust-analyzer.procMacro.enable#` to be set.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "procMacro", + "properties": { + "rust-analyzer.procMacro.enable": { + "markdownDescription": "Enable support for procedural macros, implies `#rust-analyzer.cargo.buildScripts.enable#`.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "procMacro", + "properties": { + "rust-analyzer.procMacro.ignored": { + "markdownDescription": "These proc-macros will be ignored when trying to expand them.\n\nThis config takes a map of crate names with the exported proc-macro names to ignore as values.", + "default": {}, + "type": "object" + } + } + }, + { + "title": "procMacro", + "properties": { + "rust-analyzer.procMacro.server": { + "markdownDescription": "Internal config, path to proc-macro server executable.", + "default": null, + "type": [ + "null", + "string" + ] + } + } + }, + { + "title": "references", + "properties": { + "rust-analyzer.references.excludeImports": { + "markdownDescription": "Exclude imports from find-all-references.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "references", + "properties": { + "rust-analyzer.references.excludeTests": { + "markdownDescription": "Exclude tests from find-all-references.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "runnables", + "properties": { + "rust-analyzer.runnables.command": { + "markdownDescription": "Command to be executed instead of 'cargo' for runnables.", + "default": null, + "type": [ + "null", + "string" + ] + } + } + }, + { + "title": "runnables", + "properties": { + "rust-analyzer.runnables.extraArgs": { + "markdownDescription": "Additional arguments to be passed to cargo for runnables such as\ntests or binaries. For example, it may be `--release`.", + "default": [], + "type": "array", + "items": { + "type": "string" } - ] - }, - "rust-analyzer.hover.memoryLayout.size": { - "markdownDescription": "How to render the size information in a memory layout hover.", - "default": "both", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string", - "enum": [ - "both", - "decimal", - "hexadecimal" - ], - "enumDescriptions": [ - "Render as 12 (0xC)", - "Render as 12", - "Render as 0xC" - ] + } + } + }, + { + "title": "runnables", + "properties": { + "rust-analyzer.runnables.extraTestBinaryArgs": { + "markdownDescription": "Additional arguments to be passed through Cargo to launched tests, benchmarks, or\ndoc-tests.\n\nUnless the launched target uses a\n[custom test harness](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-harness-field),\nthey will end up being interpreted as options to\n[`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments).", + "default": [ + "--show-output" + ], + "type": "array", + "items": { + "type": "string" } - ] - }, - "rust-analyzer.hover.show.enumVariants": { - "markdownDescription": "How many variants of an enum to display when hovering on. Show none if empty.", - "default": 5, - "type": [ - "null", - "integer" - ], - "minimum": 0 - }, - "rust-analyzer.hover.show.fields": { - "markdownDescription": "How many fields of a struct, variant or union to display when hovering on. Show none if empty.", - "default": 5, - "type": [ - "null", - "integer" - ], - "minimum": 0 - }, - "rust-analyzer.hover.show.traitAssocItems": { - "markdownDescription": "How many associated items of a trait to display when hovering a trait.", - "default": null, - "type": [ - "null", - "integer" - ], - "minimum": 0 - }, - "rust-analyzer.imports.granularity.enforce": { - "markdownDescription": "Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.imports.granularity.group": { - "markdownDescription": "How imports should be grouped into use statements.", - "default": "crate", - "type": "string", - "enum": [ - "preserve", - "crate", - "module", - "item", - "one" - ], - "enumDescriptions": [ - "Do not change the granularity of any imports and preserve the original structure written by the developer.", - "Merge imports from the same crate into a single use statement. Conversely, imports from different crates are split into separate statements.", - "Merge imports from the same module into a single use statement. Conversely, imports from different modules are split into separate statements.", - "Flatten imports so that each has its own use statement.", - "Merge all imports into a single use statement as long as they have the same visibility and attributes." - ] - }, - "rust-analyzer.imports.group.enable": { - "markdownDescription": "Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.imports.merge.glob": { - "markdownDescription": "Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.imports.preferNoStd": { - "markdownDescription": "Prefer to unconditionally use imports of the core and alloc crate, over the std crate.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.imports.preferPrelude": { - "markdownDescription": "Whether to prefer import paths containing a `prelude` module.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.imports.prefix": { - "markdownDescription": "The path structure for newly inserted paths to use.", - "default": "plain", - "type": "string", - "enum": [ - "plain", - "self", - "crate" - ], - "enumDescriptions": [ - "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.", - "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item. Prefixes `self` in front of the path if it starts with a module.", - "Force import paths to be absolute by always starting them with `crate` or the extern crate name they come from." - ] - }, - "rust-analyzer.inlayHints.bindingModeHints.enable": { - "markdownDescription": "Whether to show inlay type hints for binding modes.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.inlayHints.chainingHints.enable": { - "markdownDescription": "Whether to show inlay type hints for method chains.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.inlayHints.closingBraceHints.enable": { - "markdownDescription": "Whether to show inlay hints after a closing `}` to indicate what item it belongs to.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.inlayHints.closingBraceHints.minLines": { - "markdownDescription": "Minimum number of lines required before the `}` until the hint is shown (set to 0 or 1\nto always show them).", - "default": 25, - "type": "integer", - "minimum": 0 - }, - "rust-analyzer.inlayHints.closureCaptureHints.enable": { - "markdownDescription": "Whether to show inlay hints for closure captures.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.inlayHints.closureReturnTypeHints.enable": { - "markdownDescription": "Whether to show inlay type hints for return types of closures.", - "default": "never", - "type": "string", - "enum": [ - "always", - "never", - "with_block" - ], - "enumDescriptions": [ - "Always show type hints for return types of closures.", - "Never show type hints for return types of closures.", - "Only show type hints for return types of closures with blocks." - ] - }, - "rust-analyzer.inlayHints.closureStyle": { - "markdownDescription": "Closure notation in type and chaining inlay hints.", - "default": "impl_fn", - "type": "string", - "enum": [ - "impl_fn", - "rust_analyzer", - "with_id", - "hide" - ], - "enumDescriptions": [ - "`impl_fn`: `impl FnMut(i32, u64) -> i8`", - "`rust_analyzer`: `|i32, u64| -> i8`", - "`with_id`: `{closure#14352}`, where that id is the unique number of the closure in r-a internals", - "`hide`: Shows `...` for every closure type" - ] - }, - "rust-analyzer.inlayHints.discriminantHints.enable": { - "markdownDescription": "Whether to show enum variant discriminant hints.", - "default": "never", - "type": "string", - "enum": [ - "always", - "never", - "fieldless" - ], - "enumDescriptions": [ - "Always show all discriminant hints.", - "Never show discriminant hints.", - "Only show discriminant hints on fieldless enum variants." - ] - }, - "rust-analyzer.inlayHints.expressionAdjustmentHints.enable": { - "markdownDescription": "Whether to show inlay hints for type adjustments.", - "default": "never", - "type": "string", - "enum": [ - "always", - "never", - "reborrow" - ], - "enumDescriptions": [ - "Always show all adjustment hints.", - "Never show adjustment hints.", - "Only show auto borrow and dereference adjustment hints." - ] - }, - "rust-analyzer.inlayHints.expressionAdjustmentHints.hideOutsideUnsafe": { - "markdownDescription": "Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.inlayHints.expressionAdjustmentHints.mode": { - "markdownDescription": "Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).", - "default": "prefix", - "type": "string", - "enum": [ - "prefix", - "postfix", - "prefer_prefix", - "prefer_postfix" - ], - "enumDescriptions": [ - "Always show adjustment hints as prefix (`*expr`).", - "Always show adjustment hints as postfix (`expr.*`).", - "Show prefix or postfix depending on which uses less parenthesis, preferring prefix.", - "Show prefix or postfix depending on which uses less parenthesis, preferring postfix." - ] - }, - "rust-analyzer.inlayHints.implicitDrops.enable": { - "markdownDescription": "Whether to show implicit drop hints.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.inlayHints.lifetimeElisionHints.enable": { - "markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.", - "default": "never", - "type": "string", - "enum": [ - "always", - "never", - "skip_trivial" - ], - "enumDescriptions": [ - "Always show lifetime elision hints.", - "Never show lifetime elision hints.", - "Only show lifetime elision hints if a return type is involved." - ] - }, - "rust-analyzer.inlayHints.lifetimeElisionHints.useParameterNames": { - "markdownDescription": "Whether to prefer using parameter names as the name for elided lifetime hints if possible.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.inlayHints.maxLength": { - "markdownDescription": "Maximum length for inlay hints. Set to null to have an unlimited length.", - "default": 25, - "type": [ - "null", - "integer" - ], - "minimum": 0 - }, - "rust-analyzer.inlayHints.parameterHints.enable": { - "markdownDescription": "Whether to show function parameter name inlay hints at the call\nsite.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.inlayHints.rangeExclusiveHints.enable": { - "markdownDescription": "Whether to show exclusive range inlay hints.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.inlayHints.reborrowHints.enable": { - "markdownDescription": "Whether to show inlay hints for compiler inserted reborrows.\nThis setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#.", - "default": "never", - "type": "string", - "enum": [ - "always", - "never", - "mutable" - ], - "enumDescriptions": [ - "Always show reborrow hints.", - "Never show reborrow hints.", - "Only show mutable reborrow hints." - ] - }, - "rust-analyzer.inlayHints.renderColons": { - "markdownDescription": "Whether to render leading colons for type hints, and trailing colons for parameter hints.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.inlayHints.typeHints.enable": { - "markdownDescription": "Whether to show inlay type hints for variables.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.inlayHints.typeHints.hideClosureInitialization": { - "markdownDescription": "Whether to hide inlay type hints for `let` statements that initialize to a closure.\nOnly applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.inlayHints.typeHints.hideNamedConstructor": { - "markdownDescription": "Whether to hide inlay type hints for constructors.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.interpret.tests": { - "markdownDescription": "Enables the experimental support for interpreting tests.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.joinLines.joinAssignments": { - "markdownDescription": "Join lines merges consecutive declaration and initialization of an assignment.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.joinLines.joinElseIf": { - "markdownDescription": "Join lines inserts else between consecutive ifs.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.joinLines.removeTrailingComma": { - "markdownDescription": "Join lines removes trailing commas.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.joinLines.unwrapTrivialBlock": { - "markdownDescription": "Join lines unwraps trivial blocks.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.lens.debug.enable": { - "markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#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.forceCustomCommands": { - "markdownDescription": "Internal config: use custom client-side commands even when the\nclient doesn't set the corresponding capability.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.lens.implementations.enable": { - "markdownDescription": "Whether to show `Implementations` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.lens.location": { - "markdownDescription": "Where to render annotations.", - "default": "above_name", - "type": "string", - "enum": [ - "above_name", - "above_whole_item" - ], - "enumDescriptions": [ - "Render annotations above the name of the item.", - "Render annotations above the whole item, including documentation comments and attributes." - ] - }, - "rust-analyzer.lens.references.adt.enable": { - "markdownDescription": "Whether to show `References` lens for Struct, Enum, and Union.\nOnly applies when `#rust-analyzer.lens.enable#` is set.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.lens.references.enumVariant.enable": { - "markdownDescription": "Whether to show `References` lens for Enum Variants.\nOnly applies when `#rust-analyzer.lens.enable#` is set.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.lens.references.method.enable": { - "markdownDescription": "Whether to show `Method References` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.lens.references.trait.enable": { - "markdownDescription": "Whether to show `References` lens for Trait.\nOnly applies when `#rust-analyzer.lens.enable#` is set.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.lens.run.enable": { - "markdownDescription": "Whether to show `Run` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.linkedProjects": { - "markdownDescription": "Disable project auto-discovery in favor of explicitly specified set\nof projects.\n\nElements must be paths pointing to `Cargo.toml`,\n`rust-project.json`, `.rs` files (which will be treated as standalone files) or JSON\nobjects in `rust-project.json` format.", - "default": [], - "type": "array", - "items": { + } + } + }, + { + "title": "rustc", + "properties": { + "rust-analyzer.rustc.source": { + "markdownDescription": "Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private\nprojects, or \"discover\" to try to automatically find it if the `rustc-dev` component\nis installed.\n\nAny project which uses rust-analyzer with the rustcPrivate\ncrates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.\n\nThis option does not take effect until rust-analyzer is restarted.", + "default": null, "type": [ - "string", - "object" + "null", + "string" ] } - }, - "rust-analyzer.lru.capacity": { - "markdownDescription": "Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.", - "default": null, - "type": [ - "null", - "integer" - ], - "minimum": 0 - }, - "rust-analyzer.lru.query.capacities": { - "markdownDescription": "Sets the LRU capacity of the specified queries.", - "default": {}, - "type": "object" - }, - "rust-analyzer.notifications.cargoTomlNotFound": { - "markdownDescription": "Whether to show `can't find Cargo.toml` error message.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.notifications.unindexedProject": { - "markdownDescription": "Whether to send an UnindexedProject notification to the client.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.numThreads": { - "markdownDescription": "How many worker threads in the main loop. The default `null` means to pick automatically.", - "default": null, - "type": [ - "null", - "integer" - ], - "minimum": 0 - }, - "rust-analyzer.procMacro.attributes.enable": { - "markdownDescription": "Expand attribute macros. Requires `#rust-analyzer.procMacro.enable#` to be set.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.procMacro.enable": { - "markdownDescription": "Enable support for procedural macros, implies `#rust-analyzer.cargo.buildScripts.enable#`.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.procMacro.ignored": { - "markdownDescription": "These proc-macros will be ignored when trying to expand them.\n\nThis config takes a map of crate names with the exported proc-macro names to ignore as values.", - "default": {}, - "type": "object" - }, - "rust-analyzer.procMacro.server": { - "markdownDescription": "Internal config, path to proc-macro server executable.", - "default": null, - "type": [ - "null", - "string" - ] - }, - "rust-analyzer.references.excludeImports": { - "markdownDescription": "Exclude imports from find-all-references.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.references.excludeTests": { - "markdownDescription": "Exclude tests from find-all-references.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.runnables.command": { - "markdownDescription": "Command to be executed instead of 'cargo' for runnables.", - "default": null, - "type": [ - "null", - "string" - ] - }, - "rust-analyzer.runnables.extraArgs": { - "markdownDescription": "Additional arguments to be passed to cargo for runnables such as\ntests or binaries. For example, it may be `--release`.", - "default": [], - "type": "array", - "items": { - "type": "string" + } + }, + { + "title": "rustfmt", + "properties": { + "rust-analyzer.rustfmt.extraArgs": { + "markdownDescription": "Additional arguments to `rustfmt`.", + "default": [], + "type": "array", + "items": { + "type": "string" + } } - }, - "rust-analyzer.runnables.extraTestBinaryArgs": { - "markdownDescription": "Additional arguments to be passed through Cargo to launched tests, benchmarks, or\ndoc-tests.\n\nUnless the launched target uses a\n[custom test harness](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-harness-field),\nthey will end up being interpreted as options to\n[`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments).", - "default": [ - "--show-output" - ], - "type": "array", - "items": { - "type": "string" + } + }, + { + "title": "rustfmt", + "properties": { + "rust-analyzer.rustfmt.overrideCommand": { + "markdownDescription": "Advanced option, fully override the command rust-analyzer uses for\nformatting. This should be the equivalent of `rustfmt` here, and\nnot that of `cargo fmt`. The file contents will be passed on the\nstandard input and the formatted result will be read from the\nstandard output.", + "default": null, + "type": [ + "null", + "array" + ], + "items": { + "type": "string" + } } - }, - "rust-analyzer.rustc.source": { - "markdownDescription": "Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private\nprojects, or \"discover\" to try to automatically find it if the `rustc-dev` component\nis installed.\n\nAny project which uses rust-analyzer with the rustcPrivate\ncrates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.\n\nThis option does not take effect until rust-analyzer is restarted.", - "default": null, - "type": [ - "null", - "string" - ] - }, - "rust-analyzer.rustfmt.extraArgs": { - "markdownDescription": "Additional arguments to `rustfmt`.", - "default": [], - "type": "array", - "items": { - "type": "string" + } + }, + { + "title": "rustfmt", + "properties": { + "rust-analyzer.rustfmt.rangeFormatting.enable": { + "markdownDescription": "Enables the use of rustfmt's unstable range formatting command for the\n`textDocument/rangeFormatting` request. The rustfmt option is unstable and only\navailable on a nightly build.", + "default": false, + "type": "boolean" } - }, - "rust-analyzer.rustfmt.overrideCommand": { - "markdownDescription": "Advanced option, fully override the command rust-analyzer uses for\nformatting. This should be the equivalent of `rustfmt` here, and\nnot that of `cargo fmt`. The file contents will be passed on the\nstandard input and the formatted result will be read from the\nstandard output.", - "default": null, - "type": [ - "null", - "array" - ], - "items": { - "type": "string" + } + }, + { + "title": "semanticHighlighting", + "properties": { + "rust-analyzer.semanticHighlighting.doc.comment.inject.enable": { + "markdownDescription": "Inject additional highlighting into doc comments.\n\nWhen enabled, rust-analyzer will highlight rust source in doc comments as well as intra\ndoc links.", + "default": true, + "type": "boolean" } - }, - "rust-analyzer.rustfmt.rangeFormatting.enable": { - "markdownDescription": "Enables the use of rustfmt's unstable range formatting command for the\n`textDocument/rangeFormatting` request. The rustfmt option is unstable and only\navailable on a nightly build.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.semanticHighlighting.doc.comment.inject.enable": { - "markdownDescription": "Inject additional highlighting into doc comments.\n\nWhen enabled, rust-analyzer will highlight rust source in doc comments as well as intra\ndoc links.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.semanticHighlighting.nonStandardTokens": { - "markdownDescription": "Whether the server is allowed to emit non-standard tokens and modifiers.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.semanticHighlighting.operator.enable": { - "markdownDescription": "Use semantic tokens for operators.\n\nWhen disabled, rust-analyzer will emit semantic tokens only for operator tokens when\nthey are tagged with modifiers.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.semanticHighlighting.operator.specialization.enable": { - "markdownDescription": "Use specialized semantic tokens for operators.\n\nWhen enabled, rust-analyzer will emit special token types for operator tokens instead\nof the generic `operator` token type.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.semanticHighlighting.punctuation.enable": { - "markdownDescription": "Use semantic tokens for punctuation.\n\nWhen disabled, rust-analyzer will emit semantic tokens only for punctuation tokens when\nthey are tagged with modifiers or have a special role.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.semanticHighlighting.punctuation.separate.macro.bang": { - "markdownDescription": "When enabled, rust-analyzer will emit a punctuation semantic token for the `!` of macro\ncalls.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.semanticHighlighting.punctuation.specialization.enable": { - "markdownDescription": "Use specialized semantic tokens for punctuation.\n\nWhen enabled, rust-analyzer will emit special token types for punctuation tokens instead\nof the generic `punctuation` token type.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.semanticHighlighting.strings.enable": { - "markdownDescription": "Use semantic tokens for strings.\n\nIn some editors (e.g. vscode) semantic tokens override other highlighting grammars.\nBy disabling semantic tokens for strings, other grammars can be used to highlight\ntheir contents.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.signatureInfo.detail": { - "markdownDescription": "Show full signature of the callable. Only shows parameters if disabled.", - "default": "full", - "type": "string", - "enum": [ - "full", - "parameters" - ], - "enumDescriptions": [ - "Show the entire signature.", - "Show only the parameters." - ] - }, - "rust-analyzer.signatureInfo.documentation.enable": { - "markdownDescription": "Show documentation.", - "default": true, - "type": "boolean" - }, - "rust-analyzer.typing.autoClosingAngleBrackets.enable": { - "markdownDescription": "Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.", - "default": false, - "type": "boolean" - }, - "rust-analyzer.workspace.symbol.search.kind": { - "markdownDescription": "Workspace symbol search kind.", - "default": "only_types", - "type": "string", - "enum": [ - "only_types", - "all_symbols" - ], - "enumDescriptions": [ - "Search for types only.", - "Search for all symbols kinds." - ] - }, - "rust-analyzer.workspace.symbol.search.limit": { - "markdownDescription": "Limits the number of items returned from a workspace symbol search (Defaults to 128).\nSome clients like vs-code issue new searches on result filtering and don't require all results to be returned in the initial search.\nOther clients requires all results upfront and might require a higher limit.", - "default": 128, - "type": "integer", - "minimum": 0 - }, - "rust-analyzer.workspace.symbol.search.scope": { - "markdownDescription": "Workspace symbol search scope.", - "default": "workspace", - "type": "string", - "enum": [ - "workspace", - "workspace_and_dependencies" - ], - "enumDescriptions": [ - "Search in current workspace only.", - "Search in current workspace and dependencies." - ] - }, - "$generated-end": {} + } + }, + { + "title": "semanticHighlighting", + "properties": { + "rust-analyzer.semanticHighlighting.nonStandardTokens": { + "markdownDescription": "Whether the server is allowed to emit non-standard tokens and modifiers.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "semanticHighlighting", + "properties": { + "rust-analyzer.semanticHighlighting.operator.enable": { + "markdownDescription": "Use semantic tokens for operators.\n\nWhen disabled, rust-analyzer will emit semantic tokens only for operator tokens when\nthey are tagged with modifiers.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "semanticHighlighting", + "properties": { + "rust-analyzer.semanticHighlighting.operator.specialization.enable": { + "markdownDescription": "Use specialized semantic tokens for operators.\n\nWhen enabled, rust-analyzer will emit special token types for operator tokens instead\nof the generic `operator` token type.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "semanticHighlighting", + "properties": { + "rust-analyzer.semanticHighlighting.punctuation.enable": { + "markdownDescription": "Use semantic tokens for punctuation.\n\nWhen disabled, rust-analyzer will emit semantic tokens only for punctuation tokens when\nthey are tagged with modifiers or have a special role.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "semanticHighlighting", + "properties": { + "rust-analyzer.semanticHighlighting.punctuation.separate.macro.bang": { + "markdownDescription": "When enabled, rust-analyzer will emit a punctuation semantic token for the `!` of macro\ncalls.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "semanticHighlighting", + "properties": { + "rust-analyzer.semanticHighlighting.punctuation.specialization.enable": { + "markdownDescription": "Use specialized semantic tokens for punctuation.\n\nWhen enabled, rust-analyzer will emit special token types for punctuation tokens instead\nof the generic `punctuation` token type.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "semanticHighlighting", + "properties": { + "rust-analyzer.semanticHighlighting.strings.enable": { + "markdownDescription": "Use semantic tokens for strings.\n\nIn some editors (e.g. vscode) semantic tokens override other highlighting grammars.\nBy disabling semantic tokens for strings, other grammars can be used to highlight\ntheir contents.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "signatureInfo", + "properties": { + "rust-analyzer.signatureInfo.detail": { + "markdownDescription": "Show full signature of the callable. Only shows parameters if disabled.", + "default": "full", + "type": "string", + "enum": [ + "full", + "parameters" + ], + "enumDescriptions": [ + "Show the entire signature.", + "Show only the parameters." + ] + } + } + }, + { + "title": "signatureInfo", + "properties": { + "rust-analyzer.signatureInfo.documentation.enable": { + "markdownDescription": "Show documentation.", + "default": true, + "type": "boolean" + } + } + }, + { + "title": "typing", + "properties": { + "rust-analyzer.typing.autoClosingAngleBrackets.enable": { + "markdownDescription": "Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "workspace", + "properties": { + "rust-analyzer.workspace.symbol.search.kind": { + "markdownDescription": "Workspace symbol search kind.", + "default": "only_types", + "type": "string", + "enum": [ + "only_types", + "all_symbols" + ], + "enumDescriptions": [ + "Search for types only.", + "Search for all symbols kinds." + ] + } + } + }, + { + "title": "workspace", + "properties": { + "rust-analyzer.workspace.symbol.search.limit": { + "markdownDescription": "Limits the number of items returned from a workspace symbol search (Defaults to 128).\nSome clients like vs-code issue new searches on result filtering and don't require all results to be returned in the initial search.\nOther clients requires all results upfront and might require a higher limit.", + "default": 128, + "type": "integer", + "minimum": 0 + } + } + }, + { + "title": "workspace", + "properties": { + "rust-analyzer.workspace.symbol.search.scope": { + "markdownDescription": "Workspace symbol search scope.", + "default": "workspace", + "type": "string", + "enum": [ + "workspace", + "workspace_and_dependencies" + ], + "enumDescriptions": [ + "Search in current workspace only.", + "Search in current workspace and dependencies." + ] + } + } + }, + { + "title": "$generated-end" } - }, + ], "configurationDefaults": { "explorer.fileNesting.patterns": { "Cargo.toml": "Cargo.lock" @@ -2282,6 +3128,10 @@ { "command": "rust-analyzer.viewMemoryLayout", "when": "inRustProject" + }, + { + "command": "rust-analyzer.toggleLSPLogs", + "when": "inRustProject" } ], "editor/context": [ diff --git a/src/tools/rust-analyzer/editors/code/src/ast_inspector.ts b/src/tools/rust-analyzer/editors/code/src/ast_inspector.ts index 688c53a9b1f..35b705c477e 100644 --- a/src/tools/rust-analyzer/editors/code/src/ast_inspector.ts +++ b/src/tools/rust-analyzer/editors/code/src/ast_inspector.ts @@ -1,8 +1,7 @@ import * as vscode from "vscode"; import type { Ctx, Disposable } from "./ctx"; -import { type RustEditor, isRustEditor } from "./util"; -import { unwrapUndefinable } from "./undefinable"; +import { type RustEditor, isRustEditor, unwrapUndefinable } from "./util"; // FIXME: consider implementing this via the Tree View API? // https://code.visualstudio.com/api/extension-guides/tree-view diff --git a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts index 6cf399599d9..5a92b285ae6 100644 --- a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts +++ b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts @@ -1,9 +1,9 @@ import * as vscode from "vscode"; import * as os from "os"; import type { Config } from "./config"; -import { log, isValidExecutable } from "./util"; +import { type Env, log } from "./util"; import type { PersistentState } from "./persistent_state"; -import { exec } from "child_process"; +import { exec, spawnSync } from "child_process"; export async function bootstrap( context: vscode.ExtensionContext, @@ -13,7 +13,7 @@ export async function bootstrap( const path = await getServer(context, config, state); if (!path) { throw new Error( - "Rust Analyzer Language Server is not available. " + + "rust-analyzer Language Server is not available. " + "Please, ensure its [proper installation](https://rust-analyzer.github.io/manual.html#installation).", ); } @@ -21,12 +21,12 @@ export async function bootstrap( log.info("Using server binary at", path); if (!isValidExecutable(path, config.serverExtraEnv)) { - if (config.serverPath) { - throw new Error(`Failed to execute ${path} --version. \`config.server.path\` or \`config.serverPath\` has been set explicitly.\ - Consider removing this config or making a valid server binary available at that path.`); - } else { - throw new Error(`Failed to execute ${path} --version`); - } + throw new Error( + `Failed to execute ${path} --version.` + config.serverPath + ? `\`config.server.path\` or \`config.serverPath\` has been set explicitly.\ + Consider removing this config or making a valid server binary available at that path.` + : "", + ); } return path; @@ -54,27 +54,12 @@ async function getServer( if (bundledExists) { let server = bundled; if (await isNixOs()) { - await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); - const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer${ext}`); - let exists = await vscode.workspace.fs.stat(dest).then( - () => true, - () => false, - ); - if (exists && config.package.version !== state.serverVersion) { - await vscode.workspace.fs.delete(dest); - exists = false; - } - if (!exists) { - await vscode.workspace.fs.copy(bundled, dest); - await patchelf(dest); - } - server = dest; + server = await getNixOsServer(config, ext, state, bundled, server); + await state.updateServerVersion(config.package.version); } - await state.updateServerVersion(config.package.version); return server.fsPath; } - await state.updateServerVersion(undefined); await vscode.window.showErrorMessage( "Unfortunately we don't ship binaries for your platform yet. " + "You need to manually clone the rust-analyzer repository and " + @@ -86,6 +71,45 @@ async function getServer( return undefined; } +export function isValidExecutable(path: string, extraEnv: Env): boolean { + log.debug("Checking availability of a binary at", path); + + const res = spawnSync(path, ["--version"], { + encoding: "utf8", + env: { ...process.env, ...extraEnv }, + }); + + const printOutput = res.error ? log.warn : log.info; + printOutput(path, "--version:", res); + + return res.status === 0; +} + +async function getNixOsServer( + config: Config, + ext: string, + state: PersistentState, + bundled: vscode.Uri, + server: vscode.Uri, +) { + await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); + const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer${ext}`); + let exists = await vscode.workspace.fs.stat(dest).then( + () => true, + () => false, + ); + if (exists && config.package.version !== state.serverVersion) { + await vscode.workspace.fs.delete(dest); + exists = false; + } + if (!exists) { + await vscode.workspace.fs.copy(bundled, dest); + await patchelf(dest); + } + server = dest; + return server; +} + async function isNixOs(): Promise<boolean> { try { const contents = ( diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts index 372dc8bedfd..1c2a34b484d 100644 --- a/src/tools/rust-analyzer/editors/code/src/client.ts +++ b/src/tools/rust-analyzer/editors/code/src/client.ts @@ -3,73 +3,13 @@ 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 { assert, unwrapUndefinable } from "./util"; import * as diagnostics from "./diagnostics"; import { WorkspaceEdit } from "vscode"; import { type Config, prepareVSCodeConfig } from "./config"; -import { randomUUID } from "crypto"; import { sep as pathSeparator } from "path"; -import { unwrapUndefinable } from "./undefinable"; import { RaLanguageClient } from "./lang_client"; -export interface Env { - [name: string]: string; -} - -// Command URIs have a form of command:command-name?arguments, where -// arguments is a percent-encoded array of data we want to pass along to -// the command function. For "Show References" this is a list of all file -// URIs with locations of every reference, and it can get quite long. -// -// To work around it we use an intermediary linkToCommand command. When -// we render a command link, a reference to a command with all its arguments -// is stored in a map, and instead a linkToCommand link is rendered -// with the key to that map. -export const LINKED_COMMANDS = new Map<string, ra.CommandLink>(); - -// For now the map is cleaned up periodically (I've set it to every -// 10 minutes). In general case we'll probably need to introduce TTLs or -// flags to denote ephemeral links (like these in hover popups) and -// persistent links and clean those separately. But for now simply keeping -// the last few links in the map should be good enough. Likewise, we could -// add code to remove a target command from the map after the link is -// clicked, but assuming most links in hover sheets won't be clicked anyway -// this code won't change the overall memory use much. -setInterval( - function cleanupOlderCommandLinks() { - // keys are returned in insertion order, we'll keep a few - // of recent keys available, and clean the rest - const keys = [...LINKED_COMMANDS.keys()]; - const keysToRemove = keys.slice(0, keys.length - 10); - for (const key of keysToRemove) { - LINKED_COMMANDS.delete(key); - } - }, - 10 * 60 * 1000, -); - -function renderCommand(cmd: ra.CommandLink): string { - const commandId = randomUUID(); - LINKED_COMMANDS.set(commandId, cmd); - return `[${cmd.title}](command:rust-analyzer.linkToCommand?${encodeURIComponent( - JSON.stringify([commandId]), - )} '${cmd.tooltip}')`; -} - -function renderHoverActions(actions: ra.CommandLinkGroup[]): vscode.MarkdownString { - const text = actions - .map( - (group) => - (group.title ? group.title + " " : "") + - group.commands.map(renderCommand).join(" | "), - ) - .join("___"); - - const result = new vscode.MarkdownString(text); - result.isTrusted = true; - return result; -} - export async function createClient( traceOutputChannel: vscode.OutputChannel, outputChannel: vscode.OutputChannel, @@ -450,3 +390,32 @@ function isCodeActionWithoutEditsAndCommands(value: any): boolean { candidate.command === void 0 ); } + +// Command URIs have a form of command:command-name?arguments, where +// arguments is a percent-encoded array of data we want to pass along to +// the command function. For "Show References" this is a list of all file +// URIs with locations of every reference, and it can get quite long. +// So long in fact that it will fail rendering inside an `a` tag so we need +// to proxy around that. We store the last hover's reference command link +// here, as only one hover can be active at a time, and we don't need to +// keep a history of these. +export let HOVER_REFERENCE_COMMAND: ra.CommandLink | undefined = undefined; + +function renderCommand(cmd: ra.CommandLink): string { + HOVER_REFERENCE_COMMAND = cmd; + return `[${cmd.title}](command:rust-analyzer.hoverRefCommandProxy '${cmd.tooltip}')`; +} + +function renderHoverActions(actions: ra.CommandLinkGroup[]): vscode.MarkdownString { + const text = actions + .map( + (group) => + (group.title ? group.title + " " : "") + + group.commands.map(renderCommand).join(" | "), + ) + .join(" | "); + + const result = new vscode.MarkdownString(text); + result.isTrusted = true; + return result; +} diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts index 849fae5cf24..f0f9fab1c64 100644 --- a/src/tools/rust-analyzer/editors/code/src/commands.ts +++ b/src/tools/rust-analyzer/editors/code/src/commands.ts @@ -9,22 +9,27 @@ import { applySnippetTextEdits, type SnippetTextDocumentEdit, } from "./snippets"; -import { spawnSync } from "child_process"; -import { type RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run"; +import { + type RunnableQuickPick, + selectRunnable, + createTaskFromRunnable, + createCargoArgs, +} from "./run"; import { AstInspector } from "./ast_inspector"; import { isRustDocument, + isCargoRunnableArgs, isCargoTomlDocument, sleep, isRustEditor, type RustEditor, type RustDocument, + unwrapUndefinable, } from "./util"; import { startDebugSession, makeDebugConfig } from "./debug"; import type { LanguageClient } from "vscode-languageclient/node"; -import { LINKED_COMMANDS } from "./client"; +import { HOVER_REFERENCE_COMMAND } from "./client"; import type { DependencyId } from "./dependencies_provider"; -import { unwrapUndefinable } from "./undefinable"; import { log } from "./util"; export * from "./ast_inspector"; @@ -415,10 +420,9 @@ export function serverVersion(ctx: CtxInit): Cmd { void vscode.window.showWarningMessage(`rust-analyzer server is not running`); return; } - const { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" }); - const versionString = stdout.slice(`rust-analyzer `.length).trim(); - - void vscode.window.showInformationMessage(`rust-analyzer version: ${versionString}`); + void vscode.window.showInformationMessage( + `rust-analyzer version: ${ctx.serverVersion} [${ctx.serverPath}]`, + ); }; } @@ -1097,7 +1101,7 @@ export function run(ctx: CtxInit): Cmd { item.detail = "rerun"; prevRunnable = item; - const task = await createTask(item.runnable, ctx.config); + const task = await createTaskFromRunnable(item.runnable, ctx.config); return await vscode.tasks.executeTask(task); }; } @@ -1140,7 +1144,7 @@ export function runSingle(ctx: CtxInit): Cmd { const editor = ctx.activeRustEditor; if (!editor) return; - const task = await createTask(runnable, ctx.config); + const task = await createTaskFromRunnable(runnable, ctx.config); task.group = vscode.TaskGroup.Build; task.presentationOptions = { reveal: vscode.TaskRevealKind.Always, @@ -1156,8 +1160,8 @@ export function copyRunCommandLine(ctx: CtxInit) { let prevRunnable: RunnableQuickPick | undefined; return async () => { const item = await selectRunnable(ctx, prevRunnable); - if (!item) return; - const args = createArgs(item.runnable); + if (!item || !isCargoRunnableArgs(item.runnable.args)) return; + const args = createCargoArgs(item.runnable.args); const commandLine = ["cargo", ...args].join(" "); await vscode.env.clipboard.writeText(commandLine); await vscode.window.showInformationMessage("Cargo invocation copied to the clipboard."); @@ -1192,11 +1196,10 @@ export function newDebugConfig(ctx: CtxInit): Cmd { }; } -export function linkToCommand(_: Ctx): Cmd { - return async (commandId: string) => { - const link = LINKED_COMMANDS.get(commandId); - if (link) { - const { command, arguments: args = [] } = link; +export function hoverRefCommandProxy(_: Ctx): Cmd { + return async () => { + if (HOVER_REFERENCE_COMMAND) { + const { command, arguments: args = [] } = HOVER_REFERENCE_COMMAND; await vscode.commands.executeCommand(command, ...args); } }; @@ -1486,3 +1489,16 @@ export function toggleCheckOnSave(ctx: Ctx): Cmd { ctx.refreshServerStatus(); }; } + +export function toggleLSPLogs(ctx: Ctx): Cmd { + return async () => { + const config = vscode.workspace.getConfiguration("rust-analyzer"); + const targetValue = + config.get<string | undefined>("trace.server") === "verbose" ? undefined : "verbose"; + + await config.update("trace.server", targetValue, vscode.ConfigurationTarget.Workspace); + if (targetValue && ctx.client && ctx.client.traceOutputChannel) { + ctx.client.traceOutputChannel.show(); + } + }; +} diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index e676bc0826c..1931cfe3813 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -2,9 +2,7 @@ import * as Is from "vscode-languageclient/lib/common/utils/is"; import * as os from "os"; import * as path from "path"; import * as vscode from "vscode"; -import type { Env } from "./client"; -import { log } from "./util"; -import { expectNotUndefined, unwrapUndefinable } from "./undefinable"; +import { type Env, log, unwrapUndefinable, expectNotUndefined } from "./util"; import type { JsonProject } from "./rust_project"; export type RunnableEnvCfgItem = { diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts index 474e18b722f..bf0b84ec358 100644 --- a/src/tools/rust-analyzer/editors/code/src/ctx.ts +++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts @@ -25,6 +25,8 @@ import { bootstrap } from "./bootstrap"; import type { RustAnalyzerExtensionApi } from "./main"; import type { JsonProject } from "./rust_project"; import { prepareTestExplorer } from "./test_explorer"; +import { spawn } from "node:child_process"; +import { text } from "node:stream/consumers"; // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if // only those are in use. We use "Empty" to represent these scenarios @@ -71,6 +73,7 @@ export class Ctx implements RustAnalyzerExtensionApi { readonly statusBar: vscode.StatusBarItem; config: Config; readonly workspace: Workspace; + readonly version: string; private _client: lc.LanguageClient | undefined; private _serverPath: string | undefined; @@ -85,6 +88,15 @@ export class Ctx implements RustAnalyzerExtensionApi { private _dependencies: RustDependenciesProvider | undefined; private _treeView: vscode.TreeView<Dependency | DependencyFile | DependencyId> | undefined; private lastStatus: ServerStatusParams | { health: "stopped" } = { health: "stopped" }; + private _serverVersion: string; + + get serverPath(): string | undefined { + return this._serverPath; + } + + get serverVersion(): string | undefined { + return this._serverVersion; + } get client() { return this._client; @@ -104,6 +116,8 @@ export class Ctx implements RustAnalyzerExtensionApi { workspace: Workspace, ) { extCtx.subscriptions.push(this); + this.version = extCtx.extension.packageJSON.version ?? "<unknown>"; + this._serverVersion = "<not running>"; this.config = new Config(extCtx); this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); if (this.config.testExplorer) { @@ -186,6 +200,19 @@ export class Ctx implements RustAnalyzerExtensionApi { throw new Error(message); }, ); + text(spawn(this._serverPath, ["--version"]).stdout.setEncoding("utf-8")).then( + (data) => { + const prefix = `rust-analyzer `; + this._serverVersion = data + .slice(data.startsWith(prefix) ? prefix.length : 0) + .trim(); + this.refreshServerStatus(); + }, + (_) => { + this._serverVersion = "<unknown>"; + this.refreshServerStatus(); + }, + ); const newEnv = Object.assign({}, process.env, this.config.serverExtraEnv); const run: lc.Executable = { command: this._serverPath, @@ -372,10 +399,6 @@ export class Ctx implements RustAnalyzerExtensionApi { return this.extCtx.subscriptions; } - get serverPath(): string | undefined { - return this._serverPath; - } - setWorkspaces(workspaces: JsonProject[]) { this.config.discoveredWorkspaces = workspaces; } @@ -475,23 +498,24 @@ export class Ctx implements RustAnalyzerExtensionApi { if (statusBar.tooltip.value) { statusBar.tooltip.appendMarkdown("\n\n---\n\n"); } - statusBar.tooltip.appendMarkdown("\n\n[Open Logs](command:rust-analyzer.openLogs)"); - statusBar.tooltip.appendMarkdown( - `\n\n[${ - this.config.checkOnSave ? "Disable" : "Enable" - } Check on Save](command:rust-analyzer.toggleCheckOnSave)`, - ); - statusBar.tooltip.appendMarkdown( - "\n\n[Reload Workspace](command:rust-analyzer.reloadWorkspace)", - ); - statusBar.tooltip.appendMarkdown( - "\n\n[Rebuild Proc Macros](command:rust-analyzer.rebuildProcMacros)", - ); + + const toggleCheckOnSave = this.config.checkOnSave ? "Disable" : "Enable"; statusBar.tooltip.appendMarkdown( - "\n\n[Restart server](command:rust-analyzer.restartServer)", + `[Extension Info](command:analyzer.serverVersion "Show version and server binary info"): Version ${this.version}, Server Version ${this._serverVersion}` + + "\n\n---\n\n" + + '[$(terminal) Open Logs](command:rust-analyzer.openLogs "Open the server logs")' + + "\n\n" + + `[$(settings) ${toggleCheckOnSave} Check on Save](command:rust-analyzer.toggleCheckOnSave "Temporarily ${toggleCheckOnSave.toLowerCase()} check on save functionality")` + + "\n\n" + + '[$(refresh) Reload Workspace](command:rust-analyzer.reloadWorkspace "Reload and rediscover workspaces")' + + "\n\n" + + '[$(symbol-property) Rebuild Build Dependencies](command:rust-analyzer.rebuildProcMacros "Rebuild build scripts and proc-macros")' + + "\n\n" + + '[$(stop-circle) Stop server](command:rust-analyzer.stopServer "Stop the server")' + + "\n\n" + + '[$(debug-restart) Restart server](command:rust-analyzer.restartServer "Restart the server")', ); - statusBar.tooltip.appendMarkdown("\n\n[Stop server](command:rust-analyzer.stopServer)"); - if (!status.quiescent) icon = "$(sync~spin) "; + if (!status.quiescent) icon = "$(loading~spin) "; statusBar.text = `${icon}rust-analyzer`; } diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts index 4b96e4d5c8e..58fe1df51f4 100644 --- a/src/tools/rust-analyzer/editors/code/src/debug.ts +++ b/src/tools/rust-analyzer/editors/code/src/debug.ts @@ -6,11 +6,12 @@ import type * as ra from "./lsp_ext"; import { Cargo, getRustcId, getSysroot } from "./toolchain"; import type { Ctx } from "./ctx"; import { prepareEnv } from "./run"; -import { unwrapUndefinable } from "./undefinable"; +import { isCargoRunnableArgs, unwrapUndefinable } from "./util"; const debugOutput = vscode.window.createOutputChannel("Debug"); type DebugConfigProvider = ( - config: ra.Runnable, + runnable: ra.Runnable, + runnableArgs: ra.CargoRunnableArgs, executable: string, env: Record<string, string>, sourceFileMap?: Record<string, string>, @@ -76,6 +77,11 @@ async function getDebugConfiguration( ctx: Ctx, runnable: ra.Runnable, ): Promise<vscode.DebugConfiguration | undefined> { + if (!isCargoRunnableArgs(runnable.args)) { + return; + } + const runnableArgs: ra.CargoRunnableArgs = runnable.args; + const editor = ctx.activeRustEditor; if (!editor) return; @@ -119,9 +125,9 @@ async function getDebugConfiguration( const isMultiFolderWorkspace = workspaceFolders.length > 1; const firstWorkspace = workspaceFolders[0]; const maybeWorkspace = - !isMultiFolderWorkspace || !runnable.args.workspaceRoot + !isMultiFolderWorkspace || !runnableArgs.workspaceRoot ? firstWorkspace - : workspaceFolders.find((w) => runnable.args.workspaceRoot?.includes(w.uri.fsPath)) || + : workspaceFolders.find((w) => runnableArgs.workspaceRoot?.includes(w.uri.fsPath)) || firstWorkspace; const workspace = unwrapUndefinable(maybeWorkspace); @@ -129,11 +135,11 @@ async function getDebugConfiguration( const workspaceQualifier = isMultiFolderWorkspace ? `:${workspace.name}` : ""; function simplifyPath(p: string): string { // see https://github.com/rust-lang/rust-analyzer/pull/5513#issuecomment-663458818 for why this is needed - return path.normalize(p).replace(wsFolder, "${workspaceFolder" + workspaceQualifier + "}"); + return path.normalize(p).replace(wsFolder, `\${workspaceFolder${workspaceQualifier}}`); } - const env = prepareEnv(runnable, ctx.config.runnablesExtraEnv); - const executable = await getDebugExecutable(runnable, env); + const env = prepareEnv(runnable.label, runnableArgs, ctx.config.runnablesExtraEnv); + const executable = await getDebugExecutable(runnableArgs, env); let sourceFileMap = debugOptions.sourceFileMap; if (sourceFileMap === "auto") { // let's try to use the default toolchain @@ -147,7 +153,7 @@ async function getDebugConfiguration( } const provider = unwrapUndefinable(knownEngines[debugEngine.id]); - const debugConfig = provider(runnable, simplifyPath(executable), env, sourceFileMap); + const debugConfig = provider(runnable, runnableArgs, simplifyPath(executable), env); if (debugConfig.type in debugOptions.engineSettings) { const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type]; for (var key in settingsMap) { @@ -170,11 +176,11 @@ async function getDebugConfiguration( } async function getDebugExecutable( - runnable: ra.Runnable, + runnableArgs: ra.CargoRunnableArgs, env: Record<string, string>, ): Promise<string> { - const cargo = new Cargo(runnable.args.workspaceRoot || ".", debugOutput, env); - const executable = await cargo.executableFromArgs(runnable.args.cargoArgs); + const cargo = new Cargo(runnableArgs.workspaceRoot || ".", debugOutput, env); + const executable = await cargo.executableFromArgs(runnableArgs.cargoArgs); // if we are here, there were no compilation errors. return executable; @@ -182,6 +188,7 @@ async function getDebugExecutable( function getCCppDebugConfig( runnable: ra.Runnable, + runnableArgs: ra.CargoRunnableArgs, executable: string, env: Record<string, string>, sourceFileMap?: Record<string, string>, @@ -191,8 +198,8 @@ function getCCppDebugConfig( request: "launch", name: runnable.label, program: executable, - args: runnable.args.executableArgs, - cwd: runnable.args.cwd || runnable.args.workspaceRoot || ".", + args: runnableArgs.executableArgs, + cwd: runnable.args.cwd || runnableArgs.workspaceRoot || ".", sourceFileMap, environment: Object.entries(env).map((entry) => ({ name: entry[0], @@ -207,6 +214,7 @@ function getCCppDebugConfig( function getCodeLldbDebugConfig( runnable: ra.Runnable, + runnableArgs: ra.CargoRunnableArgs, executable: string, env: Record<string, string>, sourceFileMap?: Record<string, string>, @@ -216,8 +224,8 @@ function getCodeLldbDebugConfig( request: "launch", name: runnable.label, program: executable, - args: runnable.args.executableArgs, - cwd: runnable.args.cwd || runnable.args.workspaceRoot || ".", + args: runnableArgs.executableArgs, + cwd: runnable.args.cwd || runnableArgs.workspaceRoot || ".", sourceMap: sourceFileMap, sourceLanguages: ["rust"], env, @@ -226,6 +234,7 @@ function getCodeLldbDebugConfig( function getNativeDebugConfig( runnable: ra.Runnable, + runnableArgs: ra.CargoRunnableArgs, executable: string, env: Record<string, string>, _sourceFileMap?: Record<string, string>, @@ -236,8 +245,8 @@ function getNativeDebugConfig( name: runnable.label, target: executable, // See https://github.com/WebFreak001/code-debug/issues/359 - arguments: quote(runnable.args.executableArgs), - cwd: runnable.args.cwd || runnable.args.workspaceRoot || ".", + arguments: quote(runnableArgs.executableArgs), + cwd: runnable.args.cwd || runnableArgs.workspaceRoot || ".", env, valuesFormatting: "prettyPrinters", }; diff --git a/src/tools/rust-analyzer/editors/code/src/dependencies_provider.ts b/src/tools/rust-analyzer/editors/code/src/dependencies_provider.ts index 863ace07801..203ef5cc85e 100644 --- a/src/tools/rust-analyzer/editors/code/src/dependencies_provider.ts +++ b/src/tools/rust-analyzer/editors/code/src/dependencies_provider.ts @@ -4,7 +4,7 @@ import * as fs from "fs"; import type { CtxInit } from "./ctx"; import * as ra from "./lsp_ext"; import type { FetchDependencyListResult } from "./lsp_ext"; -import { unwrapUndefinable } from "./undefinable"; +import { unwrapUndefinable } from "./util"; export class RustDependenciesProvider implements vscode.TreeDataProvider<Dependency | DependencyFile> diff --git a/src/tools/rust-analyzer/editors/code/src/diagnostics.ts b/src/tools/rust-analyzer/editors/code/src/diagnostics.ts index e31a1cdcef9..9fb2993d12f 100644 --- a/src/tools/rust-analyzer/editors/code/src/diagnostics.ts +++ b/src/tools/rust-analyzer/editors/code/src/diagnostics.ts @@ -8,7 +8,7 @@ import { window, } from "vscode"; import type { Ctx } from "./ctx"; -import { unwrapUndefinable } from "./undefinable"; +import { unwrapUndefinable } from "./util"; export const URI_SCHEME = "rust-analyzer-diagnostics-view"; diff --git a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts index 8e48aeef158..699052e4d44 100644 --- a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts +++ b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts @@ -223,17 +223,35 @@ export type OpenCargoTomlParams = { export type Runnable = { label: string; location?: lc.LocationLink; +} & (RunnableCargo | RunnableShell); + +type RunnableCargo = { kind: "cargo"; - args: { - workspaceRoot?: string; - cwd?: string; - cargoArgs: string[]; - cargoExtraArgs: string[]; - executableArgs: string[]; - expectTest?: boolean; - overrideCargo?: string; - }; + args: CargoRunnableArgs; +}; + +type RunnableShell = { + kind: "shell"; + args: ShellRunnableArgs; +}; + +export type ShellRunnableArgs = { + kind: string; + program: string; + args: string[]; + cwd: string; +}; + +export type CargoRunnableArgs = { + workspaceRoot?: string; + cargoArgs: string[]; + cwd: string; + cargoExtraArgs: string[]; + executableArgs: string[]; + expectTest?: boolean; + overrideCargo?: string; }; + export type RunnablesParams = { textDocument: lc.TextDocumentIdentifier; position: lc.Position | null; diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts index 0af58fd7812..ff67bb7bd59 100644 --- a/src/tools/rust-analyzer/editors/code/src/main.ts +++ b/src/tools/rust-analyzer/editors/code/src/main.ts @@ -177,12 +177,13 @@ function createCommands(): Record<string, CommandFactory> { serverVersion: { enabled: commands.serverVersion }, viewMemoryLayout: { enabled: commands.viewMemoryLayout }, toggleCheckOnSave: { enabled: commands.toggleCheckOnSave }, + toggleLSPLogs: { enabled: commands.toggleLSPLogs }, // Internal commands which are invoked by the server. applyActionGroup: { enabled: commands.applyActionGroup }, applySnippetWorkspaceEdit: { enabled: commands.applySnippetWorkspaceEditCommand }, debugSingle: { enabled: commands.debugSingle }, gotoLocation: { enabled: commands.gotoLocation }, - linkToCommand: { enabled: commands.linkToCommand }, + hoverRefCommandProxy: { enabled: commands.hoverRefCommandProxy }, resolveCodeAction: { enabled: commands.resolveCodeAction }, runSingle: { enabled: commands.runSingle }, showReferences: { enabled: commands.showReferences }, @@ -203,14 +204,4 @@ function checkConflictingExtensions() { ) .then(() => {}, console.error); } - - if (vscode.extensions.getExtension("panicbit.cargo")) { - vscode.window - .showWarningMessage( - `You have both the rust-analyzer (rust-lang.rust-analyzer) and Cargo (panicbit.cargo) plugins enabled, ` + - 'you can disable it or set {"cargo.automaticCheck": false} in settings.json to avoid invoking cargo twice', - "Got it", - ) - .then(() => {}, console.error); - } } diff --git a/src/tools/rust-analyzer/editors/code/src/nullable.ts b/src/tools/rust-analyzer/editors/code/src/nullable.ts deleted file mode 100644 index e973e162907..00000000000 --- a/src/tools/rust-analyzer/editors/code/src/nullable.ts +++ /dev/null @@ -1,19 +0,0 @@ -export type NotNull<T> = T extends null ? never : T; - -export type Nullable<T> = T | null; - -function isNotNull<T>(input: Nullable<T>): input is NotNull<T> { - return input !== null; -} - -function expectNotNull<T>(input: Nullable<T>, msg: string): NotNull<T> { - if (isNotNull(input)) { - return input; - } - - throw new TypeError(msg); -} - -export function unwrapNullable<T>(input: Nullable<T>): NotNull<T> { - return expectNotNull(input, `unwrapping \`null\``); -} diff --git a/src/tools/rust-analyzer/editors/code/src/run.ts b/src/tools/rust-analyzer/editors/code/src/run.ts index 4470689cd8c..7a9049af0de 100644 --- a/src/tools/rust-analyzer/editors/code/src/run.ts +++ b/src/tools/rust-analyzer/editors/code/src/run.ts @@ -6,9 +6,9 @@ import * as tasks from "./tasks"; import type { CtxInit } from "./ctx"; import { makeDebugConfig } from "./debug"; import type { Config, RunnableEnvCfg, RunnableEnvCfgItem } from "./config"; -import { unwrapUndefinable } from "./undefinable"; import type { LanguageClient } from "vscode-languageclient/node"; -import type { RustEditor } from "./util"; +import { unwrapUndefinable, type RustEditor } from "./util"; +import * as toolchain from "./toolchain"; const quickPickButtons = [ { iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configuration." }, @@ -66,17 +66,23 @@ export class RunnableQuickPick implements vscode.QuickPickItem { } } +export function prepareBaseEnv(): Record<string, string> { + const env: Record<string, string> = { RUST_BACKTRACE: "short" }; + Object.assign(env, process.env as { [key: string]: string }); + return env; +} + export function prepareEnv( - runnable: ra.Runnable, + label: string, + runnableArgs: ra.CargoRunnableArgs, runnableEnvCfg: RunnableEnvCfg, ): Record<string, string> { - const env: Record<string, string> = { RUST_BACKTRACE: "short" }; + const env = prepareBaseEnv(); - if (runnable.args.expectTest) { + if (runnableArgs.expectTest) { env["UPDATE_EXPECT"] = "1"; } - Object.assign(env, process.env as { [key: string]: string }); const platform = process.platform; const checkPlatform = (it: RunnableEnvCfgItem) => { @@ -90,7 +96,7 @@ export function prepareEnv( if (runnableEnvCfg) { if (Array.isArray(runnableEnvCfg)) { for (const it of runnableEnvCfg) { - const masked = !it.mask || new RegExp(it.mask).test(runnable.label); + const masked = !it.mask || new RegExp(it.mask).test(label); if (masked && checkPlatform(it)) { Object.assign(env, it.env); } @@ -103,34 +109,52 @@ export function prepareEnv( return env; } -export async function createTask(runnable: ra.Runnable, config: Config): Promise<vscode.Task> { - if (runnable.kind !== "cargo") { - // rust-analyzer supports only one kind, "cargo" - // do not use tasks.TASK_TYPE here, these are completely different meanings. +export async function createTaskFromRunnable( + runnable: ra.Runnable, + config: Config, +): Promise<vscode.Task> { + let definition: tasks.RustTargetDefinition; + if (runnable.kind === "cargo") { + const runnableArgs = runnable.args; + let args = createCargoArgs(runnableArgs); + + let program: string; + if (runnableArgs.overrideCargo) { + // Split on spaces to allow overrides like "wrapper cargo". + const cargoParts = runnableArgs.overrideCargo.split(" "); + + program = unwrapUndefinable(cargoParts[0]); + args = [...cargoParts.slice(1), ...args]; + } else { + program = await toolchain.cargoPath(); + } - throw `Unexpected runnable kind: ${runnable.kind}`; + definition = { + type: tasks.CARGO_TASK_TYPE, + command: program, + args, + cwd: runnableArgs.workspaceRoot || ".", + env: prepareEnv(runnable.label, runnableArgs, config.runnablesExtraEnv), + }; + } else { + const runnableArgs = runnable.args; + definition = { + type: tasks.SHELL_TASK_TYPE, + command: runnableArgs.program, + args: runnableArgs.args, + cwd: runnableArgs.cwd, + env: prepareBaseEnv(), + }; } - const args = createArgs(runnable); - - const definition: tasks.CargoTaskDefinition = { - type: tasks.TASK_TYPE, - command: unwrapUndefinable(args[0]), // run, test, etc... - args: args.slice(1), - cwd: runnable.args.workspaceRoot || ".", - env: prepareEnv(runnable, config.runnablesExtraEnv), - overrideCargo: runnable.args.overrideCargo, - }; - - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - const target = vscode.workspace.workspaceFolders![0]; // safe, see main activate() + const target = vscode.workspace.workspaceFolders?.[0]; + const exec = await tasks.targetToExecution(definition, config.cargoRunner, true); const task = await tasks.buildRustTask( target, definition, runnable.label, config.problemMatcher, - config.cargoRunner, - true, + exec, ); task.presentationOptions.clear = true; @@ -141,13 +165,13 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise return task; } -export function createArgs(runnable: ra.Runnable): string[] { - const args = [...runnable.args.cargoArgs]; // should be a copy! - if (runnable.args.cargoExtraArgs) { - args.push(...runnable.args.cargoExtraArgs); // Append user-specified cargo options. +export function createCargoArgs(runnableArgs: ra.CargoRunnableArgs): string[] { + const args = [...runnableArgs.cargoArgs]; // should be a copy! + if (runnableArgs.cargoExtraArgs) { + args.push(...runnableArgs.cargoExtraArgs); // Append user-specified cargo options. } - if (runnable.args.executableArgs.length > 0) { - args.push("--", ...runnable.args.executableArgs); + if (runnableArgs.executableArgs.length > 0) { + args.push("--", ...runnableArgs.executableArgs); } return args; } diff --git a/src/tools/rust-analyzer/editors/code/src/snippets.ts b/src/tools/rust-analyzer/editors/code/src/snippets.ts index b3982bdf2be..a469a9cd1f4 100644 --- a/src/tools/rust-analyzer/editors/code/src/snippets.ts +++ b/src/tools/rust-analyzer/editors/code/src/snippets.ts @@ -1,7 +1,6 @@ import * as vscode from "vscode"; -import { assert } from "./util"; -import { unwrapUndefinable } from "./undefinable"; +import { assert, unwrapUndefinable } from "./util"; export type SnippetTextDocumentEdit = [vscode.Uri, (vscode.TextEdit | vscode.SnippetTextEdit)[]]; diff --git a/src/tools/rust-analyzer/editors/code/src/tasks.ts b/src/tools/rust-analyzer/editors/code/src/tasks.ts index 2b3abc5d65f..6f4fbf91889 100644 --- a/src/tools/rust-analyzer/editors/code/src/tasks.ts +++ b/src/tools/rust-analyzer/editors/code/src/tasks.ts @@ -1,28 +1,29 @@ import * as vscode from "vscode"; -import * as toolchain from "./toolchain"; import type { Config } from "./config"; -import { log } from "./util"; -import { unwrapUndefinable } from "./undefinable"; +import { log, unwrapUndefinable } from "./util"; +import * as toolchain from "./toolchain"; // This ends up as the `type` key in tasks.json. RLS also uses `cargo` and // our configuration should be compatible with it so use the same key. -export const TASK_TYPE = "cargo"; +export const CARGO_TASK_TYPE = "cargo"; +export const SHELL_TASK_TYPE = "shell"; -export const TASK_SOURCE = "rust"; +export const RUST_TASK_SOURCE = "rust"; -export interface CargoTaskDefinition extends vscode.TaskDefinition { - // The cargo command, such as "run" or "check". +export type RustTargetDefinition = { + readonly type: typeof CARGO_TASK_TYPE | typeof SHELL_TASK_TYPE; +} & vscode.TaskDefinition & + RustTarget; +export type RustTarget = { + // The command to run, usually `cargo`. command: string; - // Additional arguments passed to the cargo command. + // Additional arguments passed to the command. args?: string[]; - // The working directory to run the cargo command in. + // The working directory to run the command in. cwd?: string; // The shell environment. env?: { [key: string]: string }; - // Override the cargo executable name, such as - // "my_custom_cargo_bin". - overrideCargo?: string; -} +}; class RustTaskProvider implements vscode.TaskProvider { private readonly config: Config; @@ -32,6 +33,10 @@ class RustTaskProvider implements vscode.TaskProvider { } async provideTasks(): Promise<vscode.Task[]> { + if (!vscode.workspace.workspaceFolders) { + return []; + } + // Detect Rust tasks. Currently we do not do any actual detection // of tasks (e.g. aliases in .cargo/config) and just return a fixed // set of tasks that always exist. These tasks cannot be removed in @@ -46,15 +51,23 @@ class RustTaskProvider implements vscode.TaskProvider { { command: "run", group: undefined }, ]; + // FIXME: The server should provide this + const cargo = await toolchain.cargoPath(); + const tasks: vscode.Task[] = []; - for (const workspaceTarget of vscode.workspace.workspaceFolders || []) { + for (const workspaceTarget of vscode.workspace.workspaceFolders) { for (const def of defs) { + const definition = { + command: cargo, + args: [def.command], + }; + const exec = await targetToExecution(definition, this.config.cargoRunner); const vscodeTask = await buildRustTask( workspaceTarget, - { type: TASK_TYPE, command: def.command }, + { ...definition, type: CARGO_TASK_TYPE }, `cargo ${def.command}`, this.config.problemMatcher, - this.config.cargoRunner, + exec, ); vscodeTask.group = def.group; tasks.push(vscodeTask); @@ -68,16 +81,24 @@ class RustTaskProvider implements vscode.TaskProvider { // VSCode calls this for every cargo task in the user's tasks.json, // we need to inform VSCode how to execute that command by creating // a ShellExecution for it. - - const definition = task.definition as CargoTaskDefinition; - - if (definition.type === TASK_TYPE) { + if (task.definition.type === CARGO_TASK_TYPE) { + const taskDefinition = task.definition as RustTargetDefinition; + const cargo = await toolchain.cargoPath(); + const exec = await targetToExecution( + { + command: cargo, + args: [taskDefinition.command].concat(taskDefinition.args || []), + cwd: taskDefinition.cwd, + env: taskDefinition.env, + }, + this.config.cargoRunner, + ); return await buildRustTask( task.scope, - definition, + taskDefinition, task.name, this.config.problemMatcher, - this.config.cargoRunner, + exec, ); } @@ -87,37 +108,34 @@ class RustTaskProvider implements vscode.TaskProvider { export async function buildRustTask( scope: vscode.WorkspaceFolder | vscode.TaskScope | undefined, - definition: CargoTaskDefinition, + definition: RustTargetDefinition, name: string, problemMatcher: string[], - customRunner?: string, - throwOnError: boolean = false, + exec: vscode.ProcessExecution | vscode.ShellExecution, ): Promise<vscode.Task> { - const exec = await cargoToExecution(definition, customRunner, throwOnError); - return new vscode.Task( definition, // scope can sometimes be undefined. in these situations we default to the workspace taskscope as // recommended by the official docs: https://code.visualstudio.com/api/extension-guides/task-provider#task-provider) scope ?? vscode.TaskScope.Workspace, name, - TASK_SOURCE, + RUST_TASK_SOURCE, exec, problemMatcher, ); } -async function cargoToExecution( - definition: CargoTaskDefinition, - customRunner: string | undefined, - throwOnError: boolean, +export async function targetToExecution( + definition: RustTarget, + customRunner?: string, + throwOnError: boolean = false, ): Promise<vscode.ProcessExecution | vscode.ShellExecution> { if (customRunner) { const runnerCommand = `${customRunner}.buildShellExecution`; try { const runnerArgs = { - kind: TASK_TYPE, + kind: CARGO_TASK_TYPE, args: definition.args, cwd: definition.cwd, env: definition.env, @@ -137,18 +155,8 @@ async function cargoToExecution( // fallback to default processing } } - - // Check whether we must use a user-defined substitute for cargo. - // Split on spaces to allow overrides like "wrapper cargo". - const cargoPath = await toolchain.cargoPath(); - const cargoCommand = definition.overrideCargo?.split(" ") ?? [cargoPath]; - - const args = [definition.command].concat(definition.args ?? []); - const fullCommand = [...cargoCommand, ...args]; - - const processName = unwrapUndefinable(fullCommand[0]); - - return new vscode.ProcessExecution(processName, fullCommand.slice(1), { + const args = unwrapUndefinable(definition.args); + return new vscode.ProcessExecution(definition.command, args, { cwd: definition.cwd, env: definition.env, }); @@ -156,5 +164,5 @@ async function cargoToExecution( export function activateTaskProvider(config: Config): vscode.Disposable { const provider = new RustTaskProvider(config); - return vscode.tasks.registerTaskProvider(TASK_TYPE, provider); + return vscode.tasks.registerTaskProvider(CARGO_TASK_TYPE, provider); } diff --git a/src/tools/rust-analyzer/editors/code/src/toolchain.ts b/src/tools/rust-analyzer/editors/code/src/toolchain.ts index 58e5fc747a1..a48d2d90cce 100644 --- a/src/tools/rust-analyzer/editors/code/src/toolchain.ts +++ b/src/tools/rust-analyzer/editors/code/src/toolchain.ts @@ -3,9 +3,7 @@ import * as os from "os"; import * as path from "path"; import * as readline from "readline"; import * as vscode from "vscode"; -import { execute, log, memoizeAsync } from "./util"; -import { unwrapNullable } from "./nullable"; -import { unwrapUndefinable } from "./undefinable"; +import { execute, log, memoizeAsync, unwrapNullable, unwrapUndefinable } from "./util"; interface CompilationArtifact { fileName: string; @@ -151,12 +149,13 @@ export async function getRustcId(dir: string): Promise<string> { } /** Mirrors `toolchain::cargo()` implementation */ +// FIXME: The server should provide this export function cargoPath(): Promise<string> { return getPathForExecutable("cargo"); } /** Mirrors `toolchain::get_path_for_executable()` implementation */ -export const getPathForExecutable = memoizeAsync( +const getPathForExecutable = memoizeAsync( // We apply caching to decrease file-system interactions async (executableName: "cargo" | "rustc" | "rustup"): Promise<string> => { { diff --git a/src/tools/rust-analyzer/editors/code/src/undefinable.ts b/src/tools/rust-analyzer/editors/code/src/undefinable.ts deleted file mode 100644 index 813bac5a123..00000000000 --- a/src/tools/rust-analyzer/editors/code/src/undefinable.ts +++ /dev/null @@ -1,19 +0,0 @@ -export type NotUndefined<T> = T extends undefined ? never : T; - -export type Undefinable<T> = T | undefined; - -function isNotUndefined<T>(input: Undefinable<T>): input is NotUndefined<T> { - return input !== undefined; -} - -export function expectNotUndefined<T>(input: Undefinable<T>, msg: string): NotUndefined<T> { - if (isNotUndefined(input)) { - return input; - } - - throw new TypeError(msg); -} - -export function unwrapUndefinable<T>(input: Undefinable<T>): NotUndefined<T> { - return expectNotUndefined(input, `unwrapping \`undefined\``); -} diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts index 51f921a2962..dd1cbe38ff9 100644 --- a/src/tools/rust-analyzer/editors/code/src/util.ts +++ b/src/tools/rust-analyzer/editors/code/src/util.ts @@ -1,8 +1,8 @@ import * as vscode from "vscode"; import { strict as nativeAssert } from "assert"; -import { exec, type ExecOptions, spawnSync } from "child_process"; +import { exec, type ExecOptions } from "child_process"; import { inspect } from "util"; -import type { Env } from "./client"; +import type { CargoRunnableArgs, ShellRunnableArgs } from "./lsp_ext"; export function assert(condition: boolean, explanation: string): asserts condition { try { @@ -13,6 +13,10 @@ export function assert(condition: boolean, explanation: string): asserts conditi } } +export type Env = { + [name: string]: string; +}; + export const log = new (class { private enabled = true; private readonly output = vscode.window.createOutputChannel("Rust Analyzer Client"); @@ -77,6 +81,12 @@ export function isCargoTomlDocument(document: vscode.TextDocument): document is return document.uri.scheme === "file" && document.fileName.endsWith("Cargo.toml"); } +export function isCargoRunnableArgs( + args: CargoRunnableArgs | ShellRunnableArgs, +): args is CargoRunnableArgs { + return (args as CargoRunnableArgs).executableArgs !== undefined; +} + export function isRustEditor(editor: vscode.TextEditor): editor is RustEditor { return isRustDocument(editor.document); } @@ -94,20 +104,6 @@ export function isDocumentInWorkspace(document: RustDocument): boolean { return false; } -export function isValidExecutable(path: string, extraEnv: Env): boolean { - log.debug("Checking availability of a binary at", path); - - const res = spawnSync(path, ["--version"], { - encoding: "utf8", - env: { ...process.env, ...extraEnv }, - }); - - const printOutput = res.error ? log.warn : log.info; - printOutput(path, "--version:", res); - - return res.status === 0; -} - /** Sets ['when'](https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts) clause contexts */ export function setContextValue(key: string, value: any): Thenable<void> { return vscode.commands.executeCommand("setContext", key, value); @@ -199,3 +195,42 @@ export class LazyOutputChannel implements vscode.OutputChannel { } } } + +export type NotNull<T> = T extends null ? never : T; + +export type Nullable<T> = T | null; + +function isNotNull<T>(input: Nullable<T>): input is NotNull<T> { + return input !== null; +} + +function expectNotNull<T>(input: Nullable<T>, msg: string): NotNull<T> { + if (isNotNull(input)) { + return input; + } + + throw new TypeError(msg); +} + +export function unwrapNullable<T>(input: Nullable<T>): NotNull<T> { + return expectNotNull(input, `unwrapping \`null\``); +} +export type NotUndefined<T> = T extends undefined ? never : T; + +export type Undefinable<T> = T | undefined; + +function isNotUndefined<T>(input: Undefinable<T>): input is NotUndefined<T> { + return input !== undefined; +} + +export function expectNotUndefined<T>(input: Undefinable<T>, msg: string): NotUndefined<T> { + if (isNotUndefined(input)) { + return input; + } + + throw new TypeError(msg); +} + +export function unwrapUndefinable<T>(input: Undefinable<T>): NotUndefined<T> { + return expectNotUndefined(input, `unwrapping \`undefined\``); +} diff --git a/src/tools/rust-analyzer/editors/code/tests/unit/runnable_env.test.ts b/src/tools/rust-analyzer/editors/code/tests/unit/runnable_env.test.ts index b1407ce0193..21bdaf5384d 100644 --- a/src/tools/rust-analyzer/editors/code/tests/unit/runnable_env.test.ts +++ b/src/tools/rust-analyzer/editors/code/tests/unit/runnable_env.test.ts @@ -10,6 +10,7 @@ function makeRunnable(label: string): ra.Runnable { kind: "cargo", args: { cargoArgs: [], + cwd: ".", executableArgs: [], cargoExtraArgs: [], }, @@ -18,7 +19,8 @@ function makeRunnable(label: string): ra.Runnable { function fakePrepareEnv(runnableName: string, config: RunnableEnvCfg): Record<string, string> { const runnable = makeRunnable(runnableName); - return prepareEnv(runnable, config); + const runnableArgs = runnable.args as ra.CargoRunnableArgs; + return prepareEnv(runnable.label, runnableArgs, config); } export async function getTests(ctx: Context) { |
