};
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 {
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",
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",
/// 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.
/// 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).
/// 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> = "[]",
#[derive(Debug, Clone)]
pub struct FilesConfig {
pub watcher: FilesWatcher,
- pub exclude: Vec<String>,
+ pub exclude: Vec<AbsPathBuf>,
}
#[derive(Debug, Clone)]
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)
"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 {
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.as_ref().map(|it| self.root_path.join(&it));
+ 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,
.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
.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(),
},
};
ImportPrefixDef::ByCrate => PrefixKind::ByCrate,
ImportPrefixDef::BySelf => PrefixKind::BySelf,
},
+ group: self.data.assist_importGroup,
}
}
pub fn completion(&self) -> CompletionConfig {
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);
}
"type": "array",
"items": { "type": "string" },
},
+ "Vec<PathBuf>" => set! {
+ "type": "array",
+ "items": { "type": "string" },
+ },
"FxHashSet<String>" => set! {
"type": "array",
"items": { "type": "string" },