diff options
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 6 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/macros.rs | 22 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/add_explicit_type.rs | 25 |
3 files changed, 46 insertions, 7 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 0e741194b..be645a25d 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -367,6 +367,8 @@ impl DefCollector<'_> { | |||
367 | /// This improves UX when proc macros are turned off or don't work, and replicates the behavior | 367 | /// This improves UX when proc macros are turned off or don't work, and replicates the behavior |
368 | /// before we supported proc. attribute macros. | 368 | /// before we supported proc. attribute macros. |
369 | fn reseed_with_unresolved_attributes(&mut self) -> ReachedFixedPoint { | 369 | fn reseed_with_unresolved_attributes(&mut self) -> ReachedFixedPoint { |
370 | cov_mark::hit!(unresolved_attribute_fallback); | ||
371 | |||
370 | let mut added_items = false; | 372 | let mut added_items = false; |
371 | let unexpanded_macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); | 373 | let unexpanded_macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); |
372 | for directive in &unexpanded_macros { | 374 | for directive in &unexpanded_macros { |
@@ -391,7 +393,9 @@ impl DefCollector<'_> { | |||
391 | added_items = true; | 393 | added_items = true; |
392 | } | 394 | } |
393 | } | 395 | } |
394 | self.unexpanded_macros = unexpanded_macros; | 396 | |
397 | // The collection above might add new unresolved macros (eg. derives), so merge the lists. | ||
398 | self.unexpanded_macros.extend(unexpanded_macros); | ||
395 | 399 | ||
396 | if added_items { | 400 | if added_items { |
397 | // Continue name resolution with the new data. | 401 | // Continue name resolution with the new data. |
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index c37f915ab..b34ba885d 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs | |||
@@ -686,6 +686,27 @@ pub trait Clone {} | |||
686 | } | 686 | } |
687 | 687 | ||
688 | #[test] | 688 | #[test] |
689 | fn builtin_derive_with_unresolved_attributes_fall_back() { | ||
690 | // Tests that we still resolve derives after ignoring an unresolved attribute. | ||
691 | cov_mark::check!(unresolved_attribute_fallback); | ||
692 | let map = compute_crate_def_map( | ||
693 | r#" | ||
694 | //- /main.rs crate:main deps:core | ||
695 | use core::Clone; | ||
696 | |||
697 | #[derive(Clone)] | ||
698 | #[unresolved] | ||
699 | struct Foo; | ||
700 | |||
701 | //- /core.rs crate:core | ||
702 | #[rustc_builtin_macro] | ||
703 | pub macro Clone {} | ||
704 | "#, | ||
705 | ); | ||
706 | assert_eq!(map.modules[map.root].scope.impls().len(), 1); | ||
707 | } | ||
708 | |||
709 | #[test] | ||
689 | fn macro_expansion_overflow() { | 710 | fn macro_expansion_overflow() { |
690 | cov_mark::check!(macro_expansion_overflow); | 711 | cov_mark::check!(macro_expansion_overflow); |
691 | check( | 712 | check( |
@@ -842,7 +863,6 @@ fn collects_derive_helpers() { | |||
842 | fn resolve_macro_def() { | 863 | fn resolve_macro_def() { |
843 | check( | 864 | check( |
844 | r#" | 865 | r#" |
845 | //- /lib.rs | ||
846 | pub macro structs($($i:ident),*) { | 866 | pub macro structs($($i:ident),*) { |
847 | $(struct $i { field: u32 } )* | 867 | $(struct $i { field: u32 } )* |
848 | } | 868 | } |
diff --git a/crates/ide_assists/src/handlers/add_explicit_type.rs b/crates/ide_assists/src/handlers/add_explicit_type.rs index 36589203d..b7617ca3d 100644 --- a/crates/ide_assists/src/handlers/add_explicit_type.rs +++ b/crates/ide_assists/src/handlers/add_explicit_type.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use hir::HirDisplay; | 1 | use hir::HirDisplay; |
2 | use syntax::{ | 2 | use syntax::{ |
3 | ast::{self, AstNode, LetStmt, NameOwner}, | 3 | ast::{self, AstNode, LetStmt}, |
4 | TextRange, | 4 | TextRange, |
5 | }; | 5 | }; |
6 | 6 | ||
@@ -31,9 +31,6 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio | |||
31 | _ => return None, | 31 | _ => return None, |
32 | }; | 32 | }; |
33 | let pat_range = pat.syntax().text_range(); | 33 | let pat_range = pat.syntax().text_range(); |
34 | // The binding must have a name | ||
35 | let name = pat.name()?; | ||
36 | let name_range = name.syntax().text_range(); | ||
37 | 34 | ||
38 | // Assist should only be applicable if cursor is between 'let' and '=' | 35 | // Assist should only be applicable if cursor is between 'let' and '=' |
39 | let cursor_in_range = { | 36 | let cursor_in_range = { |
@@ -74,7 +71,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio | |||
74 | builder.replace(ascribed_ty.syntax().text_range(), inferred_type); | 71 | builder.replace(ascribed_ty.syntax().text_range(), inferred_type); |
75 | } | 72 | } |
76 | None => { | 73 | None => { |
77 | builder.insert(name_range.end(), format!(": {}", inferred_type)); | 74 | builder.insert(pat_range.end(), format!(": {}", inferred_type)); |
78 | } | 75 | } |
79 | }, | 76 | }, |
80 | ) | 77 | ) |
@@ -246,4 +243,22 @@ fn main() { | |||
246 | "#, | 243 | "#, |
247 | ); | 244 | ); |
248 | } | 245 | } |
246 | |||
247 | #[test] | ||
248 | fn type_should_be_added_after_pattern() { | ||
249 | // LetStmt = Attr* 'let' Pat (':' Type)? '=' initializer:Expr ';' | ||
250 | check_assist( | ||
251 | add_explicit_type, | ||
252 | r#" | ||
253 | fn main() { | ||
254 | let $0test @ () = (); | ||
255 | } | ||
256 | "#, | ||
257 | r#" | ||
258 | fn main() { | ||
259 | let test @ (): () = (); | ||
260 | } | ||
261 | "#, | ||
262 | ); | ||
263 | } | ||
249 | } | 264 | } |