aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-04-16 21:21:59 +0100
committerGitHub <[email protected]>2020-04-16 21:21:59 +0100
commit10d8cb913cb8247ae64b954cf07460f1b6d96ef7 (patch)
tree976786b86c189d8c03a15378fd62526cbe8eaab7
parenta4cda3efbbabe4c6129de4dc095953fe858d7d3f (diff)
parent16a74cfd234e94d383b0ef067fb6a3c651ed9624 (diff)
Merge #3958
3958: Add proc-macro related config and tests r=matklad a=edwin0cheng This PR do the following things: 1. Add cli argument `proc-macro` for running proc-macro server. 2. Added support for proc-macro in bench and analysis-stats 3. Added typescript config for proc-macros 4. Added an heavy test for proc-macros. To test it out: 1. run `cargo xtask install --proc-macro` 2. add `"rust-analyzer.cargo.loadOutDirsFromCheck": true"` and `"rust-analyzer.procMacro.enabled": true"` in vs code config. [Edit] Change to use `rust-analyzer proc-macro` for running proc-macro standalone process. Co-authored-by: Edwin Cheng <[email protected]>
-rw-r--r--Cargo.lock1
-rw-r--r--crates/ra_proc_macro/src/lib.rs12
-rw-r--r--crates/ra_proc_macro/src/process.rs19
-rw-r--r--crates/ra_proc_macro_srv/src/cli.rs (renamed from crates/ra_proc_macro_srv/src/main.rs)5
-rw-r--r--crates/ra_proc_macro_srv/src/lib.rs6
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/bin/args.rs24
-rw-r--r--crates/rust-analyzer/src/bin/main.rs22
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs3
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs3
-rw-r--r--crates/rust-analyzer/src/cli/diagnostics.rs9
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs12
-rw-r--r--crates/rust-analyzer/src/config.rs14
-rw-r--r--crates/rust-analyzer/src/world.rs8
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs91
-rw-r--r--editors/code/package.json5
-rw-r--r--editors/code/src/config.ts1
17 files changed, 208 insertions, 29 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2a12d9f5b..89a734c9b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1341,6 +1341,7 @@ dependencies = [
1341 "ra_hir_def", 1341 "ra_hir_def",
1342 "ra_hir_ty", 1342 "ra_hir_ty",
1343 "ra_ide", 1343 "ra_ide",
1344 "ra_proc_macro_srv",
1344 "ra_prof", 1345 "ra_prof",
1345 "ra_project_model", 1346 "ra_project_model",
1346 "ra_syntax", 1347 "ra_syntax",
diff --git a/crates/ra_proc_macro/src/lib.rs b/crates/ra_proc_macro/src/lib.rs
index 63da9f1b4..b200fd126 100644
--- a/crates/ra_proc_macro/src/lib.rs
+++ b/crates/ra_proc_macro/src/lib.rs
@@ -12,6 +12,7 @@ pub mod msg;
12use process::{ProcMacroProcessSrv, ProcMacroProcessThread}; 12use process::{ProcMacroProcessSrv, ProcMacroProcessThread};
13use ra_tt::{SmolStr, Subtree}; 13use ra_tt::{SmolStr, Subtree};
14use std::{ 14use std::{
15 ffi::OsStr,
15 path::{Path, PathBuf}, 16 path::{Path, PathBuf},
16 sync::Arc, 17 sync::Arc,
17}; 18};
@@ -56,8 +57,15 @@ pub struct ProcMacroClient {
56} 57}
57 58
58impl ProcMacroClient { 59impl ProcMacroClient {
59 pub fn extern_process(process_path: &Path) -> Result<ProcMacroClient, std::io::Error> { 60 pub fn extern_process<I, S>(
60 let (thread, process) = ProcMacroProcessSrv::run(process_path)?; 61 process_path: &Path,
62 args: I,
63 ) -> Result<ProcMacroClient, std::io::Error>
64 where
65 I: IntoIterator<Item = S>,
66 S: AsRef<OsStr>,
67 {
68 let (thread, process) = ProcMacroProcessSrv::run(process_path, args)?;
61 Ok(ProcMacroClient { 69 Ok(ProcMacroClient {
62 kind: ProcMacroClientKind::Process { process: Arc::new(process), thread }, 70 kind: ProcMacroClientKind::Process { process: Arc::new(process), thread },
63 }) 71 })
diff --git a/crates/ra_proc_macro/src/process.rs b/crates/ra_proc_macro/src/process.rs
index e8c85be38..f851570bc 100644
--- a/crates/ra_proc_macro/src/process.rs
+++ b/crates/ra_proc_macro/src/process.rs
@@ -9,6 +9,7 @@ use crate::rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTas
9use io::{BufRead, BufReader}; 9use io::{BufRead, BufReader};
10use std::{ 10use std::{
11 convert::{TryFrom, TryInto}, 11 convert::{TryFrom, TryInto},
12 ffi::OsStr,
12 io::{self, Write}, 13 io::{self, Write},
13 path::{Path, PathBuf}, 14 path::{Path, PathBuf},
14 process::{Child, Command, Stdio}, 15 process::{Child, Command, Stdio},
@@ -44,8 +45,13 @@ impl Drop for Process {
44} 45}
45 46
46impl Process { 47impl Process {
47 fn run(process_path: &Path) -> Result<Process, io::Error> { 48 fn run<I, S>(process_path: &Path, args: I) -> Result<Process, io::Error>
49 where
50 I: IntoIterator<Item = S>,
51 S: AsRef<OsStr>,
52 {
48 let child = Command::new(process_path.clone()) 53 let child = Command::new(process_path.clone())
54 .args(args)
49 .stdin(Stdio::piped()) 55 .stdin(Stdio::piped())
50 .stdout(Stdio::piped()) 56 .stdout(Stdio::piped())
51 .stderr(Stdio::null()) 57 .stderr(Stdio::null())
@@ -74,10 +80,15 @@ impl Process {
74} 80}
75 81
76impl ProcMacroProcessSrv { 82impl ProcMacroProcessSrv {
77 pub fn run( 83 pub fn run<I, S>(
78 process_path: &Path, 84 process_path: &Path,
79 ) -> Result<(ProcMacroProcessThread, ProcMacroProcessSrv), io::Error> { 85 args: I,
80 let process = Process::run(process_path)?; 86 ) -> Result<(ProcMacroProcessThread, ProcMacroProcessSrv), io::Error>
87 where
88 I: IntoIterator<Item = S>,
89 S: AsRef<OsStr>,
90 {
91 let process = Process::run(process_path, args)?;
81 92
82 let (task_tx, task_rx) = bounded(0); 93 let (task_tx, task_rx) = bounded(0);
83 let handle = jod_thread::spawn(move || { 94 let handle = jod_thread::spawn(move || {
diff --git a/crates/ra_proc_macro_srv/src/main.rs b/crates/ra_proc_macro_srv/src/cli.rs
index 70743c1f4..c771f2b38 100644
--- a/crates/ra_proc_macro_srv/src/main.rs
+++ b/crates/ra_proc_macro_srv/src/cli.rs
@@ -1,7 +1,7 @@
1//! Driver for proc macro server 1//! Driver for proc macro server
2 2
3use crate::{expand_task, list_macros};
3use ra_proc_macro::msg::{self, Message}; 4use ra_proc_macro::msg::{self, Message};
4use ra_proc_macro_srv::{expand_task, list_macros};
5 5
6use std::io; 6use std::io;
7 7
@@ -24,7 +24,8 @@ fn write_response(res: Result<msg::Response, String>) -> Result<(), io::Error> {
24 let mut stdout = stdout.lock(); 24 let mut stdout = stdout.lock();
25 msg.write(&mut stdout) 25 msg.write(&mut stdout)
26} 26}
27fn main() { 27
28pub fn run() {
28 loop { 29 loop {
29 let req = match read_request() { 30 let req = match read_request() {
30 Err(err) => { 31 Err(err) => {
diff --git a/crates/ra_proc_macro_srv/src/lib.rs b/crates/ra_proc_macro_srv/src/lib.rs
index 59716cbb3..c62b0ed89 100644
--- a/crates/ra_proc_macro_srv/src/lib.rs
+++ b/crates/ra_proc_macro_srv/src/lib.rs
@@ -22,7 +22,7 @@ mod dylib;
22use proc_macro::bridge::client::TokenStream; 22use proc_macro::bridge::client::TokenStream;
23use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask}; 23use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask};
24 24
25pub fn expand_task(task: &ExpansionTask) -> Result<ExpansionResult, String> { 25pub(crate) fn expand_task(task: &ExpansionTask) -> Result<ExpansionResult, String> {
26 let expander = dylib::Expander::new(&task.lib) 26 let expander = dylib::Expander::new(&task.lib)
27 .expect(&format!("Cannot expand with provided libraries: ${:?}", &task.lib)); 27 .expect(&format!("Cannot expand with provided libraries: ${:?}", &task.lib));
28 28
@@ -39,7 +39,7 @@ pub fn expand_task(task: &ExpansionTask) -> Result<ExpansionResult, String> {
39 } 39 }
40} 40}
41 41
42pub fn list_macros(task: &ListMacrosTask) -> Result<ListMacrosResult, String> { 42pub(crate) fn list_macros(task: &ListMacrosTask) -> Result<ListMacrosResult, String> {
43 let expander = dylib::Expander::new(&task.lib) 43 let expander = dylib::Expander::new(&task.lib)
44 .expect(&format!("Cannot expand with provided libraries: ${:?}", &task.lib)); 44 .expect(&format!("Cannot expand with provided libraries: ${:?}", &task.lib));
45 45
@@ -53,5 +53,7 @@ pub fn list_macros(task: &ListMacrosTask) -> Result<ListMacrosResult, String> {
53 } 53 }
54} 54}
55 55
56pub mod cli;
57
56#[cfg(test)] 58#[cfg(test)]
57mod tests; 59mod tests;
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index f5f773432..cee0248b6 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -46,7 +46,7 @@ ra_db = { path = "../ra_db" }
46hir = { path = "../ra_hir", package = "ra_hir" } 46hir = { path = "../ra_hir", package = "ra_hir" }
47hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } 47hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
48hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" } 48hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" }
49 49ra_proc_macro_srv = { path = "../ra_proc_macro_srv" }
50 50
51[target.'cfg(windows)'.dependencies] 51[target.'cfg(windows)'.dependencies]
52winapi = "0.3.8" 52winapi = "0.3.8"
diff --git a/crates/rust-analyzer/src/bin/args.rs b/crates/rust-analyzer/src/bin/args.rs
index f5981588a..5e19253a6 100644
--- a/crates/rust-analyzer/src/bin/args.rs
+++ b/crates/rust-analyzer/src/bin/args.rs
@@ -29,19 +29,23 @@ pub(crate) enum Command {
29 with_deps: bool, 29 with_deps: bool,
30 path: PathBuf, 30 path: PathBuf,
31 load_output_dirs: bool, 31 load_output_dirs: bool,
32 with_proc_macro: bool,
32 }, 33 },
33 Bench { 34 Bench {
34 path: PathBuf, 35 path: PathBuf,
35 what: BenchWhat, 36 what: BenchWhat,
36 load_output_dirs: bool, 37 load_output_dirs: bool,
38 with_proc_macro: bool,
37 }, 39 },
38 Diagnostics { 40 Diagnostics {
39 path: PathBuf, 41 path: PathBuf,
40 load_output_dirs: bool, 42 load_output_dirs: bool,
43 with_proc_macro: bool,
41 /// Include files which are not modules. In rust-analyzer 44 /// Include files which are not modules. In rust-analyzer
42 /// this would include the parser test files. 45 /// this would include the parser test files.
43 all: bool, 46 all: bool,
44 }, 47 },
48 ProcMacro,
45 RunServer, 49 RunServer,
46 Version, 50 Version,
47} 51}
@@ -148,6 +152,7 @@ FLAGS:
148 -h, --help Prints help information 152 -h, --help Prints help information
149 --memory-usage 153 --memory-usage
150 --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis 154 --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis
155 --with-proc-macro Use ra-proc-macro-srv for proc-macro expanding
151 -v, --verbose 156 -v, --verbose
152 -q, --quiet 157 -q, --quiet
153 158
@@ -165,6 +170,7 @@ ARGS:
165 let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?; 170 let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?;
166 let with_deps: bool = matches.contains("--with-deps"); 171 let with_deps: bool = matches.contains("--with-deps");
167 let load_output_dirs = matches.contains("--load-output-dirs"); 172 let load_output_dirs = matches.contains("--load-output-dirs");
173 let with_proc_macro = matches.contains("--with-proc-macro");
168 let path = { 174 let path = {
169 let mut trailing = matches.free()?; 175 let mut trailing = matches.free()?;
170 if trailing.len() != 1 { 176 if trailing.len() != 1 {
@@ -173,7 +179,15 @@ ARGS:
173 trailing.pop().unwrap().into() 179 trailing.pop().unwrap().into()
174 }; 180 };
175 181
176 Command::Stats { randomize, memory_usage, only, with_deps, path, load_output_dirs } 182 Command::Stats {
183 randomize,
184 memory_usage,
185 only,
186 with_deps,
187 path,
188 load_output_dirs,
189 with_proc_macro,
190 }
177 } 191 }
178 "analysis-bench" => { 192 "analysis-bench" => {
179 if matches.contains(["-h", "--help"]) { 193 if matches.contains(["-h", "--help"]) {
@@ -187,6 +201,7 @@ USAGE:
187FLAGS: 201FLAGS:
188 -h, --help Prints help information 202 -h, --help Prints help information
189 --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis 203 --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis
204 --with-proc-macro Use ra-proc-macro-srv for proc-macro expanding
190 -v, --verbose 205 -v, --verbose
191 206
192OPTIONS: 207OPTIONS:
@@ -214,7 +229,8 @@ ARGS:
214 ), 229 ),
215 }; 230 };
216 let load_output_dirs = matches.contains("--load-output-dirs"); 231 let load_output_dirs = matches.contains("--load-output-dirs");
217 Command::Bench { path, what, load_output_dirs } 232 let with_proc_macro = matches.contains("--with-proc-macro");
233 Command::Bench { path, what, load_output_dirs, with_proc_macro }
218 } 234 }
219 "diagnostics" => { 235 "diagnostics" => {
220 if matches.contains(["-h", "--help"]) { 236 if matches.contains(["-h", "--help"]) {
@@ -237,6 +253,7 @@ ARGS:
237 } 253 }
238 254
239 let load_output_dirs = matches.contains("--load-output-dirs"); 255 let load_output_dirs = matches.contains("--load-output-dirs");
256 let with_proc_macro = matches.contains("--with-proc-macro");
240 let all = matches.contains("--all"); 257 let all = matches.contains("--all");
241 let path = { 258 let path = {
242 let mut trailing = matches.free()?; 259 let mut trailing = matches.free()?;
@@ -246,8 +263,9 @@ ARGS:
246 trailing.pop().unwrap().into() 263 trailing.pop().unwrap().into()
247 }; 264 };
248 265
249 Command::Diagnostics { path, load_output_dirs, all } 266 Command::Diagnostics { path, load_output_dirs, with_proc_macro, all }
250 } 267 }
268 "proc-macro" => Command::ProcMacro,
251 _ => { 269 _ => {
252 eprintln!( 270 eprintln!(
253 "\ 271 "\
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 7cfc44f01..28b67cfe2 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -25,6 +25,7 @@ fn main() -> Result<()> {
25 with_deps, 25 with_deps,
26 path, 26 path,
27 load_output_dirs, 27 load_output_dirs,
28 with_proc_macro,
28 } => cli::analysis_stats( 29 } => cli::analysis_stats(
29 args.verbosity, 30 args.verbosity,
30 memory_usage, 31 memory_usage,
@@ -33,16 +34,24 @@ fn main() -> Result<()> {
33 with_deps, 34 with_deps,
34 randomize, 35 randomize,
35 load_output_dirs, 36 load_output_dirs,
37 with_proc_macro,
36 )?, 38 )?,
37 39
38 args::Command::Bench { path, what, load_output_dirs } => { 40 args::Command::Bench { path, what, load_output_dirs, with_proc_macro } => {
39 cli::analysis_bench(args.verbosity, path.as_ref(), what, load_output_dirs)? 41 cli::analysis_bench(
42 args.verbosity,
43 path.as_ref(),
44 what,
45 load_output_dirs,
46 with_proc_macro,
47 )?
40 } 48 }
41 49
42 args::Command::Diagnostics { path, load_output_dirs, all } => { 50 args::Command::Diagnostics { path, load_output_dirs, with_proc_macro, all } => {
43 cli::diagnostics(path.as_ref(), load_output_dirs, all)? 51 cli::diagnostics(path.as_ref(), load_output_dirs, with_proc_macro, all)?
44 } 52 }
45 53
54 args::Command::ProcMacro => run_proc_macro_sv()?,
46 args::Command::RunServer => run_server()?, 55 args::Command::RunServer => run_server()?,
47 args::Command::Version => println!("rust-analyzer {}", env!("REV")), 56 args::Command::Version => println!("rust-analyzer {}", env!("REV")),
48 } 57 }
@@ -56,6 +65,11 @@ fn setup_logging() -> Result<()> {
56 Ok(()) 65 Ok(())
57} 66}
58 67
68fn run_proc_macro_sv() -> Result<()> {
69 ra_proc_macro_srv::cli::run();
70 Ok(())
71}
72
59fn run_server() -> Result<()> { 73fn run_server() -> Result<()> {
60 log::info!("lifecycle: server started"); 74 log::info!("lifecycle: server started");
61 75
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs
index 7667873d5..6147ae207 100644
--- a/crates/rust-analyzer/src/cli/analysis_bench.rs
+++ b/crates/rust-analyzer/src/cli/analysis_bench.rs
@@ -47,12 +47,13 @@ pub fn analysis_bench(
47 path: &Path, 47 path: &Path,
48 what: BenchWhat, 48 what: BenchWhat,
49 load_output_dirs: bool, 49 load_output_dirs: bool,
50 with_proc_macro: bool,
50) -> Result<()> { 51) -> Result<()> {
51 ra_prof::init(); 52 ra_prof::init();
52 53
53 let start = Instant::now(); 54 let start = Instant::now();
54 eprint!("loading: "); 55 eprint!("loading: ");
55 let (mut host, roots) = load_cargo(path, load_output_dirs)?; 56 let (mut host, roots) = load_cargo(path, load_output_dirs, with_proc_macro)?;
56 let db = host.raw_database(); 57 let db = host.raw_database();
57 eprintln!("{:?}\n", start.elapsed()); 58 eprintln!("{:?}\n", start.elapsed());
58 59
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index e9ee0b888..d442cbd63 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -25,9 +25,10 @@ pub fn analysis_stats(
25 with_deps: bool, 25 with_deps: bool,
26 randomize: bool, 26 randomize: bool,
27 load_output_dirs: bool, 27 load_output_dirs: bool,
28 with_proc_macro: bool,
28) -> Result<()> { 29) -> Result<()> {
29 let db_load_time = Instant::now(); 30 let db_load_time = Instant::now();
30 let (mut host, roots) = load_cargo(path, load_output_dirs)?; 31 let (mut host, roots) = load_cargo(path, load_output_dirs, with_proc_macro)?;
31 let db = host.raw_database(); 32 let db = host.raw_database();
32 println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed()); 33 println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed());
33 let analysis_time = Instant::now(); 34 let analysis_time = Instant::now();
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index 92664b415..60daefa3e 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -9,8 +9,13 @@ use std::{collections::HashSet, path::Path};
9use crate::cli::{load_cargo::load_cargo, Result}; 9use crate::cli::{load_cargo::load_cargo, Result};
10use hir::Semantics; 10use hir::Semantics;
11 11
12pub fn diagnostics(path: &Path, load_output_dirs: bool, all: bool) -> Result<()> { 12pub fn diagnostics(
13 let (host, roots) = load_cargo(path, load_output_dirs)?; 13 path: &Path,
14 load_output_dirs: bool,
15 with_proc_macro: bool,
16 all: bool,
17) -> Result<()> {
18 let (host, roots) = load_cargo(path, load_output_dirs, with_proc_macro)?;
14 let db = host.raw_database(); 19 let db = host.raw_database();
15 let analysis = host.analysis(); 20 let analysis = host.analysis();
16 let semantics = Semantics::new(db); 21 let semantics = Semantics::new(db);
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 43062ea10..32a9ee339 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -25,6 +25,7 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
25pub(crate) fn load_cargo( 25pub(crate) fn load_cargo(
26 root: &Path, 26 root: &Path,
27 load_out_dirs_from_check: bool, 27 load_out_dirs_from_check: bool,
28 with_proc_macro: bool,
28) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> { 29) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> {
29 let root = std::env::current_dir()?.join(root); 30 let root = std::env::current_dir()?.join(root);
30 let ws = ProjectWorkspace::discover( 31 let ws = ProjectWorkspace::discover(
@@ -69,7 +70,14 @@ pub(crate) fn load_cargo(
69 }) 70 })
70 .collect::<FxHashMap<_, _>>(); 71 .collect::<FxHashMap<_, _>>();
71 72
72 let proc_macro_client = ProcMacroClient::dummy(); 73 let proc_macro_client = if !with_proc_macro {
74 ProcMacroClient::dummy()
75 } else {
76 let mut path = std::env::current_exe()?;
77 path.pop();
78 path.push("rust-analyzer");
79 ProcMacroClient::extern_process(&path, &["proc-macro"]).unwrap()
80 };
73 let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs, &proc_macro_client); 81 let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs, &proc_macro_client);
74 Ok((host, source_roots)) 82 Ok((host, source_roots))
75} 83}
@@ -175,7 +183,7 @@ mod tests {
175 #[test] 183 #[test]
176 fn test_loading_rust_analyzer() { 184 fn test_loading_rust_analyzer() {
177 let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); 185 let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
178 let (host, _roots) = load_cargo(path, false).unwrap(); 186 let (host, _roots) = load_cargo(path, false, false).unwrap();
179 let n_crates = Crate::all(host.raw_database()).len(); 187 let n_crates = Crate::all(host.raw_database()).len();
180 // RA has quite a few crates, but the exact count doesn't matter 188 // RA has quite a few crates, but the exact count doesn't matter
181 assert!(n_crates > 20); 189 assert!(n_crates > 20);
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 4734df16a..2b45f1310 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -20,7 +20,7 @@ pub struct Config {
20 pub with_sysroot: bool, 20 pub with_sysroot: bool,
21 pub publish_diagnostics: bool, 21 pub publish_diagnostics: bool,
22 pub lru_capacity: Option<usize>, 22 pub lru_capacity: Option<usize>,
23 pub proc_macro_srv: Option<String>, 23 pub proc_macro_srv: Option<(String, Vec<String>)>,
24 pub files: FilesConfig, 24 pub files: FilesConfig,
25 pub notifications: NotificationsConfig, 25 pub notifications: NotificationsConfig,
26 26
@@ -131,6 +131,18 @@ impl Config {
131 set(value, "/cargo/allFeatures", &mut self.cargo.all_features); 131 set(value, "/cargo/allFeatures", &mut self.cargo.all_features);
132 set(value, "/cargo/features", &mut self.cargo.features); 132 set(value, "/cargo/features", &mut self.cargo.features);
133 set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); 133 set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check);
134
135 match get::<bool>(value, "/procMacro/enabled") {
136 Some(true) => {
137 if let Ok(mut path) = std::env::current_exe() {
138 path.pop();
139 path.push("rust-analyzer");
140 self.proc_macro_srv = Some((path.to_string_lossy().to_string(), vec!["proc-macro".to_string()]));
141 }
142 }
143 _ => self.proc_macro_srv = None,
144 }
145
134 match get::<Vec<String>>(value, "/rustfmt/overrideCommand") { 146 match get::<Vec<String>>(value, "/rustfmt/overrideCommand") {
135 Some(mut args) if !args.is_empty() => { 147 Some(mut args) if !args.is_empty() => {
136 let command = args.remove(0); 148 let command = args.remove(0);
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs
index 6c42e1d76..f2ad453fa 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/world.rs
@@ -64,6 +64,7 @@ pub struct WorldState {
64 pub latest_requests: Arc<RwLock<LatestRequests>>, 64 pub latest_requests: Arc<RwLock<LatestRequests>>,
65 pub flycheck: Option<Flycheck>, 65 pub flycheck: Option<Flycheck>,
66 pub diagnostics: DiagnosticCollection, 66 pub diagnostics: DiagnosticCollection,
67 pub proc_macro_client: ProcMacroClient,
67} 68}
68 69
69/// An immutable snapshot of the world's state at a point in time. 70/// An immutable snapshot of the world's state at a point in time.
@@ -147,9 +148,9 @@ impl WorldState {
147 148
148 let proc_macro_client = match &config.proc_macro_srv { 149 let proc_macro_client = match &config.proc_macro_srv {
149 None => ProcMacroClient::dummy(), 150 None => ProcMacroClient::dummy(),
150 Some(srv) => { 151 Some((path, args)) => {
151 let path = Path::new(&srv); 152 let path = std::path::Path::new(path);
152 match ProcMacroClient::extern_process(path) { 153 match ProcMacroClient::extern_process(path, args) {
153 Ok(it) => it, 154 Ok(it) => it,
154 Err(err) => { 155 Err(err) => {
155 log::error!( 156 log::error!(
@@ -192,6 +193,7 @@ impl WorldState {
192 latest_requests: Default::default(), 193 latest_requests: Default::default(),
193 flycheck, 194 flycheck,
194 diagnostics: Default::default(), 195 diagnostics: Default::default(),
196 proc_macro_client,
195 } 197 }
196 } 198 }
197 199
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs
index 638813311..1dd2676b6 100644
--- a/crates/rust-analyzer/tests/heavy_tests/main.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/main.rs
@@ -9,7 +9,7 @@ use lsp_types::{
9}; 9};
10use rust_analyzer::req::{ 10use rust_analyzer::req::{
11 CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, 11 CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument,
12 Formatting, GotoDefinition, OnEnter, Runnables, RunnablesParams, 12 Formatting, GotoDefinition, HoverRequest, OnEnter, Runnables, RunnablesParams,
13}; 13};
14use serde_json::json; 14use serde_json::json;
15use tempfile::TempDir; 15use tempfile::TempDir;
@@ -625,3 +625,92 @@ fn main() { message(); }
625 )); 625 ));
626 assert!(format!("{}", res).contains("hello.rs")); 626 assert!(format!("{}", res).contains("hello.rs"));
627} 627}
628
629#[test]
630fn resolve_proc_macro() {
631 if skip_slow_tests() {
632 return;
633 }
634 let server = Project::with_fixture(
635 r###"
636//- foo/Cargo.toml
637[package]
638name = "foo"
639version = "0.0.0"
640edition = "2018"
641[dependencies]
642bar = {path = "../bar"}
643
644//- foo/src/main.rs
645use bar::Bar;
646trait Bar {
647 fn bar();
648}
649#[derive(Bar)]
650struct Foo {}
651fn main() {
652 Foo::bar();
653}
654
655//- bar/Cargo.toml
656[package]
657name = "bar"
658version = "0.0.0"
659edition = "2018"
660
661[lib]
662proc-macro = true
663
664//- bar/src/lib.rs
665extern crate proc_macro;
666use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
667macro_rules! t {
668 ($n:literal) => {
669 TokenTree::from(Ident::new($n, Span::call_site()))
670 };
671 ({}) => {
672 TokenTree::from(Group::new(Delimiter::Brace, TokenStream::new()))
673 };
674 (()) => {
675 TokenTree::from(Group::new(Delimiter::Parenthesis, TokenStream::new()))
676 };
677}
678#[proc_macro_derive(Bar)]
679pub fn foo(_input: TokenStream) -> TokenStream {
680 // We hard code the output here for preventing to use any deps
681 let mut res = TokenStream::new();
682
683 // impl Bar for Foo { fn bar() {} }
684 let mut tokens = vec![t!("impl"), t!("Bar"), t!("for"), t!("Foo")];
685 let mut fn_stream = TokenStream::new();
686 fn_stream.extend(vec![t!("fn"), t!("bar"), t!(()), t!({})]);
687 tokens.push(Group::new(Delimiter::Brace, fn_stream).into());
688 res.extend(tokens);
689 res
690}
691
692"###,
693 )
694 .with_config(|config| {
695 // FIXME: Use env!("CARGO_BIN_EXE_ra-analyzer") instead after
696 // https://github.com/rust-lang/cargo/pull/7697 landed
697 let macro_srv_path = std::path::Path::new(std::env!("CARGO_MANIFEST_DIR"))
698 .join("../../target/debug/rust-analyzer")
699 .to_string_lossy()
700 .to_string();
701
702 config.cargo.load_out_dirs_from_check = true;
703 config.proc_macro_srv = Some((macro_srv_path, vec!["proc-macro".to_string()]));
704 })
705 .root("foo")
706 .root("bar")
707 .server();
708 server.wait_until_workspace_is_loaded();
709 let res = server.send_request::<HoverRequest>(TextDocumentPositionParams::new(
710 server.doc_id("foo/src/main.rs"),
711 Position::new(7, 9),
712 ));
713
714 let value = res.get("contents").unwrap().get("value").unwrap().to_string();
715 assert_eq!(value, r#""```rust\nfoo::Bar\nfn bar()\n```""#)
716}
diff --git a/editors/code/package.json b/editors/code/package.json
index 5f73c8d83..5ce59e54a 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -388,6 +388,11 @@
388 "description": "Enable logging of VS Code extensions itself", 388 "description": "Enable logging of VS Code extensions itself",
389 "type": "boolean", 389 "type": "boolean",
390 "default": false 390 "default": false
391 },
392 "rust-analyzer.procMacro.enabled": {
393 "description": "Enable Proc macro support, cargo.loadOutDirsFromCheck must be enabled.",
394 "type": "boolean",
395 "default": false
391 } 396 }
392 } 397 }
393 }, 398 },
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index 35a05131c..3b2eec8ba 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -12,6 +12,7 @@ export class Config {
12 private readonly requiresReloadOpts = [ 12 private readonly requiresReloadOpts = [
13 "serverPath", 13 "serverPath",
14 "cargo", 14 "cargo",
15 "procMacro",
15 "files", 16 "files",
16 "highlighting", 17 "highlighting",
17 "updates.channel", 18 "updates.channel",