diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/completion.rs | 32 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_attribute.rs | 293 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide/src/display/short_label.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide/src/folding_ranges.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide/src/join_lines.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_tree.rs | 77 |
8 files changed, 354 insertions, 78 deletions
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index 4ca0fdf4f..a0e06faa2 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs | |||
@@ -65,21 +65,23 @@ pub(crate) fn completions( | |||
65 | let ctx = CompletionContext::new(db, position, config)?; | 65 | let ctx = CompletionContext::new(db, position, config)?; |
66 | 66 | ||
67 | let mut acc = Completions::default(); | 67 | let mut acc = Completions::default(); |
68 | 68 | if ctx.attribute_under_caret.is_some() { | |
69 | complete_fn_param::complete_fn_param(&mut acc, &ctx); | 69 | complete_attribute::complete_attribute(&mut acc, &ctx); |
70 | complete_keyword::complete_expr_keyword(&mut acc, &ctx); | 70 | } else { |
71 | complete_keyword::complete_use_tree_keyword(&mut acc, &ctx); | 71 | complete_fn_param::complete_fn_param(&mut acc, &ctx); |
72 | complete_snippet::complete_expr_snippet(&mut acc, &ctx); | 72 | complete_keyword::complete_expr_keyword(&mut acc, &ctx); |
73 | complete_snippet::complete_item_snippet(&mut acc, &ctx); | 73 | complete_keyword::complete_use_tree_keyword(&mut acc, &ctx); |
74 | complete_qualified_path::complete_qualified_path(&mut acc, &ctx); | 74 | complete_snippet::complete_expr_snippet(&mut acc, &ctx); |
75 | complete_unqualified_path::complete_unqualified_path(&mut acc, &ctx); | 75 | complete_snippet::complete_item_snippet(&mut acc, &ctx); |
76 | complete_dot::complete_dot(&mut acc, &ctx); | 76 | complete_qualified_path::complete_qualified_path(&mut acc, &ctx); |
77 | complete_record::complete_record(&mut acc, &ctx); | 77 | complete_unqualified_path::complete_unqualified_path(&mut acc, &ctx); |
78 | complete_pattern::complete_pattern(&mut acc, &ctx); | 78 | complete_dot::complete_dot(&mut acc, &ctx); |
79 | complete_postfix::complete_postfix(&mut acc, &ctx); | 79 | complete_record::complete_record(&mut acc, &ctx); |
80 | complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); | 80 | complete_pattern::complete_pattern(&mut acc, &ctx); |
81 | complete_trait_impl::complete_trait_impl(&mut acc, &ctx); | 81 | complete_postfix::complete_postfix(&mut acc, &ctx); |
82 | complete_attribute::complete_attribute(&mut acc, &ctx); | 82 | complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); |
83 | complete_trait_impl::complete_trait_impl(&mut acc, &ctx); | ||
84 | } | ||
83 | 85 | ||
84 | Some(acc) | 86 | Some(acc) |
85 | } | 87 | } |
diff --git a/crates/ra_ide/src/completion/complete_attribute.rs b/crates/ra_ide/src/completion/complete_attribute.rs index 8bf952798..20e6edc17 100644 --- a/crates/ra_ide/src/completion/complete_attribute.rs +++ b/crates/ra_ide/src/completion/complete_attribute.rs | |||
@@ -5,23 +5,26 @@ | |||
5 | 5 | ||
6 | use super::completion_context::CompletionContext; | 6 | use super::completion_context::CompletionContext; |
7 | use super::completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions}; | 7 | use super::completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions}; |
8 | use ast::AttrInput; | ||
8 | use ra_syntax::{ | 9 | use ra_syntax::{ |
9 | ast::{Attr, AttrKind}, | 10 | ast::{self, AttrKind}, |
10 | AstNode, | 11 | AstNode, SyntaxKind, |
11 | }; | 12 | }; |
13 | use rustc_hash::FxHashSet; | ||
12 | 14 | ||
13 | pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) { | 15 | pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { |
14 | if !ctx.is_attribute { | 16 | let attribute = ctx.attribute_under_caret.as_ref()?; |
15 | return; | ||
16 | } | ||
17 | 17 | ||
18 | let is_inner = ctx | 18 | match (attribute.path(), attribute.input()) { |
19 | .original_token | 19 | (Some(path), Some(AttrInput::TokenTree(token_tree))) if path.to_string() == "derive" => { |
20 | .ancestors() | 20 | complete_derive(acc, ctx, token_tree) |
21 | .find_map(Attr::cast) | 21 | } |
22 | .map(|attr| attr.kind() == AttrKind::Inner) | 22 | _ => complete_attribute_start(acc, ctx, attribute), |
23 | .unwrap_or(false); | 23 | } |
24 | Some(()) | ||
25 | } | ||
24 | 26 | ||
27 | fn complete_attribute_start(acc: &mut Completions, ctx: &CompletionContext, attribute: &ast::Attr) { | ||
25 | for attr_completion in ATTRIBUTES { | 28 | for attr_completion in ATTRIBUTES { |
26 | let mut item = CompletionItem::new( | 29 | let mut item = CompletionItem::new( |
27 | CompletionKind::Attribute, | 30 | CompletionKind::Attribute, |
@@ -37,7 +40,7 @@ pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) | |||
37 | _ => {} | 40 | _ => {} |
38 | } | 41 | } |
39 | 42 | ||
40 | if is_inner || !attr_completion.should_be_inner { | 43 | if attribute.kind() == AttrKind::Inner || !attr_completion.should_be_inner { |
41 | acc.add(item); | 44 | acc.add(item); |
42 | } | 45 | } |
43 | } | 46 | } |
@@ -126,6 +129,106 @@ const ATTRIBUTES: &[AttrCompletion] = &[ | |||
126 | }, | 129 | }, |
127 | ]; | 130 | ]; |
128 | 131 | ||
132 | fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) { | ||
133 | if let Ok(existing_derives) = parse_derive_input(derive_input) { | ||
134 | for derive_completion in DEFAULT_DERIVE_COMPLETIONS | ||
135 | .into_iter() | ||
136 | .filter(|completion| !existing_derives.contains(completion.label)) | ||
137 | { | ||
138 | let mut label = derive_completion.label.to_owned(); | ||
139 | for dependency in derive_completion | ||
140 | .dependencies | ||
141 | .into_iter() | ||
142 | .filter(|&&dependency| !existing_derives.contains(dependency)) | ||
143 | { | ||
144 | label.push_str(", "); | ||
145 | label.push_str(dependency); | ||
146 | } | ||
147 | acc.add( | ||
148 | CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label) | ||
149 | .kind(CompletionItemKind::Attribute), | ||
150 | ); | ||
151 | } | ||
152 | |||
153 | for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) { | ||
154 | acc.add( | ||
155 | CompletionItem::new( | ||
156 | CompletionKind::Attribute, | ||
157 | ctx.source_range(), | ||
158 | custom_derive_name, | ||
159 | ) | ||
160 | .kind(CompletionItemKind::Attribute), | ||
161 | ); | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | fn parse_derive_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>, ()> { | ||
167 | match (derive_input.left_delimiter_token(), derive_input.right_delimiter_token()) { | ||
168 | (Some(left_paren), Some(right_paren)) | ||
169 | if left_paren.kind() == SyntaxKind::L_PAREN | ||
170 | && right_paren.kind() == SyntaxKind::R_PAREN => | ||
171 | { | ||
172 | let mut input_derives = FxHashSet::default(); | ||
173 | let mut current_derive = String::new(); | ||
174 | for token in derive_input | ||
175 | .syntax() | ||
176 | .children_with_tokens() | ||
177 | .filter_map(|token| token.into_token()) | ||
178 | .skip_while(|token| token != &left_paren) | ||
179 | .skip(1) | ||
180 | .take_while(|token| token != &right_paren) | ||
181 | { | ||
182 | if SyntaxKind::COMMA == token.kind() { | ||
183 | if !current_derive.is_empty() { | ||
184 | input_derives.insert(current_derive); | ||
185 | current_derive = String::new(); | ||
186 | } | ||
187 | } else { | ||
188 | current_derive.push_str(token.to_string().trim()); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | if !current_derive.is_empty() { | ||
193 | input_derives.insert(current_derive); | ||
194 | } | ||
195 | Ok(input_derives) | ||
196 | } | ||
197 | _ => Err(()), | ||
198 | } | ||
199 | } | ||
200 | |||
201 | fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet<String> { | ||
202 | let mut result = FxHashSet::default(); | ||
203 | ctx.scope().process_all_names(&mut |name, scope_def| { | ||
204 | if let hir::ScopeDef::MacroDef(mac) = scope_def { | ||
205 | if mac.is_derive_macro() { | ||
206 | result.insert(name.to_string()); | ||
207 | } | ||
208 | } | ||
209 | }); | ||
210 | result | ||
211 | } | ||
212 | |||
213 | struct DeriveCompletion { | ||
214 | label: &'static str, | ||
215 | dependencies: &'static [&'static str], | ||
216 | } | ||
217 | |||
218 | /// Standard Rust derives and the information about their dependencies | ||
219 | /// (the dependencies are needed so that the main derive don't break the compilation when added) | ||
220 | const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[ | ||
221 | DeriveCompletion { label: "Clone", dependencies: &[] }, | ||
222 | DeriveCompletion { label: "Copy", dependencies: &["Clone"] }, | ||
223 | DeriveCompletion { label: "Debug", dependencies: &[] }, | ||
224 | DeriveCompletion { label: "Default", dependencies: &[] }, | ||
225 | DeriveCompletion { label: "Hash", dependencies: &[] }, | ||
226 | DeriveCompletion { label: "PartialEq", dependencies: &[] }, | ||
227 | DeriveCompletion { label: "Eq", dependencies: &["PartialEq"] }, | ||
228 | DeriveCompletion { label: "PartialOrd", dependencies: &["PartialEq"] }, | ||
229 | DeriveCompletion { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] }, | ||
230 | ]; | ||
231 | |||
129 | #[cfg(test)] | 232 | #[cfg(test)] |
130 | mod tests { | 233 | mod tests { |
131 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; | 234 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
@@ -136,6 +239,170 @@ mod tests { | |||
136 | } | 239 | } |
137 | 240 | ||
138 | #[test] | 241 | #[test] |
242 | fn empty_derive_completion() { | ||
243 | assert_debug_snapshot!( | ||
244 | do_attr_completion( | ||
245 | r" | ||
246 | #[derive(<|>)] | ||
247 | struct Test {} | ||
248 | ", | ||
249 | ), | ||
250 | @r###" | ||
251 | [ | ||
252 | CompletionItem { | ||
253 | label: "Clone", | ||
254 | source_range: 30..30, | ||
255 | delete: 30..30, | ||
256 | insert: "Clone", | ||
257 | kind: Attribute, | ||
258 | }, | ||
259 | CompletionItem { | ||
260 | label: "Copy, Clone", | ||
261 | source_range: 30..30, | ||
262 | delete: 30..30, | ||
263 | insert: "Copy, Clone", | ||
264 | kind: Attribute, | ||
265 | }, | ||
266 | CompletionItem { | ||
267 | label: "Debug", | ||
268 | source_range: 30..30, | ||
269 | delete: 30..30, | ||
270 | insert: "Debug", | ||
271 | kind: Attribute, | ||
272 | }, | ||
273 | CompletionItem { | ||
274 | label: "Default", | ||
275 | source_range: 30..30, | ||
276 | delete: 30..30, | ||
277 | insert: "Default", | ||
278 | kind: Attribute, | ||
279 | }, | ||
280 | CompletionItem { | ||
281 | label: "Eq, PartialEq", | ||
282 | source_range: 30..30, | ||
283 | delete: 30..30, | ||
284 | insert: "Eq, PartialEq", | ||
285 | kind: Attribute, | ||
286 | }, | ||
287 | CompletionItem { | ||
288 | label: "Hash", | ||
289 | source_range: 30..30, | ||
290 | delete: 30..30, | ||
291 | insert: "Hash", | ||
292 | kind: Attribute, | ||
293 | }, | ||
294 | CompletionItem { | ||
295 | label: "Ord, PartialOrd, Eq, PartialEq", | ||
296 | source_range: 30..30, | ||
297 | delete: 30..30, | ||
298 | insert: "Ord, PartialOrd, Eq, PartialEq", | ||
299 | kind: Attribute, | ||
300 | }, | ||
301 | CompletionItem { | ||
302 | label: "PartialEq", | ||
303 | source_range: 30..30, | ||
304 | delete: 30..30, | ||
305 | insert: "PartialEq", | ||
306 | kind: Attribute, | ||
307 | }, | ||
308 | CompletionItem { | ||
309 | label: "PartialOrd, PartialEq", | ||
310 | source_range: 30..30, | ||
311 | delete: 30..30, | ||
312 | insert: "PartialOrd, PartialEq", | ||
313 | kind: Attribute, | ||
314 | }, | ||
315 | ] | ||
316 | "### | ||
317 | ); | ||
318 | } | ||
319 | |||
320 | #[test] | ||
321 | fn no_completion_for_incorrect_derive() { | ||
322 | assert_debug_snapshot!( | ||
323 | do_attr_completion( | ||
324 | r" | ||
325 | #[derive{<|>)] | ||
326 | struct Test {} | ||
327 | ", | ||
328 | ), | ||
329 | @"[]" | ||
330 | ); | ||
331 | } | ||
332 | |||
333 | #[test] | ||
334 | fn derive_with_input_completion() { | ||
335 | assert_debug_snapshot!( | ||
336 | do_attr_completion( | ||
337 | r" | ||
338 | #[derive(serde::Serialize, PartialEq, <|>)] | ||
339 | struct Test {} | ||
340 | ", | ||
341 | ), | ||
342 | @r###" | ||
343 | [ | ||
344 | CompletionItem { | ||
345 | label: "Clone", | ||
346 | source_range: 59..59, | ||
347 | delete: 59..59, | ||
348 | insert: "Clone", | ||
349 | kind: Attribute, | ||
350 | }, | ||
351 | CompletionItem { | ||
352 | label: "Copy, Clone", | ||
353 | source_range: 59..59, | ||
354 | delete: 59..59, | ||
355 | insert: "Copy, Clone", | ||
356 | kind: Attribute, | ||
357 | }, | ||
358 | CompletionItem { | ||
359 | label: "Debug", | ||
360 | source_range: 59..59, | ||
361 | delete: 59..59, | ||
362 | insert: "Debug", | ||
363 | kind: Attribute, | ||
364 | }, | ||
365 | CompletionItem { | ||
366 | label: "Default", | ||
367 | source_range: 59..59, | ||
368 | delete: 59..59, | ||
369 | insert: "Default", | ||
370 | kind: Attribute, | ||
371 | }, | ||
372 | CompletionItem { | ||
373 | label: "Eq", | ||
374 | source_range: 59..59, | ||
375 | delete: 59..59, | ||
376 | insert: "Eq", | ||
377 | kind: Attribute, | ||
378 | }, | ||
379 | CompletionItem { | ||
380 | label: "Hash", | ||
381 | source_range: 59..59, | ||
382 | delete: 59..59, | ||
383 | insert: "Hash", | ||
384 | kind: Attribute, | ||
385 | }, | ||
386 | CompletionItem { | ||
387 | label: "Ord, PartialOrd, Eq", | ||
388 | source_range: 59..59, | ||
389 | delete: 59..59, | ||
390 | insert: "Ord, PartialOrd, Eq", | ||
391 | kind: Attribute, | ||
392 | }, | ||
393 | CompletionItem { | ||
394 | label: "PartialOrd", | ||
395 | source_range: 59..59, | ||
396 | delete: 59..59, | ||
397 | insert: "PartialOrd", | ||
398 | kind: Attribute, | ||
399 | }, | ||
400 | ] | ||
401 | "### | ||
402 | ); | ||
403 | } | ||
404 | |||
405 | #[test] | ||
139 | fn test_attribute_completion() { | 406 | fn test_attribute_completion() { |
140 | assert_debug_snapshot!( | 407 | assert_debug_snapshot!( |
141 | do_attr_completion( | 408 | do_attr_completion( |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 118fceb2e..dd87bd119 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -58,7 +58,7 @@ pub(crate) struct CompletionContext<'a> { | |||
58 | pub(super) is_macro_call: bool, | 58 | pub(super) is_macro_call: bool, |
59 | pub(super) is_path_type: bool, | 59 | pub(super) is_path_type: bool, |
60 | pub(super) has_type_args: bool, | 60 | pub(super) has_type_args: bool, |
61 | pub(super) is_attribute: bool, | 61 | pub(super) attribute_under_caret: Option<ast::Attr>, |
62 | } | 62 | } |
63 | 63 | ||
64 | impl<'a> CompletionContext<'a> { | 64 | impl<'a> CompletionContext<'a> { |
@@ -116,7 +116,7 @@ impl<'a> CompletionContext<'a> { | |||
116 | is_path_type: false, | 116 | is_path_type: false, |
117 | has_type_args: false, | 117 | has_type_args: false, |
118 | dot_receiver_is_ambiguous_float_literal: false, | 118 | dot_receiver_is_ambiguous_float_literal: false, |
119 | is_attribute: false, | 119 | attribute_under_caret: None, |
120 | }; | 120 | }; |
121 | 121 | ||
122 | let mut original_file = original_file.syntax().clone(); | 122 | let mut original_file = original_file.syntax().clone(); |
@@ -200,6 +200,7 @@ impl<'a> CompletionContext<'a> { | |||
200 | Some(ty) | 200 | Some(ty) |
201 | }) | 201 | }) |
202 | .flatten(); | 202 | .flatten(); |
203 | self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset); | ||
203 | 204 | ||
204 | // First, let's try to complete a reference to some declaration. | 205 | // First, let's try to complete a reference to some declaration. |
205 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&file_with_fake_ident, offset) { | 206 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&file_with_fake_ident, offset) { |
@@ -318,7 +319,6 @@ impl<'a> CompletionContext<'a> { | |||
318 | .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) | 319 | .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) |
319 | .is_some(); | 320 | .is_some(); |
320 | self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some(); | 321 | self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some(); |
321 | self.is_attribute = path.syntax().parent().and_then(ast::Attr::cast).is_some(); | ||
322 | 322 | ||
323 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); | 323 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); |
324 | self.has_type_args = segment.type_arg_list().is_some(); | 324 | self.has_type_args = segment.type_arg_list().is_some(); |
@@ -344,7 +344,7 @@ impl<'a> CompletionContext<'a> { | |||
344 | stmt.syntax().text_range() == name_ref.syntax().text_range(), | 344 | stmt.syntax().text_range() == name_ref.syntax().text_range(), |
345 | ); | 345 | ); |
346 | } | 346 | } |
347 | if let Some(block) = ast::Block::cast(node) { | 347 | if let Some(block) = ast::BlockExpr::cast(node) { |
348 | return Some( | 348 | return Some( |
349 | block.expr().map(|e| e.syntax().text_range()) | 349 | block.expr().map(|e| e.syntax().text_range()) |
350 | == Some(name_ref.syntax().text_range()), | 350 | == Some(name_ref.syntax().text_range()), |
diff --git a/crates/ra_ide/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs index 4b081bf6c..d37260e96 100644 --- a/crates/ra_ide/src/display/short_label.rs +++ b/crates/ra_ide/src/display/short_label.rs | |||
@@ -33,7 +33,11 @@ impl ShortLabel for ast::EnumDef { | |||
33 | 33 | ||
34 | impl ShortLabel for ast::TraitDef { | 34 | impl ShortLabel for ast::TraitDef { |
35 | fn short_label(&self) -> Option<String> { | 35 | fn short_label(&self) -> Option<String> { |
36 | short_label_from_node(self, "trait ") | 36 | if self.unsafe_token().is_some() { |
37 | short_label_from_node(self, "unsafe trait ") | ||
38 | } else { | ||
39 | short_label_from_node(self, "trait ") | ||
40 | } | ||
37 | } | 41 | } |
38 | } | 42 | } |
39 | 43 | ||
diff --git a/crates/ra_ide/src/folding_ranges.rs b/crates/ra_ide/src/folding_ranges.rs index 4379005aa..8657377de 100644 --- a/crates/ra_ide/src/folding_ranges.rs +++ b/crates/ra_ide/src/folding_ranges.rs | |||
@@ -88,7 +88,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> { | |||
88 | | ITEM_LIST | 88 | | ITEM_LIST |
89 | | EXTERN_ITEM_LIST | 89 | | EXTERN_ITEM_LIST |
90 | | USE_TREE_LIST | 90 | | USE_TREE_LIST |
91 | | BLOCK | 91 | | BLOCK_EXPR |
92 | | MATCH_ARM_LIST | 92 | | MATCH_ARM_LIST |
93 | | ENUM_VARIANT_LIST | 93 | | ENUM_VARIANT_LIST |
94 | | TOKEN_TREE => Some(FoldKind::Block), | 94 | | TOKEN_TREE => Some(FoldKind::Block), |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index a62f598f0..54d318858 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -869,4 +869,15 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
869 | &[r#"pub(crate) async unsafe extern "C" fn foo()"#], | 869 | &[r#"pub(crate) async unsafe extern "C" fn foo()"#], |
870 | ); | 870 | ); |
871 | } | 871 | } |
872 | |||
873 | #[test] | ||
874 | fn test_hover_trait_show_qualifiers() { | ||
875 | check_hover_result( | ||
876 | " | ||
877 | //- /lib.rs | ||
878 | unsafe trait foo<|>() {} | ||
879 | ", | ||
880 | &["unsafe trait foo"], | ||
881 | ); | ||
882 | } | ||
872 | } | 883 | } |
diff --git a/crates/ra_ide/src/join_lines.rs b/crates/ra_ide/src/join_lines.rs index d0def7eaa..63fd6b3e4 100644 --- a/crates/ra_ide/src/join_lines.rs +++ b/crates/ra_ide/src/join_lines.rs | |||
@@ -129,8 +129,7 @@ fn has_comma_after(node: &SyntaxNode) -> bool { | |||
129 | } | 129 | } |
130 | 130 | ||
131 | fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> { | 131 | fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> { |
132 | let block = ast::Block::cast(token.parent())?; | 132 | let block_expr = ast::BlockExpr::cast(token.parent())?; |
133 | let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; | ||
134 | if !block_expr.is_standalone() { | 133 | if !block_expr.is_standalone() { |
135 | return None; | 134 | return None; |
136 | } | 135 | } |
diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs index bf97f8c56..86c70ff83 100644 --- a/crates/ra_ide/src/syntax_tree.rs +++ b/crates/ra_ide/src/syntax_tree.rs | |||
@@ -120,9 +120,8 @@ [email protected] | |||
120 | [email protected] ")" | 120 | [email protected] ")" |
121 | [email protected] " " | 121 | [email protected] " " |
122 | [email protected] | 122 | [email protected] |
123 | [email protected] | 123 | [email protected] "{" |
124 | [email protected] "{" | 124 | [email protected] "}" |
125 | [email protected] "}" | ||
126 | "# | 125 | "# |
127 | .trim() | 126 | .trim() |
128 | ); | 127 | ); |
@@ -153,26 +152,25 @@ [email protected] | |||
153 | [email protected] ")" | 152 | [email protected] ")" |
154 | [email protected] " " | 153 | [email protected] " " |
155 | [email protected] | 154 | [email protected] |
156 | [email protected] | 155 | [email protected] "{" |
157 | [email protected] "{" | 156 | [email protected] "\n " |
158 | [email protected] "\n " | 157 | [email protected] |
159 | [email protected] | 158 | [email protected] |
160 | [email protected] | 159 | [email protected] |
161 | [email protected] | 160 | [email protected] |
162 | [email protected] | 161 | [email protected] |
163 | [email protected] | 162 | [email protected] "assert" |
164 | [email protected] "assert" | 163 | [email protected] "!" |
165 | [email protected] "!" | 164 | [email protected] |
166 | [email protected] | 165 | [email protected] "(" |
167 | [email protected] "(" | 166 | [email protected] "\"\n fn foo() {\n ..." |
168 | [email protected] "\"\n fn foo() {\n ..." | 167 | [email protected] "," |
169 | [email protected] "," | 168 | [email protected] " " |
170 | [email protected] " " | 169 | [email protected] "\"\"" |
171 | [email protected] "\"\"" | 170 | [email protected] ")" |
172 | [email protected] ")" | 171 | [email protected] ";" |
173 | [email protected] ";" | 172 | [email protected] "\n" |
174 | [email protected] "\n" | 173 | [email protected] "}" |
175 | [email protected] "}" | ||
176 | "# | 174 | "# |
177 | .trim() | 175 | .trim() |
178 | ); | 176 | ); |
@@ -196,9 +194,8 @@ [email protected] | |||
196 | [email protected] ")" | 194 | [email protected] ")" |
197 | [email protected] " " | 195 | [email protected] " " |
198 | [email protected] | 196 | [email protected] |
199 | [email protected] | 197 | [email protected] "{" |
200 | [email protected] "{" | 198 | [email protected] "}" |
201 | [email protected] "}" | ||
202 | "# | 199 | "# |
203 | .trim() | 200 | .trim() |
204 | ); | 201 | ); |
@@ -265,10 +262,9 @@ [email protected] | |||
265 | [email protected] ")" | 262 | [email protected] ")" |
266 | [email protected] " " | 263 | [email protected] " " |
267 | [email protected] | 264 | [email protected] |
268 | [email protected] | 265 | [email protected] "{" |
269 | [email protected] "{" | 266 | [email protected] "\n" |
270 | [email protected] "\n" | 267 | [email protected] "}" |
271 | [email protected] "}" | ||
272 | "# | 268 | "# |
273 | .trim() | 269 | .trim() |
274 | ); | 270 | ); |
@@ -300,10 +296,9 @@ [email protected] | |||
300 | [email protected] ")" | 296 | [email protected] ")" |
301 | [email protected] " " | 297 | [email protected] " " |
302 | [email protected] | 298 | [email protected] |
303 | [email protected] | 299 | [email protected] "{" |
304 | [email protected] "{" | 300 | [email protected] "\n" |
305 | [email protected] "\n" | 301 | [email protected] "}" |
306 | [email protected] "}" | ||
307 | "# | 302 | "# |
308 | .trim() | 303 | .trim() |
309 | ); | 304 | ); |
@@ -334,10 +329,9 @@ [email protected] | |||
334 | [email protected] ")" | 329 | [email protected] ")" |
335 | [email protected] " " | 330 | [email protected] " " |
336 | [email protected] | 331 | [email protected] |
337 | [email protected] | 332 | [email protected] "{" |
338 | [email protected] "{" | 333 | [email protected] "\n" |
339 | [email protected] "\n" | 334 | [email protected] "}" |
340 | [email protected] "}" | ||
341 | [email protected] "\n" | 335 | [email protected] "\n" |
342 | [email protected] | 336 | [email protected] |
343 | [email protected] "fn" | 337 | [email protected] "fn" |
@@ -349,10 +343,9 @@ [email protected] | |||
349 | [email protected] ")" | 343 | [email protected] ")" |
350 | [email protected] " " | 344 | [email protected] " " |
351 | [email protected] | 345 | [email protected] |
352 | [email protected] | 346 | [email protected] "{" |
353 | [email protected] "{" | 347 | [email protected] "\n" |
354 | [email protected] "\n" | 348 | [email protected] "}" |
355 | [email protected] "}" | ||
356 | "# | 349 | "# |
357 | .trim() | 350 | .trim() |
358 | ); | 351 | ); |