use super::*; use expect_test::expect; #[test] fn inner_item_smoke() { check_at( r#" struct inner {} fn outer() { $0 fn inner() {} } "#, expect![[r#" (block scope) - inner : value crate - inner : type - outer : value "#]], ); } #[test] fn use_from_crate() { check_at( r#" struct Struct {} fn outer() { fn Struct() {} use Struct as PlainStruct; use crate::Struct as CrateStruct; use self::Struct as SelfStruct; use super::Struct as SuperStruct; $0 } "#, expect![[r#" (block scope) - CrateStruct : type (import) - PlainStruct : type (import) value (import) - SelfStruct : type (import) - Struct : value - SuperStruct : _ crate - Struct : type - outer : value "#]], ); } #[test] fn merge_namespaces() { check_at( r#" struct name {} fn outer() { fn name() {} use name as imported; // should import both `name`s $0 } "#, expect![[r#" (block scope) - imported : type (import) value (import) - name : value crate - name : type - outer : value "#]], ); } #[test] fn nested_blocks() { check_at( r#" fn outer() { struct inner1 {} fn inner() { use inner1; use outer; fn inner2() {} $0 } } "#, expect![[r#" (block scope) - inner1 : type (import) - inner2 : value - outer : value (import) (block scope) - inner : value - inner1 : type crate - outer : value "#]], ); } #[test] fn super_imports() { check_at( r#" mod module { fn f() { use super::Struct; $0 } } struct Struct {} "#, expect![[r#" (block scope) - Struct : type (import) crate - Struct : type - module : type crate::module - f : value "#]], ); } #[test] fn super_imports_2() { check_at( r#" fn outer() { mod m { struct ResolveMe {} fn middle() { mod m2 { fn inner() { use super::ResolveMe; $0 } } } } } "#, expect![[r#" (block scope) - ResolveMe : type (import) (block scope) - m2 : type (block scope)::m2 - inner : value (block scope) - m : type (block scope)::m - ResolveMe : type - middle : value crate - outer : value "#]], ); } #[test] fn nested_module_scoping() { check_block_scopes_at( r#" fn f() { mod module { struct Struct {} fn f() { use self::Struct; $0 } } } "#, expect![[r#" ModuleIdLt { [salsa id]: Id(3803), krate: Crate( Id(2400), ), block: Some( BlockId( 4401, ), ), }"#]], ); } #[test] fn self_imports() { check_at( r#" fn f() { mod m { struct ResolveMe {} fn g() { fn h() { use self::ResolveMe; $0 } } } } "#, expect![[r#" (block scope) - ResolveMe : type (import) (block scope) - h : value (block scope) - m : type (block scope)::m - ResolveMe : type - g : value crate - f : value "#]], ); } #[test] fn legacy_macro_items() { // Checks that legacy-scoped `macro_rules!` from parent namespaces are resolved and expanded // correctly. check_at( r#" macro_rules! mark { () => { struct Hit {} } } fn f() { mark!(); $0 } "#, expect![[r#" (block scope) - Hit : type crate - f : value - (legacy) mark : macro! "#]], ); } #[test] fn macro_resolve() { check_at( r#" //- /lib.rs crate:lib deps:core use core::cov_mark; fn f() { fn nested() { cov_mark::mark!(Hit); $0 } } //- /core.rs crate:core pub mod cov_mark { #[macro_export] macro_rules! _mark { ($name:ident) => { struct $name {} } } pub use crate::_mark as mark; } "#, expect![[r#" (block scope) - Hit : type (block scope) - nested : value crate - cov_mark : type (import) - f : value "#]], ); } #[test] fn macro_exported_in_block_mod() { check_at( r#" #[macro_export] macro_rules! foo { () => { pub struct FooWorks; }; } macro_rules! bar { () => { pub struct BarWorks; }; } fn main() { mod module { foo!(); bar!(); $0 } } "#, expect![[r#" (block scope) - module : type (block scope)::module - BarWorks : type value - FooWorks : type value crate - foo : macro! - main : value - (legacy) bar : macro! - (legacy) foo : macro! "#]], ); } #[test] fn macro_resolve_legacy() { check_at( r#" //- /lib.rs mod module; //- /module.rs macro_rules! m { () => { struct Def {} }; } fn f() { { m!(); $0 } } "#, expect![[r#" (block scope) - Def : type crate - module : type crate::module - f : value - (legacy) m : macro! "#]], ) } #[test] fn super_does_not_resolve_to_block_module() { check_at( r#" fn main() { struct Struct {} mod module { use super::Struct; $0 } } "#, expect![[r#" (block scope) - Struct : type - module : type (block scope)::module - Struct : _ crate - main : value "#]], ); } #[test] fn underscore_import() { // This used to panic, because the default (private) visibility inside block expressions would // point into the containing `DefMap`, which visibilities should never be able to do. check_at( r#" mod m { fn main() { use Tr as _; trait Tr {} $0 } } "#, expect![[r#" (block scope) - _ : type - Tr : type crate - m : type crate::m - main : value "#]], ); } #[test] fn nested_macro_item_decl() { cov_mark::check!(macro_call_in_macro_stmts_is_added_to_item_tree); check_at( r#" macro_rules! inner_declare { ($ident:ident) => { static $ident: u32 = 0; }; } macro_rules! declare { ($ident:ident) => { inner_declare!($ident); }; } fn foo() { declare!(bar); bar; $0 } "#, expect![[r#" (block scope) - bar : value crate - foo : value - (legacy) declare : macro! - (legacy) inner_declare : macro! "#]], ) } #[test] fn is_visible_from_same_def_map_regression_9481() { // Regression test for https://github.com/rust-lang/rust-analyzer/issues/9481 check_at( r#" fn outer() { mod tests { use super::*; } use crate::name; $0 } "#, expect![[r#" (block scope) - name : _ - tests : type (block scope)::tests - outer : value (glob) crate - outer : value "#]], ); } #[test] fn stmt_macro_expansion_with_trailing_expr() { cov_mark::check!(macro_stmt_with_trailing_macro_expr); check_at( r#" macro_rules! mac { () => { mac!($) }; ($x:tt) => { fn inner() {} }; } fn foo() { mac!(); $0 } "#, expect![[r#" (block scope) - inner : value crate - foo : value - (legacy) mac : macro! "#]], ) } #[test] fn trailing_expr_macro_expands_stmts() { check_at( r#" macro_rules! foo { () => { const FOO: u32 = 0;const BAR: u32 = 0; }; } fn f() {$0 foo!{} }; "#, expect![[r#" (block scope) - BAR : value - FOO : value crate - f : value - (legacy) foo : macro! "#]], ) } #[test] fn resolve_extern_prelude_in_block() { check_at( r#" //- /main.rs crate:main deps:core fn main() { mod f { use core::S; $0 } } //- /core.rs crate:core pub struct S; "#, expect![[r#" (block scope) - f : type (block scope)::f - S : type (import) value (import) crate - main : value "#]], ) } #[test] fn shadow_extern_prelude_in_block() { check_at( r#" //- /main.rs crate:main deps:core fn main() { mod core { pub struct S; } { fn inner() {} // forces a block def map use core::S; // should resolve to the local one $0 } } //- /core.rs crate:core pub const S; "#, expect![[r#" (block scope) - S : type (import) value (import) - inner : value (block scope) - core : type (block scope)::core - S : type value crate - main : value "#]], ) }