]> git.lizzy.rs Git - rust.git/blobdiff - crates/rust-analyzer/src/config.rs
Add toggle to disable cache priming
[rust.git] / crates / rust-analyzer / src / config.rs
index 58539543ee81c39a7e88aff5eca22b4be2e92bb1..5826b6b114c2b455e68eab0d2a08e4b5eacf5f74 100644 (file)
@@ -12,8 +12,7 @@
 use flycheck::FlycheckConfig;
 use ide::{
     AssistConfig, CompletionConfig, DiagnosticsConfig, HighlightRelatedConfig, HoverConfig,
-    HoverDocFormat, InlayHintsConfig, JoinLinesConfig, PostfixSnippet, PostfixSnippetScope,
-    Snippet, SnippetScope,
+    HoverDocFormat, InlayHintsConfig, JoinLinesConfig, Snippet, SnippetScope,
 };
 use ide_db::helpers::{
     insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
@@ -59,6 +58,9 @@ struct ConfigData {
         /// Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`.
         assist_allowMergingIntoGlobImports: bool           = "true",
 
+        /// Warm up caches on project load.
+        cache_warmup: bool = "true",
+
         /// Show function name and docs in parameter hints.
         callInfo_full: bool                                = "true",
 
@@ -117,8 +119,6 @@ struct ConfigData {
         completion_snippets: FxHashMap<String, SnippetDef> = "{}",
         /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
         completion_postfix_enable: bool          = "true",
-        /// Custom postfix completion snippets.
-        completion_postfix_snippets: FxHashMap<String, PostfixSnippetDef> = "{}",
         /// Toggles the additional completions that automatically add imports when completed.
         /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
         completion_autoimport_enable: bool       = "true",
@@ -198,14 +198,16 @@ struct ConfigData {
         hoverActions_run: bool             = "true",
 
         /// Whether to show inlay type hints for method chains.
-        inlayHints_chainingHints: bool      = "true",
+        inlayHints_chainingHints: bool              = "true",
         /// Maximum length for inlay hints. Set to null to have an unlimited length.
-        inlayHints_maxLength: Option<usize> = "25",
+        inlayHints_maxLength: Option<usize>         = "25",
         /// Whether to show function parameter name inlay hints at the call
         /// site.
-        inlayHints_parameterHints: bool     = "true",
+        inlayHints_parameterHints: bool             = "true",
         /// Whether to show inlay type hints for variables.
-        inlayHints_typeHints: bool          = "true",
+        inlayHints_typeHints: bool                  = "true",
+        /// Whether to hide inlay hints for constructors.
+        inlayHints_hideNamedConstructorHints: bool  = "false",
 
         /// Join lines inserts else between consecutive ifs.
         joinLines_joinElseIf: bool = "true",
@@ -230,9 +232,12 @@ struct ConfigData {
         /// Whether to show `Method References` lens. Only applies when
         /// `#rust-analyzer.lens.enable#` is set.
         lens_methodReferences: bool = "false",
-        /// Whether to show `References` lens. Only applies when
-        /// `#rust-analyzer.lens.enable#` is set.
+        /// Whether to show `References` lens for Struct, Enum, Union and Trait.
+        /// Only applies when `#rust-analyzer.lens.enable#` is set.
         lens_references: bool = "false",
+        /// Whether to show `References` lens for Enum Variants.
+        /// Only applies when `#rust-analyzer.lens.enable#` is set.
+        lens_enumVariantReferences: bool = "false",
         /// Internal config: use custom client-side commands even when the
         /// client doesn't set the corresponding capability.
         lens_forceCustomCommands: bool = "true",
@@ -263,12 +268,13 @@ struct ConfigData {
         runnables_cargoExtraArgs: Vec<String>   = "[]",
 
         /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private
-        /// projects, or "discover" to try to automatically find it.
+        /// projects, or "discover" to try to automatically find it if the `rustc-dev` component
+        /// is installed.
         ///
         /// Any project which uses rust-analyzer with the rustcPrivate
         /// crates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.
         ///
-        /// This option is not reloaded automatically; you must restart rust-analyzer for it to take effect.
+        /// This option does not take effect until rust-analyzer is restarted.
         rustcSource: Option<String> = "null",
 
         /// Additional arguments to `rustfmt`.
@@ -282,9 +288,9 @@ struct ConfigData {
         rustfmt_enableRangeFormatting: bool = "false",
 
         /// Workspace symbol search scope.
-        workspace_symbol_search_scope: WorskpaceSymbolSearchScopeDef = "\"workspace\"",
+        workspace_symbol_search_scope: WorkspaceSymbolSearchScopeDef = "\"workspace\"",
         /// Workspace symbol search kind.
-        workspace_symbol_search_kind: WorskpaceSymbolSearchKindDef = "\"only_types\"",
+        workspace_symbol_search_kind: WorkspaceSymbolSearchKindDef = "\"only_types\"",
     }
 }
 
@@ -301,7 +307,6 @@ pub struct Config {
     detached_files: Vec<AbsPathBuf>,
     pub discovered_projects: Option<Vec<ProjectManifest>>,
     pub root_path: AbsPathBuf,
-    postfix_snippets: Vec<PostfixSnippet>,
     snippets: Vec<Snippet>,
 }
 
@@ -330,6 +335,7 @@ pub struct LensConfig {
     pub implementations: bool,
     pub method_refs: bool,
     pub refs: bool, // for Struct, Enum, Union and Trait
+    pub enum_variant_refs: bool,
 }
 
 impl LensConfig {
@@ -346,7 +352,7 @@ pub fn runnable(&self) -> bool {
     }
 
     pub fn references(&self) -> bool {
-        self.method_refs || self.refs
+        self.method_refs || self.refs || self.enum_variant_refs
     }
 }
 
@@ -438,7 +444,6 @@ pub fn new(root_path: AbsPathBuf, caps: ClientCapabilities) -> Self {
             detached_files: Vec::new(),
             discovered_projects: None,
             root_path,
-            postfix_snippets: Default::default(),
             snippets: Default::default(),
         }
     }
@@ -452,40 +457,28 @@ pub fn update(&mut self, mut json: serde_json::Value) {
             .map(AbsPathBuf::assert)
             .collect();
         self.data = ConfigData::from_json(json);
-        self.postfix_snippets = self
-            .data
-            .completion_postfix_snippets
-            .iter()
-            .flat_map(|(label, desc)| {
-                PostfixSnippet::new(
-                    label.clone(),
-                    &desc.snippet,
-                    &desc.description,
-                    &desc.requires,
-                    desc.scope.map(|scope| match scope {
-                        PostfixSnippetScopeDef::Expr => PostfixSnippetScope::Expr,
-                        PostfixSnippetScopeDef::Type => PostfixSnippetScope::Type,
-                    }),
-                )
-            })
-            .collect();
-        self.snippets = self
-            .data
-            .completion_snippets
-            .iter()
-            .flat_map(|(label, desc)| {
-                Snippet::new(
-                    label.clone(),
-                    &desc.snippet,
-                    &desc.description,
-                    &desc.requires,
-                    desc.scope.map(|scope| match scope {
-                        SnippetScopeDef::Expr => SnippetScope::Expr,
-                        SnippetScopeDef::Item => SnippetScope::Item,
-                    }),
-                )
-            })
-            .collect();
+        self.snippets.clear();
+        for (name, def) in self.data.completion_snippets.iter() {
+            if def.prefix.is_empty() && def.postfix.is_empty() {
+                continue;
+            }
+            let scope = match def.scope {
+                SnippetScopeDef::Expr => SnippetScope::Expr,
+                SnippetScopeDef::Type => SnippetScope::Type,
+                SnippetScopeDef::Item => SnippetScope::Item,
+            };
+            match Snippet::new(
+                &def.prefix,
+                &def.postfix,
+                &def.body,
+                def.description.as_ref().unwrap_or(name),
+                &def.requires,
+                scope,
+            ) {
+                Some(snippet) => self.snippets.push(snippet),
+                None => tracing::info!("Invalid snippet {}", name),
+            }
+        }
     }
 
     pub fn json_schema() -> serde_json::Value {
@@ -555,6 +548,10 @@ pub fn did_change_watched_files_dynamic_registration(&self) -> bool {
         )
     }
 
+    pub fn prefill_caches(&self) -> bool {
+        self.data.cache_warmup
+    }
+
     pub fn location_link(&self) -> bool {
         try_or!(self.caps.text_document.as_ref()?.definition?.link_support?, false)
     }
@@ -780,6 +777,7 @@ pub fn inlay_hints(&self) -> InlayHintsConfig {
             type_hints: self.data.inlayHints_typeHints,
             parameter_hints: self.data.inlayHints_parameterHints,
             chaining_hints: self.data.inlayHints_chainingHints,
+            hide_named_constructor_hints: self.data.inlayHints_hideNamedConstructorHints,
             max_length: self.data.inlayHints_maxLength,
         }
     }
@@ -821,7 +819,6 @@ pub fn completion(&self) -> CompletionConfig {
                     .snippet_support?,
                 false
             )),
-            postfix_snippets: self.postfix_snippets.clone(),
             snippets: self.snippets.clone(),
         }
     }
@@ -850,6 +847,7 @@ pub fn lens(&self) -> LensConfig {
             implementations: self.data.lens_enable && self.data.lens_implementations,
             method_refs: self.data.lens_enable && self.data.lens_methodReferences,
             refs: self.data.lens_enable && self.data.lens_references,
+            enum_variant_refs: self.data.lens_enable && self.data.lens_enumVariantReferences,
         }
     }
     pub fn hover_actions(&self) -> HoverActionsConfig {
@@ -893,14 +891,14 @@ pub fn hover(&self) -> HoverConfig {
     pub fn workspace_symbol(&self) -> WorkspaceSymbolConfig {
         WorkspaceSymbolConfig {
             search_scope: match self.data.workspace_symbol_search_scope {
-                WorskpaceSymbolSearchScopeDef::Workspace => WorkspaceSymbolSearchScope::Workspace,
-                WorskpaceSymbolSearchScopeDef::WorkspaceAndDependencies => {
+                WorkspaceSymbolSearchScopeDef::Workspace => WorkspaceSymbolSearchScope::Workspace,
+                WorkspaceSymbolSearchScopeDef::WorkspaceAndDependencies => {
                     WorkspaceSymbolSearchScope::WorkspaceAndDependencies
                 }
             },
             search_kind: match self.data.workspace_symbol_search_kind {
-                WorskpaceSymbolSearchKindDef::OnlyTypes => WorkspaceSymbolSearchKind::OnlyTypes,
-                WorskpaceSymbolSearchKindDef::AllSymbols => WorkspaceSymbolSearchKind::AllSymbols,
+                WorkspaceSymbolSearchKindDef::OnlyTypes => WorkspaceSymbolSearchKind::OnlyTypes,
+                WorkspaceSymbolSearchKindDef::AllSymbols => WorkspaceSymbolSearchKind::AllSymbols,
             },
         }
     }
@@ -954,37 +952,32 @@ pub fn highlight_related(&self) -> HighlightRelatedConfig {
 }
 
 #[derive(Deserialize, Debug, Clone, Copy)]
-enum PostfixSnippetScopeDef {
-    Expr,
-    Type,
-}
-
-#[derive(Deserialize, Debug, Clone, Copy)]
+#[serde(rename_all = "snake_case")]
 enum SnippetScopeDef {
     Expr,
     Item,
+    Type,
 }
 
-#[derive(Deserialize, Debug, Clone)]
-struct PostfixSnippetDef {
-    #[serde(deserialize_with = "single_or_array")]
-    description: Vec<String>,
-    #[serde(deserialize_with = "single_or_array")]
-    snippet: Vec<String>,
-    #[serde(deserialize_with = "single_or_array")]
-    requires: Vec<String>,
-    scope: Option<PostfixSnippetScopeDef>,
+impl Default for SnippetScopeDef {
+    fn default() -> Self {
+        SnippetScopeDef::Expr
+    }
 }
 
-#[derive(Deserialize, Debug, Clone)]
+#[derive(Deserialize, Debug, Clone, Default)]
+#[serde(default)]
 struct SnippetDef {
     #[serde(deserialize_with = "single_or_array")]
-    description: Vec<String>,
+    prefix: Vec<String>,
+    #[serde(deserialize_with = "single_or_array")]
+    postfix: Vec<String>,
+    description: Option<String>,
     #[serde(deserialize_with = "single_or_array")]
-    snippet: Vec<String>,
+    body: Vec<String>,
     #[serde(deserialize_with = "single_or_array")]
     requires: Vec<String>,
-    scope: Option<SnippetScopeDef>,
+    scope: SnippetScopeDef,
 }
 
 fn single_or_array<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
@@ -1049,14 +1042,14 @@ enum ImportPrefixDef {
 
 #[derive(Deserialize, Debug, Clone)]
 #[serde(rename_all = "snake_case")]
-enum WorskpaceSymbolSearchScopeDef {
+enum WorkspaceSymbolSearchScopeDef {
     Workspace,
     WorkspaceAndDependencies,
 }
 
 #[derive(Deserialize, Debug, Clone)]
 #[serde(rename_all = "snake_case")]
-enum WorskpaceSymbolSearchKindDef {
+enum WorkspaceSymbolSearchKindDef {
     OnlyTypes,
     AllSymbols,
 }
@@ -1187,6 +1180,9 @@ macro_rules! set {
             "items": { "type": "string" },
             "uniqueItems": true,
         },
+        "FxHashMap<String, SnippetDef>" => set! {
+            "type": "object",
+        },
         "FxHashMap<String, String>" => set! {
             "type": "object",
         },
@@ -1243,7 +1239,7 @@ macro_rules! set {
             "type": "array",
             "items": { "type": ["string", "object"] },
         },
-        "WorskpaceSymbolSearchScopeDef" => set! {
+        "WorkspaceSymbolSearchScopeDef" => set! {
             "type": "string",
             "enum": ["workspace", "workspace_and_dependencies"],
             "enumDescriptions": [
@@ -1251,7 +1247,7 @@ macro_rules! set {
                 "Search in current workspace and dependencies"
             ],
         },
-        "WorskpaceSymbolSearchKindDef" => set! {
+        "WorkspaceSymbolSearchKindDef" => set! {
             "type": "string",
             "enum": ["only_types", "all_symbols"],
             "enumDescriptions": [
@@ -1303,6 +1299,29 @@ fn generate_package_json_config() {
             .to_string();
         schema.push_str(",\n");
 
+        // Transform the asciidoc form link to markdown style.
+        //
+        // https://link[text] => [text](https://link)
+        let url_matches = schema.match_indices("https://");
+        let mut url_offsets = url_matches.map(|(idx, _)| idx).collect::<Vec<usize>>();
+        url_offsets.reverse();
+        for idx in url_offsets {
+            let link = &schema[idx..];
+            // matching on whitespace to ignore normal links
+            if let Some(link_end) = link.find(|c| c == ' ' || c == '[') {
+                if link.chars().nth(link_end) == Some('[') {
+                    if let Some(link_text_end) = link.find(']') {
+                        let link_text = link[link_end..(link_text_end + 1)].to_string();
+
+                        schema.replace_range((idx + link_end)..(idx + link_text_end + 1), "");
+                        schema.insert(idx, '(');
+                        schema.insert(idx + link_end + 1, ')');
+                        schema.insert_str(idx, &link_text);
+                    }
+                }
+            }
+        }
+
         let package_json_path = project_root().join("editors/code/package.json");
         let mut package_json = fs::read_to_string(&package_json_path).unwrap();