diff options
-rw-r--r-- | Cargo.lock | 75 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/extract_variable.rs | 103 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/fix_visibility.rs | 90 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_scope.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 72 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests.rs | 130 | ||||
-rw-r--r-- | crates/ra_hir_def/src/visibility.rs | 41 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 22 | ||||
-rw-r--r-- | crates/ra_prof/Cargo.toml | 10 | ||||
-rw-r--r-- | crates/ra_prof/src/lib.rs | 10 | ||||
-rw-r--r-- | crates/ra_prof/src/memory_usage.rs | 21 | ||||
-rw-r--r-- | crates/rust-analyzer/Cargo.toml | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/args.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/main.rs | 4 | ||||
-rw-r--r-- | docs/dev/README.md | 8 | ||||
-rw-r--r-- | xtask/src/dist.rs | 2 | ||||
-rw-r--r-- | xtask/src/install.rs | 2 | ||||
-rw-r--r-- | xtask/src/main.rs | 12 |
19 files changed, 428 insertions, 214 deletions
diff --git a/Cargo.lock b/Cargo.lock index cf4de8bbe..280d97432 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -216,12 +216,12 @@ dependencies = [ | |||
216 | 216 | ||
217 | [[package]] | 217 | [[package]] |
218 | name = "crossbeam-channel" | 218 | name = "crossbeam-channel" |
219 | version = "0.4.2" | 219 | version = "0.4.3" |
220 | source = "registry+https://github.com/rust-lang/crates.io-index" | 220 | source = "registry+https://github.com/rust-lang/crates.io-index" |
221 | checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" | 221 | checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6" |
222 | dependencies = [ | 222 | dependencies = [ |
223 | "cfg-if", | ||
223 | "crossbeam-utils", | 224 | "crossbeam-utils", |
224 | "maybe-uninit", | ||
225 | ] | 225 | ] |
226 | 226 | ||
227 | [[package]] | 227 | [[package]] |
@@ -360,12 +360,6 @@ dependencies = [ | |||
360 | ] | 360 | ] |
361 | 361 | ||
362 | [[package]] | 362 | [[package]] |
363 | name = "fs_extra" | ||
364 | version = "1.1.0" | ||
365 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
366 | checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" | ||
367 | |||
368 | [[package]] | ||
369 | name = "fsevent" | 363 | name = "fsevent" |
370 | version = "2.0.2" | 364 | version = "2.0.2" |
371 | source = "registry+https://github.com/rust-lang/crates.io-index" | 365 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -542,38 +536,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
542 | checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" | 536 | checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" |
543 | 537 | ||
544 | [[package]] | 538 | [[package]] |
545 | name = "jemalloc-ctl" | ||
546 | version = "0.3.3" | ||
547 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
548 | checksum = "c502a5ff9dd2924f1ed32ba96e3b65735d837b4bfd978d3161b1702e66aca4b7" | ||
549 | dependencies = [ | ||
550 | "jemalloc-sys", | ||
551 | "libc", | ||
552 | "paste", | ||
553 | ] | ||
554 | |||
555 | [[package]] | ||
556 | name = "jemalloc-sys" | ||
557 | version = "0.3.2" | ||
558 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
559 | checksum = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45" | ||
560 | dependencies = [ | ||
561 | "cc", | ||
562 | "fs_extra", | ||
563 | "libc", | ||
564 | ] | ||
565 | |||
566 | [[package]] | ||
567 | name = "jemallocator" | ||
568 | version = "0.3.2" | ||
569 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
570 | checksum = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69" | ||
571 | dependencies = [ | ||
572 | "jemalloc-sys", | ||
573 | "libc", | ||
574 | ] | ||
575 | |||
576 | [[package]] | ||
577 | name = "jod-thread" | 539 | name = "jod-thread" |
578 | version = "0.1.2" | 540 | version = "0.1.2" |
579 | source = "registry+https://github.com/rust-lang/crates.io-index" | 541 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -875,25 +837,6 @@ dependencies = [ | |||
875 | ] | 837 | ] |
876 | 838 | ||
877 | [[package]] | 839 | [[package]] |
878 | name = "paste" | ||
879 | version = "0.1.18" | ||
880 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
881 | checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" | ||
882 | dependencies = [ | ||
883 | "paste-impl", | ||
884 | "proc-macro-hack", | ||
885 | ] | ||
886 | |||
887 | [[package]] | ||
888 | name = "paste-impl" | ||
889 | version = "0.1.18" | ||
890 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
891 | checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" | ||
892 | dependencies = [ | ||
893 | "proc-macro-hack", | ||
894 | ] | ||
895 | |||
896 | [[package]] | ||
897 | name = "paths" | 840 | name = "paths" |
898 | version = "0.1.0" | 841 | version = "0.1.0" |
899 | 842 | ||
@@ -932,12 +875,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
932 | checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" | 875 | checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" |
933 | 876 | ||
934 | [[package]] | 877 | [[package]] |
935 | name = "proc-macro-hack" | ||
936 | version = "0.5.16" | ||
937 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
938 | checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" | ||
939 | |||
940 | [[package]] | ||
941 | name = "proc-macro2" | 878 | name = "proc-macro2" |
942 | version = "1.0.19" | 879 | version = "1.0.19" |
943 | source = "registry+https://github.com/rust-lang/crates.io-index" | 880 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1198,9 +1135,8 @@ name = "ra_prof" | |||
1198 | version = "0.1.0" | 1135 | version = "0.1.0" |
1199 | dependencies = [ | 1136 | dependencies = [ |
1200 | "backtrace", | 1137 | "backtrace", |
1201 | "jemalloc-ctl", | 1138 | "cfg-if", |
1202 | "jemallocator", | 1139 | "libc", |
1203 | "mimalloc", | ||
1204 | "once_cell", | 1140 | "once_cell", |
1205 | "ra_arena", | 1141 | "ra_arena", |
1206 | ] | 1142 | ] |
@@ -1425,6 +1361,7 @@ dependencies = [ | |||
1425 | "log", | 1361 | "log", |
1426 | "lsp-server", | 1362 | "lsp-server", |
1427 | "lsp-types", | 1363 | "lsp-types", |
1364 | "mimalloc", | ||
1428 | "parking_lot", | 1365 | "parking_lot", |
1429 | "pico-args", | 1366 | "pico-args", |
1430 | "ra_cfg", | 1367 | "ra_cfg", |
diff --git a/crates/ra_assists/src/handlers/extract_variable.rs b/crates/ra_assists/src/handlers/extract_variable.rs index 481baf1a4..098adf078 100644 --- a/crates/ra_assists/src/handlers/extract_variable.rs +++ b/crates/ra_assists/src/handlers/extract_variable.rs | |||
@@ -2,7 +2,6 @@ use ra_syntax::{ | |||
2 | ast::{self, AstNode}, | 2 | ast::{self, AstNode}, |
3 | SyntaxKind::{ | 3 | SyntaxKind::{ |
4 | BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, | 4 | BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, |
5 | WHITESPACE, | ||
6 | }, | 5 | }, |
7 | SyntaxNode, | 6 | SyntaxNode, |
8 | }; | 7 | }; |
@@ -36,22 +35,20 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
36 | mark::hit!(extract_var_in_comment_is_not_applicable); | 35 | mark::hit!(extract_var_in_comment_is_not_applicable); |
37 | return None; | 36 | return None; |
38 | } | 37 | } |
39 | let expr = node.ancestors().find_map(valid_target_expr)?; | 38 | let to_extract = node.ancestors().find_map(valid_target_expr)?; |
40 | let (anchor_stmt, wrap_in_block) = anchor_stmt(expr.clone())?; | 39 | let anchor = Anchor::from(&to_extract)?; |
41 | let indent = anchor_stmt.prev_sibling_or_token()?.as_token()?.clone(); | 40 | let indent = anchor.syntax().prev_sibling_or_token()?.as_token()?.clone(); |
42 | if indent.kind() != WHITESPACE { | 41 | let target = to_extract.syntax().text_range(); |
43 | return None; | ||
44 | } | ||
45 | let target = expr.syntax().text_range(); | ||
46 | acc.add( | 42 | acc.add( |
47 | AssistId("extract_variable", AssistKind::RefactorExtract), | 43 | AssistId("extract_variable", AssistKind::RefactorExtract), |
48 | "Extract into variable", | 44 | "Extract into variable", |
49 | target, | 45 | target, |
50 | move |edit| { | 46 | move |edit| { |
51 | let field_shorthand = match expr.syntax().parent().and_then(ast::RecordField::cast) { | 47 | let field_shorthand = |
52 | Some(field) => field.name_ref(), | 48 | match to_extract.syntax().parent().and_then(ast::RecordField::cast) { |
53 | None => None, | 49 | Some(field) => field.name_ref(), |
54 | }; | 50 | None => None, |
51 | }; | ||
55 | 52 | ||
56 | let mut buf = String::new(); | 53 | let mut buf = String::new(); |
57 | 54 | ||
@@ -60,26 +57,20 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
60 | None => "var_name".to_string(), | 57 | None => "var_name".to_string(), |
61 | }; | 58 | }; |
62 | let expr_range = match &field_shorthand { | 59 | let expr_range = match &field_shorthand { |
63 | Some(it) => it.syntax().text_range().cover(expr.syntax().text_range()), | 60 | Some(it) => it.syntax().text_range().cover(to_extract.syntax().text_range()), |
64 | None => expr.syntax().text_range(), | 61 | None => to_extract.syntax().text_range(), |
65 | }; | 62 | }; |
66 | 63 | ||
67 | if wrap_in_block { | 64 | if let Anchor::WrapInBlock(_) = anchor { |
68 | format_to!(buf, "{{ let {} = ", var_name); | 65 | format_to!(buf, "{{ let {} = ", var_name); |
69 | } else { | 66 | } else { |
70 | format_to!(buf, "let {} = ", var_name); | 67 | format_to!(buf, "let {} = ", var_name); |
71 | }; | 68 | }; |
72 | format_to!(buf, "{}", expr.syntax()); | 69 | format_to!(buf, "{}", to_extract.syntax()); |
73 | 70 | ||
74 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); | 71 | if let Anchor::Replace(stmt) = anchor { |
75 | let is_full_stmt = if let Some(expr_stmt) = &full_stmt { | ||
76 | Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) | ||
77 | } else { | ||
78 | false | ||
79 | }; | ||
80 | if is_full_stmt { | ||
81 | mark::hit!(test_extract_var_expr_stmt); | 72 | mark::hit!(test_extract_var_expr_stmt); |
82 | if full_stmt.unwrap().semicolon_token().is_none() { | 73 | if stmt.semicolon_token().is_none() { |
83 | buf.push_str(";"); | 74 | buf.push_str(";"); |
84 | } | 75 | } |
85 | match ctx.config.snippet_cap { | 76 | match ctx.config.snippet_cap { |
@@ -107,7 +98,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
107 | } | 98 | } |
108 | 99 | ||
109 | edit.replace(expr_range, var_name.clone()); | 100 | edit.replace(expr_range, var_name.clone()); |
110 | let offset = anchor_stmt.text_range().start(); | 101 | let offset = anchor.syntax().text_range().start(); |
111 | match ctx.config.snippet_cap { | 102 | match ctx.config.snippet_cap { |
112 | Some(cap) => { | 103 | Some(cap) => { |
113 | let snip = | 104 | let snip = |
@@ -117,8 +108,8 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
117 | None => edit.insert(offset, buf), | 108 | None => edit.insert(offset, buf), |
118 | } | 109 | } |
119 | 110 | ||
120 | if wrap_in_block { | 111 | if let Anchor::WrapInBlock(_) = anchor { |
121 | edit.insert(anchor_stmt.text_range().end(), " }"); | 112 | edit.insert(anchor.syntax().text_range().end(), " }"); |
122 | } | 113 | } |
123 | }, | 114 | }, |
124 | ) | 115 | ) |
@@ -138,32 +129,48 @@ fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> { | |||
138 | } | 129 | } |
139 | } | 130 | } |
140 | 131 | ||
141 | /// Returns the syntax node which will follow the freshly extractd var | 132 | enum Anchor { |
142 | /// and a boolean indicating whether we have to wrap it within a { } block | 133 | Before(SyntaxNode), |
143 | /// to produce correct code. | 134 | Replace(ast::ExprStmt), |
144 | /// It can be a statement, the last in a block expression or a wanna be block | 135 | WrapInBlock(SyntaxNode), |
145 | /// expression like a lambda or match arm. | 136 | } |
146 | fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> { | 137 | |
147 | expr.syntax().ancestors().find_map(|node| { | 138 | impl Anchor { |
148 | if let Some(expr) = node.parent().and_then(ast::BlockExpr::cast).and_then(|it| it.expr()) { | 139 | fn from(to_extract: &ast::Expr) -> Option<Anchor> { |
149 | if expr.syntax() == &node { | 140 | to_extract.syntax().ancestors().find_map(|node| { |
150 | mark::hit!(test_extract_var_last_expr); | 141 | if let Some(expr) = |
151 | return Some((node, false)); | 142 | node.parent().and_then(ast::BlockExpr::cast).and_then(|it| it.expr()) |
143 | { | ||
144 | if expr.syntax() == &node { | ||
145 | mark::hit!(test_extract_var_last_expr); | ||
146 | return Some(Anchor::Before(node)); | ||
147 | } | ||
152 | } | 148 | } |
153 | } | ||
154 | 149 | ||
155 | if let Some(parent) = node.parent() { | 150 | if let Some(parent) = node.parent() { |
156 | if parent.kind() == MATCH_ARM || parent.kind() == LAMBDA_EXPR { | 151 | if parent.kind() == MATCH_ARM || parent.kind() == LAMBDA_EXPR { |
157 | return Some((node, true)); | 152 | return Some(Anchor::WrapInBlock(node)); |
153 | } | ||
158 | } | 154 | } |
159 | } | ||
160 | 155 | ||
161 | if ast::Stmt::cast(node.clone()).is_some() { | 156 | if let Some(stmt) = ast::Stmt::cast(node.clone()) { |
162 | return Some((node, false)); | 157 | if let ast::Stmt::ExprStmt(stmt) = stmt { |
163 | } | 158 | if stmt.expr().as_ref() == Some(to_extract) { |
159 | return Some(Anchor::Replace(stmt)); | ||
160 | } | ||
161 | } | ||
162 | return Some(Anchor::Before(node)); | ||
163 | } | ||
164 | None | ||
165 | }) | ||
166 | } | ||
164 | 167 | ||
165 | None | 168 | fn syntax(&self) -> &SyntaxNode { |
166 | }) | 169 | match self { |
170 | Anchor::Before(it) | Anchor::WrapInBlock(it) => it, | ||
171 | Anchor::Replace(stmt) => stmt.syntax(), | ||
172 | } | ||
173 | } | ||
167 | } | 174 | } |
168 | 175 | ||
169 | #[cfg(test)] | 176 | #[cfg(test)] |
diff --git a/crates/ra_assists/src/handlers/fix_visibility.rs b/crates/ra_assists/src/handlers/fix_visibility.rs index e212557c8..1d3ed3c6a 100644 --- a/crates/ra_assists/src/handlers/fix_visibility.rs +++ b/crates/ra_assists/src/handlers/fix_visibility.rs | |||
@@ -3,6 +3,7 @@ use ra_db::FileId; | |||
3 | use ra_syntax::{ast, AstNode, TextRange, TextSize}; | 3 | use ra_syntax::{ast, AstNode, TextRange, TextSize}; |
4 | 4 | ||
5 | use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; | 5 | use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; |
6 | use ast::VisibilityOwner; | ||
6 | 7 | ||
7 | // FIXME: this really should be a fix for diagnostic, rather than an assist. | 8 | // FIXME: this really should be a fix for diagnostic, rather than an assist. |
8 | 9 | ||
@@ -48,7 +49,8 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O | |||
48 | return None; | 49 | return None; |
49 | }; | 50 | }; |
50 | 51 | ||
51 | let (offset, target, target_file, target_name) = target_data_for_def(ctx.db(), def)?; | 52 | let (offset, current_visibility, target, target_file, target_name) = |
53 | target_data_for_def(ctx.db(), def)?; | ||
52 | 54 | ||
53 | let missing_visibility = | 55 | let missing_visibility = |
54 | if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" }; | 56 | if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" }; |
@@ -61,8 +63,20 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O | |||
61 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { | 63 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { |
62 | builder.edit_file(target_file); | 64 | builder.edit_file(target_file); |
63 | match ctx.config.snippet_cap { | 65 | match ctx.config.snippet_cap { |
64 | Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | 66 | Some(cap) => match current_visibility { |
65 | None => builder.insert(offset, format!("{} ", missing_visibility)), | 67 | Some(current_visibility) => builder.replace_snippet( |
68 | cap, | ||
69 | current_visibility.syntax().text_range(), | ||
70 | format!("$0{}", missing_visibility), | ||
71 | ), | ||
72 | None => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | ||
73 | }, | ||
74 | None => match current_visibility { | ||
75 | Some(current_visibility) => { | ||
76 | builder.replace(current_visibility.syntax().text_range(), missing_visibility) | ||
77 | } | ||
78 | None => builder.insert(offset, format!("{} ", missing_visibility)), | ||
79 | }, | ||
66 | } | 80 | } |
67 | }) | 81 | }) |
68 | } | 82 | } |
@@ -82,14 +96,14 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> | |||
82 | let target_module = parent.module(ctx.db()); | 96 | let target_module = parent.module(ctx.db()); |
83 | 97 | ||
84 | let in_file_source = record_field_def.source(ctx.db()); | 98 | let in_file_source = record_field_def.source(ctx.db()); |
85 | let (offset, target) = match in_file_source.value { | 99 | let (offset, current_visibility, target) = match in_file_source.value { |
86 | hir::FieldSource::Named(it) => { | 100 | hir::FieldSource::Named(it) => { |
87 | let s = it.syntax(); | 101 | let s = it.syntax(); |
88 | (vis_offset(s), s.text_range()) | 102 | (vis_offset(s), it.visibility(), s.text_range()) |
89 | } | 103 | } |
90 | hir::FieldSource::Pos(it) => { | 104 | hir::FieldSource::Pos(it) => { |
91 | let s = it.syntax(); | 105 | let s = it.syntax(); |
92 | (vis_offset(s), s.text_range()) | 106 | (vis_offset(s), it.visibility(), s.text_range()) |
93 | } | 107 | } |
94 | }; | 108 | }; |
95 | 109 | ||
@@ -104,8 +118,20 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> | |||
104 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { | 118 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { |
105 | builder.edit_file(target_file); | 119 | builder.edit_file(target_file); |
106 | match ctx.config.snippet_cap { | 120 | match ctx.config.snippet_cap { |
107 | Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | 121 | Some(cap) => match current_visibility { |
108 | None => builder.insert(offset, format!("{} ", missing_visibility)), | 122 | Some(current_visibility) => builder.replace_snippet( |
123 | cap, | ||
124 | dbg!(current_visibility.syntax()).text_range(), | ||
125 | format!("$0{}", missing_visibility), | ||
126 | ), | ||
127 | None => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | ||
128 | }, | ||
129 | None => match current_visibility { | ||
130 | Some(current_visibility) => { | ||
131 | builder.replace(current_visibility.syntax().text_range(), missing_visibility) | ||
132 | } | ||
133 | None => builder.insert(offset, format!("{} ", missing_visibility)), | ||
134 | }, | ||
109 | } | 135 | } |
110 | }) | 136 | }) |
111 | } | 137 | } |
@@ -113,24 +139,30 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> | |||
113 | fn target_data_for_def( | 139 | fn target_data_for_def( |
114 | db: &dyn HirDatabase, | 140 | db: &dyn HirDatabase, |
115 | def: hir::ModuleDef, | 141 | def: hir::ModuleDef, |
116 | ) -> Option<(TextSize, TextRange, FileId, Option<hir::Name>)> { | 142 | ) -> Option<(TextSize, Option<ast::Visibility>, TextRange, FileId, Option<hir::Name>)> { |
117 | fn offset_target_and_file_id<S, Ast>( | 143 | fn offset_target_and_file_id<S, Ast>( |
118 | db: &dyn HirDatabase, | 144 | db: &dyn HirDatabase, |
119 | x: S, | 145 | x: S, |
120 | ) -> (TextSize, TextRange, FileId) | 146 | ) -> (TextSize, Option<ast::Visibility>, TextRange, FileId) |
121 | where | 147 | where |
122 | S: HasSource<Ast = Ast>, | 148 | S: HasSource<Ast = Ast>, |
123 | Ast: AstNode, | 149 | Ast: AstNode + ast::VisibilityOwner, |
124 | { | 150 | { |
125 | let source = x.source(db); | 151 | let source = x.source(db); |
126 | let in_file_syntax = source.syntax(); | 152 | let in_file_syntax = source.syntax(); |
127 | let file_id = in_file_syntax.file_id; | 153 | let file_id = in_file_syntax.file_id; |
128 | let syntax = in_file_syntax.value; | 154 | let syntax = in_file_syntax.value; |
129 | (vis_offset(syntax), syntax.text_range(), file_id.original_file(db.upcast())) | 155 | let current_visibility = source.value.visibility(); |
156 | ( | ||
157 | vis_offset(syntax), | ||
158 | current_visibility, | ||
159 | syntax.text_range(), | ||
160 | file_id.original_file(db.upcast()), | ||
161 | ) | ||
130 | } | 162 | } |
131 | 163 | ||
132 | let target_name; | 164 | let target_name; |
133 | let (offset, target, target_file) = match def { | 165 | let (offset, current_visibility, target, target_file) = match def { |
134 | hir::ModuleDef::Function(f) => { | 166 | hir::ModuleDef::Function(f) => { |
135 | target_name = Some(f.name(db)); | 167 | target_name = Some(f.name(db)); |
136 | offset_target_and_file_id(db, f) | 168 | offset_target_and_file_id(db, f) |
@@ -164,13 +196,13 @@ fn target_data_for_def( | |||
164 | let in_file_source = m.declaration_source(db)?; | 196 | let in_file_source = m.declaration_source(db)?; |
165 | let file_id = in_file_source.file_id.original_file(db.upcast()); | 197 | let file_id = in_file_source.file_id.original_file(db.upcast()); |
166 | let syntax = in_file_source.value.syntax(); | 198 | let syntax = in_file_source.value.syntax(); |
167 | (vis_offset(syntax), syntax.text_range(), file_id) | 199 | (vis_offset(syntax), in_file_source.value.visibility(), syntax.text_range(), file_id) |
168 | } | 200 | } |
169 | // Enum variants can't be private, we can't modify builtin types | 201 | // Enum variants can't be private, we can't modify builtin types |
170 | hir::ModuleDef::EnumVariant(_) | hir::ModuleDef::BuiltinType(_) => return None, | 202 | hir::ModuleDef::EnumVariant(_) | hir::ModuleDef::BuiltinType(_) => return None, |
171 | }; | 203 | }; |
172 | 204 | ||
173 | Some((offset, target, target_file, target_name)) | 205 | Some((offset, current_visibility, target, target_file, target_name)) |
174 | } | 206 | } |
175 | 207 | ||
176 | #[cfg(test)] | 208 | #[cfg(test)] |
@@ -523,6 +555,34 @@ struct Bar; | |||
523 | } | 555 | } |
524 | 556 | ||
525 | #[test] | 557 | #[test] |
558 | fn replaces_pub_crate_with_pub() { | ||
559 | check_assist( | ||
560 | fix_visibility, | ||
561 | r" | ||
562 | //- /main.rs crate:a deps:foo | ||
563 | foo::Bar<|> | ||
564 | //- /lib.rs crate:foo | ||
565 | pub(crate) struct Bar; | ||
566 | ", | ||
567 | r"$0pub struct Bar; | ||
568 | ", | ||
569 | ); | ||
570 | check_assist( | ||
571 | fix_visibility, | ||
572 | r" | ||
573 | //- /main.rs crate:a deps:foo | ||
574 | fn main() { | ||
575 | foo::Foo { <|>bar: () }; | ||
576 | } | ||
577 | //- /lib.rs crate:foo | ||
578 | pub struct Foo { pub(crate) bar: () } | ||
579 | ", | ||
580 | r"pub struct Foo { $0pub bar: () } | ||
581 | ", | ||
582 | ); | ||
583 | } | ||
584 | |||
585 | #[test] | ||
526 | #[ignore] | 586 | #[ignore] |
527 | // FIXME handle reexports properly | 587 | // FIXME handle reexports properly |
528 | fn fix_visibility_of_reexport() { | 588 | fn fix_visibility_of_reexport() { |
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index beeb98559..8fee4b15e 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -36,6 +36,8 @@ pub struct ItemScope { | |||
36 | 36 | ||
37 | defs: Vec<ModuleDefId>, | 37 | defs: Vec<ModuleDefId>, |
38 | impls: Vec<ImplId>, | 38 | impls: Vec<ImplId>, |
39 | /// Traits imported via `use Trait as _;`. | ||
40 | unnamed_trait_imports: FxHashMap<TraitId, Visibility>, | ||
39 | /// Macros visible in current module in legacy textual scope | 41 | /// Macros visible in current module in legacy textual scope |
40 | /// | 42 | /// |
41 | /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. | 43 | /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. |
@@ -126,10 +128,13 @@ impl ItemScope { | |||
126 | } | 128 | } |
127 | 129 | ||
128 | pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { | 130 | pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { |
129 | self.types.values().filter_map(|(def, _)| match def { | 131 | self.types |
130 | ModuleDefId::TraitId(t) => Some(*t), | 132 | .values() |
131 | _ => None, | 133 | .filter_map(|(def, _)| match def { |
132 | }) | 134 | ModuleDefId::TraitId(t) => Some(*t), |
135 | _ => None, | ||
136 | }) | ||
137 | .chain(self.unnamed_trait_imports.keys().copied()) | ||
133 | } | 138 | } |
134 | 139 | ||
135 | pub(crate) fn define_def(&mut self, def: ModuleDefId) { | 140 | pub(crate) fn define_def(&mut self, def: ModuleDefId) { |
@@ -148,6 +153,14 @@ impl ItemScope { | |||
148 | self.legacy_macros.insert(name, mac); | 153 | self.legacy_macros.insert(name, mac); |
149 | } | 154 | } |
150 | 155 | ||
156 | pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> { | ||
157 | self.unnamed_trait_imports.get(&tr).copied() | ||
158 | } | ||
159 | |||
160 | pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) { | ||
161 | self.unnamed_trait_imports.insert(tr, vis); | ||
162 | } | ||
163 | |||
151 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { | 164 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { |
152 | let mut changed = false; | 165 | let mut changed = false; |
153 | 166 | ||
@@ -241,8 +254,12 @@ impl ItemScope { | |||
241 | changed | 254 | changed |
242 | } | 255 | } |
243 | 256 | ||
244 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a { | 257 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Option<Name>, PerNs)> + 'a { |
245 | self.entries().map(|(name, res)| (name.clone(), res)) | 258 | self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( |
259 | self.unnamed_trait_imports | ||
260 | .iter() | ||
261 | .map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), | ||
262 | ) | ||
246 | } | 263 | } |
247 | 264 | ||
248 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { | 265 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { |
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 5a9de3d3e..3d9b55a73 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -239,7 +239,7 @@ impl CrateDefMap { | |||
239 | entries.sort_by_key(|(name, _)| name.clone()); | 239 | entries.sort_by_key(|(name, _)| name.clone()); |
240 | 240 | ||
241 | for (name, def) in entries { | 241 | for (name, def) in entries { |
242 | format_to!(buf, "{}:", name); | 242 | format_to!(buf, "{}:", name.map_or("_".to_string(), |name| name.to_string())); |
243 | 243 | ||
244 | if def.types.is_some() { | 244 | if def.types.is_some() { |
245 | buf.push_str(" t"); | 245 | buf.push_str(" t"); |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d85a86c0a..a030cab47 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -310,7 +310,7 @@ impl DefCollector<'_> { | |||
310 | if export { | 310 | if export { |
311 | self.update( | 311 | self.update( |
312 | self.def_map.root, | 312 | self.def_map.root, |
313 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 313 | &[(Some(name), PerNs::macros(macro_, Visibility::Public))], |
314 | Visibility::Public, | 314 | Visibility::Public, |
315 | ImportType::Named, | 315 | ImportType::Named, |
316 | ); | 316 | ); |
@@ -336,7 +336,7 @@ impl DefCollector<'_> { | |||
336 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { | 336 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { |
337 | self.update( | 337 | self.update( |
338 | self.def_map.root, | 338 | self.def_map.root, |
339 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 339 | &[(Some(name), PerNs::macros(macro_, Visibility::Public))], |
340 | Visibility::Public, | 340 | Visibility::Public, |
341 | ImportType::Named, | 341 | ImportType::Named, |
342 | ); | 342 | ); |
@@ -534,7 +534,7 @@ impl DefCollector<'_> { | |||
534 | let name = variant_data.name.clone(); | 534 | let name = variant_data.name.clone(); |
535 | let variant = EnumVariantId { parent: e, local_id }; | 535 | let variant = EnumVariantId { parent: e, local_id }; |
536 | let res = PerNs::both(variant.into(), variant.into(), vis); | 536 | let res = PerNs::both(variant.into(), variant.into(), vis); |
537 | (name, res) | 537 | (Some(name), res) |
538 | }) | 538 | }) |
539 | .collect::<Vec<_>>(); | 539 | .collect::<Vec<_>>(); |
540 | self.update(module_id, &resolutions, vis, ImportType::Glob); | 540 | self.update(module_id, &resolutions, vis, ImportType::Glob); |
@@ -550,15 +550,15 @@ impl DefCollector<'_> { | |||
550 | match import.path.segments.last() { | 550 | match import.path.segments.last() { |
551 | Some(last_segment) => { | 551 | Some(last_segment) => { |
552 | let name = match &import.alias { | 552 | let name = match &import.alias { |
553 | Some(ImportAlias::Alias(name)) => name.clone(), | 553 | Some(ImportAlias::Alias(name)) => Some(name.clone()), |
554 | Some(ImportAlias::Underscore) => last_segment.clone(), // FIXME rust-analyzer#2736 | 554 | Some(ImportAlias::Underscore) => None, |
555 | None => last_segment.clone(), | 555 | None => Some(last_segment.clone()), |
556 | }; | 556 | }; |
557 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); | 557 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); |
558 | 558 | ||
559 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 | 559 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 |
560 | if import.is_extern_crate && module_id == self.def_map.root { | 560 | if import.is_extern_crate && module_id == self.def_map.root { |
561 | if let Some(def) = def.take_types() { | 561 | if let (Some(def), Some(name)) = (def.take_types(), name.as_ref()) { |
562 | self.def_map.extern_prelude.insert(name.clone(), def); | 562 | self.def_map.extern_prelude.insert(name.clone(), def); |
563 | } | 563 | } |
564 | } | 564 | } |
@@ -573,7 +573,7 @@ impl DefCollector<'_> { | |||
573 | fn update( | 573 | fn update( |
574 | &mut self, | 574 | &mut self, |
575 | module_id: LocalModuleId, | 575 | module_id: LocalModuleId, |
576 | resolutions: &[(Name, PerNs)], | 576 | resolutions: &[(Option<Name>, PerNs)], |
577 | vis: Visibility, | 577 | vis: Visibility, |
578 | import_type: ImportType, | 578 | import_type: ImportType, |
579 | ) { | 579 | ) { |
@@ -584,7 +584,7 @@ impl DefCollector<'_> { | |||
584 | fn update_recursive( | 584 | fn update_recursive( |
585 | &mut self, | 585 | &mut self, |
586 | module_id: LocalModuleId, | 586 | module_id: LocalModuleId, |
587 | resolutions: &[(Name, PerNs)], | 587 | resolutions: &[(Option<Name>, PerNs)], |
588 | // All resolutions are imported with this visibility; the visibilies in | 588 | // All resolutions are imported with this visibility; the visibilies in |
589 | // the `PerNs` values are ignored and overwritten | 589 | // the `PerNs` values are ignored and overwritten |
590 | vis: Visibility, | 590 | vis: Visibility, |
@@ -595,15 +595,51 @@ impl DefCollector<'_> { | |||
595 | // prevent stack overflows (but this shouldn't be possible) | 595 | // prevent stack overflows (but this shouldn't be possible) |
596 | panic!("infinite recursion in glob imports!"); | 596 | panic!("infinite recursion in glob imports!"); |
597 | } | 597 | } |
598 | let scope = &mut self.def_map.modules[module_id].scope; | ||
599 | let mut changed = false; | 598 | let mut changed = false; |
599 | |||
600 | for (name, res) in resolutions { | 600 | for (name, res) in resolutions { |
601 | changed |= scope.push_res_with_import( | 601 | match name { |
602 | &mut self.from_glob_import, | 602 | Some(name) => { |
603 | (module_id, name.clone()), | 603 | let scope = &mut self.def_map.modules[module_id].scope; |
604 | res.with_visibility(vis), | 604 | changed |= scope.push_res_with_import( |
605 | import_type, | 605 | &mut self.from_glob_import, |
606 | ); | 606 | (module_id, name.clone()), |
607 | res.with_visibility(vis), | ||
608 | import_type, | ||
609 | ); | ||
610 | } | ||
611 | None => { | ||
612 | let tr = match res.take_types() { | ||
613 | Some(ModuleDefId::TraitId(tr)) => tr, | ||
614 | Some(other) => { | ||
615 | log::debug!("non-trait `_` import of {:?}", other); | ||
616 | continue; | ||
617 | } | ||
618 | None => continue, | ||
619 | }; | ||
620 | let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr); | ||
621 | let should_update = match old_vis { | ||
622 | None => true, | ||
623 | Some(old_vis) => { | ||
624 | let max_vis = old_vis.max(vis, &self.def_map).unwrap_or_else(|| { | ||
625 | panic!("`Tr as _` imports with unrelated visibilities {:?} and {:?} (trait {:?})", old_vis, vis, tr); | ||
626 | }); | ||
627 | |||
628 | if max_vis == old_vis { | ||
629 | false | ||
630 | } else { | ||
631 | mark::hit!(upgrade_underscore_visibility); | ||
632 | true | ||
633 | } | ||
634 | } | ||
635 | }; | ||
636 | |||
637 | if should_update { | ||
638 | changed = true; | ||
639 | self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis); | ||
640 | } | ||
641 | } | ||
642 | } | ||
607 | } | 643 | } |
608 | 644 | ||
609 | if !changed { | 645 | if !changed { |
@@ -950,7 +986,7 @@ impl ModCollector<'_, '_> { | |||
950 | .unwrap_or(Visibility::Public); | 986 | .unwrap_or(Visibility::Public); |
951 | self.def_collector.update( | 987 | self.def_collector.update( |
952 | self.module_id, | 988 | self.module_id, |
953 | &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], | 989 | &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], |
954 | vis, | 990 | vis, |
955 | ImportType::Named, | 991 | ImportType::Named, |
956 | ) | 992 | ) |
@@ -1057,7 +1093,7 @@ impl ModCollector<'_, '_> { | |||
1057 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 1093 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
1058 | self.def_collector.update( | 1094 | self.def_collector.update( |
1059 | self.module_id, | 1095 | self.module_id, |
1060 | &[(name, PerNs::from_def(def, vis, false))], | 1096 | &[(Some(name), PerNs::from_def(def, vis, false))], |
1061 | vis, | 1097 | vis, |
1062 | ImportType::Named, | 1098 | ImportType::Named, |
1063 | ); | 1099 | ); |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 205d3528b..839b1de57 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -558,3 +558,133 @@ mod b { | |||
558 | "#]], | 558 | "#]], |
559 | ); | 559 | ); |
560 | } | 560 | } |
561 | |||
562 | #[test] | ||
563 | fn underscore_import() { | ||
564 | check( | ||
565 | r#" | ||
566 | //- /main.rs | ||
567 | use tr::Tr as _; | ||
568 | use tr::Tr2 as _; | ||
569 | |||
570 | mod tr { | ||
571 | pub trait Tr {} | ||
572 | pub trait Tr2 {} | ||
573 | } | ||
574 | "#, | ||
575 | expect![[r#" | ||
576 | crate | ||
577 | _: t | ||
578 | _: t | ||
579 | tr: t | ||
580 | |||
581 | crate::tr | ||
582 | Tr: t | ||
583 | Tr2: t | ||
584 | "#]], | ||
585 | ); | ||
586 | } | ||
587 | |||
588 | #[test] | ||
589 | fn underscore_reexport() { | ||
590 | check( | ||
591 | r#" | ||
592 | //- /main.rs | ||
593 | mod tr { | ||
594 | pub trait PubTr {} | ||
595 | pub trait PrivTr {} | ||
596 | } | ||
597 | mod reex { | ||
598 | use crate::tr::PrivTr as _; | ||
599 | pub use crate::tr::PubTr as _; | ||
600 | } | ||
601 | use crate::reex::*; | ||
602 | "#, | ||
603 | expect![[r#" | ||
604 | crate | ||
605 | _: t | ||
606 | reex: t | ||
607 | tr: t | ||
608 | |||
609 | crate::tr | ||
610 | PrivTr: t | ||
611 | PubTr: t | ||
612 | |||
613 | crate::reex | ||
614 | _: t | ||
615 | _: t | ||
616 | "#]], | ||
617 | ); | ||
618 | } | ||
619 | |||
620 | #[test] | ||
621 | fn underscore_pub_crate_reexport() { | ||
622 | mark::check!(upgrade_underscore_visibility); | ||
623 | check( | ||
624 | r#" | ||
625 | //- /main.rs crate:main deps:lib | ||
626 | use lib::*; | ||
627 | |||
628 | //- /lib.rs crate:lib | ||
629 | use tr::Tr as _; | ||
630 | pub use tr::Tr as _; | ||
631 | |||
632 | mod tr { | ||
633 | pub trait Tr {} | ||
634 | } | ||
635 | "#, | ||
636 | expect![[r#" | ||
637 | crate | ||
638 | _: t | ||
639 | "#]], | ||
640 | ); | ||
641 | } | ||
642 | |||
643 | #[test] | ||
644 | fn underscore_nontrait() { | ||
645 | check( | ||
646 | r#" | ||
647 | //- /main.rs | ||
648 | mod m { | ||
649 | pub struct Struct; | ||
650 | pub enum Enum {} | ||
651 | pub const CONST: () = (); | ||
652 | } | ||
653 | use crate::m::{Struct as _, Enum as _, CONST as _}; | ||
654 | "#, | ||
655 | expect![[r#" | ||
656 | crate | ||
657 | m: t | ||
658 | |||
659 | crate::m | ||
660 | CONST: v | ||
661 | Enum: t | ||
662 | Struct: t v | ||
663 | "#]], | ||
664 | ); | ||
665 | } | ||
666 | |||
667 | #[test] | ||
668 | fn underscore_name_conflict() { | ||
669 | check( | ||
670 | r#" | ||
671 | //- /main.rs | ||
672 | struct Tr; | ||
673 | |||
674 | use tr::Tr as _; | ||
675 | |||
676 | mod tr { | ||
677 | pub trait Tr {} | ||
678 | } | ||
679 | "#, | ||
680 | expect![[r#" | ||
681 | crate | ||
682 | _: t | ||
683 | Tr: t v | ||
684 | tr: t | ||
685 | |||
686 | crate::tr | ||
687 | Tr: t | ||
688 | "#]], | ||
689 | ); | ||
690 | } | ||
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs index 8136cb50c..1abffb4c3 100644 --- a/crates/ra_hir_def/src/visibility.rs +++ b/crates/ra_hir_def/src/visibility.rs | |||
@@ -5,6 +5,7 @@ use ra_syntax::ast; | |||
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | db::DefDatabase, | 7 | db::DefDatabase, |
8 | nameres::CrateDefMap, | ||
8 | path::{ModPath, PathKind}, | 9 | path::{ModPath, PathKind}, |
9 | ModuleId, | 10 | ModuleId, |
10 | }; | 11 | }; |
@@ -115,7 +116,7 @@ impl Visibility { | |||
115 | 116 | ||
116 | pub(crate) fn is_visible_from_def_map( | 117 | pub(crate) fn is_visible_from_def_map( |
117 | self, | 118 | self, |
118 | def_map: &crate::nameres::CrateDefMap, | 119 | def_map: &CrateDefMap, |
119 | from_module: crate::LocalModuleId, | 120 | from_module: crate::LocalModuleId, |
120 | ) -> bool { | 121 | ) -> bool { |
121 | let to_module = match self { | 122 | let to_module = match self { |
@@ -129,4 +130,42 @@ impl Visibility { | |||
129 | }); | 130 | }); |
130 | ancestors.any(|m| m == to_module.local_id) | 131 | ancestors.any(|m| m == to_module.local_id) |
131 | } | 132 | } |
133 | |||
134 | /// Returns the most permissive visibility of `self` and `other`. | ||
135 | /// | ||
136 | /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only | ||
137 | /// visible in unrelated modules). | ||
138 | pub(crate) fn max(self, other: Visibility, def_map: &CrateDefMap) -> Option<Visibility> { | ||
139 | match (self, other) { | ||
140 | (Visibility::Module(_), Visibility::Public) | ||
141 | | (Visibility::Public, Visibility::Module(_)) | ||
142 | | (Visibility::Public, Visibility::Public) => Some(Visibility::Public), | ||
143 | (Visibility::Module(mod_a), Visibility::Module(mod_b)) => { | ||
144 | if mod_a.krate != mod_b.krate { | ||
145 | return None; | ||
146 | } | ||
147 | |||
148 | let mut a_ancestors = std::iter::successors(Some(mod_a.local_id), |m| { | ||
149 | let parent_id = def_map[*m].parent?; | ||
150 | Some(parent_id) | ||
151 | }); | ||
152 | let mut b_ancestors = std::iter::successors(Some(mod_b.local_id), |m| { | ||
153 | let parent_id = def_map[*m].parent?; | ||
154 | Some(parent_id) | ||
155 | }); | ||
156 | |||
157 | if a_ancestors.any(|m| m == mod_b.local_id) { | ||
158 | // B is above A | ||
159 | return Some(Visibility::Module(mod_b)); | ||
160 | } | ||
161 | |||
162 | if b_ancestors.any(|m| m == mod_a.local_id) { | ||
163 | // A is above B | ||
164 | return Some(Visibility::Module(mod_a)); | ||
165 | } | ||
166 | |||
167 | None | ||
168 | } | ||
169 | } | ||
170 | } | ||
132 | } | 171 | } |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index d3c4d3f2a..526e61caf 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -3089,3 +3089,25 @@ fn test() { | |||
3089 | "#, | 3089 | "#, |
3090 | ); | 3090 | ); |
3091 | } | 3091 | } |
3092 | |||
3093 | #[test] | ||
3094 | fn underscore_import() { | ||
3095 | check_types( | ||
3096 | r#" | ||
3097 | mod tr { | ||
3098 | pub trait Tr { | ||
3099 | fn method(&self) -> u8 { 0 } | ||
3100 | } | ||
3101 | } | ||
3102 | |||
3103 | struct Tr; | ||
3104 | impl crate::tr::Tr for Tr {} | ||
3105 | |||
3106 | use crate::tr::Tr as _; | ||
3107 | fn test() { | ||
3108 | Tr.method(); | ||
3109 | //^^^^^^^^^^^ u8 | ||
3110 | } | ||
3111 | "#, | ||
3112 | ); | ||
3113 | } | ||
diff --git a/crates/ra_prof/Cargo.toml b/crates/ra_prof/Cargo.toml index b3d52985a..6c214501e 100644 --- a/crates/ra_prof/Cargo.toml +++ b/crates/ra_prof/Cargo.toml | |||
@@ -13,18 +13,12 @@ doctest = false | |||
13 | ra_arena = { path = "../ra_arena" } | 13 | ra_arena = { path = "../ra_arena" } |
14 | once_cell = "1.3.1" | 14 | once_cell = "1.3.1" |
15 | backtrace = { version = "0.3.44", optional = true } | 15 | backtrace = { version = "0.3.44", optional = true } |
16 | mimalloc = { version = "0.1.19", default-features = false, optional = true } | 16 | cfg-if = "0.1.10" |
17 | 17 | libc = "0.2.73" | |
18 | [target.'cfg(not(target_env = "msvc"))'.dependencies] | ||
19 | jemallocator = { version = "0.3.2", optional = true } | ||
20 | jemalloc-ctl = { version = "0.3.3", optional = true } | ||
21 | 18 | ||
22 | [features] | 19 | [features] |
23 | jemalloc = [ "jemallocator", "jemalloc-ctl" ] | ||
24 | cpu_profiler = [] | 20 | cpu_profiler = [] |
25 | 21 | ||
26 | # Uncomment to enable for the whole crate graph | 22 | # Uncomment to enable for the whole crate graph |
27 | # default = [ "backtrace" ] | 23 | # default = [ "backtrace" ] |
28 | # default = [ "jemalloc" ] | ||
29 | # default = [ "mimalloc" ] | ||
30 | # default = [ "cpu_profiler" ] | 24 | # default = [ "cpu_profiler" ] |
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index b54531b4e..ba5609703 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs | |||
@@ -13,16 +13,6 @@ pub use crate::{ | |||
13 | memory_usage::{Bytes, MemoryUsage}, | 13 | memory_usage::{Bytes, MemoryUsage}, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | // We use jemalloc mainly to get heap usage statistics, actual performance | ||
17 | // difference is not measures. | ||
18 | #[cfg(all(feature = "jemalloc", not(target_env = "msvc")))] | ||
19 | #[global_allocator] | ||
20 | static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; | ||
21 | |||
22 | #[cfg(all(feature = "mimalloc"))] | ||
23 | #[global_allocator] | ||
24 | static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; | ||
25 | |||
26 | /// Prints backtrace to stderr, useful for debugging. | 16 | /// Prints backtrace to stderr, useful for debugging. |
27 | #[cfg(feature = "backtrace")] | 17 | #[cfg(feature = "backtrace")] |
28 | pub fn print_backtrace() { | 18 | pub fn print_backtrace() { |
diff --git a/crates/ra_prof/src/memory_usage.rs b/crates/ra_prof/src/memory_usage.rs index 9768f656c..ee79ec3ee 100644 --- a/crates/ra_prof/src/memory_usage.rs +++ b/crates/ra_prof/src/memory_usage.rs | |||
@@ -1,26 +1,25 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | |||
3 | use std::fmt; | 2 | use std::fmt; |
4 | 3 | ||
4 | use cfg_if::cfg_if; | ||
5 | |||
5 | pub struct MemoryUsage { | 6 | pub struct MemoryUsage { |
6 | pub allocated: Bytes, | 7 | pub allocated: Bytes, |
7 | pub resident: Bytes, | 8 | pub resident: Bytes, |
8 | } | 9 | } |
9 | 10 | ||
10 | impl MemoryUsage { | 11 | impl MemoryUsage { |
11 | #[cfg(all(feature = "jemalloc", not(target_env = "msvc")))] | ||
12 | pub fn current() -> MemoryUsage { | 12 | pub fn current() -> MemoryUsage { |
13 | jemalloc_ctl::epoch::advance().unwrap(); | 13 | cfg_if! { |
14 | MemoryUsage { | 14 | if #[cfg(target_os = "linux")] { |
15 | allocated: Bytes(jemalloc_ctl::stats::allocated::read().unwrap()), | 15 | // Note: This is incredibly slow. |
16 | resident: Bytes(jemalloc_ctl::stats::resident::read().unwrap()), | 16 | let alloc = unsafe { libc::mallinfo() }.uordblks as u32 as usize; |
17 | MemoryUsage { allocated: Bytes(alloc), resident: Bytes(0) } | ||
18 | } else { | ||
19 | MemoryUsage { allocated: Bytes(0), resident: Bytes(0) } | ||
20 | } | ||
17 | } | 21 | } |
18 | } | 22 | } |
19 | |||
20 | #[cfg(any(not(feature = "jemalloc"), target_env = "msvc"))] | ||
21 | pub fn current() -> MemoryUsage { | ||
22 | MemoryUsage { allocated: Bytes(0), resident: Bytes(0) } | ||
23 | } | ||
24 | } | 23 | } |
25 | 24 | ||
26 | impl fmt::Display for MemoryUsage { | 25 | impl fmt::Display for MemoryUsage { |
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 5eb2d0bb7..023c104d1 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml | |||
@@ -29,6 +29,7 @@ serde = { version = "1.0.106", features = ["derive"] } | |||
29 | serde_json = "1.0.48" | 29 | serde_json = "1.0.48" |
30 | threadpool = "1.7.1" | 30 | threadpool = "1.7.1" |
31 | rayon = "1.3.1" | 31 | rayon = "1.3.1" |
32 | mimalloc = { version = "0.1.19", default-features = false, optional = true } | ||
32 | 33 | ||
33 | stdx = { path = "../stdx" } | 34 | stdx = { path = "../stdx" } |
34 | 35 | ||
@@ -62,7 +63,3 @@ expect = { path = "../expect" } | |||
62 | test_utils = { path = "../test_utils" } | 63 | test_utils = { path = "../test_utils" } |
63 | mbe = { path = "../ra_mbe", package = "ra_mbe" } | 64 | mbe = { path = "../ra_mbe", package = "ra_mbe" } |
64 | tt = { path = "../ra_tt", package = "ra_tt" } | 65 | tt = { path = "../ra_tt", package = "ra_tt" } |
65 | |||
66 | [features] | ||
67 | jemalloc = [ "ra_prof/jemalloc" ] | ||
68 | mimalloc = [ "ra_prof/mimalloc" ] | ||
diff --git a/crates/rust-analyzer/src/bin/args.rs b/crates/rust-analyzer/src/bin/args.rs index 3210416ee..741a2a951 100644 --- a/crates/rust-analyzer/src/bin/args.rs +++ b/crates/rust-analyzer/src/bin/args.rs | |||
@@ -166,7 +166,7 @@ USAGE: | |||
166 | FLAGS: | 166 | FLAGS: |
167 | -o, --only Only analyze items matching this path | 167 | -o, --only Only analyze items matching this path |
168 | -h, --help Prints help information | 168 | -h, --help Prints help information |
169 | --memory-usage Collect memory usage statistics (requires `--features jemalloc`) | 169 | --memory-usage Collect memory usage statistics |
170 | --randomize Randomize order in which crates, modules, and items are processed | 170 | --randomize Randomize order in which crates, modules, and items are processed |
171 | --parallel Run type inference in parallel | 171 | --parallel Run type inference in parallel |
172 | --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis | 172 | --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis |
@@ -221,7 +221,7 @@ USAGE: | |||
221 | 221 | ||
222 | FLAGS: | 222 | FLAGS: |
223 | -h, --help Prints help information | 223 | -h, --help Prints help information |
224 | --memory-usage Collect memory usage statistics (requires `--features jemalloc`) | 224 | --memory-usage Collect memory usage statistics |
225 | --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis | 225 | --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis |
226 | --with-proc-macro Use ra-proc-macro-srv for proc-macro expanding | 226 | --with-proc-macro Use ra-proc-macro-srv for proc-macro expanding |
227 | -v, --verbose | 227 | -v, --verbose |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 408892eab..a473c9165 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -16,6 +16,10 @@ use vfs::AbsPathBuf; | |||
16 | 16 | ||
17 | use crate::args::HelpPrinted; | 17 | use crate::args::HelpPrinted; |
18 | 18 | ||
19 | #[cfg(all(feature = "mimalloc"))] | ||
20 | #[global_allocator] | ||
21 | static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; | ||
22 | |||
19 | fn main() -> Result<()> { | 23 | fn main() -> Result<()> { |
20 | setup_logging()?; | 24 | setup_logging()?; |
21 | let args = match args::Args::parse()? { | 25 | let args = match args::Args::parse()? { |
diff --git a/docs/dev/README.md b/docs/dev/README.md index 3af01cd6b..2bb2f75bd 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -397,13 +397,7 @@ To log all communication between the server and the client, there are two choice | |||
397 | 397 | ||
398 | There are also two VS Code commands which might be of interest: | 398 | There are also two VS Code commands which might be of interest: |
399 | 399 | ||
400 | * `Rust Analyzer: Status` shows some memory-usage statistics. To take full | 400 | * `Rust Analyzer: Status` shows some memory-usage statistics. |
401 | advantage of it, you need to compile rust-analyzer with jemalloc support: | ||
402 | ``` | ||
403 | $ cargo install --path crates/rust-analyzer --force --features jemalloc | ||
404 | ``` | ||
405 | |||
406 | There's an alias for this: `cargo xtask install --server --jemalloc`. | ||
407 | 401 | ||
408 | * `Rust Analyzer: Syntax Tree` shows syntax tree of the current file/selection. | 402 | * `Rust Analyzer: Syntax Tree` shows syntax tree of the current file/selection. |
409 | 403 | ||
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs index b8f68027c..c198c0907 100644 --- a/xtask/src/dist.rs +++ b/xtask/src/dist.rs | |||
@@ -57,8 +57,6 @@ fn dist_server() -> Result<()> { | |||
57 | env::set_var("CC", "clang"); | 57 | env::set_var("CC", "clang"); |
58 | run!( | 58 | run!( |
59 | "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release" | 59 | "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release" |
60 | // We'd want to add, but that requires setting the right linker somehow | ||
61 | // --features=jemalloc | ||
62 | )?; | 60 | )?; |
63 | } else { | 61 | } else { |
64 | run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?; | 62 | run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?; |
diff --git a/xtask/src/install.rs b/xtask/src/install.rs index a0dc0c9c2..b25a6e301 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs | |||
@@ -24,7 +24,6 @@ pub struct ServerOpt { | |||
24 | 24 | ||
25 | pub enum Malloc { | 25 | pub enum Malloc { |
26 | System, | 26 | System, |
27 | Jemalloc, | ||
28 | Mimalloc, | 27 | Mimalloc, |
29 | } | 28 | } |
30 | 29 | ||
@@ -138,7 +137,6 @@ fn install_server(opts: ServerOpt) -> Result<()> { | |||
138 | 137 | ||
139 | let malloc_feature = match opts.malloc { | 138 | let malloc_feature = match opts.malloc { |
140 | Malloc::System => "", | 139 | Malloc::System => "", |
141 | Malloc::Jemalloc => "--features jemalloc", | ||
142 | Malloc::Mimalloc => "--features mimalloc", | 140 | Malloc::Mimalloc => "--features mimalloc", |
143 | }; | 141 | }; |
144 | let res = run!("cargo install --path crates/rust-analyzer --locked --force {}", malloc_feature); | 142 | let res = run!("cargo install --path crates/rust-analyzer --locked --force {}", malloc_feature); |
diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 399ff7204..53d3ce3e7 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs | |||
@@ -45,7 +45,6 @@ USAGE: | |||
45 | FLAGS: | 45 | FLAGS: |
46 | --client-code Install only VS Code plugin | 46 | --client-code Install only VS Code plugin |
47 | --server Install only the language server | 47 | --server Install only the language server |
48 | --jemalloc Use jemalloc for server | ||
49 | --mimalloc Use mimalloc for server | 48 | --mimalloc Use mimalloc for server |
50 | -h, --help Prints help information | 49 | -h, --help Prints help information |
51 | " | 50 | " |
@@ -62,15 +61,8 @@ FLAGS: | |||
62 | return Ok(()); | 61 | return Ok(()); |
63 | } | 62 | } |
64 | 63 | ||
65 | let malloc = match (args.contains("--jemalloc"), args.contains("--mimalloc")) { | 64 | let malloc = |
66 | (false, false) => Malloc::System, | 65 | if args.contains("--mimalloc") { Malloc::Mimalloc } else { Malloc::System }; |
67 | (true, false) => Malloc::Jemalloc, | ||
68 | (false, true) => Malloc::Mimalloc, | ||
69 | (true, true) => { | ||
70 | eprintln!("error: Cannot use both `--jemalloc` and `--mimalloc`"); | ||
71 | return Ok(()); | ||
72 | } | ||
73 | }; | ||
74 | 66 | ||
75 | args.finish()?; | 67 | args.finish()?; |
76 | 68 | ||