aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/rust-analyzer/src/config.rs119
-rw-r--r--crates/rust-analyzer/src/main_loop.rs28
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs30
-rw-r--r--crates/rust-analyzer/src/req.rs4
-rw-r--r--editors/code/package.json239
-rw-r--r--editors/code/src/client.ts26
-rw-r--r--editors/code/src/commands/runnables.ts4
-rw-r--r--editors/code/src/config.ts30
-rw-r--r--editors/code/src/ctx.ts3
-rw-r--r--editors/code/src/status_display.ts2
10 files changed, 229 insertions, 256 deletions
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 602423919..f3d8773cc 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -16,20 +16,33 @@ use serde::Deserialize;
16#[derive(Debug, Clone)] 16#[derive(Debug, Clone)]
17pub struct Config { 17pub struct Config {
18 pub client_caps: ClientCapsConfig, 18 pub client_caps: ClientCapsConfig,
19
20 pub with_sysroot: bool,
19 pub publish_diagnostics: bool, 21 pub publish_diagnostics: bool,
22 pub lru_capacity: Option<usize>,
23 pub proc_macro_srv: Option<String>,
24 pub files: FilesConfig,
20 pub notifications: NotificationsConfig, 25 pub notifications: NotificationsConfig,
26
27 pub cargo: CargoConfig,
28 pub rustfmt: RustfmtConfig,
29 pub check: Option<FlycheckConfig>,
30
21 pub inlay_hints: InlayHintsConfig, 31 pub inlay_hints: InlayHintsConfig,
22 pub completion: CompletionConfig, 32 pub completion: CompletionConfig,
23 pub call_info_full: bool, 33 pub call_info_full: bool,
24 pub rustfmt: RustfmtConfig, 34}
25 pub check: Option<FlycheckConfig>, 35
26 pub vscode_lldb: bool, 36#[derive(Debug, Clone)]
27 pub proc_macro_srv: Option<String>, 37pub struct FilesConfig {
28 pub lru_capacity: Option<usize>, 38 pub watcher: FilesWatcher,
29 pub use_client_watching: bool, 39 pub exclude: Vec<String>,
30 pub exclude_globs: Vec<String>, 40}
31 pub cargo: CargoConfig, 41
32 pub with_sysroot: bool, 42#[derive(Debug, Clone)]
43pub enum FilesWatcher {
44 Client,
45 Notify,
33} 46}
34 47
35#[derive(Debug, Clone)] 48#[derive(Debug, Clone)]
@@ -59,12 +72,26 @@ pub struct ClientCapsConfig {
59impl Default for Config { 72impl Default for Config {
60 fn default() -> Self { 73 fn default() -> Self {
61 Config { 74 Config {
75 client_caps: ClientCapsConfig::default(),
76
77 with_sysroot: true,
62 publish_diagnostics: true, 78 publish_diagnostics: true,
79 lru_capacity: None,
80 proc_macro_srv: None,
81 files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() },
63 notifications: NotificationsConfig { 82 notifications: NotificationsConfig {
64 workspace_loaded: true, 83 workspace_loaded: true,
65 cargo_toml_not_found: true, 84 cargo_toml_not_found: true,
66 }, 85 },
67 client_caps: ClientCapsConfig::default(), 86
87 cargo: CargoConfig::default(),
88 rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() },
89 check: Some(FlycheckConfig::CargoCommand {
90 command: "check".to_string(),
91 all_targets: true,
92 extra_args: Vec::new(),
93 }),
94
68 inlay_hints: InlayHintsConfig { 95 inlay_hints: InlayHintsConfig {
69 type_hints: true, 96 type_hints: true,
70 parameter_hints: true, 97 parameter_hints: true,
@@ -77,19 +104,6 @@ impl Default for Config {
77 add_call_argument_snippets: true, 104 add_call_argument_snippets: true,
78 }, 105 },
79 call_info_full: true, 106 call_info_full: true,
80 rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() },
81 check: Some(FlycheckConfig::CargoCommand {
82 command: "check".to_string(),
83 all_targets: true,
84 extra_args: Vec::new(),
85 }),
86 vscode_lldb: false,
87 proc_macro_srv: None,
88 lru_capacity: None,
89 use_client_watching: false,
90 exclude_globs: Vec::new(),
91 cargo: CargoConfig::default(),
92 with_sysroot: true,
93 } 107 }
94 } 108 }
95} 109}
@@ -103,45 +117,44 @@ impl Config {
103 *self = Default::default(); 117 *self = Default::default();
104 self.client_caps = client_caps; 118 self.client_caps = client_caps;
105 119
106 set(value, "/excludeGlobs", &mut self.exclude_globs); 120 set(value, "/withSysroot", &mut self.with_sysroot);
107 set(value, "/useClientWatching", &mut self.use_client_watching); 121 set(value, "/featureFlags/lsp.diagnostics", &mut self.publish_diagnostics);
108 set(value, "/lruCapacity", &mut self.lru_capacity); 122 set(value, "/lruCapacity", &mut self.lru_capacity);
123 if let Some(watcher) = get::<String>(value, "/files/watcher") {
124 self.files.watcher = match watcher.as_str() {
125 "client" => FilesWatcher::Client,
126 "notify"| _ => FilesWatcher::Notify,
127 }
128 }
129 set(value, "/notifications/workspaceLoaded", &mut self.notifications.workspace_loaded);
130 set(value, "/notifications/cargoTomlNotFound", &mut self.notifications.cargo_toml_not_found);
109 131
110 set(value, "/inlayHintsType", &mut self.inlay_hints.type_hints); 132 set(value, "/cargo/noDefaultFeatures", &mut self.cargo.no_default_features);
111 set(value, "/inlayHintsParameter", &mut self.inlay_hints.parameter_hints); 133 set(value, "/cargo/allFeatures", &mut self.cargo.all_features);
112 set(value, "/inlayHintsChaining", &mut self.inlay_hints.chaining_hints); 134 set(value, "/cargo/features", &mut self.cargo.features);
113 set(value, "/inlayHintsMaxLength", &mut self.inlay_hints.max_length); 135 set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check);
114 136 if let RustfmtConfig::Rustfmt { extra_args } = &mut self.rustfmt {
115 if let Some(false) = get(value, "cargo_watch_enable") { 137 set(value, "/rustfmt/extraArgs", extra_args);
138 }
139 if let Some(false) = get(value, "/checkOnSave/enable") {
116 self.check = None 140 self.check = None
117 } else { 141 } else {
118 if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets }) = &mut self.check 142 if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets }) = &mut self.check
119 { 143 {
120 set(value, "/cargoWatchArgs", extra_args); 144 set(value, "/checkOnSave/extraArgs", extra_args);
121 set(value, "/cargoWatchCommand", command); 145 set(value, "/checkOnSave/command", command);
122 set(value, "/cargoWatchAllTargets", all_targets); 146 set(value, "/checkOnSave/allTargets", all_targets);
123 } 147 }
124 }; 148 };
125 149
126 set(value, "/withSysroot", &mut self.with_sysroot); 150 set(value, "/inlayHints/typeHints", &mut self.inlay_hints.type_hints);
127 if let RustfmtConfig::Rustfmt { extra_args } = &mut self.rustfmt { 151 set(value, "/inlayHints/parameterHints", &mut self.inlay_hints.parameter_hints);
128 set(value, "/rustfmtArgs", extra_args); 152 set(value, "/inlayHints/chainingHints", &mut self.inlay_hints.chaining_hints);
129 } 153 set(value, "/inlayHints/maxLength", &mut self.inlay_hints.max_length);
130 154 set(value, "/completion/postfix/enable", &mut self.completion.enable_postfix_completions);
131 set(value, "/cargoFeatures/noDefaultFeatures", &mut self.cargo.no_default_features); 155 set(value, "/completion/addCallParenthesis", &mut self.completion.add_call_parenthesis);
132 set(value, "/cargoFeatures/allFeatures", &mut self.cargo.all_features); 156 set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets);
133 set(value, "/cargoFeatures/features", &mut self.cargo.features); 157 set(value, "/callInfo/full", &mut self.call_info_full);
134 set(value, "/cargoFeatures/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check);
135
136 set(value, "/vscodeLldb", &mut self.vscode_lldb);
137
138 set(value, "/featureFlags/lsp.diagnostics", &mut self.publish_diagnostics);
139 set(value, "/featureFlags/notifications.workspace-loaded", &mut self.notifications.workspace_loaded);
140 set(value, "/featureFlags/notifications.cargo-toml-not-found", &mut self.notifications.cargo_toml_not_found);
141 set(value, "/featureFlags/completion.enable-postfix", &mut self.completion.enable_postfix_completions);
142 set(value, "/featureFlags/completion.insertion.add-call-parenthesis", &mut self.completion.add_call_parenthesis);
143 set(value, "/featureFlags/completion.insertion.add-argument-snippets", &mut self.completion.add_call_argument_snippets);
144 set(value, "/featureFlags/call-info.full", &mut self.call_info_full);
145 158
146 log::info!("Config::update() = {:#?}", self); 159 log::info!("Config::update() = {:#?}", self);
147 160
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 47fef59d4..95e676e0f 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -30,7 +30,7 @@ use serde::{de::DeserializeOwned, Serialize};
30use threadpool::ThreadPool; 30use threadpool::ThreadPool;
31 31
32use crate::{ 32use crate::{
33 config::Config, 33 config::{Config, FilesWatcher},
34 diagnostics::DiagnosticTask, 34 diagnostics::DiagnosticTask,
35 main_loop::{ 35 main_loop::{
36 pending_requests::{PendingRequest, PendingRequests}, 36 pending_requests::{PendingRequest, PendingRequests},
@@ -40,7 +40,6 @@ use crate::{
40 world::{WorldSnapshot, WorldState}, 40 world::{WorldSnapshot, WorldState},
41 Result, 41 Result,
42}; 42};
43use req::ConfigurationParams;
44 43
45#[derive(Debug)] 44#[derive(Debug)]
46pub struct LspError { 45pub struct LspError {
@@ -122,12 +121,13 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
122 }; 121 };
123 122
124 let globs = config 123 let globs = config
125 .exclude_globs 124 .files
125 .exclude
126 .iter() 126 .iter()
127 .map(|glob| crate::vfs_glob::Glob::new(glob)) 127 .map(|glob| crate::vfs_glob::Glob::new(glob))
128 .collect::<std::result::Result<Vec<_>, _>>()?; 128 .collect::<std::result::Result<Vec<_>, _>>()?;
129 129
130 if config.use_client_watching { 130 if let FilesWatcher::Client = config.files.watcher {
131 let registration_options = req::DidChangeWatchedFilesRegistrationOptions { 131 let registration_options = req::DidChangeWatchedFilesRegistrationOptions {
132 watchers: workspaces 132 watchers: workspaces
133 .iter() 133 .iter()
@@ -153,7 +153,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
153 workspaces, 153 workspaces,
154 config.lru_capacity, 154 config.lru_capacity,
155 &globs, 155 &globs,
156 Watch(!config.use_client_watching), 156 Watch(matches!(config.files.watcher, FilesWatcher::Notify)),
157 config, 157 config,
158 ) 158 )
159 }; 159 };
@@ -607,7 +607,12 @@ fn on_notification(
607 let request_id = loop_state.next_request_id(); 607 let request_id = loop_state.next_request_id();
608 let request = request_new::<req::WorkspaceConfiguration>( 608 let request = request_new::<req::WorkspaceConfiguration>(
609 request_id.clone(), 609 request_id.clone(),
610 ConfigurationParams::default(), 610 req::ConfigurationParams {
611 items: vec![req::ConfigurationItem {
612 scope_uri: None,
613 section: Some("rust-analyzer".to_string()),
614 }],
615 },
611 ); 616 );
612 msg_sender.send(request.into())?; 617 msg_sender.send(request.into())?;
613 loop_state.configuration_request_id = Some(request_id); 618 loop_state.configuration_request_id = Some(request_id);
@@ -884,10 +889,9 @@ fn update_file_notifications_on_threadpool(
884 subscriptions: Vec<FileId>, 889 subscriptions: Vec<FileId>,
885) { 890) {
886 log::trace!("updating notifications for {:?}", subscriptions); 891 log::trace!("updating notifications for {:?}", subscriptions);
887 let publish_diagnostics = world.config.publish_diagnostics; 892 if world.config.publish_diagnostics {
888 pool.execute(move || { 893 pool.execute(move || {
889 for file_id in subscriptions { 894 for file_id in subscriptions {
890 if publish_diagnostics {
891 match handlers::publish_diagnostics(&world, file_id) { 895 match handlers::publish_diagnostics(&world, file_id) {
892 Err(e) => { 896 Err(e) => {
893 if !is_canceled(&e) { 897 if !is_canceled(&e) {
@@ -899,8 +903,8 @@ fn update_file_notifications_on_threadpool(
899 } 903 }
900 } 904 }
901 } 905 }
902 } 906 })
903 }); 907 }
904} 908}
905 909
906pub fn show_message(typ: req::MessageType, message: impl Into<String>, sender: &Sender<Message>) { 910pub fn show_message(typ: req::MessageType, message: impl Into<String>, sender: &Sender<Message>) {
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index db620dca3..b207f0764 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -810,23 +810,21 @@ pub fn handle_code_lens(
810 }; 810 };
811 lenses.push(lens); 811 lenses.push(lens);
812 812
813 if world.config.vscode_lldb { 813 if r.args[0] == "run" {
814 if r.args[0] == "run" { 814 r.args[0] = "build".into();
815 r.args[0] = "build".into(); 815 } else {
816 } else { 816 r.args.push("--no-run".into());
817 r.args.push("--no-run".into());
818 }
819 let debug_lens = CodeLens {
820 range: r.range,
821 command: Some(Command {
822 title: "Debug".into(),
823 command: "rust-analyzer.debugSingle".into(),
824 arguments: Some(vec![to_value(r).unwrap()]),
825 }),
826 data: None,
827 };
828 lenses.push(debug_lens);
829 } 817 }
818 let debug_lens = CodeLens {
819 range: r.range,
820 command: Some(Command {
821 title: "Debug".into(),
822 command: "rust-analyzer.debugSingle".into(),
823 arguments: Some(vec![to_value(r).unwrap()]),
824 }),
825 data: None,
826 };
827 lenses.push(debug_lens);
830 } 828 }
831 829
832 // Handle impls 830 // Handle impls
diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/req.rs
index ce799a683..b8b627e28 100644
--- a/crates/rust-analyzer/src/req.rs
+++ b/crates/rust-analyzer/src/req.rs
@@ -6,8 +6,8 @@ use serde::{Deserialize, Serialize};
6 6
7pub use lsp_types::{ 7pub use lsp_types::{
8 notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens, 8 notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens,
9 CodeLensParams, CompletionParams, CompletionResponse, ConfigurationParams, DiagnosticTag, 9 CodeLensParams, CompletionParams, CompletionResponse, ConfigurationItem, ConfigurationParams,
10 DidChangeConfigurationParams, DidChangeWatchedFilesParams, 10 DiagnosticTag, DidChangeConfigurationParams, DidChangeWatchedFilesParams,
11 DidChangeWatchedFilesRegistrationOptions, DocumentOnTypeFormattingParams, DocumentSymbolParams, 11 DidChangeWatchedFilesRegistrationOptions, DocumentOnTypeFormattingParams, DocumentSymbolParams,
12 DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType, 12 DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType,
13 PartialResultParams, ProgressParams, ProgressParamsValue, ProgressToken, 13 PartialResultParams, ProgressParams, ProgressParamsValue, ProgressToken,
diff --git a/editors/code/package.json b/editors/code/package.json
index 946145df8..1f95cd130 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -177,81 +177,70 @@
177 "type": "object", 177 "type": "object",
178 "title": "Rust Analyzer", 178 "title": "Rust Analyzer",
179 "properties": { 179 "properties": {
180 "rust-analyzer.highlighting.semanticTokens": { 180 "rust-analyzer.diagnostics.enable": {
181 "type": "boolean", 181 "type": "boolean",
182 "default": false, 182 "default": true,
183 "description": "Use proposed semantic tokens API for syntax highlighting" 183 "markdownDescription": "Whether to show native rust-analyzer diagnostics."
184 }, 184 },
185 "rust-analyzer.featureFlags": { 185 "rust-analyzer.lruCapacity": {
186 "type": "object", 186 "type": [
187 "default": {}, 187 "null",
188 "description": "Fine grained feature flags to disable annoying features", 188 "integer"
189 "properties": { 189 ],
190 "lsp.diagnostics": { 190 "default": null,
191 "type": "boolean", 191 "minimum": 0,
192 "markdownDescription": "Whether to show diagnostics from `cargo check`" 192 "exclusiveMinimum": true,
193 }, 193 "description": "Number of syntax trees rust-analyzer keeps in memory."
194 "completion.insertion.add-call-parenthesis": {
195 "type": "boolean",
196 "description": "Whether to add parenthesis when completing functions"
197 },
198 "completion.insertion.add-argument-snippets": {
199 "type": "boolean",
200 "description": "Whether to add argument snippets when completing functions"
201 },
202 "completion.enable-postfix": {
203 "type": "boolean",
204 "markdownDescription": "Whether to show postfix snippets like `dbg`, `if`, `not`, etc."
205 },
206 "call-info.full": {
207 "type": "boolean",
208 "description": "Show function name and docs in parameter hints"
209 },
210 "notifications.workspace-loaded": {
211 "type": "boolean",
212 "markdownDescription": "Whether to show `workspace loaded` message"
213 },
214 "notifications.cargo-toml-not-found": {
215 "type": "boolean",
216 "markdownDescription": "Whether to show `can't find Cargo.toml` error message"
217 }
218 }
219 }, 194 },
220 "rust-analyzer.updates.channel": { 195 "rust-analyzer.files.watcher": {
221 "type": "string", 196 "type": "string",
222 "enum": [ 197 "enum": [
223 "stable", 198 "client",
224 "nightly" 199 "notify"
225 ],
226 "default": "stable",
227 "markdownEnumDescriptions": [
228 "`\"stable\"` updates are shipped weekly, they don't contain cutting-edge features from VSCode proposed APIs but have less bugs in general",
229 "`\"nightly\"` updates are shipped daily (extension updates automatically by downloading artifacts directly from GitHub), they contain cutting-edge features and latest bug fixes. These releases help us get your feedback very quickly and speed up rust-analyzer development **drastically**"
230 ], 200 ],
231 "markdownDescription": "Choose `\"nightly\"` updates to get the latest features and bug fixes every day. While `\"stable\"` releases occur weekly and don't contain cutting-edge features from VSCode proposed APIs" 201 "default": "client",
202 "description": "Controls file watching implementation."
232 }, 203 },
233 "rust-analyzer.updates.askBeforeDownload": { 204 "rust-analyzer.files.exclude": {
205 "type": "array",
206 "items": {
207 "type": "string"
208 },
209 "default": [],
210 "description": "Paths to exclude from analysis."
211 },
212 "rust-analyzer.notifications.workspaceLoaded": {
234 "type": "boolean", 213 "type": "boolean",
235 "default": true, 214 "markdownDescription": "Whether to show `workspace loaded` message."
236 "description": "Whether to ask for permission before downloading any files from the Internet"
237 }, 215 },
238 "rust-analyzer.serverPath": { 216 "rust-analyzer.notifications.cargoTomlNotFound": {
239 "type": [ 217 "type": "boolean",
240 "null", 218 "markdownDescription": "Whether to show `can't find Cargo.toml` error message"
241 "string" 219 },
242 ], 220 "rust-analyzer.cargo.noDefaultFeatures": {
243 "default": null, 221 "type": "boolean",
244 "description": "Path to rust-analyzer executable (points to bundled binary by default). If this is set, then \"rust-analyzer.updates.channel\" setting is not used" 222 "default": false,
223 "markdownDescription": "Do not activate the `default` feature"
224 },
225 "rust-analyzer.cargo.allFeatures": {
226 "type": "boolean",
227 "default": true,
228 "description": "Activate all available features"
245 }, 229 },
246 "rust-analyzer.excludeGlobs": { 230 "rust-analyzer.cargo.features": {
247 "type": "array", 231 "type": "array",
248 "items": { 232 "items": {
249 "type": "string" 233 "type": "string"
250 }, 234 },
251 "default": [], 235 "default": [],
252 "description": "Paths to exclude from analysis" 236 "description": "List of features to activate"
237 },
238 "rust-analyzer.cargo.loadOutDirsFromCheck": {
239 "type": "boolean",
240 "default": false,
241 "markdownDescription": "Run `cargo check` on startup to get the correct value for package OUT_DIRs"
253 }, 242 },
254 "rust-analyzer.rustfmtArgs": { 243 "rust-analyzer.rustfmt.extraArgs": {
255 "type": "array", 244 "type": "array",
256 "items": { 245 "items": {
257 "type": "string" 246 "type": "string"
@@ -259,64 +248,28 @@
259 "default": [], 248 "default": [],
260 "description": "Additional arguments to rustfmt" 249 "description": "Additional arguments to rustfmt"
261 }, 250 },
262 "rust-analyzer.useClientWatching": { 251 "rust-analyzer.checkOnSave.enable": {
263 "type": "boolean", 252 "type": "boolean",
264 "default": true, 253 "default": true,
265 "description": "client provided file watching instead of notify watching." 254 "markdownDescription": "Run specified `cargo check` command for diagnostics on save"
266 }, 255 },
267 "rust-analyzer.cargo-watch.enable": { 256 "rust-analyzer.checkOnSave.extraArgs": {
268 "type": "boolean",
269 "default": true,
270 "markdownDescription": "Run specified `cargo-watch` command for diagnostics on save"
271 },
272 "rust-analyzer.cargo-watch.arguments": {
273 "type": "array", 257 "type": "array",
274 "items": { 258 "items": {
275 "type": "string" 259 "type": "string"
276 }, 260 },
277 "markdownDescription": "`cargo-watch` arguments. (e.g: `--features=\"shumway,pdf\"` will run as `cargo watch -x \"check --features=\"shumway,pdf\"\"` )", 261 "markdownDescription": "Extra arguments for `cargo check`",
278 "default": [] 262 "default": []
279 }, 263 },
280 "rust-analyzer.cargo-watch.command": { 264 "rust-analyzer.checkOnSave.command": {
281 "type": "string",
282 "markdownDescription": "`cargo-watch` command. (e.g: `clippy` will run as `cargo watch -x clippy` )",
283 "default": "check"
284 },
285 "rust-analyzer.cargo-watch.allTargets": {
286 "type": "boolean",
287 "markdownDescription": "Check all targets and tests (will be passed as `--all-targets`)",
288 "default": true
289 },
290 "rust-analyzer.trace.server": {
291 "type": "string", 265 "type": "string",
292 "scope": "window", 266 "default": "check",
293 "enum": [ 267 "markdownDescription": "Cargo command to use for `cargo check`"
294 "off",
295 "messages",
296 "verbose"
297 ],
298 "enumDescriptions": [
299 "No traces",
300 "Error only",
301 "Full log"
302 ],
303 "default": "off",
304 "description": "Trace requests to the rust-analyzer"
305 }, 268 },
306 "rust-analyzer.trace.extension": { 269 "rust-analyzer.checkOnSave.allTargets": {
307 "description": "Enable logging of VS Code extensions itself",
308 "type": "boolean", 270 "type": "boolean",
309 "default": false 271 "default": true,
310 }, 272 "markdownDescription": "Check all targets and tests (will be passed as `--all-targets`)"
311 "rust-analyzer.lruCapacity": {
312 "type": [
313 "null",
314 "integer"
315 ],
316 "default": null,
317 "minimum": 0,
318 "exclusiveMinimum": true,
319 "description": "Number of syntax trees rust-analyzer keeps in memory"
320 }, 273 },
321 "rust-analyzer.inlayHints.typeHints": { 274 "rust-analyzer.inlayHints.typeHints": {
322 "type": "boolean", 275 "type": "boolean",
@@ -343,28 +296,76 @@
343 "exclusiveMinimum": true, 296 "exclusiveMinimum": true,
344 "description": "Maximum length for inlay hints" 297 "description": "Maximum length for inlay hints"
345 }, 298 },
346 "rust-analyzer.cargoFeatures.noDefaultFeatures": { 299 "rust-analyzer.completion.addCallParenthesis": {
347 "type": "boolean", 300 "type": "boolean",
348 "default": false, 301 "default": true,
349 "markdownDescription": "Do not activate the `default` feature" 302 "description": "Whether to add parenthesis when completing functions"
350 }, 303 },
351 "rust-analyzer.cargoFeatures.allFeatures": { 304 "rust-analyzer.completion.addCallArgumentSnippets": {
352 "type": "boolean", 305 "type": "boolean",
353 "default": true, 306 "default": true,
354 "description": "Activate all available features" 307 "description": "Whether to add argument snippets when completing functions"
355 }, 308 },
356 "rust-analyzer.cargoFeatures.features": { 309 "rust-analyzer.completion.postfix.enable": {
357 "type": "array", 310 "type": "boolean",
358 "items": { 311 "default": true,
359 "type": "string" 312 "markdownDescription": "Whether to show postfix snippets like `dbg`, `if`, `not`, etc."
360 }, 313 },
361 "default": [], 314 "rust-analyzer.callInfo.full": {
362 "description": "List of features to activate" 315 "type": "boolean",
316 "description": "Show function name and docs in parameter hints"
363 }, 317 },
364 "rust-analyzer.cargoFeatures.loadOutDirsFromCheck": { 318 "rust-analyzer.highlighting.semanticTokens": {
365 "type": "boolean", 319 "type": "boolean",
366 "default": false, 320 "default": false,
367 "markdownDescription": "Run `cargo check` on startup to get the correct value for package OUT_DIRs" 321 "description": "Use proposed semantic tokens API for syntax highlighting"
322 },
323 "rust-analyzer.updates.channel": {
324 "type": "string",
325 "enum": [
326 "stable",
327 "nightly"
328 ],
329 "default": "stable",
330 "markdownEnumDescriptions": [
331 "`\"stable\"` updates are shipped weekly, they don't contain cutting-edge features from VSCode proposed APIs but have less bugs in general",
332 "`\"nightly\"` updates are shipped daily (extension updates automatically by downloading artifacts directly from GitHub), they contain cutting-edge features and latest bug fixes. These releases help us get your feedback very quickly and speed up rust-analyzer development **drastically**"
333 ],
334 "markdownDescription": "Choose `\"nightly\"` updates to get the latest features and bug fixes every day. While `\"stable\"` releases occur weekly and don't contain cutting-edge features from VSCode proposed APIs"
335 },
336 "rust-analyzer.updates.askBeforeDownload": {
337 "type": "boolean",
338 "default": true,
339 "description": "Whether to ask for permission before downloading any files from the Internet"
340 },
341 "rust-analyzer.serverPath": {
342 "type": [
343 "null",
344 "string"
345 ],
346 "default": null,
347 "description": "Path to rust-analyzer executable (points to bundled binary by default). If this is set, then \"rust-analyzer.updates.channel\" setting is not used"
348 },
349 "rust-analyzer.trace.server": {
350 "type": "string",
351 "scope": "window",
352 "enum": [
353 "off",
354 "messages",
355 "verbose"
356 ],
357 "enumDescriptions": [
358 "No traces",
359 "Error only",
360 "Full log"
361 ],
362 "default": "off",
363 "description": "Trace requests to the rust-analyzer"
364 },
365 "rust-analyzer.trace.extension": {
366 "description": "Enable logging of VS Code extensions itself",
367 "type": "boolean",
368 "default": false
368 } 369 }
369 } 370 }
370 }, 371 },
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index 8ddc1cdca..3b1d00bca 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -5,30 +5,6 @@ import { Config } from './config';
5import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.proposed'; 5import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.proposed';
6import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed'; 6import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed';
7 7
8export function configToServerOptions(config: Config) {
9 return {
10 lruCapacity: config.lruCapacity,
11
12 inlayHintsType: config.inlayHints.typeHints,
13 inlayHintsParameter: config.inlayHints.parameterHints,
14 inlayHintsChaining: config.inlayHints.chainingHints,
15 inlayHintsMaxLength: config.inlayHints.maxLength,
16
17 cargoWatchEnable: config.cargoWatchOptions.enable,
18 cargoWatchArgs: config.cargoWatchOptions.arguments,
19 cargoWatchCommand: config.cargoWatchOptions.command,
20 cargoWatchAllTargets: config.cargoWatchOptions.allTargets,
21
22 excludeGlobs: config.excludeGlobs,
23 useClientWatching: config.useClientWatching,
24 featureFlags: config.featureFlags,
25 withSysroot: config.withSysroot,
26 cargoFeatures: config.cargoFeatures,
27 rustfmtArgs: config.rustfmtArgs,
28 vscodeLldb: vscode.extensions.getExtension("vadimcn.vscode-lldb") != null,
29 };
30}
31
32export async function createClient(config: Config, serverPath: string, cwd: string): Promise<lc.LanguageClient> { 8export async function createClient(config: Config, serverPath: string, cwd: string): Promise<lc.LanguageClient> {
33 // '.' Is the fallback if no folder is open 9 // '.' Is the fallback if no folder is open
34 // TODO?: Workspace folders support Uri's (eg: file://test.txt). 10 // TODO?: Workspace folders support Uri's (eg: file://test.txt).
@@ -48,7 +24,7 @@ export async function createClient(config: Config, serverPath: string, cwd: stri
48 24
49 const clientOptions: lc.LanguageClientOptions = { 25 const clientOptions: lc.LanguageClientOptions = {
50 documentSelector: [{ scheme: 'file', language: 'rust' }], 26 documentSelector: [{ scheme: 'file', language: 'rust' }],
51 initializationOptions: configToServerOptions(config), 27 initializationOptions: vscode.workspace.getConfiguration("rust-analyzer"),
52 traceOutputChannel, 28 traceOutputChannel,
53 middleware: { 29 middleware: {
54 // Workaround for https://github.com/microsoft/vscode-languageserver-node/issues/576 30 // Workaround for https://github.com/microsoft/vscode-languageserver-node/issues/576
diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts
index 357155163..2635a1440 100644
--- a/editors/code/src/commands/runnables.ts
+++ b/editors/code/src/commands/runnables.ts
@@ -66,6 +66,10 @@ export function debugSingle(ctx: Ctx): Cmd {
66 return async (config: ra.Runnable) => { 66 return async (config: ra.Runnable) => {
67 const editor = ctx.activeRustEditor; 67 const editor = ctx.activeRustEditor;
68 if (!editor) return; 68 if (!editor) return;
69 if (!vscode.extensions.getExtension("vadimcn.vscode-lldb")) {
70 vscode.window.showErrorMessage("Install `vadimcn.vscode-lldb` extension for debugging");
71 return;
72 }
69 73
70 const debugConfig = { 74 const debugConfig = {
71 type: "lldb", 75 type: "lldb",
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index c37c6276b..1f45f1de0 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -11,9 +11,8 @@ export class Config {
11 private readonly rootSection = "rust-analyzer"; 11 private readonly rootSection = "rust-analyzer";
12 private readonly requiresReloadOpts = [ 12 private readonly requiresReloadOpts = [
13 "serverPath", 13 "serverPath",
14 "cargoFeatures", 14 "cargo",
15 "excludeGlobs", 15 "files",
16 "useClientWatching",
17 "highlighting", 16 "highlighting",
18 "updates.channel", 17 "updates.channel",
19 ] 18 ]
@@ -71,17 +70,8 @@ export class Config {
71 get channel() { return this.cfg.get<UpdatesChannel>("updates.channel")!; } 70 get channel() { return this.cfg.get<UpdatesChannel>("updates.channel")!; }
72 get askBeforeDownload() { return this.cfg.get<boolean>("updates.askBeforeDownload")!; } 71 get askBeforeDownload() { return this.cfg.get<boolean>("updates.askBeforeDownload")!; }
73 get highlightingSemanticTokens() { return this.cfg.get<boolean>("highlighting.semanticTokens")!; } 72 get highlightingSemanticTokens() { return this.cfg.get<boolean>("highlighting.semanticTokens")!; }
74 get lruCapacity() { return this.cfg.get<null | number>("lruCapacity")!; }
75 get excludeGlobs() { return this.cfg.get<string[]>("excludeGlobs")!; }
76 get useClientWatching() { return this.cfg.get<boolean>("useClientWatching")!; }
77 get featureFlags() { return this.cfg.get<Record<string, boolean>>("featureFlags")!; }
78 get rustfmtArgs() { return this.cfg.get<string[]>("rustfmtArgs")!; }
79 get loadOutDirsFromCheck() { return this.cfg.get<boolean>("loadOutDirsFromCheck")!; }
80 get traceExtension() { return this.cfg.get<boolean>("trace.extension")!; } 73 get traceExtension() { return this.cfg.get<boolean>("trace.extension")!; }
81 74
82 // for internal use
83 get withSysroot() { return this.cfg.get<boolean>("withSysroot", true)!; }
84
85 get inlayHints() { 75 get inlayHints() {
86 return { 76 return {
87 typeHints: this.cfg.get<boolean>("inlayHints.typeHints")!, 77 typeHints: this.cfg.get<boolean>("inlayHints.typeHints")!,
@@ -91,21 +81,9 @@ export class Config {
91 }; 81 };
92 } 82 }
93 83
94 get cargoWatchOptions() { 84 get checkOnSave() {
95 return {
96 enable: this.cfg.get<boolean>("cargo-watch.enable")!,
97 arguments: this.cfg.get<string[]>("cargo-watch.arguments")!,
98 allTargets: this.cfg.get<boolean>("cargo-watch.allTargets")!,
99 command: this.cfg.get<string>("cargo-watch.command")!,
100 };
101 }
102
103 get cargoFeatures() {
104 return { 85 return {
105 noDefaultFeatures: this.cfg.get<boolean>("cargoFeatures.noDefaultFeatures")!, 86 command: this.cfg.get<string>("checkOnSave.command")!,
106 allFeatures: this.cfg.get<boolean>("cargoFeatures.allFeatures")!,
107 features: this.cfg.get<string[]>("cargoFeatures.features")!,
108 loadOutDirsFromCheck: this.cfg.get<boolean>("cargoFeatures.loadOutDirsFromCheck")!,
109 }; 87 };
110 } 88 }
111} 89}
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts
index 86b5f3629..bd1c3de07 100644
--- a/editors/code/src/ctx.ts
+++ b/editors/code/src/ctx.ts
@@ -2,7 +2,7 @@ import * as vscode from 'vscode';
2import * as lc from 'vscode-languageclient'; 2import * as lc from 'vscode-languageclient';
3 3
4import { Config } from './config'; 4import { Config } from './config';
5import { createClient, configToServerOptions } from './client'; 5import { createClient } from './client';
6import { isRustEditor, RustEditor } from './util'; 6import { isRustEditor, RustEditor } from './util';
7 7
8export class Ctx { 8export class Ctx {
@@ -25,7 +25,6 @@ export class Ctx {
25 const res = new Ctx(config, extCtx, client, serverPath); 25 const res = new Ctx(config, extCtx, client, serverPath);
26 res.pushCleanup(client.start()); 26 res.pushCleanup(client.start());
27 await client.onReady(); 27 await client.onReady();
28 client.onRequest('workspace/configuration', _ => [configToServerOptions(config)]);
29 return res; 28 return res;
30 } 29 }
31 30
diff --git a/editors/code/src/status_display.ts b/editors/code/src/status_display.ts
index 0f5f6ef99..f9cadc8a2 100644
--- a/editors/code/src/status_display.ts
+++ b/editors/code/src/status_display.ts
@@ -7,7 +7,7 @@ import { Ctx } from './ctx';
7const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; 7const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
8 8
9export function activateStatusDisplay(ctx: Ctx) { 9export function activateStatusDisplay(ctx: Ctx) {
10 const statusDisplay = new StatusDisplay(ctx.config.cargoWatchOptions.command); 10 const statusDisplay = new StatusDisplay(ctx.config.checkOnSave.command);
11 ctx.pushCleanup(statusDisplay); 11 ctx.pushCleanup(statusDisplay);
12 const client = ctx.client; 12 const client = ctx.client;
13 if (client != null) { 13 if (client != null) {