]> git.lizzy.rs Git - rust.git/blobdiff - crates/rust-analyzer/src/config.rs
Make group imports configurable
[rust.git] / crates / rust-analyzer / src / config.rs
index 071fde64dead0e7e808d5d4fe3ded46cf6fb689a..cac48e9117099074a33638e3137cdc66b32e3d2e 100644 (file)
@@ -7,7 +7,7 @@
 //! configure the server itself, feature flags are passed into analysis, and
 //! tweak things like automatic insertion of `()` in completions.
 
-use std::{convert::TryFrom, ffi::OsString, iter, path::PathBuf};
+use std::{ffi::OsString, iter, path::PathBuf};
 
 use flycheck::FlycheckConfig;
 use hir::PrefixKind;
 };
 use itertools::Itertools;
 use lsp_types::{ClientCapabilities, MarkupKind};
-use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
+use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource};
 use rustc_hash::FxHashSet;
 use serde::{de::DeserializeOwned, Deserialize};
 use vfs::AbsPathBuf;
 
-use crate::{caps::completion_item_edit_resolve, diagnostics::DiagnosticsMapConfig};
+use crate::{
+    caps::completion_item_edit_resolve, diagnostics::DiagnosticsMapConfig,
+    line_index::OffsetEncoding, lsp_ext::supports_utf8,
+};
 
 config_data! {
     struct ConfigData {
@@ -32,7 +35,8 @@ struct ConfigData {
         assist_importMergeBehaviour: MergeBehaviorDef  = "\"full\"",
         /// The path structure for newly inserted paths to use.
         assist_importPrefix: ImportPrefixDef           = "\"plain\"",
-
+        /// Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.
+        assist_importGroup: bool                       = "true",
         /// Show function name and docs in parameter hints.
         callInfo_full: bool = "true",
 
@@ -43,8 +47,8 @@ struct ConfigData {
         cargo_allFeatures: bool          = "false",
         /// List of features to activate.
         cargo_features: Vec<String>      = "[]",
-        /// Run `cargo check` on startup to get the correct value for package
-        /// OUT_DIRs.
+        /// Run build scripts (`build.rs`) for more precise code analysis.
+        cargo_runBuildScripts |
         cargo_loadOutDirsFromCheck: bool = "false",
         /// Do not activate the `default` feature.
         cargo_noDefaultFeatures: bool    = "false",
@@ -105,6 +109,8 @@ struct ConfigData {
 
         /// Controls file watching implementation.
         files_watcher: String = "\"client\"",
+        /// These directories will be ignored by rust-analyzer.
+        files_excludeDirs: Vec<PathBuf> = "[]",
 
         /// Whether to show `Debug` action. Only applies when
         /// `#rust-analyzer.hoverActions.enable#` is set.
@@ -162,8 +168,7 @@ struct ConfigData {
         /// Whether to show `can't find Cargo.toml` error message.
         notifications_cargoTomlNotFound: bool      = "true",
 
-        /// Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be
-        /// enabled.
+        /// Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScripts#`.
         procMacro_enable: bool                     = "false",
         /// Internal config, path to proc-macro server executable (typically,
         /// this is rust-analyzer itself, but we override this in tests).
@@ -175,8 +180,9 @@ struct ConfigData {
         /// tests or binaries.\nFor example, it may be `--release`.
         runnables_cargoExtraArgs: Vec<String>   = "[]",
 
-        /// Path to the rust compiler sources, for usage in rustc_private projects.
-        rustcSource : Option<PathBuf> = "null",
+        /// Path to the rust compiler sources, for usage in rustc_private projects, or "discover"
+        /// to try to automatically find it.
+        rustcSource : Option<String> = "null",
 
         /// Additional arguments to `rustfmt`.
         rustfmt_extraArgs: Vec<String>               = "[]",
@@ -248,7 +254,7 @@ pub fn references(&self) -> bool {
 #[derive(Debug, Clone)]
 pub struct FilesConfig {
     pub watcher: FilesWatcher,
-    pub exclude: Vec<String>,
+    pub exclude: Vec<AbsPathBuf>,
 }
 
 #[derive(Debug, Clone)]
@@ -412,6 +418,13 @@ pub fn signature_help_label_offsets(&self) -> bool {
             false
         )
     }
+    pub fn offset_encoding(&self) -> OffsetEncoding {
+        if supports_utf8(&self.caps) {
+            OffsetEncoding::Utf8
+        } else {
+            OffsetEncoding::Utf16
+        }
+    }
 
     fn experimental(&self, index: &'static str) -> bool {
         try_or!(self.caps.experimental.as_ref()?.get(index)?.as_bool()?, false)
@@ -458,7 +471,7 @@ pub fn files(&self) -> FilesConfig {
                 "notify" => FilesWatcher::Notify,
                 "client" | _ => FilesWatcher::Client,
             },
-            exclude: Vec::new(),
+            exclude: self.data.files_excludeDirs.iter().map(|it| self.root_path.join(it)).collect(),
         }
     }
     pub fn notifications(&self) -> NotificationsConfig {
@@ -467,18 +480,22 @@ pub fn notifications(&self) -> NotificationsConfig {
     pub fn cargo_autoreload(&self) -> bool {
         self.data.cargo_autoreload
     }
+    pub fn run_build_scripts(&self) -> bool {
+        self.data.cargo_runBuildScripts || self.data.procMacro_enable
+    }
     pub fn cargo(&self) -> CargoConfig {
-        let rustc_source = self.data.rustcSource.clone().and_then(|it| {
-            AbsPathBuf::try_from(it)
-                .map_err(|_| log::error!("rustc source directory must be an absolute path"))
-                .ok()
+        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))
+            }
         });
 
         CargoConfig {
             no_default_features: self.data.cargo_noDefaultFeatures,
             all_features: self.data.cargo_allFeatures,
             features: self.data.cargo_features.clone(),
-            load_out_dirs_from_check: self.data.cargo_loadOutDirsFromCheck,
             target: self.data.cargo_target.clone(),
             rustc_source,
             no_sysroot: self.data.cargo_noSysroot,
@@ -512,7 +529,7 @@ pub fn flycheck(&self) -> Option<FlycheckConfig> {
                     .data
                     .checkOnSave_target
                     .clone()
-                    .or(self.data.cargo_target.clone()),
+                    .or_else(|| self.data.cargo_target.clone()),
                 all_targets: self.data.checkOnSave_allTargets,
                 no_default_features: self
                     .data
@@ -526,7 +543,7 @@ pub fn flycheck(&self) -> Option<FlycheckConfig> {
                     .data
                     .checkOnSave_features
                     .clone()
-                    .unwrap_or(self.data.cargo_features.clone()),
+                    .unwrap_or_else(|| self.data.cargo_features.clone()),
                 extra_args: self.data.checkOnSave_extraArgs.clone(),
             },
         };
@@ -558,6 +575,7 @@ fn insert_use_config(&self) -> InsertUseConfig {
                 ImportPrefixDef::ByCrate => PrefixKind::ByCrate,
                 ImportPrefixDef::BySelf => PrefixKind::BySelf,
             },
+            group: self.data.assist_importGroup,
         }
     }
     pub fn completion(&self) -> CompletionConfig {
@@ -724,7 +742,7 @@ fn get_field<T: DeserializeOwned>(
 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 {
-            f.splitn(2, "_").next().unwrap()
+            f.splitn(2, '_').next().unwrap()
         }
         assert!(key(f1) <= key(f2), "wrong field order: {:?} {:?}", f1, f2);
     }
@@ -767,6 +785,10 @@ macro_rules! set {
             "type": "array",
             "items": { "type": "string" },
         },
+        "Vec<PathBuf>" => set! {
+            "type": "array",
+            "items": { "type": "string" },
+        },
         "FxHashSet<String>" => set! {
             "type": "array",
             "items": { "type": "string" },