diff options
27 files changed, 229 insertions, 153 deletions
diff --git a/Cargo.lock b/Cargo.lock index 3bb1df05b..8d81c4839 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -354,12 +354,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
354 | checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" | 354 | checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" |
355 | 355 | ||
356 | [[package]] | 356 | [[package]] |
357 | name = "format-buf" | ||
358 | version = "1.0.0" | ||
359 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
360 | checksum = "f7aea5a5909a74969507051a3b17adc84737e31a5f910559892aedce026f4d53" | ||
361 | |||
362 | [[package]] | ||
363 | name = "fs_extra" | 357 | name = "fs_extra" |
364 | version = "1.1.0" | 358 | version = "1.1.0" |
365 | source = "registry+https://github.com/rust-lang/crates.io-index" | 359 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -574,12 +568,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
574 | checksum = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" | 568 | checksum = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" |
575 | 569 | ||
576 | [[package]] | 570 | [[package]] |
577 | name = "join_to_string" | ||
578 | version = "0.1.3" | ||
579 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
580 | checksum = "4dc7a5290e8c2606ce2be49f456d50f69173cb96d1541e4f66e34ac8b331a98f" | ||
581 | |||
582 | [[package]] | ||
583 | name = "kernel32-sys" | 571 | name = "kernel32-sys" |
584 | version = "0.2.2" | 572 | version = "0.2.2" |
585 | source = "registry+https://github.com/rust-lang/crates.io-index" | 573 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -885,9 +873,7 @@ name = "ra_assists" | |||
885 | version = "0.1.0" | 873 | version = "0.1.0" |
886 | dependencies = [ | 874 | dependencies = [ |
887 | "either", | 875 | "either", |
888 | "format-buf", | ||
889 | "itertools 0.9.0", | 876 | "itertools 0.9.0", |
890 | "join_to_string", | ||
891 | "ra_db", | 877 | "ra_db", |
892 | "ra_fmt", | 878 | "ra_fmt", |
893 | "ra_hir", | 879 | "ra_hir", |
@@ -896,6 +882,7 @@ dependencies = [ | |||
896 | "ra_syntax", | 882 | "ra_syntax", |
897 | "ra_text_edit", | 883 | "ra_text_edit", |
898 | "rustc-hash", | 884 | "rustc-hash", |
885 | "stdx", | ||
899 | "test_utils", | 886 | "test_utils", |
900 | ] | 887 | ] |
901 | 888 | ||
@@ -979,6 +966,7 @@ dependencies = [ | |||
979 | "ra_syntax", | 966 | "ra_syntax", |
980 | "ra_tt", | 967 | "ra_tt", |
981 | "rustc-hash", | 968 | "rustc-hash", |
969 | "stdx", | ||
982 | "test_utils", | 970 | "test_utils", |
983 | ] | 971 | ] |
984 | 972 | ||
@@ -1015,6 +1003,7 @@ dependencies = [ | |||
1015 | "ra_prof", | 1003 | "ra_prof", |
1016 | "ra_syntax", | 1004 | "ra_syntax", |
1017 | "rustc-hash", | 1005 | "rustc-hash", |
1006 | "stdx", | ||
1018 | "test_utils", | 1007 | "test_utils", |
1019 | ] | 1008 | ] |
1020 | 1009 | ||
@@ -1023,11 +1012,9 @@ name = "ra_ide" | |||
1023 | version = "0.1.0" | 1012 | version = "0.1.0" |
1024 | dependencies = [ | 1013 | dependencies = [ |
1025 | "either", | 1014 | "either", |
1026 | "format-buf", | ||
1027 | "indexmap", | 1015 | "indexmap", |
1028 | "insta", | 1016 | "insta", |
1029 | "itertools 0.9.0", | 1017 | "itertools 0.9.0", |
1030 | "join_to_string", | ||
1031 | "log", | 1018 | "log", |
1032 | "ra_assists", | 1019 | "ra_assists", |
1033 | "ra_cfg", | 1020 | "ra_cfg", |
@@ -1040,6 +1027,7 @@ dependencies = [ | |||
1040 | "ra_text_edit", | 1027 | "ra_text_edit", |
1041 | "rand", | 1028 | "rand", |
1042 | "rustc-hash", | 1029 | "rustc-hash", |
1030 | "stdx", | ||
1043 | "test_utils", | 1031 | "test_utils", |
1044 | ] | 1032 | ] |
1045 | 1033 | ||
@@ -1130,6 +1118,7 @@ dependencies = [ | |||
1130 | "rustc_lexer", | 1118 | "rustc_lexer", |
1131 | "serde", | 1119 | "serde", |
1132 | "smol_str", | 1120 | "smol_str", |
1121 | "stdx", | ||
1133 | "test_utils", | 1122 | "test_utils", |
1134 | "walkdir", | 1123 | "walkdir", |
1135 | ] | 1124 | ] |
@@ -1321,6 +1310,7 @@ dependencies = [ | |||
1321 | "rustc-hash", | 1310 | "rustc-hash", |
1322 | "serde", | 1311 | "serde", |
1323 | "serde_json", | 1312 | "serde_json", |
1313 | "stdx", | ||
1324 | "tempfile", | 1314 | "tempfile", |
1325 | "test_utils", | 1315 | "test_utils", |
1326 | "threadpool", | 1316 | "threadpool", |
@@ -1489,6 +1479,10 @@ dependencies = [ | |||
1489 | ] | 1479 | ] |
1490 | 1480 | ||
1491 | [[package]] | 1481 | [[package]] |
1482 | name = "stdx" | ||
1483 | version = "0.1.0" | ||
1484 | |||
1485 | [[package]] | ||
1492 | name = "superslice" | 1486 | name = "superslice" |
1493 | version = "1.0.0" | 1487 | version = "1.0.0" |
1494 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" |
diff --git a/crates/ra_assists/Cargo.toml b/crates/ra_assists/Cargo.toml index a87f4052a..3bcf58ba4 100644 --- a/crates/ra_assists/Cargo.toml +++ b/crates/ra_assists/Cargo.toml | |||
@@ -8,12 +8,12 @@ authors = ["rust-analyzer developers"] | |||
8 | doctest = false | 8 | doctest = false |
9 | 9 | ||
10 | [dependencies] | 10 | [dependencies] |
11 | format-buf = "1.0.0" | ||
12 | join_to_string = "0.1.3" | ||
13 | rustc-hash = "1.1.0" | 11 | rustc-hash = "1.1.0" |
14 | itertools = "0.9.0" | 12 | itertools = "0.9.0" |
15 | either = "1.5.3" | 13 | either = "1.5.3" |
16 | 14 | ||
15 | stdx = { path = "../stdx" } | ||
16 | |||
17 | ra_syntax = { path = "../ra_syntax" } | 17 | ra_syntax = { path = "../ra_syntax" } |
18 | ra_text_edit = { path = "../ra_text_edit" } | 18 | ra_text_edit = { path = "../ra_text_edit" } |
19 | ra_fmt = { path = "../ra_fmt" } | 19 | ra_fmt = { path = "../ra_fmt" } |
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs index dd2bed25a..15f9b216b 100644 --- a/crates/ra_assists/src/handlers/add_custom_impl.rs +++ b/crates/ra_assists/src/handlers/add_custom_impl.rs | |||
@@ -1,17 +1,13 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use join_to_string::join; | ||
4 | use ra_syntax::{ | 1 | use ra_syntax::{ |
5 | ast::{self, AstNode}, | 2 | ast::{self, AstNode}, |
6 | Direction, SmolStr, | 3 | Direction, SmolStr, |
7 | SyntaxKind::{IDENT, WHITESPACE}, | 4 | SyntaxKind::{IDENT, WHITESPACE}, |
8 | TextRange, TextUnit, | 5 | TextRange, TextUnit, |
9 | }; | 6 | }; |
7 | use stdx::SepBy; | ||
10 | 8 | ||
11 | use crate::{Assist, AssistCtx, AssistId}; | 9 | use crate::{Assist, AssistCtx, AssistId}; |
12 | 10 | ||
13 | const DERIVE_TRAIT: &str = "derive"; | ||
14 | |||
15 | // Assist: add_custom_impl | 11 | // Assist: add_custom_impl |
16 | // | 12 | // |
17 | // Adds impl block for derived trait. | 13 | // Adds impl block for derived trait. |
@@ -38,7 +34,7 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> { | |||
38 | .descendants_with_tokens() | 34 | .descendants_with_tokens() |
39 | .filter(|t| t.kind() == IDENT) | 35 | .filter(|t| t.kind() == IDENT) |
40 | .find_map(|i| i.into_token()) | 36 | .find_map(|i| i.into_token()) |
41 | .filter(|t| *t.text() == DERIVE_TRAIT)? | 37 | .filter(|t| *t.text() == "derive")? |
42 | .text() | 38 | .text() |
43 | .clone(); | 39 | .clone(); |
44 | 40 | ||
@@ -63,8 +59,7 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> { | |||
63 | .filter(|t| t != trait_token.text()) | 59 | .filter(|t| t != trait_token.text()) |
64 | .collect::<Vec<SmolStr>>(); | 60 | .collect::<Vec<SmolStr>>(); |
65 | let has_more_derives = !new_attr_input.is_empty(); | 61 | let has_more_derives = !new_attr_input.is_empty(); |
66 | let new_attr_input = | 62 | let new_attr_input = new_attr_input.iter().sep_by(", ").surround_with("(", ")").to_string(); |
67 | join(new_attr_input.iter()).separator(", ").surround_with("(", ")").to_string(); | ||
68 | let new_attr_input_len = new_attr_input.len(); | 63 | let new_attr_input_len = new_attr_input.len(); |
69 | 64 | ||
70 | let mut buf = String::new(); | 65 | let mut buf = String::new(); |
@@ -100,9 +95,10 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> { | |||
100 | 95 | ||
101 | #[cfg(test)] | 96 | #[cfg(test)] |
102 | mod tests { | 97 | mod tests { |
103 | use super::*; | ||
104 | use crate::helpers::{check_assist, check_assist_not_applicable}; | 98 | use crate::helpers::{check_assist, check_assist_not_applicable}; |
105 | 99 | ||
100 | use super::*; | ||
101 | |||
106 | #[test] | 102 | #[test] |
107 | fn add_custom_impl_for_unique_input() { | 103 | fn add_custom_impl_for_unique_input() { |
108 | check_assist( | 104 | check_assist( |
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index afae7d385..6622eadb2 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs | |||
@@ -1,9 +1,8 @@ | |||
1 | use format_buf::format; | ||
2 | use join_to_string::join; | ||
3 | use ra_syntax::{ | 1 | use ra_syntax::{ |
4 | ast::{self, AstNode, NameOwner, TypeParamsOwner}, | 2 | ast::{self, AstNode, NameOwner, TypeParamsOwner}, |
5 | TextUnit, | 3 | TextUnit, |
6 | }; | 4 | }; |
5 | use stdx::{format_to, SepBy}; | ||
7 | 6 | ||
8 | use crate::{Assist, AssistCtx, AssistId}; | 7 | use crate::{Assist, AssistCtx, AssistId}; |
9 | 8 | ||
@@ -36,7 +35,7 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> { | |||
36 | let mut buf = String::new(); | 35 | let mut buf = String::new(); |
37 | buf.push_str("\n\nimpl"); | 36 | buf.push_str("\n\nimpl"); |
38 | if let Some(type_params) = &type_params { | 37 | if let Some(type_params) = &type_params { |
39 | format!(buf, "{}", type_params.syntax()); | 38 | format_to!(buf, "{}", type_params.syntax()); |
40 | } | 39 | } |
41 | buf.push_str(" "); | 40 | buf.push_str(" "); |
42 | buf.push_str(name.text().as_str()); | 41 | buf.push_str(name.text().as_str()); |
@@ -47,7 +46,9 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> { | |||
47 | .map(|it| it.text().clone()); | 46 | .map(|it| it.text().clone()); |
48 | let type_params = | 47 | let type_params = |
49 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); | 48 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); |
50 | join(lifetime_params.chain(type_params)).surround_with("<", ">").to_buf(&mut buf); | 49 | |
50 | let generic_params = lifetime_params.chain(type_params).sep_by(", "); | ||
51 | format_to!(buf, "<{}>", generic_params) | ||
51 | } | 52 | } |
52 | buf.push_str(" {\n"); | 53 | buf.push_str(" {\n"); |
53 | edit.set_cursor(start_offset + TextUnit::of_str(&buf)); | 54 | edit.set_cursor(start_offset + TextUnit::of_str(&buf)); |
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index 729a223e0..240b19fa3 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs | |||
@@ -1,14 +1,11 @@ | |||
1 | use std::fmt::Write; | ||
2 | |||
3 | use format_buf::format; | ||
4 | use hir::Adt; | 1 | use hir::Adt; |
5 | use join_to_string::join; | ||
6 | use ra_syntax::{ | 2 | use ra_syntax::{ |
7 | ast::{ | 3 | ast::{ |
8 | self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, | 4 | self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, |
9 | }, | 5 | }, |
10 | TextUnit, T, | 6 | TextUnit, T, |
11 | }; | 7 | }; |
8 | use stdx::{format_to, SepBy}; | ||
12 | 9 | ||
13 | use crate::{Assist, AssistCtx, AssistId}; | 10 | use crate::{Assist, AssistCtx, AssistId}; |
14 | 11 | ||
@@ -53,24 +50,22 @@ pub(crate) fn add_new(ctx: AssistCtx) -> Option<Assist> { | |||
53 | buf.push('\n'); | 50 | buf.push('\n'); |
54 | } | 51 | } |
55 | 52 | ||
56 | let vis = strukt.visibility().map(|v| format!("{} ", v.syntax())); | 53 | let vis = strukt.visibility().map(|v| format!("{} ", v)); |
57 | let vis = vis.as_deref().unwrap_or(""); | 54 | let vis = vis.as_deref().unwrap_or(""); |
58 | write!(&mut buf, " {}fn new(", vis).unwrap(); | ||
59 | |||
60 | join(field_list.fields().filter_map(|f| { | ||
61 | Some(format!("{}: {}", f.name()?.syntax().text(), f.ascribed_type()?.syntax().text())) | ||
62 | })) | ||
63 | .separator(", ") | ||
64 | .to_buf(&mut buf); | ||
65 | 55 | ||
66 | buf.push_str(") -> Self { Self {"); | 56 | let params = field_list |
67 | 57 | .fields() | |
68 | join(field_list.fields().filter_map(|f| Some(f.name()?.syntax().text()))) | 58 | .filter_map(|f| { |
69 | .separator(", ") | 59 | Some(format!( |
70 | .surround_with(" ", " ") | 60 | "{}: {}", |
71 | .to_buf(&mut buf); | 61 | f.name()?.syntax().text(), |
62 | f.ascribed_type()?.syntax().text() | ||
63 | )) | ||
64 | }) | ||
65 | .sep_by(", "); | ||
66 | let fields = field_list.fields().filter_map(|f| f.name()).sep_by(", "); | ||
72 | 67 | ||
73 | buf.push_str("} }"); | 68 | format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields); |
74 | 69 | ||
75 | let (start_offset, end_offset) = impl_def | 70 | let (start_offset, end_offset) = impl_def |
76 | .and_then(|impl_def| { | 71 | .and_then(|impl_def| { |
@@ -103,7 +98,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String { | |||
103 | let mut buf = String::with_capacity(code.len()); | 98 | let mut buf = String::with_capacity(code.len()); |
104 | buf.push_str("\n\nimpl"); | 99 | buf.push_str("\n\nimpl"); |
105 | if let Some(type_params) = &type_params { | 100 | if let Some(type_params) = &type_params { |
106 | format!(buf, "{}", type_params.syntax()); | 101 | format_to!(buf, "{}", type_params.syntax()); |
107 | } | 102 | } |
108 | buf.push_str(" "); | 103 | buf.push_str(" "); |
109 | buf.push_str(strukt.name().unwrap().text().as_str()); | 104 | buf.push_str(strukt.name().unwrap().text().as_str()); |
@@ -114,10 +109,10 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String { | |||
114 | .map(|it| it.text().clone()); | 109 | .map(|it| it.text().clone()); |
115 | let type_params = | 110 | let type_params = |
116 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); | 111 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); |
117 | join(lifetime_params.chain(type_params)).surround_with("<", ">").to_buf(&mut buf); | 112 | format_to!(buf, "<{}>", lifetime_params.chain(type_params).sep_by(", ")) |
118 | } | 113 | } |
119 | 114 | ||
120 | format!(&mut buf, " {{\n{}\n}}\n", code); | 115 | format_to!(buf, " {{\n{}\n}}\n", code); |
121 | 116 | ||
122 | buf | 117 | buf |
123 | } | 118 | } |
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index b453c51fb..1edbdc14c 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs | |||
@@ -1,4 +1,3 @@ | |||
1 | use format_buf::format; | ||
2 | use ra_syntax::{ | 1 | use ra_syntax::{ |
3 | ast::{self, AstNode}, | 2 | ast::{self, AstNode}, |
4 | SyntaxKind::{ | 3 | SyntaxKind::{ |
@@ -7,6 +6,7 @@ use ra_syntax::{ | |||
7 | }, | 6 | }, |
8 | SyntaxNode, TextUnit, | 7 | SyntaxNode, TextUnit, |
9 | }; | 8 | }; |
9 | use stdx::format_to; | ||
10 | use test_utils::tested_by; | 10 | use test_utils::tested_by; |
11 | 11 | ||
12 | use crate::{Assist, AssistCtx, AssistId}; | 12 | use crate::{Assist, AssistCtx, AssistId}; |
@@ -52,7 +52,7 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> { | |||
52 | buf.push_str("let var_name = "); | 52 | buf.push_str("let var_name = "); |
53 | TextUnit::of_str("let ") | 53 | TextUnit::of_str("let ") |
54 | }; | 54 | }; |
55 | format!(buf, "{}", expr.syntax()); | 55 | format_to!(buf, "{}", expr.syntax()); |
56 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); | 56 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); |
57 | let is_full_stmt = if let Some(expr_stmt) = &full_stmt { | 57 | let is_full_stmt = if let Some(expr_stmt) = &full_stmt { |
58 | Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) | 58 | Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) |
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml index 30a12337e..56e791e3e 100644 --- a/crates/ra_hir_def/Cargo.toml +++ b/crates/ra_hir_def/Cargo.toml | |||
@@ -15,6 +15,8 @@ either = "1.5.3" | |||
15 | anymap = "0.12.1" | 15 | anymap = "0.12.1" |
16 | drop_bomb = "0.1.4" | 16 | drop_bomb = "0.1.4" |
17 | 17 | ||
18 | stdx = { path = "../stdx" } | ||
19 | |||
18 | ra_arena = { path = "../ra_arena" } | 20 | ra_arena = { path = "../ra_arena" } |
19 | ra_db = { path = "../ra_db" } | 21 | ra_db = { path = "../ra_db" } |
20 | ra_syntax = { path = "../ra_syntax" } | 22 | ra_syntax = { path = "../ra_syntax" } |
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 40bdc34f5..f279c2ad4 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -63,6 +63,7 @@ use ra_db::{CrateId, Edition, FileId}; | |||
63 | use ra_prof::profile; | 63 | use ra_prof::profile; |
64 | use ra_syntax::ast; | 64 | use ra_syntax::ast; |
65 | use rustc_hash::FxHashMap; | 65 | use rustc_hash::FxHashMap; |
66 | use stdx::format_to; | ||
66 | 67 | ||
67 | use crate::{ | 68 | use crate::{ |
68 | db::DefDatabase, | 69 | db::DefDatabase, |
@@ -246,7 +247,7 @@ impl CrateDefMap { | |||
246 | entries.sort_by_key(|(name, _)| name.clone()); | 247 | entries.sort_by_key(|(name, _)| name.clone()); |
247 | 248 | ||
248 | for (name, def) in entries { | 249 | for (name, def) in entries { |
249 | *buf += &format!("{}:", name); | 250 | format_to!(buf, "{}:", name); |
250 | 251 | ||
251 | if def.types.is_some() { | 252 | if def.types.is_some() { |
252 | *buf += " t"; | 253 | *buf += " t"; |
@@ -265,7 +266,7 @@ impl CrateDefMap { | |||
265 | } | 266 | } |
266 | 267 | ||
267 | for (name, child) in map.modules[module].children.iter() { | 268 | for (name, child) in map.modules[module].children.iter() { |
268 | let path = path.to_string() + &format!("::{}", name); | 269 | let path = &format!("{}::{}", path, name); |
269 | go(buf, map, &path, *child); | 270 | go(buf, map, &path, *child); |
270 | } | 271 | } |
271 | } | 272 | } |
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index 9962112db..5a58d70cf 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml | |||
@@ -13,6 +13,8 @@ ena = "0.13.1" | |||
13 | log = "0.4.8" | 13 | log = "0.4.8" |
14 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
15 | 15 | ||
16 | stdx = { path = "../stdx" } | ||
17 | |||
16 | hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } | 18 | hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } |
17 | hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" } | 19 | hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" } |
18 | ra_arena = { path = "../ra_arena" } | 20 | ra_arena = { path = "../ra_arena" } |
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 6eafdc8f6..0f8522021 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs | |||
@@ -4,6 +4,7 @@ use std::any::Any; | |||
4 | 4 | ||
5 | use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; | 5 | use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; |
6 | use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; | 6 | use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; |
7 | use stdx::format_to; | ||
7 | 8 | ||
8 | pub use hir_def::diagnostics::UnresolvedModule; | 9 | pub use hir_def::diagnostics::UnresolvedModule; |
9 | pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; | 10 | pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; |
@@ -37,12 +38,11 @@ pub struct MissingFields { | |||
37 | 38 | ||
38 | impl Diagnostic for MissingFields { | 39 | impl Diagnostic for MissingFields { |
39 | fn message(&self) -> String { | 40 | fn message(&self) -> String { |
40 | use std::fmt::Write; | 41 | let mut buf = String::from("Missing structure fields:\n"); |
41 | let mut message = String::from("Missing structure fields:\n"); | ||
42 | for field in &self.missed_fields { | 42 | for field in &self.missed_fields { |
43 | writeln!(message, "- {}", field).unwrap(); | 43 | format_to!(buf, "- {}", field); |
44 | } | 44 | } |
45 | message | 45 | buf |
46 | } | 46 | } |
47 | fn source(&self) -> InFile<SyntaxNodePtr> { | 47 | fn source(&self) -> InFile<SyntaxNodePtr> { |
48 | InFile { file_id: self.file, value: self.field_list.into() } | 48 | InFile { file_id: self.file, value: self.field_list.into() } |
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 5bbeabf51..208096aab 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs | |||
@@ -10,6 +10,7 @@ use hir_expand::{db::AstDatabase, diagnostics::DiagnosticSink}; | |||
10 | use ra_db::{ | 10 | use ra_db::{ |
11 | salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase, Upcast, | 11 | salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase, Upcast, |
12 | }; | 12 | }; |
13 | use stdx::format_to; | ||
13 | 14 | ||
14 | use crate::{db::HirDatabase, expr::ExprValidator}; | 15 | use crate::{db::HirDatabase, expr::ExprValidator}; |
15 | 16 | ||
@@ -131,7 +132,7 @@ impl TestDB { | |||
131 | for f in fns { | 132 | for f in fns { |
132 | let infer = self.infer(f.into()); | 133 | let infer = self.infer(f.into()); |
133 | let mut sink = DiagnosticSink::new(|d| { | 134 | let mut sink = DiagnosticSink::new(|d| { |
134 | buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message()); | 135 | format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message()); |
135 | }); | 136 | }); |
136 | infer.add_diagnostics(self, f, &mut sink); | 137 | infer.add_diagnostics(self, f, &mut sink); |
137 | let mut validator = ExprValidator::new(f, infer, &mut sink); | 138 | let mut validator = ExprValidator::new(f, infer, &mut sink); |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 7e9547340..027e5a8f8 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -7,7 +7,6 @@ mod traits; | |||
7 | mod method_resolution; | 7 | mod method_resolution; |
8 | mod macros; | 8 | mod macros; |
9 | 9 | ||
10 | use std::fmt::Write; | ||
11 | use std::sync::Arc; | 10 | use std::sync::Arc; |
12 | 11 | ||
13 | use hir_def::{ | 12 | use hir_def::{ |
@@ -26,6 +25,7 @@ use ra_syntax::{ | |||
26 | algo, | 25 | algo, |
27 | ast::{self, AstNode}, | 26 | ast::{self, AstNode}, |
28 | }; | 27 | }; |
28 | use stdx::format_to; | ||
29 | 29 | ||
30 | use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResult}; | 30 | use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResult}; |
31 | 31 | ||
@@ -63,7 +63,7 @@ fn infer(ra_fixture: &str) -> String { | |||
63 | fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | 63 | fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { |
64 | let (db, file_id) = TestDB::with_single_file(content); | 64 | let (db, file_id) = TestDB::with_single_file(content); |
65 | 65 | ||
66 | let mut acc = String::new(); | 66 | let mut buf = String::new(); |
67 | 67 | ||
68 | let mut infer_def = |inference_result: Arc<InferenceResult>, | 68 | let mut infer_def = |inference_result: Arc<InferenceResult>, |
69 | body_source_map: Arc<BodySourceMap>| { | 69 | body_source_map: Arc<BodySourceMap>| { |
@@ -106,15 +106,14 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
106 | (src_ptr.value.range(), node.text().to_string().replace("\n", " ")) | 106 | (src_ptr.value.range(), node.text().to_string().replace("\n", " ")) |
107 | }; | 107 | }; |
108 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; | 108 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; |
109 | writeln!( | 109 | format_to!( |
110 | acc, | 110 | buf, |
111 | "{}{} '{}': {}", | 111 | "{}{} '{}': {}\n", |
112 | macro_prefix, | 112 | macro_prefix, |
113 | range, | 113 | range, |
114 | ellipsize(text, 15), | 114 | ellipsize(text, 15), |
115 | ty.display(&db) | 115 | ty.display(&db) |
116 | ) | 116 | ); |
117 | .unwrap(); | ||
118 | } | 117 | } |
119 | if include_mismatches { | 118 | if include_mismatches { |
120 | mismatches.sort_by_key(|(src_ptr, _)| { | 119 | mismatches.sort_by_key(|(src_ptr, _)| { |
@@ -123,15 +122,14 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
123 | for (src_ptr, mismatch) in &mismatches { | 122 | for (src_ptr, mismatch) in &mismatches { |
124 | let range = src_ptr.value.range(); | 123 | let range = src_ptr.value.range(); |
125 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; | 124 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; |
126 | writeln!( | 125 | format_to!( |
127 | acc, | 126 | buf, |
128 | "{}{}: expected {}, got {}", | 127 | "{}{}: expected {}, got {}\n", |
129 | macro_prefix, | 128 | macro_prefix, |
130 | range, | 129 | range, |
131 | mismatch.expected.display(&db), | 130 | mismatch.expected.display(&db), |
132 | mismatch.actual.display(&db), | 131 | mismatch.actual.display(&db), |
133 | ) | 132 | ); |
134 | .unwrap(); | ||
135 | } | 133 | } |
136 | } | 134 | } |
137 | }; | 135 | }; |
@@ -158,8 +156,8 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
158 | infer_def(infer, source_map); | 156 | infer_def(infer, source_map); |
159 | } | 157 | } |
160 | 158 | ||
161 | acc.truncate(acc.trim_end().len()); | 159 | buf.truncate(buf.trim_end().len()); |
162 | acc | 160 | buf |
163 | } | 161 | } |
164 | 162 | ||
165 | fn visit_module( | 163 | fn visit_module( |
diff --git a/crates/ra_ide/Cargo.toml b/crates/ra_ide/Cargo.toml index 36eec0e60..b4a29b81b 100644 --- a/crates/ra_ide/Cargo.toml +++ b/crates/ra_ide/Cargo.toml | |||
@@ -12,14 +12,14 @@ wasm = [] | |||
12 | 12 | ||
13 | [dependencies] | 13 | [dependencies] |
14 | either = "1.5.3" | 14 | either = "1.5.3" |
15 | format-buf = "1.0.0" | ||
16 | indexmap = "1.3.2" | 15 | indexmap = "1.3.2" |
17 | itertools = "0.9.0" | 16 | itertools = "0.9.0" |
18 | join_to_string = "0.1.3" | ||
19 | log = "0.4.8" | 17 | log = "0.4.8" |
20 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
21 | rand = { version = "0.7.3", features = ["small_rng"] } | 19 | rand = { version = "0.7.3", features = ["small_rng"] } |
22 | 20 | ||
21 | stdx = { path = "../stdx" } | ||
22 | |||
23 | ra_syntax = { path = "../ra_syntax" } | 23 | ra_syntax = { path = "../ra_syntax" } |
24 | ra_text_edit = { path = "../ra_text_edit" } | 24 | ra_text_edit = { path = "../ra_text_edit" } |
25 | ra_db = { path = "../ra_db" } | 25 | ra_db = { path = "../ra_db" } |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 253848602..60f1b83f3 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -1,15 +1,14 @@ | |||
1 | //! This modules takes care of rendering various definitions as completion items. | 1 | //! This modules takes care of rendering various definitions as completion items. |
2 | 2 | ||
3 | use hir::{Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type}; | 3 | use hir::{Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type}; |
4 | use join_to_string::join; | ||
5 | use ra_syntax::ast::NameOwner; | 4 | use ra_syntax::ast::NameOwner; |
5 | use stdx::SepBy; | ||
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
7 | 7 | ||
8 | use crate::completion::{ | ||
9 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, | ||
10 | }; | ||
11 | |||
12 | use crate::{ | 8 | use crate::{ |
9 | completion::{ | ||
10 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, | ||
11 | }, | ||
13 | display::{const_label, macro_label, type_label, FunctionSignature}, | 12 | display::{const_label, macro_label, type_label, FunctionSignature}, |
14 | RootDatabase, | 13 | RootDatabase, |
15 | }; | 14 | }; |
@@ -221,13 +220,13 @@ impl Completions { | |||
221 | builder = builder.trigger_call_info(); | 220 | builder = builder.trigger_call_info(); |
222 | let snippet = if ctx.options.add_call_argument_snippets { | 221 | let snippet = if ctx.options.add_call_argument_snippets { |
223 | let to_skip = if has_self_param { 1 } else { 0 }; | 222 | let to_skip = if has_self_param { 1 } else { 0 }; |
224 | let function_params_snippet = join( | 223 | let function_params_snippet = function_signature |
225 | function_signature.parameter_names.iter().skip(to_skip).enumerate().map( | 224 | .parameter_names |
226 | |(index, param_name)| format!("${{{}:{}}}", index + 1, param_name), | 225 | .iter() |
227 | ), | 226 | .skip(to_skip) |
228 | ) | 227 | .enumerate() |
229 | .separator(", ") | 228 | .map(|(index, param_name)| format!("${{{}:{}}}", index + 1, param_name)) |
230 | .to_string(); | 229 | .sep_by(", "); |
231 | format!("{}({})$0", name, function_params_snippet) | 230 | format!("{}({})$0", name, function_params_snippet) |
232 | } else { | 231 | } else { |
233 | format!("{}($0)", name) | 232 | format!("{}($0)", name) |
@@ -281,18 +280,16 @@ impl Completions { | |||
281 | .into_iter() | 280 | .into_iter() |
282 | .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); | 281 | .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); |
283 | let detail = match variant.kind(ctx.db) { | 282 | let detail = match variant.kind(ctx.db) { |
284 | StructKind::Tuple | StructKind::Unit => { | 283 | StructKind::Tuple | StructKind::Unit => detail_types |
285 | join(detail_types.map(|(_, t)| t.display(ctx.db).to_string())) | 284 | .map(|(_, t)| t.display(ctx.db).to_string()) |
286 | .separator(", ") | 285 | .sep_by(", ") |
287 | .surround_with("(", ")") | 286 | .surround_with("(", ")") |
288 | .to_string() | 287 | .to_string(), |
289 | } | 288 | StructKind::Record => detail_types |
290 | StructKind::Record => { | 289 | .map(|(n, t)| format!("{}: {}", n, t.display(ctx.db).to_string())) |
291 | join(detail_types.map(|(n, t)| format!("{}: {}", n, t.display(ctx.db).to_string()))) | 290 | .sep_by(", ") |
292 | .separator(", ") | 291 | .surround_with("{ ", " }") |
293 | .surround_with("{ ", " }") | 292 | .to_string(), |
294 | .to_string() | ||
295 | } | ||
296 | }; | 293 | }; |
297 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) | 294 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) |
298 | .kind(CompletionItemKind::EnumVariant) | 295 | .kind(CompletionItemKind::EnumVariant) |
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index a10e642db..c1d7ddaf2 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -200,8 +200,8 @@ fn check_struct_shorthand_initialization( | |||
200 | #[cfg(test)] | 200 | #[cfg(test)] |
201 | mod tests { | 201 | mod tests { |
202 | use insta::assert_debug_snapshot; | 202 | use insta::assert_debug_snapshot; |
203 | use join_to_string::join; | ||
204 | use ra_syntax::SourceFile; | 203 | use ra_syntax::SourceFile; |
204 | use stdx::SepBy; | ||
205 | use test_utils::assert_eq_text; | 205 | use test_utils::assert_eq_text; |
206 | 206 | ||
207 | use crate::mock_analysis::{analysis_and_position, single_file}; | 207 | use crate::mock_analysis::{analysis_and_position, single_file}; |
@@ -254,16 +254,12 @@ mod tests { | |||
254 | .map(|it| it.len() - it.trim_start().len()) | 254 | .map(|it| it.len() - it.trim_start().len()) |
255 | .next() | 255 | .next() |
256 | .expect("empty fixture"); | 256 | .expect("empty fixture"); |
257 | let after = join(after.lines().filter_map(|line| { | 257 | let after = after |
258 | if line.len() > margin { | 258 | .lines() |
259 | Some(&line[margin..]) | 259 | .filter_map(|line| if line.len() > margin { Some(&line[margin..]) } else { None }) |
260 | } else { | 260 | .sep_by("\n") |
261 | None | 261 | .suffix("\n") |
262 | } | 262 | .to_string(); |
263 | })) | ||
264 | .separator("\n") | ||
265 | .suffix("\n") | ||
266 | .to_string(); | ||
267 | 263 | ||
268 | assert_eq_text!(&after, &actual); | 264 | assert_eq_text!(&after, &actual); |
269 | assert!( | 265 | assert!( |
diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs index c395057a7..722092de9 100644 --- a/crates/ra_ide/src/display.rs +++ b/crates/ra_ide/src/display.rs | |||
@@ -6,12 +6,13 @@ mod navigation_target; | |||
6 | mod structure; | 6 | mod structure; |
7 | mod short_label; | 7 | mod short_label; |
8 | 8 | ||
9 | use std::fmt::{Display, Write}; | 9 | use std::fmt::Display; |
10 | 10 | ||
11 | use ra_syntax::{ | 11 | use ra_syntax::{ |
12 | ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, | 12 | ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, |
13 | SyntaxKind::{ATTR, COMMENT}, | 13 | SyntaxKind::{ATTR, COMMENT}, |
14 | }; | 14 | }; |
15 | use stdx::format_to; | ||
15 | 16 | ||
16 | pub use function_signature::FunctionSignature; | 17 | pub use function_signature::FunctionSignature; |
17 | pub use navigation_target::NavigationTarget; | 18 | pub use navigation_target::NavigationTarget; |
@@ -78,18 +79,18 @@ pub(crate) fn rust_code_markup_with_doc( | |||
78 | doc: Option<&str>, | 79 | doc: Option<&str>, |
79 | mod_path: Option<&str>, | 80 | mod_path: Option<&str>, |
80 | ) -> String { | 81 | ) -> String { |
81 | let mut markup = "```rust\n".to_owned(); | 82 | let mut buf = "```rust\n".to_owned(); |
82 | 83 | ||
83 | if let Some(mod_path) = mod_path { | 84 | if let Some(mod_path) = mod_path { |
84 | if !mod_path.is_empty() { | 85 | if !mod_path.is_empty() { |
85 | write!(markup, "{}\n", mod_path).unwrap(); | 86 | format_to!(buf, "{}\n", mod_path); |
86 | } | 87 | } |
87 | } | 88 | } |
88 | write!(markup, "{}\n```", code).unwrap(); | 89 | format_to!(buf, "{}\n```", code); |
89 | 90 | ||
90 | if let Some(doc) = doc { | 91 | if let Some(doc) = doc { |
91 | write!(markup, "\n\n{}", doc).unwrap(); | 92 | format_to!(buf, "\n\n{}", doc); |
92 | } | 93 | } |
93 | 94 | ||
94 | markup | 95 | buf |
95 | } | 96 | } |
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index ec1bbd5a0..b967a6816 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs | |||
@@ -1,12 +1,14 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::fmt::{self, Display}; | 3 | use std::{ |
4 | convert::From, | ||
5 | fmt::{self, Display}, | ||
6 | }; | ||
4 | 7 | ||
5 | use hir::{Docs, Documentation, HasSource, HirDisplay}; | 8 | use hir::{Docs, Documentation, HasSource, HirDisplay}; |
6 | use join_to_string::join; | ||
7 | use ra_ide_db::RootDatabase; | 9 | use ra_ide_db::RootDatabase; |
8 | use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; | 10 | use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; |
9 | use std::convert::From; | 11 | use stdx::SepBy; |
10 | 12 | ||
11 | use crate::display::{generic_parameters, where_predicates}; | 13 | use crate::display::{generic_parameters, where_predicates}; |
12 | 14 | ||
@@ -227,21 +229,17 @@ impl Display for FunctionSignature { | |||
227 | } | 229 | } |
228 | 230 | ||
229 | if !self.generic_parameters.is_empty() { | 231 | if !self.generic_parameters.is_empty() { |
230 | join(self.generic_parameters.iter()) | 232 | write!(f, "{}", self.generic_parameters.iter().sep_by(", ").surround_with("<", ">"))?; |
231 | .separator(", ") | ||
232 | .surround_with("<", ">") | ||
233 | .to_fmt(f)?; | ||
234 | } | 233 | } |
235 | 234 | ||
236 | join(self.parameters.iter()).separator(", ").surround_with("(", ")").to_fmt(f)?; | 235 | write!(f, "{}", self.parameters.iter().sep_by(", ").surround_with("(", ")"))?; |
237 | 236 | ||
238 | if let Some(t) = &self.ret_type { | 237 | if let Some(t) = &self.ret_type { |
239 | write!(f, " -> {}", t)?; | 238 | write!(f, " -> {}", t)?; |
240 | } | 239 | } |
241 | 240 | ||
242 | if !self.where_predicates.is_empty() { | 241 | if !self.where_predicates.is_empty() { |
243 | write!(f, "\nwhere ")?; | 242 | write!(f, "\nwhere {}", self.where_predicates.iter().sep_by(",\n "))?; |
244 | join(self.where_predicates.iter()).separator(",\n ").to_fmt(f)?; | ||
245 | } | 243 | } |
246 | 244 | ||
247 | Ok(()) | 245 | Ok(()) |
diff --git a/crates/ra_ide/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs index 9ffc9b980..4b081bf6c 100644 --- a/crates/ra_ide/src/display/short_label.rs +++ b/crates/ra_ide/src/display/short_label.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use format_buf::format; | ||
4 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeAscriptionOwner, VisibilityOwner}; | 3 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeAscriptionOwner, VisibilityOwner}; |
4 | use stdx::format_to; | ||
5 | 5 | ||
6 | pub(crate) trait ShortLabel { | 6 | pub(crate) trait ShortLabel { |
7 | fn short_label(&self) -> Option<String>; | 7 | fn short_label(&self) -> Option<String>; |
@@ -80,7 +80,7 @@ where | |||
80 | let mut buf = short_label_from_node(node, prefix)?; | 80 | let mut buf = short_label_from_node(node, prefix)?; |
81 | 81 | ||
82 | if let Some(type_ref) = node.ascribed_type() { | 82 | if let Some(type_ref) = node.ascribed_type() { |
83 | format!(buf, ": {}", type_ref.syntax()); | 83 | format_to!(buf, ": {}", type_ref.syntax()); |
84 | } | 84 | } |
85 | 85 | ||
86 | Some(buf) | 86 | Some(buf) |
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index 6fccc2303..3c6ae77e4 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml | |||
@@ -18,6 +18,8 @@ rustc-hash = "1.1.0" | |||
18 | arrayvec = "0.5.1" | 18 | arrayvec = "0.5.1" |
19 | once_cell = "1.3.1" | 19 | once_cell = "1.3.1" |
20 | 20 | ||
21 | stdx = { path = "../stdx" } | ||
22 | |||
21 | ra_text_edit = { path = "../ra_text_edit" } | 23 | ra_text_edit = { path = "../ra_text_edit" } |
22 | ra_parser = { path = "../ra_parser" } | 24 | ra_parser = { path = "../ra_parser" } |
23 | 25 | ||
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index dbf8e6370..0c908573d 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! This module contains free-standing functions for creating AST fragments out | 1 | //! This module contains free-standing functions for creating AST fragments out |
2 | //! of smaller pieces. | 2 | //! of smaller pieces. |
3 | use itertools::Itertools; | 3 | use itertools::Itertools; |
4 | use stdx::format_to; | ||
4 | 5 | ||
5 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; | 6 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; |
6 | 7 | ||
@@ -34,14 +35,14 @@ pub fn use_tree( | |||
34 | let mut buf = "use ".to_string(); | 35 | let mut buf = "use ".to_string(); |
35 | buf += &path.syntax().to_string(); | 36 | buf += &path.syntax().to_string(); |
36 | if let Some(use_tree_list) = use_tree_list { | 37 | if let Some(use_tree_list) = use_tree_list { |
37 | buf += &format!("::{}", use_tree_list); | 38 | format_to!(buf, "::{}", use_tree_list); |
38 | } | 39 | } |
39 | if add_star { | 40 | if add_star { |
40 | buf += "::*"; | 41 | buf += "::*"; |
41 | } | 42 | } |
42 | 43 | ||
43 | if let Some(alias) = alias { | 44 | if let Some(alias) = alias { |
44 | buf += &format!(" {}", alias); | 45 | format_to!(buf, " {}", alias); |
45 | } | 46 | } |
46 | ast_from_text(&buf) | 47 | ast_from_text(&buf) |
47 | } | 48 | } |
@@ -70,15 +71,15 @@ pub fn block_expr( | |||
70 | stmts: impl IntoIterator<Item = ast::Stmt>, | 71 | stmts: impl IntoIterator<Item = ast::Stmt>, |
71 | tail_expr: Option<ast::Expr>, | 72 | tail_expr: Option<ast::Expr>, |
72 | ) -> ast::BlockExpr { | 73 | ) -> ast::BlockExpr { |
73 | let mut text = "{\n".to_string(); | 74 | let mut buf = "{\n".to_string(); |
74 | for stmt in stmts.into_iter() { | 75 | for stmt in stmts.into_iter() { |
75 | text += &format!(" {}\n", stmt); | 76 | format_to!(buf, " {}\n", stmt); |
76 | } | 77 | } |
77 | if let Some(tail_expr) = tail_expr { | 78 | if let Some(tail_expr) = tail_expr { |
78 | text += &format!(" {}\n", tail_expr) | 79 | format_to!(buf, " {}\n", tail_expr) |
79 | } | 80 | } |
80 | text += "}"; | 81 | buf += "}"; |
81 | ast_from_text(&format!("fn f() {}", text)) | 82 | ast_from_text(&format!("fn f() {}", buf)) |
82 | } | 83 | } |
83 | 84 | ||
84 | pub fn block_from_expr(e: ast::Expr) -> ast::Block { | 85 | pub fn block_from_expr(e: ast::Expr) -> ast::Block { |
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index cef926ed3..f0e16dc2b 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -32,9 +32,10 @@ pub mod ast; | |||
32 | #[doc(hidden)] | 32 | #[doc(hidden)] |
33 | pub mod fuzz; | 33 | pub mod fuzz; |
34 | 34 | ||
35 | use std::{fmt::Write, marker::PhantomData, sync::Arc}; | 35 | use std::{marker::PhantomData, sync::Arc}; |
36 | 36 | ||
37 | use ra_text_edit::AtomTextEdit; | 37 | use ra_text_edit::AtomTextEdit; |
38 | use stdx::format_to; | ||
38 | 39 | ||
39 | use crate::syntax_node::GreenNode; | 40 | use crate::syntax_node::GreenNode; |
40 | 41 | ||
@@ -115,7 +116,7 @@ impl Parse<SourceFile> { | |||
115 | pub fn debug_dump(&self) -> String { | 116 | pub fn debug_dump(&self) -> String { |
116 | let mut buf = format!("{:#?}", self.tree().syntax()); | 117 | let mut buf = format!("{:#?}", self.tree().syntax()); |
117 | for err in self.errors.iter() { | 118 | for err in self.errors.iter() { |
118 | writeln!(buf, "error {:?}: {}", err.range(), err).unwrap(); | 119 | format_to!(buf, "error {:?}: {}\n", err.range(), err); |
119 | } | 120 | } |
120 | buf | 121 | buf |
121 | } | 122 | } |
@@ -296,7 +297,7 @@ fn api_walkthrough() { | |||
296 | NodeOrToken::Node(it) => it.text().to_string(), | 297 | NodeOrToken::Node(it) => it.text().to_string(), |
297 | NodeOrToken::Token(it) => it.text().to_string(), | 298 | NodeOrToken::Token(it) => it.text().to_string(), |
298 | }; | 299 | }; |
299 | buf += &format!("{:indent$}{:?} {:?}\n", " ", text, node.kind(), indent = indent); | 300 | format_to!(buf, "{:indent$}{:?} {:?}\n", " ", text, node.kind(), indent = indent); |
300 | indent += 2; | 301 | indent += 2; |
301 | } | 302 | } |
302 | WalkEvent::Leave(_) => indent -= 2, | 303 | WalkEvent::Leave(_) => indent -= 2, |
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index e071e9b8d..8fe6799d2 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml | |||
@@ -30,6 +30,8 @@ serde = { version = "1.0.104", features = ["derive"] } | |||
30 | serde_json = "1.0.48" | 30 | serde_json = "1.0.48" |
31 | threadpool = "1.7.1" | 31 | threadpool = "1.7.1" |
32 | 32 | ||
33 | stdx = { path = "../stdx" } | ||
34 | |||
33 | lsp-server = "0.3.1" | 35 | lsp-server = "0.3.1" |
34 | ra_cargo_watch = { path = "../ra_cargo_watch" } | 36 | ra_cargo_watch = { path = "../ra_cargo_watch" } |
35 | ra_ide = { path = "../ra_ide" } | 37 | ra_ide = { path = "../ra_ide" } |
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 27459be8c..75cf2dae5 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Fully type-check project and print various stats, like the number of type | 1 | //! Fully type-check project and print various stats, like the number of type |
2 | //! errors. | 2 | //! errors. |
3 | 3 | ||
4 | use std::{collections::HashSet, fmt::Write, path::Path, time::Instant}; | 4 | use std::{collections::HashSet, path::Path, time::Instant}; |
5 | 5 | ||
6 | use hir::{ | 6 | use hir::{ |
7 | db::{AstDatabase, DefDatabase, HirDatabase}, | 7 | db::{AstDatabase, DefDatabase, HirDatabase}, |
@@ -13,6 +13,7 @@ use itertools::Itertools; | |||
13 | use ra_db::SourceDatabaseExt; | 13 | use ra_db::SourceDatabaseExt; |
14 | use ra_syntax::AstNode; | 14 | use ra_syntax::AstNode; |
15 | use rand::{seq::SliceRandom, thread_rng}; | 15 | use rand::{seq::SliceRandom, thread_rng}; |
16 | use stdx::format_to; | ||
16 | 17 | ||
17 | use crate::cli::{load_cargo::load_cargo, progress_report::ProgressReport, Result, Verbosity}; | 18 | use crate::cli::{load_cargo::load_cargo, progress_report::ProgressReport, Result, Verbosity}; |
18 | 19 | ||
@@ -128,7 +129,7 @@ pub fn analysis_stats( | |||
128 | let original_file = src.file_id.original_file(db); | 129 | let original_file = src.file_id.original_file(db); |
129 | let path = db.file_relative_path(original_file); | 130 | let path = db.file_relative_path(original_file); |
130 | let syntax_range = src.value.syntax().text_range(); | 131 | let syntax_range = src.value.syntax().text_range(); |
131 | write!(msg, " ({:?} {})", path, syntax_range).unwrap(); | 132 | format_to!(msg, " ({:?} {})", path, syntax_range); |
132 | } | 133 | } |
133 | if verbosity.is_spammy() { | 134 | if verbosity.is_spammy() { |
134 | bar.println(msg.to_string()); | 135 | bar.println(msg.to_string()); |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index 1033d6de9..12f8ca297 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -3,7 +3,6 @@ | |||
3 | //! `ra_ide` crate. | 3 | //! `ra_ide` crate. |
4 | 4 | ||
5 | use std::{ | 5 | use std::{ |
6 | fmt::Write as _, | ||
7 | io::Write as _, | 6 | io::Write as _, |
8 | process::{self, Stdio}, | 7 | process::{self, Stdio}, |
9 | }; | 8 | }; |
@@ -28,6 +27,7 @@ use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit}; | |||
28 | use rustc_hash::FxHashMap; | 27 | use rustc_hash::FxHashMap; |
29 | use serde::{Deserialize, Serialize}; | 28 | use serde::{Deserialize, Serialize}; |
30 | use serde_json::to_value; | 29 | use serde_json::to_value; |
30 | use stdx::format_to; | ||
31 | 31 | ||
32 | use crate::{ | 32 | use crate::{ |
33 | cargo_target_spec::CargoTargetSpec, | 33 | cargo_target_spec::CargoTargetSpec, |
@@ -46,11 +46,11 @@ use crate::{ | |||
46 | pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> { | 46 | pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> { |
47 | let _p = profile("handle_analyzer_status"); | 47 | let _p = profile("handle_analyzer_status"); |
48 | let mut buf = world.status(); | 48 | let mut buf = world.status(); |
49 | writeln!(buf, "\n\nrequests:").unwrap(); | 49 | format_to!(buf, "\n\nrequests:"); |
50 | let requests = world.latest_requests.read(); | 50 | let requests = world.latest_requests.read(); |
51 | for (is_last, r) in requests.iter() { | 51 | for (is_last, r) in requests.iter() { |
52 | let mark = if is_last { "*" } else { " " }; | 52 | let mark = if is_last { "*" } else { " " }; |
53 | writeln!(buf, "{}{:4} {:<36}{}ms", mark, r.id, r.method, r.duration.as_millis()).unwrap(); | 53 | format_to!(buf, "{}{:4} {:<36}{}ms", mark, r.id, r.method, r.duration.as_millis()); |
54 | } | 54 | } |
55 | Ok(buf) | 55 | Ok(buf) |
56 | } | 56 | } |
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index de85bb017..64a7b907e 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs | |||
@@ -19,6 +19,7 @@ use ra_ide::{ | |||
19 | use ra_project_model::{get_rustc_cfg_options, ProcMacroClient, ProjectWorkspace}; | 19 | use ra_project_model::{get_rustc_cfg_options, ProcMacroClient, ProjectWorkspace}; |
20 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; | 20 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; |
21 | use relative_path::RelativePathBuf; | 21 | use relative_path::RelativePathBuf; |
22 | use stdx::format_to; | ||
22 | 23 | ||
23 | use crate::{ | 24 | use crate::{ |
24 | diagnostics::{CheckFixes, DiagnosticCollection}, | 25 | diagnostics::{CheckFixes, DiagnosticCollection}, |
@@ -319,23 +320,23 @@ impl WorldSnapshot { | |||
319 | } | 320 | } |
320 | 321 | ||
321 | pub fn status(&self) -> String { | 322 | pub fn status(&self) -> String { |
322 | let mut res = String::new(); | 323 | let mut buf = String::new(); |
323 | if self.workspaces.is_empty() { | 324 | if self.workspaces.is_empty() { |
324 | res.push_str("no workspaces\n") | 325 | buf.push_str("no workspaces\n") |
325 | } else { | 326 | } else { |
326 | res.push_str("workspaces:\n"); | 327 | buf.push_str("workspaces:\n"); |
327 | for w in self.workspaces.iter() { | 328 | for w in self.workspaces.iter() { |
328 | res += &format!("{} packages loaded\n", w.n_packages()); | 329 | format_to!(buf, "{} packages loaded\n", w.n_packages()); |
329 | } | 330 | } |
330 | } | 331 | } |
331 | res.push_str("\nanalysis:\n"); | 332 | buf.push_str("\nanalysis:\n"); |
332 | res.push_str( | 333 | buf.push_str( |
333 | &self | 334 | &self |
334 | .analysis | 335 | .analysis |
335 | .status() | 336 | .status() |
336 | .unwrap_or_else(|_| "Analysis retrieval was cancelled".to_owned()), | 337 | .unwrap_or_else(|_| "Analysis retrieval was cancelled".to_owned()), |
337 | ); | 338 | ); |
338 | res | 339 | buf |
339 | } | 340 | } |
340 | 341 | ||
341 | pub fn workspace_root_for(&self, file_id: FileId) -> Option<&Path> { | 342 | pub fn workspace_root_for(&self, file_id: FileId) -> Option<&Path> { |
diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml new file mode 100644 index 000000000..f9e380c10 --- /dev/null +++ b/crates/stdx/Cargo.toml | |||
@@ -0,0 +1,11 @@ | |||
1 | [package] | ||
2 | name = "stdx" | ||
3 | version = "0.1.0" | ||
4 | authors = ["rust-analyzer developers"] | ||
5 | edition = "2018" | ||
6 | |||
7 | [lib] | ||
8 | doctest = false | ||
9 | |||
10 | [dependencies] | ||
11 | # Think twice before adding anything here | ||
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs new file mode 100644 index 000000000..8492c17af --- /dev/null +++ b/crates/stdx/src/lib.rs | |||
@@ -0,0 +1,75 @@ | |||
1 | //! Missing batteries for standard libraries. | ||
2 | |||
3 | use std::{cell::Cell, fmt}; | ||
4 | |||
5 | /// Appends formatted string to a `String`. | ||
6 | #[macro_export] | ||
7 | macro_rules! format_to { | ||
8 | (&buf:expr) => (); | ||
9 | ($buf:expr, $lit:literal $($arg:tt)*) => { | ||
10 | { use ::std::fmt::Write as _; let _ = ::std::write!($buf, $lit $($arg)*); } | ||
11 | }; | ||
12 | } | ||
13 | |||
14 | pub trait SepBy: Sized { | ||
15 | /// Returns an `impl fmt::Display`, which joins elements via a separator. | ||
16 | fn sep_by<'a>(self, sep: &'a str) -> SepByBuilder<'a, Self>; | ||
17 | } | ||
18 | |||
19 | impl<I> SepBy for I | ||
20 | where | ||
21 | I: Iterator, | ||
22 | I::Item: fmt::Display, | ||
23 | { | ||
24 | fn sep_by<'a>(self, sep: &'a str) -> SepByBuilder<'a, Self> { | ||
25 | SepByBuilder::new(sep, self) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | pub struct SepByBuilder<'a, I> { | ||
30 | sep: &'a str, | ||
31 | prefix: &'a str, | ||
32 | suffix: &'a str, | ||
33 | iter: Cell<Option<I>>, | ||
34 | } | ||
35 | |||
36 | impl<'a, I> SepByBuilder<'a, I> { | ||
37 | fn new(sep: &'a str, iter: I) -> SepByBuilder<'a, I> { | ||
38 | SepByBuilder { sep, prefix: "", suffix: "", iter: Cell::new(Some(iter)) } | ||
39 | } | ||
40 | |||
41 | pub fn prefix(mut self, prefix: &'a str) -> Self { | ||
42 | self.prefix = prefix; | ||
43 | self | ||
44 | } | ||
45 | |||
46 | pub fn suffix(mut self, suffix: &'a str) -> Self { | ||
47 | self.suffix = suffix; | ||
48 | self | ||
49 | } | ||
50 | |||
51 | /// Set both suffix and prefix. | ||
52 | pub fn surround_with(self, prefix: &'a str, suffix: &'a str) -> Self { | ||
53 | self.prefix(prefix).suffix(suffix) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | impl<I> fmt::Display for SepByBuilder<'_, I> | ||
58 | where | ||
59 | I: Iterator, | ||
60 | I::Item: fmt::Display, | ||
61 | { | ||
62 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
63 | f.write_str(self.prefix)?; | ||
64 | let mut first = true; | ||
65 | for item in self.iter.take().unwrap() { | ||
66 | if !first { | ||
67 | f.write_str(self.sep)?; | ||
68 | } | ||
69 | first = false; | ||
70 | fmt::Display::fmt(&item, f)?; | ||
71 | } | ||
72 | f.write_str(self.suffix)?; | ||
73 | Ok(()) | ||
74 | } | ||
75 | } | ||