2019-10-25 09:00:30 +03:00
//! Config used by the language server.
//!
//! We currently get this config from `initialize` LSP request, which is not the
//! best way to do it, but was the simplest thing we could implement.
//!
//! Of particular interest is the `feature_flags` hash map: while other fields
//! configure the server itself, feature flags are passed into analysis, and
//! tweak things like automatic insertion of `()` in completions.
2019-09-30 11:58:53 +03:00
2021-01-26 16:10:51 +03:00
use std ::{ ffi ::OsString , iter , path ::PathBuf } ;
2020-04-23 18:50:25 +02:00
2020-06-25 09:13:46 +02:00
use flycheck ::FlycheckConfig ;
2021-01-16 19:33:36 +02:00
use ide ::{ AssistConfig , CompletionConfig , DiagnosticsConfig , HoverConfig , InlayHintsConfig } ;
use ide_db ::helpers ::{
2021-05-18 19:49:15 +02:00
insert_use ::{ ImportGranularity , InsertUseConfig , PrefixKind } ,
2021-01-16 19:33:36 +02:00
SnippetCap ,
2021-01-06 20:43:46 +03:00
} ;
2020-10-05 19:27:29 +02:00
use lsp_types ::{ ClientCapabilities , MarkupKind } ;
2021-02-11 17:34:56 +01:00
use project_model ::{ CargoConfig , ProjectJson , ProjectJsonData , ProjectManifest , RustcSource } ;
2021-04-20 20:03:35 -07:00
use rustc_hash ::{ FxHashMap , FxHashSet } ;
2020-12-02 17:31:24 +03:00
use serde ::{ de ::DeserializeOwned , Deserialize } ;
2020-07-08 18:22:57 +02:00
use vfs ::AbsPathBuf ;
2019-03-07 21:06:25 +01:00
2021-02-13 01:26:01 +03:00
use crate ::{
caps ::completion_item_edit_resolve , diagnostics ::DiagnosticsMapConfig ,
2021-02-23 14:03:31 +02:00
line_index ::OffsetEncoding , lsp_ext ::supports_utf8 , lsp_ext ::WorkspaceSymbolSearchKind ,
lsp_ext ::WorkspaceSymbolSearchScope ,
2021-02-13 01:26:01 +03:00
} ;
2020-07-03 17:19:00 +02:00
2021-04-28 13:06:46 +03:00
// Defines the server-side configuration of the rust-analyzer. We generate
// *parts* of VS Code's `package.json` config from this.
//
// However, editor specific config, which the server doesn't know about, should
// be specified directly in `package.json`.
2021-06-21 21:41:06 +02:00
//
// To deprecate an option by replacing it with another name use `new_name | `old_name` so that we keep
// parsing the old name.
2020-12-02 17:31:24 +03:00
config_data! {
struct ConfigData {
2021-05-18 20:21:47 +02:00
/// How imports should be grouped into use statements.
2021-05-18 19:49:15 +02:00
assist_importGranularity |
2021-01-07 14:37:38 +03:00
assist_importMergeBehavior |
2021-05-18 20:21:47 +02:00
assist_importMergeBehaviour : ImportGranularityDef = " \" crate \" " ,
/// 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.
assist_importEnforceGranularity : bool = " false " ,
2020-12-02 17:31:24 +03:00
/// The path structure for newly inserted paths to use.
2021-05-18 20:21:47 +02:00
assist_importPrefix : ImportPrefixDef = " \" plain \" " ,
2021-03-06 13:02:26 +02:00
/// Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.
2021-05-18 20:21:47 +02:00
assist_importGroup : bool = " true " ,
2021-06-18 23:11:56 +02:00
/// Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`.
assist_allowMergingIntoGlobImports : bool = " true " ,
2020-12-02 17:31:24 +03:00
/// Show function name and docs in parameter hints.
2021-05-18 20:21:47 +02:00
callInfo_full : bool = " true " ,
2020-12-02 17:31:24 +03:00
/// Automatically refresh project info via `cargo metadata` on
2020-12-22 01:15:50 +01:00
/// `Cargo.toml` changes.
2020-12-02 17:31:24 +03:00
cargo_autoreload : bool = " true " ,
2021-01-26 16:03:24 +03:00
/// Activate all available features (`--all-features`).
2020-12-02 17:31:24 +03:00
cargo_allFeatures : bool = " false " ,
2021-06-13 21:41:46 -07:00
/// Unsets `#[cfg(test)]` for the specified crates.
cargo_unsetTest : Vec < String > = " [ \" core \" ] " ,
2020-12-02 17:31:24 +03:00
/// List of features to activate.
cargo_features : Vec < String > = " [] " ,
2021-03-04 14:52:36 +03:00
/// Run build scripts (`build.rs`) for more precise code analysis.
cargo_runBuildScripts |
2021-03-08 14:52:16 +03:00
cargo_loadOutDirsFromCheck : bool = " true " ,
2021-04-12 11:04:36 +03:00
/// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
/// avoid compiling unnecessary things.
cargo_useRustcWrapperForBuildScripts : bool = " true " ,
2020-12-02 17:31:24 +03:00
/// Do not activate the `default` feature.
cargo_noDefaultFeatures : bool = " false " ,
/// Compilation target (target triple).
cargo_target : Option < String > = " null " ,
/// Internal config for debugging, disables loading of sysroot crates.
cargo_noSysroot : bool = " false " ,
/// Run specified `cargo check` command for diagnostics on save.
checkOnSave_enable : bool = " true " ,
2021-01-26 16:03:24 +03:00
/// Check with all features (`--all-features`).
2020-12-22 01:15:50 +01:00
/// Defaults to `#rust-analyzer.cargo.allFeatures#`.
2020-12-02 17:31:24 +03:00
checkOnSave_allFeatures : Option < bool > = " null " ,
2021-01-26 16:03:24 +03:00
/// Check all targets and tests (`--all-targets`).
2020-12-02 17:31:24 +03:00
checkOnSave_allTargets : bool = " true " ,
/// Cargo command to use for `cargo check`.
checkOnSave_command : String = " \" check \" " ,
/// Do not activate the `default` feature.
checkOnSave_noDefaultFeatures : Option < bool > = " null " ,
/// Check for a specific target. Defaults to
2020-12-22 01:15:50 +01:00
/// `#rust-analyzer.cargo.target#`.
2020-12-02 17:31:24 +03:00
checkOnSave_target : Option < String > = " null " ,
/// Extra arguments for `cargo check`.
checkOnSave_extraArgs : Vec < String > = " [] " ,
/// List of features to activate. Defaults to
2020-12-22 01:15:50 +01:00
/// `#rust-analyzer.cargo.features#`.
2020-12-02 17:31:24 +03:00
checkOnSave_features : Option < Vec < String > > = " null " ,
/// Advanced option, fully override the command rust-analyzer uses for
/// checking. The command should include `--message-format=json` or
/// similar option.
checkOnSave_overrideCommand : Option < Vec < String > > = " null " ,
/// Whether to add argument snippets when completing functions.
2021-06-02 22:10:09 +02:00
/// Only applies when `#rust-analyzer.completion.addCallParenthesis#` is set.
2020-12-02 17:31:24 +03:00
completion_addCallArgumentSnippets : bool = " true " ,
/// Whether to add parenthesis when completing functions.
completion_addCallParenthesis : bool = " true " ,
/// Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
completion_postfix_enable : bool = " true " ,
/// Toggles the additional completions that automatically add imports when completed.
2020-12-22 01:15:50 +01:00
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
2020-12-02 17:31:24 +03:00
completion_autoimport_enable : bool = " true " ,
2021-05-30 16:41:33 +02:00
/// Toggles the additional completions that automatically show method calls and field accesses
/// with `self` prefixed to them when inside a method.
completion_autoself_enable : bool = " true " ,
2020-12-02 17:31:24 +03:00
/// Whether to show native rust-analyzer diagnostics.
diagnostics_enable : bool = " true " ,
/// Whether to show experimental rust-analyzer diagnostics that might
/// have more false positives than usual.
diagnostics_enableExperimental : bool = " true " ,
/// List of rust-analyzer diagnostics to disable.
diagnostics_disabled : FxHashSet < String > = " [] " ,
2021-04-21 15:09:37 -07:00
/// Map of prefixes to be substituted when parsing diagnostic file paths.
2021-04-20 20:03:35 -07:00
/// This should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`.
2021-04-21 15:09:37 -07:00
diagnostics_remapPrefix : FxHashMap < String , String > = " {} " ,
2021-03-09 14:43:05 +03:00
/// List of warnings that should be displayed with hint severity.
///
/// The warnings will be indicated by faded text or three dots in code
/// and will not show up in the `Problems Panel`.
2021-05-29 18:08:14 +02:00
diagnostics_warningsAsHint : Vec < String > = " [] " ,
/// List of warnings that should be displayed with info severity.
///
/// The warnings will be indicated by a blue squiggly underline in code
/// and a blue icon in the `Problems Panel`.
2020-12-02 17:31:24 +03:00
diagnostics_warningsAsInfo : Vec < String > = " [] " ,
2021-06-03 16:11:20 +02:00
/// Expand attribute macros.
experimental_procAttrMacros : bool = " false " ,
2020-12-02 17:31:24 +03:00
/// Controls file watching implementation.
files_watcher : String = " \" client \" " ,
2021-01-26 16:18:01 +03:00
/// These directories will be ignored by rust-analyzer.
files_excludeDirs : Vec < PathBuf > = " [] " ,
2020-12-02 17:31:24 +03:00
2021-05-17 18:37:06 +03:00
/// Use semantic tokens for strings.
///
/// In some editors (e.g. vscode) semantic tokens override other highlighting grammars.
/// By disabling semantic tokens for strings, other grammars can be used to highlight
/// their contents.
highlighting_strings : bool = " true " ,
2021-06-14 15:25:10 +02:00
/// Whether to show documentation on hover.
2021-06-21 16:01:03 +02:00
hover_documentation : bool = " true " ,
2021-06-14 15:25:10 +02:00
/// Use markdown syntax for links in hover.
2021-06-21 16:01:03 +02:00
hover_linksInHover |
hoverActions_linksInHover : bool = " true " ,
2021-06-14 15:25:10 +02:00
2020-12-02 17:31:24 +03:00
/// Whether to show `Debug` action. Only applies when
/// `#rust-analyzer.hoverActions.enable#` is set.
hoverActions_debug : bool = " true " ,
/// Whether to show HoverActions in Rust files.
hoverActions_enable : bool = " true " ,
/// Whether to show `Go to Type Definition` action. Only applies when
/// `#rust-analyzer.hoverActions.enable#` is set.
hoverActions_gotoTypeDef : bool = " true " ,
/// Whether to show `Implementations` action. Only applies when
/// `#rust-analyzer.hoverActions.enable#` is set.
hoverActions_implementations : bool = " true " ,
2021-06-04 15:49:43 +02:00
/// Whether to show `References` action. Only applies when
/// `#rust-analyzer.hoverActions.enable#` is set.
hoverActions_references : bool = " false " ,
2020-12-02 17:31:24 +03:00
/// Whether to show `Run` action. Only applies when
/// `#rust-analyzer.hoverActions.enable#` is set.
hoverActions_run : bool = " true " ,
/// Whether to show inlay type hints for method chains.
inlayHints_chainingHints : bool = " true " ,
2021-03-23 19:04:48 +02:00
/// Maximum length for inlay hints. Set to null to have an unlimited length.
2021-03-23 19:43:55 +02:00
inlayHints_maxLength : Option < usize > = " 25 " ,
2020-12-02 17:31:24 +03:00
/// Whether to show function parameter name inlay hints at the call
/// site.
inlayHints_parameterHints : bool = " true " ,
/// Whether to show inlay type hints for variables.
inlayHints_typeHints : bool = " true " ,
/// Whether to show `Debug` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_debug : bool = " true " ,
/// Whether to show CodeLens in Rust files.
lens_enable : bool = " true " ,
/// Whether to show `Implementations` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_implementations : bool = " true " ,
/// Whether to show `Run` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_run : bool = " true " ,
/// Whether to show `Method References` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_methodReferences : bool = " false " ,
2021-01-23 16:56:20 +03:00
/// Whether to show `References` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_references : bool = " false " ,
2020-12-02 17:31:24 +03:00
/// Disable project auto-discovery in favor of explicitly specified set
2021-03-09 14:43:05 +03:00
/// of projects.
///
/// Elements must be paths pointing to `Cargo.toml`,
2020-12-22 01:15:50 +01:00
/// `rust-project.json`, or JSON objects in `rust-project.json` format.
2020-12-02 17:31:24 +03:00
linkedProjects : Vec < ManifestOrProjectJson > = " [] " ,
2021-01-06 13:54:28 +03:00
2021-01-26 16:03:24 +03:00
/// Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.
2020-12-02 17:31:24 +03:00
lruCapacity : Option < usize > = " null " ,
2021-01-06 13:54:28 +03:00
2020-12-02 17:31:24 +03:00
/// Whether to show `can't find Cargo.toml` error message.
notifications_cargoTomlNotFound : bool = " true " ,
2021-01-06 13:54:28 +03:00
2021-03-04 14:52:36 +03:00
/// Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScripts#`.
2021-03-15 18:19:08 +03:00
procMacro_enable : bool = " true " ,
2021-01-06 13:54:28 +03:00
/// Internal config, path to proc-macro server executable (typically,
/// this is rust-analyzer itself, but we override this in tests).
procMacro_server : Option < PathBuf > = " null " ,
2020-12-02 17:31:24 +03:00
/// Command to be executed instead of 'cargo' for runnables.
runnables_overrideCargo : Option < String > = " null " ,
/// Additional arguments to be passed to cargo for runnables such as
2021-03-09 14:43:05 +03:00
/// tests or binaries. For example, it may be `--release`.
2020-12-02 17:31:24 +03:00
runnables_cargoExtraArgs : Vec < String > = " [] " ,
2021-03-08 16:56:42 -05:00
/// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private
/// projects, or "discover" to try to automatically find it.
///
/// Any project which uses rust-analyzer with the rustcPrivate
2021-03-08 16:47:40 +00:00
/// crates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.
2021-03-08 16:56:42 -05:00
///
/// This option is not reloaded automatically; you must restart rust-analyzer for it to take effect.
rustcSource : Option < String > = " null " ,
2020-12-02 17:31:24 +03:00
2020-12-22 01:15:50 +01:00
/// Additional arguments to `rustfmt`.
2020-12-02 17:31:24 +03:00
rustfmt_extraArgs : Vec < String > = " [] " ,
/// Advanced option, fully override the command rust-analyzer uses for
/// formatting.
rustfmt_overrideCommand : Option < Vec < String > > = " null " ,
2021-05-04 17:13:51 -04:00
/// Enables the use of rustfmt's unstable range formatting command for the
/// `textDocument/rangeFormatting` request. The rustfmt option is unstable and only
/// available on a nightly build.
rustfmt_enableRangeFormatting : bool = " false " ,
2021-02-23 14:03:31 +02:00
/// Workspace symbol search scope.
workspace_symbol_search_scope : WorskpaceSymbolSearchScopeDef = " \" workspace \" " ,
/// Workspace symbol search kind.
workspace_symbol_search_kind : WorskpaceSymbolSearchKindDef = " \" only_types \" " ,
2020-12-02 17:31:24 +03:00
}
}
2021-01-06 13:54:28 +03:00
impl Default for ConfigData {
fn default ( ) -> Self {
ConfigData ::from_json ( serde_json ::Value ::Null )
}
}
2020-04-01 14:32:04 +02:00
#[ derive(Debug, Clone) ]
pub struct Config {
2021-05-27 17:36:13 -04:00
pub caps : lsp_types ::ClientCapabilities ,
2021-01-06 13:54:28 +03:00
data : ConfigData ,
2021-05-23 20:56:54 +03:00
detached_files : Vec < AbsPathBuf > ,
2021-01-06 13:54:28 +03:00
pub discovered_projects : Option < Vec < ProjectManifest > > ,
2020-06-24 13:34:24 +02:00
pub root_path : AbsPathBuf ,
2020-08-18 13:35:36 +03:00
}
2020-07-01 16:42:14 +02:00
#[ derive(Debug, Clone, Eq, PartialEq) ]
2020-06-03 12:22:01 +02:00
pub enum LinkedProject {
ProjectManifest ( ProjectManifest ) ,
2020-06-24 14:57:37 +02:00
InlineJsonProject ( ProjectJson ) ,
2020-06-03 12:22:01 +02:00
}
impl From < ProjectManifest > for LinkedProject {
fn from ( v : ProjectManifest ) -> Self {
LinkedProject ::ProjectManifest ( v )
}
}
2020-06-24 14:57:37 +02:00
impl From < ProjectJson > for LinkedProject {
fn from ( v : ProjectJson ) -> Self {
2020-06-09 21:26:42 +02:00
LinkedProject ::InlineJsonProject ( v )
2020-06-03 12:22:01 +02:00
}
2020-05-17 19:51:44 +03:00
}
#[ derive(Clone, Debug, PartialEq, Eq) ]
pub struct LensConfig {
pub run : bool ,
pub debug : bool ,
2020-07-05 11:19:16 +02:00
pub implementations : bool ,
2020-09-01 16:33:02 +03:00
pub method_refs : bool ,
2021-01-23 16:56:20 +03:00
pub refs : bool , // for Struct, Enum, Union and Trait
2020-05-17 19:51:44 +03:00
}
impl LensConfig {
pub fn any ( & self ) -> bool {
2020-09-01 16:33:02 +03:00
self . implementations | | self . runnable ( ) | | self . references ( )
2020-05-17 19:51:44 +03:00
}
pub fn none ( & self ) -> bool {
! self . any ( )
}
pub fn runnable ( & self ) -> bool {
self . run | | self . debug
}
2020-09-01 16:33:02 +03:00
pub fn references ( & self ) -> bool {
2021-01-23 16:56:20 +03:00
self . method_refs | | self . refs
2020-09-01 16:33:02 +03:00
}
2020-04-01 14:32:04 +02:00
}
2021-06-21 21:41:06 +02:00
#[ derive(Clone, Debug, PartialEq, Eq) ]
pub struct HoverActionsConfig {
pub implementations : bool ,
pub references : bool ,
pub run : bool ,
pub debug : bool ,
pub goto_type_def : bool ,
}
impl HoverActionsConfig {
pub const NO_ACTIONS : Self = Self {
implementations : false ,
references : false ,
run : false ,
debug : false ,
goto_type_def : false ,
} ;
pub fn any ( & self ) -> bool {
self . implementations | | self . references | | self . runnable ( ) | | self . goto_type_def
}
pub fn none ( & self ) -> bool {
! self . any ( )
}
pub fn runnable ( & self ) -> bool {
self . run | | self . debug
}
}
2020-04-02 11:55:04 +02:00
#[ derive(Debug, Clone) ]
pub struct FilesConfig {
2020-04-02 12:47:58 +02:00
pub watcher : FilesWatcher ,
2021-01-26 16:18:01 +03:00
pub exclude : Vec < AbsPathBuf > ,
2020-04-02 11:55:04 +02:00
}
#[ derive(Debug, Clone) ]
2020-04-02 12:47:58 +02:00
pub enum FilesWatcher {
2020-04-02 11:55:04 +02:00
Client ,
Notify ,
}
2020-04-01 17:00:37 +02:00
#[ derive(Debug, Clone) ]
pub struct NotificationsConfig {
pub cargo_toml_not_found : bool ,
}
2020-04-01 14:32:04 +02:00
#[ derive(Debug, Clone) ]
pub enum RustfmtConfig {
2021-05-04 17:13:51 -04:00
Rustfmt { extra_args : Vec < String > , enable_range_formatting : bool } ,
2020-07-10 00:28:12 +02:00
CustomCommand { command : String , args : Vec < String > } ,
2020-04-01 14:32:04 +02:00
}
2020-09-05 12:52:27 +03:00
/// Configuration for runnable items, such as `main` function or tests.
2021-01-06 13:54:28 +03:00
#[ derive(Debug, Clone) ]
2020-09-05 12:52:27 +03:00
pub struct RunnablesConfig {
2020-09-05 16:20:33 +03:00
/// Custom command to be executed instead of `cargo` for runnables.
pub override_cargo : Option < String > ,
2020-09-05 12:52:27 +03:00
/// Additional arguments for the `cargo`, e.g. `--release`.
pub cargo_extra_args : Vec < String > ,
}
2021-02-23 14:03:31 +02:00
/// Configuration for workspace symbol search requests.
#[ derive(Debug, Clone) ]
pub struct WorkspaceSymbolConfig {
/// In what scope should the symbol be searched in.
pub search_scope : WorkspaceSymbolSearchScope ,
/// What kind of symbol is being search for.
pub search_kind : WorkspaceSymbolSearchKind ,
}
2020-06-24 13:34:24 +02:00
impl Config {
2021-01-06 13:54:28 +03:00
pub fn new ( root_path : AbsPathBuf , caps : ClientCapabilities ) -> Self {
2021-05-23 20:32:22 +03:00
Config {
caps ,
data : ConfigData ::default ( ) ,
detached_files : Vec ::new ( ) ,
discovered_projects : None ,
root_path ,
}
2020-04-01 17:00:37 +02:00
}
2021-05-23 20:32:22 +03:00
pub fn update ( & mut self , mut json : serde_json ::Value ) {
2020-12-23 10:47:05 +03:00
log ::info! ( " updating config from JSON: {:#} " , json ) ;
2020-07-20 18:11:32 -04:00
if json . is_null ( ) | | json . as_object ( ) . map_or ( false , | it | it . is_empty ( ) ) {
2020-07-20 17:25:48 -04:00
return ;
}
2021-05-23 20:32:22 +03:00
self . detached_files = get_field ::< Vec < PathBuf > > ( & mut json , " detachedFiles " , None , " [] " )
. into_iter ( )
. map ( AbsPathBuf ::assert )
. collect ( ) ;
2021-01-06 13:54:28 +03:00
self . data = ConfigData ::from_json ( json ) ;
2019-03-07 21:06:25 +01:00
}
2020-12-02 17:31:24 +03:00
pub fn json_schema ( ) -> serde_json ::Value {
ConfigData ::json_schema ( )
}
2019-03-07 21:06:25 +01:00
}
2020-06-03 14:48:38 +02:00
2021-01-05 16:57:05 +03:00
macro_rules ! try_ {
( $expr :expr ) = > {
| | -> _ { Some ( $expr ) } ( )
} ;
}
macro_rules ! try_or {
( $expr :expr , $or :expr ) = > {
try_! ( $expr ) . unwrap_or ( $or )
} ;
}
impl Config {
2021-01-06 13:54:28 +03:00
pub fn linked_projects ( & self ) -> Vec < LinkedProject > {
if self . data . linkedProjects . is_empty ( ) {
self . discovered_projects
. as_ref ( )
. into_iter ( )
. flatten ( )
. cloned ( )
. map ( LinkedProject ::from )
. collect ( )
} else {
self . data
. linkedProjects
. iter ( )
. filter_map ( | linked_project | {
let res = match linked_project {
ManifestOrProjectJson ::Manifest ( it ) = > {
let path = self . root_path . join ( it ) ;
ProjectManifest ::from_manifest_file ( path )
. map_err ( | e | log ::error! ( " failed to load linked project: {} " , e ) )
. ok ( ) ?
. into ( )
}
ManifestOrProjectJson ::ProjectJson ( it ) = > {
ProjectJson ::new ( & self . root_path , it . clone ( ) ) . into ( )
}
} ;
Some ( res )
} )
. collect ( )
}
}
2021-05-23 20:56:54 +03:00
pub fn detached_files ( & self ) -> & [ AbsPathBuf ] {
2021-05-23 20:32:22 +03:00
& self . detached_files
}
2021-01-10 22:38:35 +03:00
pub fn did_save_text_document_dynamic_registration ( & self ) -> bool {
let caps =
try_or! ( self . caps . text_document . as_ref ( ) ? . synchronization . clone ( ) ? , Default ::default ( ) ) ;
caps . did_save = = Some ( true ) & & caps . dynamic_registration = = Some ( true )
}
pub fn did_change_watched_files_dynamic_registration ( & self ) -> bool {
try_or! (
self . caps . workspace . as_ref ( ) ? . did_change_watched_files . as_ref ( ) ? . dynamic_registration ? ,
false
)
}
2021-01-05 16:57:05 +03:00
pub fn location_link ( & self ) -> bool {
try_or! ( self . caps . text_document . as_ref ( ) ? . definition ? . link_support ? , false )
}
pub fn line_folding_only ( & self ) -> bool {
try_or! ( self . caps . text_document . as_ref ( ) ? . folding_range . as_ref ( ) ? . line_folding_only ? , false )
}
pub fn hierarchical_symbols ( & self ) -> bool {
try_or! (
self . caps
. text_document
. as_ref ( ) ?
. document_symbol
. as_ref ( ) ?
. hierarchical_document_symbol_support ? ,
false
)
}
pub fn code_action_literals ( & self ) -> bool {
try_! ( self
. caps
. text_document
. as_ref ( ) ?
. code_action
. as_ref ( ) ?
. code_action_literal_support
. as_ref ( ) ? )
. is_some ( )
}
pub fn work_done_progress ( & self ) -> bool {
try_or! ( self . caps . window . as_ref ( ) ? . work_done_progress ? , false )
}
2021-03-10 15:49:01 +01:00
pub fn will_rename ( & self ) -> bool {
try_or! ( self . caps . workspace . as_ref ( ) ? . file_operations . as_ref ( ) ? . will_rename ? , false )
}
2021-04-16 17:31:47 +02:00
pub fn change_annotation_support ( & self ) -> bool {
try_! ( self
. caps
. workspace
. as_ref ( ) ?
. workspace_edit
. as_ref ( ) ?
. change_annotation_support
. as_ref ( ) ? )
. is_some ( )
}
2021-01-05 16:57:05 +03:00
pub fn code_action_resolve ( & self ) -> bool {
try_or! (
self . caps
. text_document
. as_ref ( ) ?
. code_action
. as_ref ( ) ?
. resolve_support
. as_ref ( ) ?
. properties
. as_slice ( ) ,
& [ ]
)
. iter ( )
. any ( | it | it = = " edit " )
}
pub fn signature_help_label_offsets ( & self ) -> bool {
try_or! (
self . caps
. text_document
. as_ref ( ) ?
. signature_help
. as_ref ( ) ?
. signature_information
. as_ref ( ) ?
. parameter_information
. as_ref ( ) ?
. label_offset_support ? ,
false
)
}
2021-02-13 01:26:01 +03:00
pub fn offset_encoding ( & self ) -> OffsetEncoding {
if supports_utf8 ( & self . caps ) {
OffsetEncoding ::Utf8
} else {
OffsetEncoding ::Utf16
}
}
2021-01-05 16:57:05 +03:00
fn experimental ( & self , index : & 'static str ) -> bool {
try_or! ( self . caps . experimental . as_ref ( ) ? . get ( index ) ? . as_bool ( ) ? , false )
}
pub fn code_action_group ( & self ) -> bool {
self . experimental ( " codeActionGroup " )
}
2021-06-21 21:41:06 +02:00
pub fn experimental_hover_actions ( & self ) -> bool {
2021-01-05 16:57:05 +03:00
self . experimental ( " hoverActions " )
}
2021-04-06 14:16:35 +03:00
pub fn server_status_notification ( & self ) -> bool {
self . experimental ( " serverStatusNotification " )
2021-01-05 16:57:05 +03:00
}
2021-01-06 13:54:28 +03:00
pub fn publish_diagnostics ( & self ) -> bool {
self . data . diagnostics_enable
}
pub fn diagnostics ( & self ) -> DiagnosticsConfig {
DiagnosticsConfig {
disable_experimental : ! self . data . diagnostics_enableExperimental ,
disabled : self . data . diagnostics_disabled . clone ( ) ,
}
}
pub fn diagnostics_map ( & self ) -> DiagnosticsMapConfig {
DiagnosticsMapConfig {
2021-04-21 15:09:37 -07:00
remap_prefix : self . data . diagnostics_remapPrefix . clone ( ) ,
2021-01-06 13:54:28 +03:00
warnings_as_info : self . data . diagnostics_warningsAsInfo . clone ( ) ,
warnings_as_hint : self . data . diagnostics_warningsAsHint . clone ( ) ,
}
}
pub fn lru_capacity ( & self ) -> Option < usize > {
self . data . lruCapacity
}
pub fn proc_macro_srv ( & self ) -> Option < ( PathBuf , Vec < OsString > ) > {
if ! self . data . procMacro_enable {
return None ;
}
let path = self . data . procMacro_server . clone ( ) . or_else ( | | std ::env ::current_exe ( ) . ok ( ) ) ? ;
Some ( ( path , vec! [ " proc-macro " . into ( ) ] ) )
}
2021-06-03 16:11:20 +02:00
pub fn expand_proc_attr_macros ( & self ) -> bool {
self . data . experimental_procAttrMacros
}
2021-01-06 13:54:28 +03:00
pub fn files ( & self ) -> FilesConfig {
FilesConfig {
watcher : match self . data . files_watcher . as_str ( ) {
" notify " = > FilesWatcher ::Notify ,
" client " | _ = > FilesWatcher ::Client ,
} ,
2021-01-26 16:18:01 +03:00
exclude : self . data . files_excludeDirs . iter ( ) . map ( | it | self . root_path . join ( it ) ) . collect ( ) ,
2021-01-06 13:54:28 +03:00
}
}
pub fn notifications ( & self ) -> NotificationsConfig {
NotificationsConfig { cargo_toml_not_found : self . data . notifications_cargoTomlNotFound }
}
pub fn cargo_autoreload ( & self ) -> bool {
self . data . cargo_autoreload
}
2021-03-04 14:52:36 +03:00
pub fn run_build_scripts ( & self ) -> bool {
self . data . cargo_runBuildScripts | | self . data . procMacro_enable
2021-01-28 23:33:02 +08:00
}
2021-04-12 11:04:36 +03:00
pub fn wrap_rustc ( & self ) -> bool {
self . data . cargo_useRustcWrapperForBuildScripts
}
2021-01-06 13:54:28 +03:00
pub fn cargo ( & self ) -> CargoConfig {
2021-02-11 17:34:56 +01:00
let rustc_source = self . data . rustcSource . as_ref ( ) . map ( | rustc_src | {
if rustc_src = = " discover " {
RustcSource ::Discover
} else {
RustcSource ::Path ( self . root_path . join ( rustc_src ) )
}
} ) ;
2021-01-06 13:54:28 +03:00
CargoConfig {
no_default_features : self . data . cargo_noDefaultFeatures ,
all_features : self . data . cargo_allFeatures ,
features : self . data . cargo_features . clone ( ) ,
target : self . data . cargo_target . clone ( ) ,
rustc_source ,
no_sysroot : self . data . cargo_noSysroot ,
2021-06-13 21:41:46 -07:00
unset_test_crates : self . data . cargo_unsetTest . clone ( ) ,
2021-01-06 13:54:28 +03:00
}
}
2021-06-13 21:41:46 -07:00
2021-01-06 13:54:28 +03:00
pub fn rustfmt ( & self ) -> RustfmtConfig {
match & self . data . rustfmt_overrideCommand {
Some ( args ) if ! args . is_empty ( ) = > {
let mut args = args . clone ( ) ;
let command = args . remove ( 0 ) ;
RustfmtConfig ::CustomCommand { command , args }
}
2021-05-04 17:13:51 -04:00
Some ( _ ) | None = > RustfmtConfig ::Rustfmt {
extra_args : self . data . rustfmt_extraArgs . clone ( ) ,
enable_range_formatting : self . data . rustfmt_enableRangeFormatting ,
} ,
2021-01-06 13:54:28 +03:00
}
}
pub fn flycheck ( & self ) -> Option < FlycheckConfig > {
if ! self . data . checkOnSave_enable {
return None ;
}
let flycheck_config = match & self . data . checkOnSave_overrideCommand {
Some ( args ) if ! args . is_empty ( ) = > {
let mut args = args . clone ( ) ;
let command = args . remove ( 0 ) ;
FlycheckConfig ::CustomCommand { command , args }
}
Some ( _ ) | None = > FlycheckConfig ::CargoCommand {
command : self . data . checkOnSave_command . clone ( ) ,
target_triple : self
. data
. checkOnSave_target
. clone ( )
2021-02-16 10:55:34 -05:00
. or_else ( | | self . data . cargo_target . clone ( ) ) ,
2021-01-06 13:54:28 +03:00
all_targets : self . data . checkOnSave_allTargets ,
no_default_features : self
. data
. checkOnSave_noDefaultFeatures
. unwrap_or ( self . data . cargo_noDefaultFeatures ) ,
all_features : self
. data
. checkOnSave_allFeatures
. unwrap_or ( self . data . cargo_allFeatures ) ,
features : self
. data
. checkOnSave_features
. clone ( )
2021-02-16 10:55:34 -05:00
. unwrap_or_else ( | | self . data . cargo_features . clone ( ) ) ,
2021-01-06 13:54:28 +03:00
extra_args : self . data . checkOnSave_extraArgs . clone ( ) ,
} ,
} ;
Some ( flycheck_config )
}
pub fn runnables ( & self ) -> RunnablesConfig {
RunnablesConfig {
override_cargo : self . data . runnables_overrideCargo . clone ( ) ,
cargo_extra_args : self . data . runnables_cargoExtraArgs . clone ( ) ,
}
}
pub fn inlay_hints ( & self ) -> InlayHintsConfig {
InlayHintsConfig {
type_hints : self . data . inlayHints_typeHints ,
parameter_hints : self . data . inlayHints_parameterHints ,
chaining_hints : self . data . inlayHints_chainingHints ,
max_length : self . data . inlayHints_maxLength ,
}
}
2021-01-16 19:33:36 +02:00
fn insert_use_config ( & self ) -> InsertUseConfig {
InsertUseConfig {
2021-05-18 19:49:15 +02:00
granularity : match self . data . assist_importGranularity {
ImportGranularityDef ::Preserve = > ImportGranularity ::Preserve ,
ImportGranularityDef ::Item = > ImportGranularity ::Item ,
ImportGranularityDef ::Crate = > ImportGranularity ::Crate ,
ImportGranularityDef ::Module = > ImportGranularity ::Module ,
2021-01-16 19:33:36 +02:00
} ,
2021-05-18 20:21:47 +02:00
enforce_granularity : self . data . assist_importEnforceGranularity ,
2021-01-16 19:33:36 +02:00
prefix_kind : match self . data . assist_importPrefix {
ImportPrefixDef ::Plain = > PrefixKind ::Plain ,
ImportPrefixDef ::ByCrate = > PrefixKind ::ByCrate ,
ImportPrefixDef ::BySelf = > PrefixKind ::BySelf ,
} ,
2021-03-06 13:02:26 +02:00
group : self . data . assist_importGroup ,
2021-06-18 23:11:56 +02:00
skip_glob_imports : ! self . data . assist_allowMergingIntoGlobImports ,
2021-01-06 13:54:28 +03:00
}
}
pub fn completion ( & self ) -> CompletionConfig {
2021-01-06 20:43:46 +03:00
CompletionConfig {
enable_postfix_completions : self . data . completion_postfix_enable ,
2021-01-05 10:34:03 +02:00
enable_imports_on_the_fly : self . data . completion_autoimport_enable
2021-01-06 20:43:46 +03:00
& & completion_item_edit_resolve ( & self . caps ) ,
2021-05-30 16:41:33 +02:00
enable_self_on_the_fly : self . data . completion_autoself_enable ,
2021-01-06 20:43:46 +03:00
add_call_parenthesis : self . data . completion_addCallParenthesis ,
add_call_argument_snippets : self . data . completion_addCallArgumentSnippets ,
2021-01-16 19:33:36 +02:00
insert_use : self . insert_use_config ( ) ,
2021-01-06 20:43:46 +03:00
snippet_cap : SnippetCap ::new ( try_or! (
self . caps
. text_document
. as_ref ( ) ?
. completion
. as_ref ( ) ?
. completion_item
. as_ref ( ) ?
. snippet_support ? ,
false
) ) ,
}
2021-01-06 13:54:28 +03:00
}
pub fn assist ( & self ) -> AssistConfig {
2021-01-06 20:43:46 +03:00
AssistConfig {
snippet_cap : SnippetCap ::new ( self . experimental ( " snippetTextEdit " ) ) ,
allowed : None ,
2021-01-05 10:34:03 +02:00
insert_use : self . insert_use_config ( ) ,
2021-01-06 20:43:46 +03:00
}
2021-01-06 13:54:28 +03:00
}
pub fn call_info_full ( & self ) -> bool {
self . data . callInfo_full
}
pub fn lens ( & self ) -> LensConfig {
LensConfig {
run : self . data . lens_enable & & self . data . lens_run ,
debug : self . data . lens_enable & & self . data . lens_debug ,
implementations : self . data . lens_enable & & self . data . lens_implementations ,
method_refs : self . data . lens_enable & & self . data . lens_methodReferences ,
2021-01-23 16:56:20 +03:00
refs : self . data . lens_enable & & self . data . lens_references ,
2021-01-06 13:54:28 +03:00
}
}
2021-06-21 21:41:06 +02:00
pub fn hover_actions ( & self ) -> HoverActionsConfig {
HoverActionsConfig {
2021-01-06 13:54:28 +03:00
implementations : self . data . hoverActions_enable
& & self . data . hoverActions_implementations ,
2021-06-04 15:49:43 +02:00
references : self . data . hoverActions_enable & & self . data . hoverActions_references ,
2021-01-06 13:54:28 +03:00
run : self . data . hoverActions_enable & & self . data . hoverActions_run ,
debug : self . data . hoverActions_enable & & self . data . hoverActions_debug ,
goto_type_def : self . data . hoverActions_enable & & self . data . hoverActions_gotoTypeDef ,
2021-06-21 21:41:06 +02:00
}
}
pub fn highlighting_strings ( & self ) -> bool {
self . data . highlighting_strings
}
pub fn hover ( & self ) -> HoverConfig {
HoverConfig {
2021-06-21 16:01:03 +02:00
links_in_hover : self . data . hover_linksInHover ,
2021-01-06 13:54:28 +03:00
markdown : try_or ! (
self . caps
. text_document
. as_ref ( ) ?
. hover
. as_ref ( ) ?
. content_format
. as_ref ( ) ?
. as_slice ( ) ,
& [ ]
)
. contains ( & MarkupKind ::Markdown ) ,
2021-06-14 15:25:10 +02:00
documentation : self . data . hover_documentation ,
2021-01-06 13:54:28 +03:00
}
}
2021-02-23 14:03:31 +02:00
pub fn workspace_symbol ( & self ) -> WorkspaceSymbolConfig {
WorkspaceSymbolConfig {
search_scope : match self . data . workspace_symbol_search_scope {
WorskpaceSymbolSearchScopeDef ::Workspace = > WorkspaceSymbolSearchScope ::Workspace ,
WorskpaceSymbolSearchScopeDef ::WorkspaceAndDependencies = > {
WorkspaceSymbolSearchScope ::WorkspaceAndDependencies
}
} ,
search_kind : match self . data . workspace_symbol_search_kind {
WorskpaceSymbolSearchKindDef ::OnlyTypes = > WorkspaceSymbolSearchKind ::OnlyTypes ,
WorskpaceSymbolSearchKindDef ::AllSymbols = > WorkspaceSymbolSearchKind ::AllSymbols ,
} ,
}
}
2021-01-06 13:54:28 +03:00
pub fn semantic_tokens_refresh ( & self ) -> bool {
try_or! ( self . caps . workspace . as_ref ( ) ? . semantic_tokens . as_ref ( ) ? . refresh_support ? , false )
}
pub fn code_lens_refresh ( & self ) -> bool {
try_or! ( self . caps . workspace . as_ref ( ) ? . code_lens . as_ref ( ) ? . refresh_support ? , false )
}
2021-04-08 14:22:54 +02:00
pub fn insert_replace_support ( & self ) -> bool {
try_or! (
self . caps
. text_document
. as_ref ( ) ?
. completion
. as_ref ( ) ?
. completion_item
. as_ref ( ) ?
. insert_replace_support ? ,
false
)
}
2021-01-05 16:57:05 +03:00
}
2021-01-06 13:54:28 +03:00
#[ derive(Deserialize, Debug, Clone) ]
2020-06-03 14:48:38 +02:00
#[ serde(untagged) ]
2020-06-24 15:52:07 +02:00
enum ManifestOrProjectJson {
2020-06-03 14:48:38 +02:00
Manifest ( PathBuf ) ,
2020-06-24 15:52:07 +02:00
ProjectJson ( ProjectJsonData ) ,
2020-06-03 14:48:38 +02:00
}
2020-07-10 00:28:12 +02:00
2021-01-06 13:54:28 +03:00
#[ derive(Deserialize, Debug, Clone) ]
2020-10-05 17:41:49 +02:00
#[ serde(rename_all = " snake_case " ) ]
2021-05-18 19:49:15 +02:00
enum ImportGranularityDef {
2021-05-18 20:21:47 +02:00
Preserve ,
2021-05-18 19:49:15 +02:00
#[ serde(alias = " none " ) ]
Item ,
2021-05-10 21:33:01 +02:00
#[ serde(alias = " full " ) ]
2021-05-10 21:03:50 +02:00
Crate ,
2021-05-10 21:33:01 +02:00
#[ serde(alias = " last " ) ]
2021-05-10 21:03:50 +02:00
Module ,
2020-09-12 11:55:01 +02:00
}
2021-01-06 13:54:28 +03:00
#[ derive(Deserialize, Debug, Clone) ]
2020-10-05 17:41:49 +02:00
#[ serde(rename_all = " snake_case " ) ]
enum ImportPrefixDef {
Plain ,
2021-06-13 22:00:39 +02:00
#[ serde(alias = " self " ) ]
2020-10-05 17:41:49 +02:00
BySelf ,
2021-06-13 22:00:39 +02:00
#[ serde(alias = " crate " ) ]
2020-10-05 17:41:49 +02:00
ByCrate ,
}
2021-02-23 14:03:31 +02:00
#[ derive(Deserialize, Debug, Clone) ]
#[ serde(rename_all = " snake_case " ) ]
enum WorskpaceSymbolSearchScopeDef {
Workspace ,
WorkspaceAndDependencies ,
}
#[ derive(Deserialize, Debug, Clone) ]
#[ serde(rename_all = " snake_case " ) ]
enum WorskpaceSymbolSearchKindDef {
OnlyTypes ,
AllSymbols ,
}
2020-12-02 17:31:24 +03:00
macro_rules ! _config_data {
( struct $name :ident {
$(
$( #[ doc=$doc:literal ] ) *
2021-05-18 19:49:15 +02:00
$field :ident $( | $alias :ident ) * : $ty :ty = $default :expr ,
2020-12-02 17:31:24 +03:00
) *
} ) = > {
2020-07-10 00:28:12 +02:00
#[ allow(non_snake_case) ]
2021-01-06 13:54:28 +03:00
#[ derive(Debug, Clone) ]
2020-07-10 00:28:12 +02:00
struct $name { $( $field : $ty , ) * }
impl $name {
fn from_json ( mut json : serde_json ::Value ) -> $name {
$name { $(
2021-01-07 14:37:38 +03:00
$field : get_field (
& mut json ,
stringify! ( $field ) ,
2021-05-18 19:49:15 +02:00
None $( . or ( Some ( stringify! ( $alias ) ) ) ) * ,
2021-01-07 14:37:38 +03:00
$default ,
) ,
2020-07-10 00:28:12 +02:00
) * }
}
2020-12-02 17:31:24 +03:00
fn json_schema ( ) -> serde_json ::Value {
schema ( & [
$( {
let field = stringify! ( $field ) ;
let ty = stringify! ( $ty ) ;
2021-06-14 15:44:32 +02:00
2020-12-02 17:31:24 +03:00
( field , ty , & [ $( $doc ) , * ] , $default )
} , ) *
] )
}
2020-12-09 15:07:37 +03:00
#[ cfg(test) ]
fn manual ( ) -> String {
manual ( & [
$( {
let field = stringify! ( $field ) ;
let ty = stringify! ( $ty ) ;
2021-06-14 15:44:32 +02:00
2020-12-09 15:07:37 +03:00
( field , ty , & [ $( $doc ) , * ] , $default )
} , ) *
] )
}
2020-12-02 17:31:24 +03:00
}
2020-07-10 00:28:12 +02:00
} ;
}
2020-12-02 17:31:24 +03:00
use _config_data as config_data ;
fn get_field < T : DeserializeOwned > (
json : & mut serde_json ::Value ,
field : & 'static str ,
2021-01-07 14:37:38 +03:00
alias : Option < & 'static str > ,
2020-12-02 17:31:24 +03:00
default : & str ,
) -> T {
let default = serde_json ::from_str ( default ) . unwrap ( ) ;
2021-01-07 14:37:38 +03:00
// XXX: check alias first, to work-around the VS Code where it pre-fills the
// defaults instead of sending an empty object.
alias
. into_iter ( )
. chain ( iter ::once ( field ) )
. find_map ( move | field | {
let mut pointer = field . replace ( '_' , " / " ) ;
pointer . insert ( 0 , '/' ) ;
json . pointer_mut ( & pointer ) . and_then ( | it | serde_json ::from_value ( it . take ( ) ) . ok ( ) )
} )
2020-12-02 17:31:24 +03:00
. unwrap_or ( default )
}
2020-07-10 00:28:12 +02:00
2020-12-02 17:31:24 +03:00
fn schema ( fields : & [ ( & 'static str , & 'static str , & [ & str ] , & str ) ] ) -> serde_json ::Value {
for ( ( f1 , .. ) , ( f2 , .. ) ) in fields . iter ( ) . zip ( & fields [ 1 .. ] ) {
fn key ( f : & str ) -> & str {
2021-02-16 10:55:34 -05:00
f . splitn ( 2 , '_' ) . next ( ) . unwrap ( )
2021-01-02 20:48:39 +01:00
}
2020-12-02 17:31:24 +03:00
assert! ( key ( f1 ) < = key ( f2 ) , " wrong field order: {:?} {:?} " , f1 , f2 ) ;
}
let map = fields
. iter ( )
. map ( | ( field , ty , doc , default ) | {
let name = field . replace ( " _ " , " . " ) ;
let name = format! ( " rust-analyzer. {} " , name ) ;
let props = field_props ( field , ty , doc , default ) ;
( name , props )
} )
. collect ::< serde_json ::Map < _ , _ > > ( ) ;
map . into ( )
}
fn field_props ( field : & str , ty : & str , doc : & [ & str ] , default : & str ) -> serde_json ::Value {
2021-03-09 14:43:05 +03:00
let doc = doc_comment_to_string ( doc ) ;
let doc = doc . trim_end_matches ( '\n' ) ;
2020-12-02 17:31:24 +03:00
assert! (
doc . ends_with ( '.' ) & & doc . starts_with ( char ::is_uppercase ) ,
" bad docs for {}: {:?} " ,
field ,
doc
) ;
let default = default . parse ::< serde_json ::Value > ( ) . unwrap ( ) ;
let mut map = serde_json ::Map ::default ( ) ;
macro_rules ! set {
( $( $key :literal : $value :tt ) , * $(, ) ? ) = > { { $(
map . insert ( $key . into ( ) , serde_json ::json! ( $value ) ) ;
) * } } ;
2020-07-10 00:28:12 +02:00
}
2020-12-02 17:31:24 +03:00
set! ( " markdownDescription " : doc ) ;
set! ( " default " : default ) ;
match ty {
" bool " = > set! ( " type " : " boolean " ) ,
" String " = > set! ( " type " : " string " ) ,
" Vec<String> " = > set! {
" type " : " array " ,
2021-01-26 16:18:01 +03:00
" items " : { " type " : " string " } ,
} ,
" Vec<PathBuf> " = > set! {
" type " : " array " ,
2020-12-02 17:31:24 +03:00
" items " : { " type " : " string " } ,
} ,
" FxHashSet<String> " = > set! {
" type " : " array " ,
" items " : { " type " : " string " } ,
" uniqueItems " : true ,
} ,
2021-04-20 20:03:35 -07:00
" FxHashMap<String, String> " = > set! {
" type " : " object " ,
} ,
2020-12-02 17:31:24 +03:00
" Option<usize> " = > set! {
" type " : [ " null " , " integer " ] ,
" minimum " : 0 ,
} ,
" Option<String> " = > set! {
" type " : [ " null " , " string " ] ,
} ,
2021-01-06 13:54:28 +03:00
" Option<PathBuf> " = > set! {
" type " : [ " null " , " string " ] ,
} ,
2020-12-02 17:31:24 +03:00
" Option<bool> " = > set! {
" type " : [ " null " , " boolean " ] ,
} ,
" Option<Vec<String>> " = > set! {
" type " : [ " null " , " array " ] ,
" items " : { " type " : " string " } ,
} ,
2020-12-10 17:41:57 +03:00
" MergeBehaviorDef " = > set! {
2020-12-02 17:31:24 +03:00
" type " : " string " ,
2021-05-10 21:03:50 +02:00
" enum " : [ " none " , " crate " , " module " ] ,
2020-12-02 17:31:24 +03:00
" enumDescriptions " : [
2021-05-10 21:03:50 +02:00
" Do not merge imports at all. " ,
" Merge imports from the same crate into a single `use` statement. " ,
" Merge imports from the same module into a single `use` statement. "
2020-12-02 17:31:24 +03:00
] ,
} ,
2021-05-18 20:21:47 +02:00
" ImportGranularityDef " = > set! {
" type " : " string " ,
" enum " : [ " preserve " , " crate " , " module " , " item " ] ,
" 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. "
2020-12-02 17:31:24 +03:00
] ,
} ,
" ImportPrefixDef " = > set! {
" type " : " string " ,
" enum " : [
" plain " ,
2021-06-13 22:00:39 +02:00
" self " ,
" crate "
2020-12-02 17:31:24 +03:00
] ,
" enumDescriptions " : [
" Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item. " ,
2021-06-13 22:00:39 +02:00
" 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. "
2020-12-02 17:31:24 +03:00
] ,
} ,
" Vec<ManifestOrProjectJson> " = > set! {
" type " : " array " ,
" items " : { " type " : [ " string " , " object " ] } ,
} ,
2021-02-23 14:03:31 +02:00
" WorskpaceSymbolSearchScopeDef " = > set! {
" type " : " string " ,
" enum " : [ " workspace " , " workspace_and_dependencies " ] ,
" enumDescriptions " : [
" Search in current workspace only " ,
" Search in current workspace and dependencies "
] ,
} ,
" WorskpaceSymbolSearchKindDef " = > set! {
" type " : " string " ,
" enum " : [ " only_types " , " all_symbols " ] ,
" enumDescriptions " : [
" Search for types only " ,
" Search for all symbols kinds "
] ,
} ,
2020-12-02 17:31:24 +03:00
_ = > panic! ( " {} : {} " , ty , default ) ,
}
map . into ( )
}
2020-12-09 15:07:37 +03:00
#[ cfg(test) ]
fn manual ( fields : & [ ( & 'static str , & 'static str , & [ & str ] , & str ) ] ) -> String {
fields
. iter ( )
. map ( | ( field , _ty , doc , default ) | {
2021-01-05 13:09:06 +03:00
let name = format! ( " rust-analyzer. {} " , field . replace ( " _ " , " . " ) ) ;
2021-03-09 14:43:05 +03:00
let doc = doc_comment_to_string ( * doc ) ;
format! ( " [[ {} ]] {} (default: ` {} `):: \n + \n -- \n {} -- \n " , name , name , default , doc )
2020-12-09 15:07:37 +03:00
} )
. collect ::< String > ( )
}
2021-03-09 14:43:05 +03:00
fn doc_comment_to_string ( doc : & [ & str ] ) -> String {
doc . iter ( ) . map ( | it | it . strip_prefix ( ' ' ) . unwrap_or ( it ) ) . map ( | it | format! ( " {} \n " , it ) ) . collect ( )
}
2020-12-09 15:07:37 +03:00
#[ cfg(test) ]
mod tests {
use std ::fs ;
2021-03-08 20:22:33 +03:00
use test_utils ::{ ensure_file_contents , project_root } ;
2020-12-09 15:07:37 +03:00
use super ::* ;
2020-12-02 17:31:24 +03:00
2020-12-09 15:07:37 +03:00
#[ test ]
2021-03-08 21:13:15 +03:00
fn generate_package_json_config ( ) {
2020-12-09 15:07:37 +03:00
let s = Config ::json_schema ( ) ;
let schema = format! ( " {:#} " , s ) ;
2021-01-26 16:03:24 +03:00
let mut schema = schema
. trim_start_matches ( '{' )
. trim_end_matches ( '}' )
. replace ( " " , " " )
. replace ( " \n " , " \n " )
. trim_start_matches ( '\n' )
. trim_end ( )
. to_string ( ) ;
schema . push_str ( " , \n " ) ;
2021-03-08 20:22:33 +03:00
let package_json_path = project_root ( ) . join ( " editors/code/package.json " ) ;
2021-01-26 16:03:24 +03:00
let mut package_json = fs ::read_to_string ( & package_json_path ) . unwrap ( ) ;
2021-06-15 09:32:53 +03:00
let start_marker = " \" $generated-start \" : {}, \n " ;
let end_marker = " \" $generated-end \" : {} \n " ;
2021-01-26 16:03:24 +03:00
let start = package_json . find ( start_marker ) . unwrap ( ) + start_marker . len ( ) ;
let end = package_json . find ( end_marker ) . unwrap ( ) ;
2021-03-08 17:20:36 +03:00
2021-01-26 16:03:24 +03:00
let p = remove_ws ( & package_json [ start .. end ] ) ;
2020-12-09 15:07:37 +03:00
let s = remove_ws ( & schema ) ;
2021-01-26 16:03:24 +03:00
if ! p . contains ( & s ) {
package_json . replace_range ( start .. end , & schema ) ;
2021-03-08 17:20:36 +03:00
ensure_file_contents ( & package_json_path , & package_json )
2021-01-26 16:03:24 +03:00
}
2020-12-09 15:07:37 +03:00
}
2020-12-02 17:31:24 +03:00
2020-12-09 15:07:37 +03:00
#[ test ]
2021-03-08 21:13:15 +03:00
fn generate_config_documentation ( ) {
2021-03-08 20:22:33 +03:00
let docs_path = project_root ( ) . join ( " docs/user/generated_config.adoc " ) ;
2020-12-09 15:07:37 +03:00
let expected = ConfigData ::manual ( ) ;
2021-03-09 14:43:05 +03:00
ensure_file_contents ( & docs_path , & expected ) ;
2020-12-09 15:07:37 +03:00
}
fn remove_ws ( text : & str ) -> String {
text . replace ( char ::is_whitespace , " " )
}
2020-07-10 00:28:12 +02:00
}