diff options
author | Aleksey Kladov <[email protected]> | 2021-04-12 09:04:36 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-04-12 13:29:31 +0100 |
commit | 186c5c47cbfde4ae9d81dc67450c958cb6aece2c (patch) | |
tree | 05141f6e9aa7d20c4ce2a8b59324a3d82d43f895 /crates/rust-analyzer | |
parent | 7be06139b632ee615fc18af04dd67947e2c794b2 (diff) |
feat: avoid checking the whole project during initial loading
Diffstat (limited to 'crates/rust-analyzer')
-rw-r--r-- | crates/rust-analyzer/src/benchmarks.rs | 7 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/main.rs | 15 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/rustc_wrapper.rs | 46 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/analysis_stats.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/diagnostics.rs | 3 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 10 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/ssr.rs | 9 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 3 | ||||
-rw-r--r-- | crates/rust-analyzer/tests/rust-analyzer/main.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/tests/rust-analyzer/support.rs | 20 |
11 files changed, 108 insertions, 14 deletions
diff --git a/crates/rust-analyzer/src/benchmarks.rs b/crates/rust-analyzer/src/benchmarks.rs index bf569b40b..bdd94b1c4 100644 --- a/crates/rust-analyzer/src/benchmarks.rs +++ b/crates/rust-analyzer/src/benchmarks.rs | |||
@@ -30,8 +30,11 @@ fn benchmark_integrated_highlighting() { | |||
30 | let file = "./crates/ide_db/src/apply_change.rs"; | 30 | let file = "./crates/ide_db/src/apply_change.rs"; |
31 | 31 | ||
32 | let cargo_config = Default::default(); | 32 | let cargo_config = Default::default(); |
33 | let load_cargo_config = | 33 | let load_cargo_config = LoadCargoConfig { |
34 | LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: false }; | 34 | load_out_dirs_from_check: true, |
35 | wrap_rustc: false, | ||
36 | with_proc_macro: false, | ||
37 | }; | ||
35 | 38 | ||
36 | let (mut host, vfs, _proc_macro) = { | 39 | let (mut host, vfs, _proc_macro) = { |
37 | let _it = stdx::timeit("workspace loading"); | 40 | let _it = stdx::timeit("workspace loading"); |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 873e82c7b..f0abb5b15 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -3,6 +3,7 @@ | |||
3 | //! Based on cli flags, either spawns an LSP server, or runs a batch analysis | 3 | //! Based on cli flags, either spawns an LSP server, or runs a batch analysis |
4 | mod flags; | 4 | mod flags; |
5 | mod logger; | 5 | mod logger; |
6 | mod rustc_wrapper; | ||
6 | 7 | ||
7 | use std::{convert::TryFrom, env, fs, path::Path, process}; | 8 | use std::{convert::TryFrom, env, fs, path::Path, process}; |
8 | 9 | ||
@@ -26,6 +27,20 @@ static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; | |||
26 | static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; | 27 | static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; |
27 | 28 | ||
28 | fn main() { | 29 | fn main() { |
30 | if std::env::var("RA_RUSTC_WRAPPER").is_ok() { | ||
31 | let mut args = std::env::args_os(); | ||
32 | let _me = args.next().unwrap(); | ||
33 | let rustc = args.next().unwrap(); | ||
34 | let code = match rustc_wrapper::run_rustc_skipping_cargo_checking(rustc, args.collect()) { | ||
35 | Ok(rustc_wrapper::ExitCode(code)) => code.unwrap_or(102), | ||
36 | Err(err) => { | ||
37 | eprintln!("{}", err); | ||
38 | 101 | ||
39 | } | ||
40 | }; | ||
41 | process::exit(code); | ||
42 | } | ||
43 | |||
29 | if let Err(err) = try_main() { | 44 | if let Err(err) = try_main() { |
30 | log::error!("Unexpected error: {}", err); | 45 | log::error!("Unexpected error: {}", err); |
31 | eprintln!("{}", err); | 46 | eprintln!("{}", err); |
diff --git a/crates/rust-analyzer/src/bin/rustc_wrapper.rs b/crates/rust-analyzer/src/bin/rustc_wrapper.rs new file mode 100644 index 000000000..2f6d4706d --- /dev/null +++ b/crates/rust-analyzer/src/bin/rustc_wrapper.rs | |||
@@ -0,0 +1,46 @@ | |||
1 | //! We setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself during the | ||
2 | //! initial `cargo check`. That way, we avoid checking the actual project, and | ||
3 | //! only build proc macros and build.rs. | ||
4 | //! | ||
5 | //! Code taken from IntelliJ :0) | ||
6 | //! https://github.com/intellij-rust/intellij-rust/blob/master/native-helper/src/main.rs | ||
7 | use std::{ | ||
8 | ffi::OsString, | ||
9 | io, | ||
10 | process::{Command, Stdio}, | ||
11 | }; | ||
12 | |||
13 | /// ExitCode/ExitStatus are impossible to create :(. | ||
14 | pub(crate) struct ExitCode(pub(crate) Option<i32>); | ||
15 | |||
16 | pub(crate) fn run_rustc_skipping_cargo_checking( | ||
17 | rustc_executable: OsString, | ||
18 | args: Vec<OsString>, | ||
19 | ) -> io::Result<ExitCode> { | ||
20 | let is_cargo_check = args.iter().any(|arg| { | ||
21 | let arg = arg.to_string_lossy(); | ||
22 | // `cargo check` invokes `rustc` with `--emit=metadata` argument. | ||
23 | // | ||
24 | // https://doc.rust-lang.org/rustc/command-line-arguments.html#--emit-specifies-the-types-of-output-files-to-generate | ||
25 | // link — Generates the crates specified by --crate-type. The default | ||
26 | // output filenames depend on the crate type and platform. This | ||
27 | // is the default if --emit is not specified. | ||
28 | // metadata — Generates a file containing metadata about the crate. | ||
29 | // The default output filename is CRATE_NAME.rmeta. | ||
30 | arg.starts_with("--emit=") && arg.contains("metadata") && !arg.contains("link") | ||
31 | }); | ||
32 | if is_cargo_check { | ||
33 | return Ok(ExitCode(Some(0))); | ||
34 | } | ||
35 | run_rustc(rustc_executable, args) | ||
36 | } | ||
37 | |||
38 | fn run_rustc(rustc_executable: OsString, args: Vec<OsString>) -> io::Result<ExitCode> { | ||
39 | let mut child = Command::new(rustc_executable) | ||
40 | .args(args) | ||
41 | .stdin(Stdio::inherit()) | ||
42 | .stdout(Stdio::inherit()) | ||
43 | .stderr(Stdio::inherit()) | ||
44 | .spawn()?; | ||
45 | Ok(ExitCode(child.wait()?.code())) | ||
46 | } | ||
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index fe9f273b0..3f3134562 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -68,6 +68,7 @@ impl AnalysisStatsCmd { | |||
68 | cargo_config.no_sysroot = self.no_sysroot; | 68 | cargo_config.no_sysroot = self.no_sysroot; |
69 | let load_cargo_config = LoadCargoConfig { | 69 | let load_cargo_config = LoadCargoConfig { |
70 | load_out_dirs_from_check: self.load_output_dirs, | 70 | load_out_dirs_from_check: self.load_output_dirs, |
71 | wrap_rustc: false, | ||
71 | with_proc_macro: self.with_proc_macro, | 72 | with_proc_macro: self.with_proc_macro, |
72 | }; | 73 | }; |
73 | let (host, vfs, _proc_macro) = | 74 | let (host, vfs, _proc_macro) = |
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index 8b985716b..0085d0e4d 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs | |||
@@ -34,7 +34,8 @@ pub fn diagnostics( | |||
34 | with_proc_macro: bool, | 34 | with_proc_macro: bool, |
35 | ) -> Result<()> { | 35 | ) -> Result<()> { |
36 | let cargo_config = Default::default(); | 36 | let cargo_config = Default::default(); |
37 | let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check, with_proc_macro }; | 37 | let load_cargo_config = |
38 | LoadCargoConfig { load_out_dirs_from_check, with_proc_macro, wrap_rustc: false }; | ||
38 | let (host, _vfs, _proc_macro) = | 39 | let (host, _vfs, _proc_macro) = |
39 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; | 40 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; |
40 | let db = host.raw_database(); | 41 | let db = host.raw_database(); |
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 310c36904..75bad1112 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -15,6 +15,7 @@ use crate::reload::{ProjectFolders, SourceRootConfig}; | |||
15 | 15 | ||
16 | pub struct LoadCargoConfig { | 16 | pub struct LoadCargoConfig { |
17 | pub load_out_dirs_from_check: bool, | 17 | pub load_out_dirs_from_check: bool, |
18 | pub wrap_rustc: bool, | ||
18 | pub with_proc_macro: bool, | 19 | pub with_proc_macro: bool, |
19 | } | 20 | } |
20 | 21 | ||
@@ -52,7 +53,7 @@ pub fn load_workspace( | |||
52 | }; | 53 | }; |
53 | 54 | ||
54 | let build_data = if config.load_out_dirs_from_check { | 55 | let build_data = if config.load_out_dirs_from_check { |
55 | let mut collector = BuildDataCollector::default(); | 56 | let mut collector = BuildDataCollector::new(config.wrap_rustc); |
56 | ws.collect_build_data_configs(&mut collector); | 57 | ws.collect_build_data_configs(&mut collector); |
57 | Some(collector.collect(progress)?) | 58 | Some(collector.collect(progress)?) |
58 | } else { | 59 | } else { |
@@ -136,8 +137,11 @@ mod tests { | |||
136 | fn test_loading_rust_analyzer() -> Result<()> { | 137 | fn test_loading_rust_analyzer() -> Result<()> { |
137 | let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); | 138 | let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); |
138 | let cargo_config = Default::default(); | 139 | let cargo_config = Default::default(); |
139 | let load_cargo_config = | 140 | let load_cargo_config = LoadCargoConfig { |
140 | LoadCargoConfig { load_out_dirs_from_check: false, with_proc_macro: false }; | 141 | load_out_dirs_from_check: false, |
142 | wrap_rustc: false, | ||
143 | with_proc_macro: false, | ||
144 | }; | ||
141 | let (host, _vfs, _proc_macro) = | 145 | let (host, _vfs, _proc_macro) = |
142 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; | 146 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; |
143 | 147 | ||
diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs index 79f426fff..1fd9b5a9b 100644 --- a/crates/rust-analyzer/src/cli/ssr.rs +++ b/crates/rust-analyzer/src/cli/ssr.rs | |||
@@ -9,8 +9,11 @@ use ide_ssr::{MatchFinder, SsrPattern, SsrRule}; | |||
9 | pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { | 9 | pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { |
10 | use ide_db::base_db::SourceDatabaseExt; | 10 | use ide_db::base_db::SourceDatabaseExt; |
11 | let cargo_config = Default::default(); | 11 | let cargo_config = Default::default(); |
12 | let load_cargo_config = | 12 | let load_cargo_config = LoadCargoConfig { |
13 | LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true }; | 13 | load_out_dirs_from_check: true, |
14 | wrap_rustc: false, | ||
15 | with_proc_macro: true, | ||
16 | }; | ||
14 | let (host, vfs, _proc_macro) = | 17 | let (host, vfs, _proc_macro) = |
15 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; | 18 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; |
16 | let db = host.raw_database(); | 19 | let db = host.raw_database(); |
@@ -37,7 +40,7 @@ pub fn search_for_patterns(patterns: Vec<SsrPattern>, debug_snippet: Option<Stri | |||
37 | use ide_db::symbol_index::SymbolsDatabase; | 40 | use ide_db::symbol_index::SymbolsDatabase; |
38 | let cargo_config = Default::default(); | 41 | let cargo_config = Default::default(); |
39 | let load_cargo_config = | 42 | let load_cargo_config = |
40 | LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true }; | 43 | LoadCargoConfig { load_out_dirs_from_check: true, wrap_rustc: true, with_proc_macro: true }; |
41 | let (host, _vfs, _proc_macro) = | 44 | let (host, _vfs, _proc_macro) = |
42 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; | 45 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; |
43 | let db = host.raw_database(); | 46 | let db = host.raw_database(); |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index f809667e9..1edaa394a 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -48,6 +48,9 @@ config_data! { | |||
48 | /// Run build scripts (`build.rs`) for more precise code analysis. | 48 | /// Run build scripts (`build.rs`) for more precise code analysis. |
49 | cargo_runBuildScripts | | 49 | cargo_runBuildScripts | |
50 | cargo_loadOutDirsFromCheck: bool = "true", | 50 | cargo_loadOutDirsFromCheck: bool = "true", |
51 | /// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to | ||
52 | /// avoid compiling unnecessary things. | ||
53 | cargo_useRustcWrapperForBuildScripts: bool = "true", | ||
51 | /// Do not activate the `default` feature. | 54 | /// Do not activate the `default` feature. |
52 | cargo_noDefaultFeatures: bool = "false", | 55 | cargo_noDefaultFeatures: bool = "false", |
53 | /// Compilation target (target triple). | 56 | /// Compilation target (target triple). |
@@ -493,6 +496,9 @@ impl Config { | |||
493 | pub fn run_build_scripts(&self) -> bool { | 496 | pub fn run_build_scripts(&self) -> bool { |
494 | self.data.cargo_runBuildScripts || self.data.procMacro_enable | 497 | self.data.cargo_runBuildScripts || self.data.procMacro_enable |
495 | } | 498 | } |
499 | pub fn wrap_rustc(&self) -> bool { | ||
500 | self.data.cargo_useRustcWrapperForBuildScripts | ||
501 | } | ||
496 | pub fn cargo(&self) -> CargoConfig { | 502 | pub fn cargo(&self) -> CargoConfig { |
497 | let rustc_source = self.data.rustcSource.as_ref().map(|rustc_src| { | 503 | let rustc_source = self.data.rustcSource.as_ref().map(|rustc_src| { |
498 | if rustc_src == "discover" { | 504 | if rustc_src == "discover" { |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 47c6c6d77..b3d4c6ec5 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -236,7 +236,8 @@ impl GlobalState { | |||
236 | let workspaces_updated = !Arc::ptr_eq(&old, &self.workspaces); | 236 | let workspaces_updated = !Arc::ptr_eq(&old, &self.workspaces); |
237 | 237 | ||
238 | if self.config.run_build_scripts() && workspaces_updated { | 238 | if self.config.run_build_scripts() && workspaces_updated { |
239 | let mut collector = BuildDataCollector::default(); | 239 | let mut collector = |
240 | BuildDataCollector::new(self.config.wrap_rustc()); | ||
240 | for ws in self.workspaces.iter() { | 241 | for ws in self.workspaces.iter() { |
241 | ws.collect_build_data_configs(&mut collector); | 242 | ws.collect_build_data_configs(&mut collector); |
242 | } | 243 | } |
diff --git a/crates/rust-analyzer/tests/rust-analyzer/main.rs b/crates/rust-analyzer/tests/rust-analyzer/main.rs index 4442cbff6..1e4c04bbf 100644 --- a/crates/rust-analyzer/tests/rust-analyzer/main.rs +++ b/crates/rust-analyzer/tests/rust-analyzer/main.rs | |||
@@ -527,7 +527,7 @@ version = \"0.0.0\" | |||
527 | #[test] | 527 | #[test] |
528 | fn out_dirs_check() { | 528 | fn out_dirs_check() { |
529 | if skip_slow_tests() { | 529 | if skip_slow_tests() { |
530 | return; | 530 | // return; |
531 | } | 531 | } |
532 | 532 | ||
533 | let server = Project::with_fixture( | 533 | let server = Project::with_fixture( |
diff --git a/crates/rust-analyzer/tests/rust-analyzer/support.rs b/crates/rust-analyzer/tests/rust-analyzer/support.rs index 8d68f1b7d..5e388c0f0 100644 --- a/crates/rust-analyzer/tests/rust-analyzer/support.rs +++ b/crates/rust-analyzer/tests/rust-analyzer/support.rs | |||
@@ -32,8 +32,12 @@ impl<'a> Project<'a> { | |||
32 | tmp_dir: None, | 32 | tmp_dir: None, |
33 | roots: vec![], | 33 | roots: vec![], |
34 | config: serde_json::json!({ | 34 | config: serde_json::json!({ |
35 | // Loading standard library is costly, let's ignore it by default | 35 | "cargo": { |
36 | "cargo": { "noSysroot": true } | 36 | // Loading standard library is costly, let's ignore it by default |
37 | "noSysroot": true, | ||
38 | // Can't use test binary as rustc wrapper. | ||
39 | "useRustcWrapperForBuildScripts": false, | ||
40 | } | ||
37 | }), | 41 | }), |
38 | } | 42 | } |
39 | } | 43 | } |
@@ -49,7 +53,17 @@ impl<'a> Project<'a> { | |||
49 | } | 53 | } |
50 | 54 | ||
51 | pub(crate) fn with_config(mut self, config: serde_json::Value) -> Project<'a> { | 55 | pub(crate) fn with_config(mut self, config: serde_json::Value) -> Project<'a> { |
52 | self.config = config; | 56 | fn merge(dst: &mut serde_json::Value, src: serde_json::Value) { |
57 | match (dst, src) { | ||
58 | (Value::Object(dst), Value::Object(src)) => { | ||
59 | for (k, v) in src { | ||
60 | merge(dst.entry(k).or_insert(v.clone()), v) | ||
61 | } | ||
62 | } | ||
63 | (dst, src) => *dst = src, | ||
64 | } | ||
65 | } | ||
66 | merge(&mut self.config, config); | ||
53 | self | 67 | self |
54 | } | 68 | } |
55 | 69 | ||