diff options
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 4 | ||||
-rw-r--r-- | crates/hir_expand/src/quote.rs | 4 | ||||
-rw-r--r-- | crates/ide/src/join_lines.rs | 41 | ||||
-rw-r--r-- | crates/project_model/src/cargo_workspace.rs | 67 | ||||
-rw-r--r-- | crates/project_model/src/rustc_cfg.rs | 45 | ||||
-rw-r--r-- | crates/project_model/src/workspace.rs | 7 |
6 files changed, 118 insertions, 50 deletions
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 0dd725ec3..af9802144 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -789,9 +789,9 @@ mod tests { | |||
789 | r##" | 789 | r##" |
790 | #[rustc_builtin_macro] | 790 | #[rustc_builtin_macro] |
791 | macro_rules! concat {} | 791 | macro_rules! concat {} |
792 | concat!("foo", "r", 0, r#"bar"#, false); | 792 | concat!("foo", "r", 0, r#"bar"#, "\n", false); |
793 | "##, | 793 | "##, |
794 | expect![[r#""foor0barfalse""#]], | 794 | expect![[r#""foor0bar\nfalse""#]], |
795 | ); | 795 | ); |
796 | } | 796 | } |
797 | } | 797 | } |
diff --git a/crates/hir_expand/src/quote.rs b/crates/hir_expand/src/quote.rs index c82487ef0..230a59964 100644 --- a/crates/hir_expand/src/quote.rs +++ b/crates/hir_expand/src/quote.rs | |||
@@ -196,8 +196,8 @@ impl_to_to_tokentrees! { | |||
196 | tt::Literal => self { self }; | 196 | tt::Literal => self { self }; |
197 | tt::Ident => self { self }; | 197 | tt::Ident => self { self }; |
198 | tt::Punct => self { self }; | 198 | tt::Punct => self { self }; |
199 | &str => self { tt::Literal{text: format!("{:?}", self.escape_default().to_string()).into(), id: tt::TokenId::unspecified()}}; | 199 | &str => self { tt::Literal{text: format!("\"{}\"", self.escape_debug()).into(), id: tt::TokenId::unspecified()}}; |
200 | String => self { tt::Literal{text: format!("{:?}", self.escape_default().to_string()).into(), id: tt::TokenId::unspecified()}} | 200 | String => self { tt::Literal{text: format!("\"{}\"", self.escape_debug()).into(), id: tt::TokenId::unspecified()}} |
201 | } | 201 | } |
202 | 202 | ||
203 | #[cfg(test)] | 203 | #[cfg(test)] |
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs index fe2a349e6..482b23cf5 100644 --- a/crates/ide/src/join_lines.rs +++ b/crates/ide/src/join_lines.rs | |||
@@ -65,11 +65,15 @@ fn remove_newlines(edit: &mut TextEditBuilder, token: &SyntaxToken, range: TextR | |||
65 | 65 | ||
66 | fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextSize) { | 66 | fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextSize) { |
67 | if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 { | 67 | if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 { |
68 | let mut string_open_quote = false; | 68 | let mut no_space = false; |
69 | if let Some(string) = ast::String::cast(token.clone()) { | 69 | if let Some(string) = ast::String::cast(token.clone()) { |
70 | if let Some(range) = string.open_quote_text_range() { | 70 | if let Some(range) = string.open_quote_text_range() { |
71 | cov_mark::hit!(join_string_literal); | 71 | cov_mark::hit!(join_string_literal_open_quote); |
72 | string_open_quote = range.end() == offset; | 72 | no_space |= range.end() == offset; |
73 | } | ||
74 | if let Some(range) = string.close_quote_text_range() { | ||
75 | cov_mark::hit!(join_string_literal_close_quote); | ||
76 | no_space |= range.start() == offset + TextSize::of('\n'); | ||
73 | } | 77 | } |
74 | } | 78 | } |
75 | 79 | ||
@@ -82,7 +86,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextS | |||
82 | }; | 86 | }; |
83 | 87 | ||
84 | let range = TextRange::at(offset, ((n_spaces_after_line_break + 1) as u32).into()); | 88 | let range = TextRange::at(offset, ((n_spaces_after_line_break + 1) as u32).into()); |
85 | let replace_with = if string_open_quote { "" } else { " " }; | 89 | let replace_with = if no_space { "" } else { " " }; |
86 | edit.replace(range, replace_with.to_string()); | 90 | edit.replace(range, replace_with.to_string()); |
87 | return; | 91 | return; |
88 | } | 92 | } |
@@ -797,22 +801,41 @@ fn foo() { | |||
797 | 801 | ||
798 | #[test] | 802 | #[test] |
799 | fn join_string_literal() { | 803 | fn join_string_literal() { |
800 | cov_mark::check!(join_string_literal); | 804 | { |
801 | check_join_lines( | 805 | cov_mark::check!(join_string_literal_open_quote); |
802 | r#" | 806 | check_join_lines( |
807 | r#" | ||
803 | fn main() { | 808 | fn main() { |
804 | $0" | 809 | $0" |
805 | hello | 810 | hello |
806 | "; | 811 | "; |
807 | } | 812 | } |
808 | "#, | 813 | "#, |
809 | r#" | 814 | r#" |
810 | fn main() { | 815 | fn main() { |
811 | $0"hello | 816 | $0"hello |
812 | "; | 817 | "; |
813 | } | 818 | } |
814 | "#, | 819 | "#, |
815 | ); | 820 | ); |
821 | } | ||
822 | |||
823 | { | ||
824 | cov_mark::check!(join_string_literal_close_quote); | ||
825 | check_join_lines( | ||
826 | r#" | ||
827 | fn main() { | ||
828 | $0"hello | ||
829 | "; | ||
830 | } | ||
831 | "#, | ||
832 | r#" | ||
833 | fn main() { | ||
834 | $0"hello"; | ||
835 | } | ||
836 | "#, | ||
837 | ); | ||
838 | } | ||
816 | 839 | ||
817 | check_join_lines( | 840 | check_join_lines( |
818 | r#" | 841 | r#" |
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index bc6e20341..b18699b77 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs | |||
@@ -201,31 +201,12 @@ impl CargoWorkspace { | |||
201 | if let Some(parent) = cargo_toml.parent() { | 201 | if let Some(parent) = cargo_toml.parent() { |
202 | meta.current_dir(parent.to_path_buf()); | 202 | meta.current_dir(parent.to_path_buf()); |
203 | } | 203 | } |
204 | let target = if let Some(target) = config.target.as_ref() { | 204 | let target = if let Some(target) = &config.target { |
205 | Some(target.clone()) | 205 | Some(target.clone()) |
206 | } else if let stdout @ Some(_) = cargo_config_build_target(cargo_toml) { | ||
207 | stdout | ||
206 | } else { | 208 | } else { |
207 | // cargo metadata defaults to giving information for _all_ targets. | 209 | rustc_discover_host_triple(cargo_toml) |
208 | // In the absence of a preference from the user, we use the host platform. | ||
209 | let mut rustc = Command::new(toolchain::rustc()); | ||
210 | rustc.current_dir(cargo_toml.parent().unwrap()).arg("-vV"); | ||
211 | log::debug!("Discovering host platform by {:?}", rustc); | ||
212 | match utf8_stdout(rustc) { | ||
213 | Ok(stdout) => { | ||
214 | let field = "host: "; | ||
215 | let target = stdout.lines().find_map(|l| l.strip_prefix(field)); | ||
216 | if let Some(target) = target { | ||
217 | Some(target.to_string()) | ||
218 | } else { | ||
219 | // If we fail to resolve the host platform, it's not the end of the world. | ||
220 | log::info!("rustc -vV did not report host platform, got:\n{}", stdout); | ||
221 | None | ||
222 | } | ||
223 | } | ||
224 | Err(e) => { | ||
225 | log::warn!("Failed to discover host platform: {}", e); | ||
226 | None | ||
227 | } | ||
228 | } | ||
229 | }; | 210 | }; |
230 | if let Some(target) = target { | 211 | if let Some(target) = target { |
231 | meta.other_options(vec![String::from("--filter-platform"), target]); | 212 | meta.other_options(vec![String::from("--filter-platform"), target]); |
@@ -368,3 +349,43 @@ impl CargoWorkspace { | |||
368 | self.packages.iter().filter(|(_, v)| v.name == name).count() == 1 | 349 | self.packages.iter().filter(|(_, v)| v.name == name).count() == 1 |
369 | } | 350 | } |
370 | } | 351 | } |
352 | |||
353 | fn rustc_discover_host_triple(cargo_toml: &AbsPath) -> Option<String> { | ||
354 | let mut rustc = Command::new(toolchain::rustc()); | ||
355 | rustc.current_dir(cargo_toml.parent().unwrap()).arg("-vV"); | ||
356 | log::debug!("Discovering host platform by {:?}", rustc); | ||
357 | match utf8_stdout(rustc) { | ||
358 | Ok(stdout) => { | ||
359 | let field = "host: "; | ||
360 | let target = stdout.lines().find_map(|l| l.strip_prefix(field)); | ||
361 | if let Some(target) = target { | ||
362 | Some(target.to_string()) | ||
363 | } else { | ||
364 | // If we fail to resolve the host platform, it's not the end of the world. | ||
365 | log::info!("rustc -vV did not report host platform, got:\n{}", stdout); | ||
366 | None | ||
367 | } | ||
368 | } | ||
369 | Err(e) => { | ||
370 | log::warn!("Failed to discover host platform: {}", e); | ||
371 | None | ||
372 | } | ||
373 | } | ||
374 | } | ||
375 | |||
376 | fn cargo_config_build_target(cargo_toml: &AbsPath) -> Option<String> { | ||
377 | let mut cargo_config = Command::new(toolchain::cargo()); | ||
378 | cargo_config | ||
379 | .current_dir(cargo_toml.parent().unwrap()) | ||
380 | .args(&["-Z", "unstable-options", "config", "get", "build.target"]) | ||
381 | .env("RUSTC_BOOTSTRAP", "1"); | ||
382 | // if successful we receive `build.target = "target-triple"` | ||
383 | log::debug!("Discovering cargo config target by {:?}", cargo_config); | ||
384 | match utf8_stdout(cargo_config) { | ||
385 | Ok(stdout) => stdout | ||
386 | .strip_prefix("build.target = \"") | ||
387 | .and_then(|stdout| stdout.strip_suffix('"')) | ||
388 | .map(ToOwned::to_owned), | ||
389 | Err(_) => None, | ||
390 | } | ||
391 | } | ||
diff --git a/crates/project_model/src/rustc_cfg.rs b/crates/project_model/src/rustc_cfg.rs index 312708575..012eab256 100644 --- a/crates/project_model/src/rustc_cfg.rs +++ b/crates/project_model/src/rustc_cfg.rs | |||
@@ -2,9 +2,12 @@ | |||
2 | 2 | ||
3 | use std::process::Command; | 3 | use std::process::Command; |
4 | 4 | ||
5 | use anyhow::Result; | ||
6 | use paths::AbsPath; | ||
7 | |||
5 | use crate::{cfg_flag::CfgFlag, utf8_stdout}; | 8 | use crate::{cfg_flag::CfgFlag, utf8_stdout}; |
6 | 9 | ||
7 | pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> { | 10 | pub(crate) fn get(cargo_toml: Option<&AbsPath>, target: Option<&str>) -> Vec<CfgFlag> { |
8 | let _p = profile::span("rustc_cfg::get"); | 11 | let _p = profile::span("rustc_cfg::get"); |
9 | let mut res = Vec::with_capacity(6 * 2 + 1); | 12 | let mut res = Vec::with_capacity(6 * 2 + 1); |
10 | 13 | ||
@@ -16,19 +19,39 @@ pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> { | |||
16 | } | 19 | } |
17 | } | 20 | } |
18 | 21 | ||
19 | let rustc_cfgs = { | 22 | match get_rust_cfgs(cargo_toml, target) { |
20 | let mut cmd = Command::new(toolchain::rustc()); | ||
21 | cmd.args(&["--print", "cfg", "-O"]); | ||
22 | if let Some(target) = target { | ||
23 | cmd.args(&["--target", target]); | ||
24 | } | ||
25 | utf8_stdout(cmd) | ||
26 | }; | ||
27 | |||
28 | match rustc_cfgs { | ||
29 | Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())), | 23 | Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())), |
30 | Err(e) => log::error!("failed to get rustc cfgs: {:#}", e), | 24 | Err(e) => log::error!("failed to get rustc cfgs: {:#}", e), |
31 | } | 25 | } |
32 | 26 | ||
33 | res | 27 | res |
34 | } | 28 | } |
29 | |||
30 | fn get_rust_cfgs(cargo_toml: Option<&AbsPath>, target: Option<&str>) -> Result<String> { | ||
31 | let cargo_rust_cfgs = match cargo_toml { | ||
32 | Some(cargo_toml) => { | ||
33 | let mut cargo_config = Command::new(toolchain::cargo()); | ||
34 | cargo_config | ||
35 | .current_dir(cargo_toml.parent().unwrap()) | ||
36 | .args(&["-Z", "unstable-options", "rustc", "--print", "cfg"]) | ||
37 | .env("RUSTC_BOOTSTRAP", "1"); | ||
38 | if let Some(target) = target { | ||
39 | cargo_config.args(&["--target", target]); | ||
40 | } | ||
41 | utf8_stdout(cargo_config).ok() | ||
42 | } | ||
43 | None => None, | ||
44 | }; | ||
45 | match cargo_rust_cfgs { | ||
46 | Some(stdout) => Ok(stdout), | ||
47 | None => { | ||
48 | // using unstable cargo features failed, fall back to using plain rustc | ||
49 | let mut cmd = Command::new(toolchain::rustc()); | ||
50 | cmd.args(&["--print", "cfg", "-O"]); | ||
51 | if let Some(target) = target { | ||
52 | cmd.args(&["--target", target]); | ||
53 | } | ||
54 | utf8_stdout(cmd) | ||
55 | } | ||
56 | } | ||
57 | } | ||
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 2fcd0f8fa..84c702fdf 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -143,7 +143,8 @@ impl ProjectWorkspace { | |||
143 | } else { | 143 | } else { |
144 | None | 144 | None |
145 | }; | 145 | }; |
146 | let rustc_cfg = rustc_cfg::get(config.target.as_deref()); | 146 | |
147 | let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref()); | ||
147 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } | 148 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } |
148 | } | 149 | } |
149 | }; | 150 | }; |
@@ -159,7 +160,7 @@ impl ProjectWorkspace { | |||
159 | Some(path) => Some(Sysroot::load(path)?), | 160 | Some(path) => Some(Sysroot::load(path)?), |
160 | None => None, | 161 | None => None, |
161 | }; | 162 | }; |
162 | let rustc_cfg = rustc_cfg::get(target); | 163 | let rustc_cfg = rustc_cfg::get(None, target); |
163 | Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }) | 164 | Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }) |
164 | } | 165 | } |
165 | 166 | ||
@@ -310,7 +311,7 @@ fn project_json_to_crate_graph( | |||
310 | 311 | ||
311 | let target_cfgs = match krate.target.as_deref() { | 312 | let target_cfgs = match krate.target.as_deref() { |
312 | Some(target) => { | 313 | Some(target) => { |
313 | cfg_cache.entry(target).or_insert_with(|| rustc_cfg::get(Some(target))) | 314 | cfg_cache.entry(target).or_insert_with(|| rustc_cfg::get(None, Some(target))) |
314 | } | 315 | } |
315 | None => &rustc_cfg, | 316 | None => &rustc_cfg, |
316 | }; | 317 | }; |