use flycheck::FlycheckConfig;
use ide::{
AssistConfig, CompletionConfig, DiagnosticsConfig, HighlightRelatedConfig, HoverConfig,
- HoverDocFormat, InlayHintsConfig, JoinLinesConfig,
+ HoverDocFormat, InlayHintsConfig, JoinLinesConfig, Snippet, SnippetScope,
};
use ide_db::helpers::{
insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
/// 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",
completion_addCallArgumentSnippets: bool = "true",
/// Whether to add parenthesis when completing functions.
completion_addCallParenthesis: bool = "true",
+ /// Custom completion snippets.
+ completion_snippets: FxHashMap<String, SnippetDef> = "{}",
/// Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
completion_postfix_enable: bool = "true",
/// Toggles the additional completions that automatically add imports when completed.
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",
/// 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",
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`.
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\"",
}
}
detached_files: Vec<AbsPathBuf>,
pub discovered_projects: Option<Vec<ProjectManifest>>,
pub root_path: AbsPathBuf,
+ snippets: Vec<Snippet>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub implementations: bool,
pub method_refs: bool,
pub refs: bool, // for Struct, Enum, Union and Trait
+ pub enum_variant_refs: bool,
}
impl LensConfig {
}
pub fn references(&self) -> bool {
- self.method_refs || self.refs
+ self.method_refs || self.refs || self.enum_variant_refs
}
}
detached_files: Vec::new(),
discovered_projects: None,
root_path,
+ snippets: Default::default(),
}
}
pub fn update(&mut self, mut json: serde_json::Value) {
.map(AbsPathBuf::assert)
.collect();
self.data = ConfigData::from_json(json);
+ 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 {
)
}
+ 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)
}
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,
}
}
.snippet_support?,
false
)),
+ snippets: self.snippets.clone(),
}
}
pub fn assist(&self) -> AssistConfig {
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 {
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,
},
}
}
}
}
+#[derive(Deserialize, Debug, Clone, Copy)]
+#[serde(rename_all = "snake_case")]
+enum SnippetScopeDef {
+ Expr,
+ Item,
+ Type,
+}
+
+impl Default for SnippetScopeDef {
+ fn default() -> Self {
+ SnippetScopeDef::Expr
+ }
+}
+
+#[derive(Deserialize, Debug, Clone, Default)]
+#[serde(default)]
+struct SnippetDef {
+ #[serde(deserialize_with = "single_or_array")]
+ prefix: Vec<String>,
+ #[serde(deserialize_with = "single_or_array")]
+ postfix: Vec<String>,
+ description: Option<String>,
+ #[serde(deserialize_with = "single_or_array")]
+ body: Vec<String>,
+ #[serde(deserialize_with = "single_or_array")]
+ requires: Vec<String>,
+ scope: SnippetScopeDef,
+}
+
+fn single_or_array<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
+where
+ D: serde::Deserializer<'de>,
+{
+ struct SingleOrVec;
+
+ impl<'de> serde::de::Visitor<'de> for SingleOrVec {
+ type Value = Vec<String>;
+
+ fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+ formatter.write_str("string or array of strings")
+ }
+
+ fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
+ where
+ E: serde::de::Error,
+ {
+ Ok(vec![value.to_owned()])
+ }
+
+ fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
+ where
+ A: serde::de::SeqAccess<'de>,
+ {
+ Deserialize::deserialize(serde::de::value::SeqAccessDeserializer::new(seq))
+ }
+ }
+
+ deserializer.deserialize_any(SingleOrVec)
+}
+
#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
enum ManifestOrProjectJson {
#[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,
}
"items": { "type": "string" },
"uniqueItems": true,
},
+ "FxHashMap<String, SnippetDef>" => set! {
+ "type": "object",
+ },
"FxHashMap<String, String>" => set! {
"type": "object",
},
"type": "array",
"items": { "type": ["string", "object"] },
},
- "WorskpaceSymbolSearchScopeDef" => set! {
+ "WorkspaceSymbolSearchScopeDef" => set! {
"type": "string",
"enum": ["workspace", "workspace_and_dependencies"],
"enumDescriptions": [
"Search in current workspace and dependencies"
],
},
- "WorskpaceSymbolSearchKindDef" => set! {
+ "WorkspaceSymbolSearchKindDef" => set! {
"type": "string",
"enum": ["only_types", "all_symbols"],
"enumDescriptions": [
.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();