diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-04-16 21:21:59 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-04-16 21:21:59 +0100 |
commit | 10d8cb913cb8247ae64b954cf07460f1b6d96ef7 (patch) | |
tree | 976786b86c189d8c03a15378fd62526cbe8eaab7 | |
parent | a4cda3efbbabe4c6129de4dc095953fe858d7d3f (diff) | |
parent | 16a74cfd234e94d383b0ef067fb6a3c651ed9624 (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.lock | 1 | ||||
-rw-r--r-- | crates/ra_proc_macro/src/lib.rs | 12 | ||||
-rw-r--r-- | crates/ra_proc_macro/src/process.rs | 19 | ||||
-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.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/args.rs | 24 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/main.rs | 22 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/analysis_bench.rs | 3 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/analysis_stats.rs | 3 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/diagnostics.rs | 9 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 12 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 14 | ||||
-rw-r--r-- | crates/rust-analyzer/src/world.rs | 8 | ||||
-rw-r--r-- | crates/rust-analyzer/tests/heavy_tests/main.rs | 91 | ||||
-rw-r--r-- | editors/code/package.json | 5 | ||||
-rw-r--r-- | editors/code/src/config.ts | 1 |
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; | |||
12 | use process::{ProcMacroProcessSrv, ProcMacroProcessThread}; | 12 | use process::{ProcMacroProcessSrv, ProcMacroProcessThread}; |
13 | use ra_tt::{SmolStr, Subtree}; | 13 | use ra_tt::{SmolStr, Subtree}; |
14 | use std::{ | 14 | use 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 | ||
58 | impl ProcMacroClient { | 59 | impl 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 | |||
9 | use io::{BufRead, BufReader}; | 9 | use io::{BufRead, BufReader}; |
10 | use std::{ | 10 | use 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 | ||
46 | impl Process { | 47 | impl 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 | ||
76 | impl ProcMacroProcessSrv { | 82 | impl 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 | ||
3 | use crate::{expand_task, list_macros}; | ||
3 | use ra_proc_macro::msg::{self, Message}; | 4 | use ra_proc_macro::msg::{self, Message}; |
4 | use ra_proc_macro_srv::{expand_task, list_macros}; | ||
5 | 5 | ||
6 | use std::io; | 6 | use 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 | } |
27 | fn main() { | 27 | |
28 | pub 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; | |||
22 | use proc_macro::bridge::client::TokenStream; | 22 | use proc_macro::bridge::client::TokenStream; |
23 | use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask}; | 23 | use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask}; |
24 | 24 | ||
25 | pub fn expand_task(task: &ExpansionTask) -> Result<ExpansionResult, String> { | 25 | pub(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 | ||
42 | pub fn list_macros(task: &ListMacrosTask) -> Result<ListMacrosResult, String> { | 42 | pub(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 | ||
56 | pub mod cli; | ||
57 | |||
56 | #[cfg(test)] | 58 | #[cfg(test)] |
57 | mod tests; | 59 | mod 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" } | |||
46 | hir = { path = "../ra_hir", package = "ra_hir" } | 46 | hir = { path = "../ra_hir", package = "ra_hir" } |
47 | hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } | 47 | hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } |
48 | hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" } | 48 | hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" } |
49 | 49 | ra_proc_macro_srv = { path = "../ra_proc_macro_srv" } | |
50 | 50 | ||
51 | [target.'cfg(windows)'.dependencies] | 51 | [target.'cfg(windows)'.dependencies] |
52 | winapi = "0.3.8" | 52 | winapi = "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: | |||
187 | FLAGS: | 201 | FLAGS: |
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 | ||
192 | OPTIONS: | 207 | OPTIONS: |
@@ -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 | ||
68 | fn run_proc_macro_sv() -> Result<()> { | ||
69 | ra_proc_macro_srv::cli::run(); | ||
70 | Ok(()) | ||
71 | } | ||
72 | |||
59 | fn run_server() -> Result<()> { | 73 | fn 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}; | |||
9 | use crate::cli::{load_cargo::load_cargo, Result}; | 9 | use crate::cli::{load_cargo::load_cargo, Result}; |
10 | use hir::Semantics; | 10 | use hir::Semantics; |
11 | 11 | ||
12 | pub fn diagnostics(path: &Path, load_output_dirs: bool, all: bool) -> Result<()> { | 12 | pub 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 { | |||
25 | pub(crate) fn load_cargo( | 25 | pub(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 | }; |
10 | use rust_analyzer::req::{ | 10 | use 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 | }; |
14 | use serde_json::json; | 14 | use serde_json::json; |
15 | use tempfile::TempDir; | 15 | use 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] | ||
630 | fn 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] | ||
638 | name = "foo" | ||
639 | version = "0.0.0" | ||
640 | edition = "2018" | ||
641 | [dependencies] | ||
642 | bar = {path = "../bar"} | ||
643 | |||
644 | //- foo/src/main.rs | ||
645 | use bar::Bar; | ||
646 | trait Bar { | ||
647 | fn bar(); | ||
648 | } | ||
649 | #[derive(Bar)] | ||
650 | struct Foo {} | ||
651 | fn main() { | ||
652 | Foo::bar(); | ||
653 | } | ||
654 | |||
655 | //- bar/Cargo.toml | ||
656 | [package] | ||
657 | name = "bar" | ||
658 | version = "0.0.0" | ||
659 | edition = "2018" | ||
660 | |||
661 | [lib] | ||
662 | proc-macro = true | ||
663 | |||
664 | //- bar/src/lib.rs | ||
665 | extern crate proc_macro; | ||
666 | use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; | ||
667 | macro_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)] | ||
679 | pub 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", |