diff options
-rw-r--r-- | crates/ra_assists/src/ast_transform.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests.rs | 36 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path/lower.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path/lower/lower_use.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/pat.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/patterns.rs | 93 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 39 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 4 | ||||
-rw-r--r-- | xtask/src/install.rs | 3 |
9 files changed, 208 insertions, 10 deletions
diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs index 0e53c1eee..42856f0ca 100644 --- a/crates/ra_assists/src/ast_transform.rs +++ b/crates/ra_assists/src/ast_transform.rs | |||
@@ -178,5 +178,10 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> { | |||
178 | 178 | ||
179 | pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path { | 179 | pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path { |
180 | let parse = ast::SourceFile::parse(&path.to_string()); | 180 | let parse = ast::SourceFile::parse(&path.to_string()); |
181 | parse.tree().syntax().descendants().find_map(ast::Path::cast).unwrap() | 181 | parse |
182 | .tree() | ||
183 | .syntax() | ||
184 | .descendants() | ||
185 | .find_map(ast::Path::cast) | ||
186 | .unwrap_or_else(|| panic!("failed to parse path {:?}, `{}`", path, path)) | ||
182 | } | 187 | } |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 82f0f835c..dda5ed699 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -66,6 +66,42 @@ fn crate_def_map_smoke_test() { | |||
66 | } | 66 | } |
67 | 67 | ||
68 | #[test] | 68 | #[test] |
69 | fn crate_def_map_super_super() { | ||
70 | let map = def_map( | ||
71 | " | ||
72 | //- /lib.rs | ||
73 | mod a { | ||
74 | const A: usize = 0; | ||
75 | |||
76 | mod b { | ||
77 | const B: usize = 0; | ||
78 | |||
79 | mod c { | ||
80 | use super::super::*; | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | ", | ||
85 | ); | ||
86 | assert_snapshot!(map, @r###" | ||
87 | ⋮crate | ||
88 | ⋮a: t | ||
89 | ⋮ | ||
90 | ⋮crate::a | ||
91 | ⋮A: v | ||
92 | ⋮b: t | ||
93 | ⋮ | ||
94 | ⋮crate::a::b | ||
95 | ⋮B: v | ||
96 | ⋮c: t | ||
97 | ⋮ | ||
98 | ⋮crate::a::b::c | ||
99 | ⋮A: v | ||
100 | ⋮b: t | ||
101 | "###) | ||
102 | } | ||
103 | |||
104 | #[test] | ||
69 | fn bogus_paths() { | 105 | fn bogus_paths() { |
70 | covers!(bogus_paths); | 106 | covers!(bogus_paths); |
71 | let map = def_map( | 107 | let map = def_map( |
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index 62aafd508..0934520d7 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs | |||
@@ -101,8 +101,12 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
101 | break; | 101 | break; |
102 | } | 102 | } |
103 | ast::PathSegmentKind::SuperKw => { | 103 | ast::PathSegmentKind::SuperKw => { |
104 | kind = PathKind::Super(1); | 104 | let nested_super_count = if let PathKind::Super(n) = kind { |
105 | break; | 105 | n |
106 | } else { | ||
107 | 0 | ||
108 | }; | ||
109 | kind = PathKind::Super(nested_super_count + 1); | ||
106 | } | 110 | } |
107 | } | 111 | } |
108 | path = match qualifier(&path) { | 112 | path = match qualifier(&path) { |
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs index b6d1125e2..278d5196e 100644 --- a/crates/ra_hir_def/src/path/lower/lower_use.rs +++ b/crates/ra_hir_def/src/path/lower/lower_use.rs | |||
@@ -103,10 +103,13 @@ fn convert_path(prefix: Option<ModPath>, path: ast::Path, hygiene: &Hygiene) -> | |||
103 | ModPath::from_segments(PathKind::Super(0), iter::empty()) | 103 | ModPath::from_segments(PathKind::Super(0), iter::empty()) |
104 | } | 104 | } |
105 | ast::PathSegmentKind::SuperKw => { | 105 | ast::PathSegmentKind::SuperKw => { |
106 | if prefix.is_some() { | 106 | let nested_super_count = match prefix.map(|p| p.kind) { |
107 | return None; | 107 | Some(PathKind::Super(n)) => n, |
108 | } | 108 | Some(_) => return None, |
109 | ModPath::from_segments(PathKind::Super(1), iter::empty()) | 109 | None => 0, |
110 | }; | ||
111 | |||
112 | ModPath::from_segments(PathKind::Super(nested_super_count + 1), iter::empty()) | ||
110 | } | 113 | } |
111 | ast::PathSegmentKind::Type { .. } => { | 114 | ast::PathSegmentKind::Type { .. } => { |
112 | // not allowed in imports | 115 | // not allowed in imports |
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index bf8ea192b..623e52599 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -185,6 +185,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
185 | self.write_pat_ty(pat, bound_ty); | 185 | self.write_pat_ty(pat, bound_ty); |
186 | return inner_ty; | 186 | return inner_ty; |
187 | } | 187 | } |
188 | Pat::Slice { prefix, slice: _slice, suffix } => { | ||
189 | let (container_ty, elem_ty) = match &expected { | ||
190 | ty_app!(TypeCtor::Array, st) => { | ||
191 | (TypeCtor::Array, st.as_single().clone()) | ||
192 | }, | ||
193 | ty_app!(TypeCtor::Slice, st) => { | ||
194 | (TypeCtor::Slice, st.as_single().clone()) | ||
195 | }, | ||
196 | _ => (TypeCtor::Slice, Ty::Unknown), | ||
197 | }; | ||
198 | |||
199 | for pat_id in prefix.iter().chain(suffix) { | ||
200 | self.infer_pat(*pat_id, &elem_ty, default_bm); | ||
201 | } | ||
202 | |||
203 | Ty::apply_one(container_ty, elem_ty) | ||
204 | } | ||
188 | _ => Ty::Unknown, | 205 | _ => Ty::Unknown, |
189 | }; | 206 | }; |
190 | // use a new type variable if we got Ty::Unknown here | 207 | // use a new type variable if we got Ty::Unknown here |
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index 81d00c2af..76aa32024 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs | |||
@@ -53,8 +53,9 @@ fn test(x: &i32) { | |||
53 | [140; 141) 'g': {unknown} | 53 | [140; 141) 'g': {unknown} |
54 | [144; 145) 'e': {unknown} | 54 | [144; 145) 'e': {unknown} |
55 | [158; 205) 'if let... }': () | 55 | [158; 205) 'if let... }': () |
56 | [165; 170) '[val]': {unknown} | 56 | [165; 170) '[val]': [{unknown}] |
57 | [173; 176) 'opt': {unknown} | 57 | [166; 169) 'val': {unknown} |
58 | [173; 176) 'opt': [{unknown}] | ||
58 | [177; 205) '{ ... }': () | 59 | [177; 205) '{ ... }': () |
59 | [191; 192) 'h': {unknown} | 60 | [191; 192) 'h': {unknown} |
60 | [195; 198) 'val': {unknown} | 61 | [195; 198) 'val': {unknown} |
@@ -137,6 +138,94 @@ fn test() { | |||
137 | } | 138 | } |
138 | 139 | ||
139 | #[test] | 140 | #[test] |
141 | fn infer_pattern_match_slice() { | ||
142 | assert_snapshot!( | ||
143 | infer(r#" | ||
144 | fn test() { | ||
145 | let slice: &[f64] = &[0.0]; | ||
146 | match slice { | ||
147 | &[] => {}, | ||
148 | &[a] => { | ||
149 | a; | ||
150 | }, | ||
151 | &[b, c] => { | ||
152 | b; | ||
153 | c; | ||
154 | } | ||
155 | _ => {} | ||
156 | } | ||
157 | } | ||
158 | "#), | ||
159 | @r###" | ||
160 | [11; 210) '{ ... } }': () | ||
161 | [21; 26) 'slice': &[f64] | ||
162 | [37; 43) '&[0.0]': &[f64; _] | ||
163 | [38; 43) '[0.0]': [f64; _] | ||
164 | [39; 42) '0.0': f64 | ||
165 | [49; 208) 'match ... }': () | ||
166 | [55; 60) 'slice': &[f64] | ||
167 | [71; 74) '&[]': &[f64] | ||
168 | [72; 74) '[]': [f64] | ||
169 | [78; 80) '{}': () | ||
170 | [90; 94) '&[a]': &[f64] | ||
171 | [91; 94) '[a]': [f64] | ||
172 | [92; 93) 'a': f64 | ||
173 | [98; 124) '{ ... }': () | ||
174 | [112; 113) 'a': f64 | ||
175 | [134; 141) '&[b, c]': &[f64] | ||
176 | [135; 141) '[b, c]': [f64] | ||
177 | [136; 137) 'b': f64 | ||
178 | [139; 140) 'c': f64 | ||
179 | [145; 186) '{ ... }': () | ||
180 | [159; 160) 'b': f64 | ||
181 | [174; 175) 'c': f64 | ||
182 | [195; 196) '_': &[f64] | ||
183 | [200; 202) '{}': () | ||
184 | "### | ||
185 | ); | ||
186 | } | ||
187 | |||
188 | #[test] | ||
189 | fn infer_pattern_match_arr() { | ||
190 | assert_snapshot!( | ||
191 | infer(r#" | ||
192 | fn test() { | ||
193 | let arr: [f64; 2] = [0.0, 1.0]; | ||
194 | match arr { | ||
195 | [1.0, a] => { | ||
196 | a; | ||
197 | }, | ||
198 | [b, c] => { | ||
199 | b; | ||
200 | c; | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | "#), | ||
205 | @r###" | ||
206 | [11; 180) '{ ... } }': () | ||
207 | [21; 24) 'arr': [f64; _] | ||
208 | [37; 47) '[0.0, 1.0]': [f64; _] | ||
209 | [38; 41) '0.0': f64 | ||
210 | [43; 46) '1.0': f64 | ||
211 | [53; 178) 'match ... }': () | ||
212 | [59; 62) 'arr': [f64; _] | ||
213 | [73; 81) '[1.0, a]': [f64; _] | ||
214 | [74; 77) '1.0': f64 | ||
215 | [79; 80) 'a': f64 | ||
216 | [85; 111) '{ ... }': () | ||
217 | [99; 100) 'a': f64 | ||
218 | [121; 127) '[b, c]': [f64; _] | ||
219 | [122; 123) 'b': f64 | ||
220 | [125; 126) 'c': f64 | ||
221 | [131; 172) '{ ... }': () | ||
222 | [145; 146) 'b': f64 | ||
223 | [160; 161) 'c': f64 | ||
224 | "### | ||
225 | ); | ||
226 | } | ||
227 | |||
228 | #[test] | ||
140 | fn infer_adt_pattern() { | 229 | fn infer_adt_pattern() { |
141 | assert_snapshot!( | 230 | assert_snapshot!( |
142 | infer(r#" | 231 | infer(r#" |
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index a6e0158b2..9145aa183 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -545,4 +545,43 @@ mod tests { | |||
545 | "### | 545 | "### |
546 | ) | 546 | ) |
547 | } | 547 | } |
548 | |||
549 | #[test] | ||
550 | fn test_super_super_completion() { | ||
551 | assert_debug_snapshot!( | ||
552 | do_ref_completion( | ||
553 | r" | ||
554 | mod a { | ||
555 | const A: usize = 0; | ||
556 | |||
557 | mod b { | ||
558 | const B: usize = 0; | ||
559 | |||
560 | mod c { | ||
561 | use super::super::<|> | ||
562 | } | ||
563 | } | ||
564 | } | ||
565 | ", | ||
566 | ), | ||
567 | @r###" | ||
568 | [ | ||
569 | CompletionItem { | ||
570 | label: "A", | ||
571 | source_range: [217; 217), | ||
572 | delete: [217; 217), | ||
573 | insert: "A", | ||
574 | kind: Const, | ||
575 | }, | ||
576 | CompletionItem { | ||
577 | label: "b", | ||
578 | source_range: [217; 217), | ||
579 | delete: [217; 217), | ||
580 | insert: "b", | ||
581 | kind: Module, | ||
582 | }, | ||
583 | ] | ||
584 | "### | ||
585 | ); | ||
586 | } | ||
548 | } | 587 | } |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index 6f517760f..f51263f22 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -184,6 +184,10 @@ pub fn handle_on_type_formatting( | |||
184 | // `text.char_at(position) == typed_char`. | 184 | // `text.char_at(position) == typed_char`. |
185 | position.offset -= TextUnit::of_char('.'); | 185 | position.offset -= TextUnit::of_char('.'); |
186 | let char_typed = params.ch.chars().next().unwrap_or('\0'); | 186 | let char_typed = params.ch.chars().next().unwrap_or('\0'); |
187 | assert!({ | ||
188 | let text = world.analysis().file_text(position.file_id)?; | ||
189 | text[position.offset.to_usize()..].starts_with(char_typed) | ||
190 | }); | ||
187 | 191 | ||
188 | // We have an assist that inserts ` ` after typing `->` in `fn foo() ->{`, | 192 | // We have an assist that inserts ` ` after typing `->` in `fn foo() ->{`, |
189 | // but it requires precise cursor positioning to work, and one can't | 193 | // but it requires precise cursor positioning to work, and one can't |
diff --git a/xtask/src/install.rs b/xtask/src/install.rs index 1d13b26da..f76467cac 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs | |||
@@ -122,7 +122,8 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { | |||
122 | if !installed_extensions.contains("rust-analyzer") { | 122 | if !installed_extensions.contains("rust-analyzer") { |
123 | bail!( | 123 | bail!( |
124 | "Could not install the Visual Studio Code extension. \ | 124 | "Could not install the Visual Studio Code extension. \ |
125 | Please make sure you have at least NodeJS 12.x together with the latest version of VS Code installed and try again." | 125 | Please make sure you have at least NodeJS 12.x together with the latest version of VS Code installed and try again. \ |
126 | Note that installing via xtask install does not work for VS Code Remote, instead you’ll need to install the .vsix manually." | ||
126 | ); | 127 | ); |
127 | } | 128 | } |
128 | 129 | ||