blob: 1af16ef857d03696b8ac523904f1652c5c9a51db [file] [log] [blame]
use expect_test::{expect, Expect};
use crate::{
context::{CompletionAnalysis, NameContext, NameKind, NameRefKind},
tests::{check_edit, check_edit_with_config, TEST_CONFIG},
};
fn check(ra_fixture: &str, expect: Expect) {
let config = TEST_CONFIG;
let (db, position) = crate::tests::position(ra_fixture);
let (ctx, analysis) = crate::context::CompletionContext::new(&db, position, &config).unwrap();
let mut acc = crate::completions::Completions::default();
if let CompletionAnalysis::Name(NameContext { kind: NameKind::IdentPat(pat_ctx), .. }) =
&analysis
{
crate::completions::flyimport::import_on_the_fly_pat(&mut acc, &ctx, pat_ctx);
}
if let CompletionAnalysis::NameRef(name_ref_ctx) = &analysis {
match &name_ref_ctx.kind {
NameRefKind::Path(path) => {
crate::completions::flyimport::import_on_the_fly_path(&mut acc, &ctx, path);
}
NameRefKind::DotAccess(dot_access) => {
crate::completions::flyimport::import_on_the_fly_dot(&mut acc, &ctx, dot_access);
}
NameRefKind::Pattern(pattern) => {
crate::completions::flyimport::import_on_the_fly_pat(&mut acc, &ctx, pattern);
}
_ => (),
}
}
expect.assert_eq(&super::render_completion_list(Vec::from(acc)));
}
#[test]
fn function_fuzzy_completion() {
check_edit(
"stdin",
r#"
//- /lib.rs crate:dep
pub mod io {
pub fn stdin() {}
};
//- /main.rs crate:main deps:dep
fn main() {
stdi$0
}
"#,
r#"
use dep::io::stdin;
fn main() {
stdin()$0
}
"#,
);
}
#[test]
fn macro_fuzzy_completion() {
check_edit(
"macro_with_curlies!",
r#"
//- /lib.rs crate:dep
/// Please call me as macro_with_curlies! {}
#[macro_export]
macro_rules! macro_with_curlies {
() => {}
}
//- /main.rs crate:main deps:dep
fn main() {
curli$0
}
"#,
r#"
use dep::macro_with_curlies;
fn main() {
macro_with_curlies! {$0}
}
"#,
);
}
#[test]
fn struct_fuzzy_completion() {
check_edit(
"ThirdStruct",
r#"
//- /lib.rs crate:dep
pub struct FirstStruct;
pub mod some_module {
pub struct SecondStruct;
pub struct ThirdStruct;
}
//- /main.rs crate:main deps:dep
use dep::{FirstStruct, some_module::SecondStruct};
fn main() {
this$0
}
"#,
r#"
use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};
fn main() {
ThirdStruct
}
"#,
);
}
#[test]
fn short_paths_are_prefix_matched() {
cov_mark::check!(flyimport_prefix_on_short_path);
check(
r#"
//- /lib.rs crate:dep
pub struct Barc;
pub struct Rcar;
pub struct Rc;
pub const RC: () = ();
pub mod some_module {
pub struct Bar;
pub struct Rcar;
pub struct Rc;
pub const RC: () = ();
}
//- /main.rs crate:main deps:dep
fn main() {
Rc$0
}
"#,
expect![[r#"
st Rc (use dep::Rc) Rc
st Rcar (use dep::Rcar) Rcar
st Rc (use dep::some_module::Rc) Rc
st Rcar (use dep::some_module::Rcar) Rcar
"#]],
);
check(
r#"
//- /lib.rs crate:dep
pub struct Barc;
pub struct Rcar;
pub struct Rc;
pub const RC: () = ();
pub mod some_module {
pub struct Bar;
pub struct Rcar;
pub struct Rc;
pub const RC: () = ();
}
//- /main.rs crate:main deps:dep
fn main() {
rc$0
}
"#,
expect![[r#"
ct RC (use dep::RC) ()
st Rc (use dep::Rc) Rc
st Rcar (use dep::Rcar) Rcar
ct RC (use dep::some_module::RC) ()
st Rc (use dep::some_module::Rc) Rc
st Rcar (use dep::some_module::Rcar) Rcar
"#]],
);
check(
r#"
//- /lib.rs crate:dep
pub struct Barc;
pub struct Rcar;
pub struct Rc;
pub const RC: () = ();
pub mod some_module {
pub struct Bar;
pub struct Rcar;
pub struct Rc;
pub const RC: () = ();
}
//- /main.rs crate:main deps:dep
fn main() {
RC$0
}
"#,
expect![[r#"
ct RC (use dep::RC) ()
ct RC (use dep::some_module::RC) ()
"#]],
);
}
#[test]
fn fuzzy_completions_come_in_specific_order() {
cov_mark::check!(certain_fuzzy_order_test);
check(
r#"
//- /lib.rs crate:dep
pub struct FirstStruct;
pub mod some_module {
// already imported, omitted
pub struct SecondStruct;
// does not contain all letters from the query, omitted
pub struct UnrelatedOne;
// contains all letters from the query, but not in sequence, displayed last
pub struct ThiiiiiirdStruct;
// contains all letters from the query, but not in the beginning, displayed second
pub struct AfterThirdStruct;
// contains all letters from the query in the beginning, displayed first
pub struct ThirdStruct;
}
//- /main.rs crate:main deps:dep
use dep::{FirstStruct, some_module::SecondStruct};
fn main() {
hir$0
}
"#,
expect![[r#"
st ThirdStruct (use dep::some_module::ThirdStruct) ThirdStruct
st AfterThirdStruct (use dep::some_module::AfterThirdStruct) AfterThirdStruct
st ThiiiiiirdStruct (use dep::some_module::ThiiiiiirdStruct) ThiiiiiirdStruct
"#]],
);
}
#[test]
fn trait_function_fuzzy_completion() {
let fixture = r#"
//- /lib.rs crate:dep
pub mod test_mod {
pub trait TestTrait {
const SPECIAL_CONST: u8;
type HumbleType;
fn weird_function();
fn random_method(&self);
}
pub struct TestStruct {}
impl TestTrait for TestStruct {
const SPECIAL_CONST: u8 = 42;
type HumbleType = ();
fn weird_function() {}
fn random_method(&self) {}
}
}
//- /main.rs crate:main deps:dep
fn main() {
dep::test_mod::TestStruct::wei$0
}
"#;
check(
fixture,
expect![[r#"
fn weird_function() (use dep::test_mod::TestTrait) fn()
"#]],
);
check_edit(
"weird_function",
fixture,
r#"
use dep::test_mod::TestTrait;
fn main() {
dep::test_mod::TestStruct::weird_function()$0
}
"#,
);
}
#[test]
fn trait_const_fuzzy_completion() {
let fixture = r#"
//- /lib.rs crate:dep
pub mod test_mod {
pub trait TestTrait {
const SPECIAL_CONST: u8;
type HumbleType;
fn weird_function();
fn random_method(&self);
}
pub struct TestStruct {}
impl TestTrait for TestStruct {
const SPECIAL_CONST: u8 = 42;
type HumbleType = ();
fn weird_function() {}
fn random_method(&self) {}
}
}
//- /main.rs crate:main deps:dep
fn main() {
dep::test_mod::TestStruct::spe$0
}
"#;
check(
fixture,
expect![[r#"
ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8
"#]],
);
check_edit(
"SPECIAL_CONST",
fixture,
r#"
use dep::test_mod::TestTrait;
fn main() {
dep::test_mod::TestStruct::SPECIAL_CONST
}
"#,
);
}
#[test]
fn trait_method_fuzzy_completion() {
let fixture = r#"
//- /lib.rs crate:dep
pub mod test_mod {
pub trait TestTrait {
const SPECIAL_CONST: u8;
type HumbleType;
fn weird_function();
fn random_method(&self);
}
pub struct TestStruct {}
impl TestTrait for TestStruct {
const SPECIAL_CONST: u8 = 42;
type HumbleType = ();
fn weird_function() {}
fn random_method(&self) {}
}
}
//- /main.rs crate:main deps:dep
fn main() {
let test_struct = dep::test_mod::TestStruct {};
test_struct.ran$0
}
"#;
check(
fixture,
expect![[r#"
me random_method() (use dep::test_mod::TestTrait) fn(&self)
"#]],
);
check_edit(
"random_method",
fixture,
r#"
use dep::test_mod::TestTrait;
fn main() {
let test_struct = dep::test_mod::TestStruct {};
test_struct.random_method()$0
}
"#,
);
}
#[test]
fn trait_method_from_alias() {
let fixture = r#"
//- /lib.rs crate:dep
pub mod test_mod {
pub trait TestTrait {
fn random_method();
}
pub struct TestStruct {}
impl TestTrait for TestStruct {
fn random_method() {}
}
pub type TestAlias = TestStruct;
}
//- /main.rs crate:main deps:dep
fn main() {
dep::test_mod::TestAlias::ran$0
}
"#;
check(
fixture,
expect![[r#"
fn random_method() (use dep::test_mod::TestTrait) fn()
"#]],
);
check_edit(
"random_method",
fixture,
r#"
use dep::test_mod::TestTrait;
fn main() {
dep::test_mod::TestAlias::random_method()$0
}
"#,
);
}
#[test]
fn no_trait_type_fuzzy_completion() {
check(
r#"
//- /lib.rs crate:dep
pub mod test_mod {
pub trait TestTrait {
const SPECIAL_CONST: u8;
type HumbleType;
fn weird_function();
fn random_method(&self);
}
pub struct TestStruct {}
impl TestTrait for TestStruct {
const SPECIAL_CONST: u8 = 42;
type HumbleType = ();
fn weird_function() {}
fn random_method(&self) {}
}
}
//- /main.rs crate:main deps:dep
fn main() {
dep::test_mod::TestStruct::hum$0
}
"#,
expect![[r#""#]],
);
}
#[test]
fn does_not_propose_names_in_scope() {
check(
r#"
//- /lib.rs crate:dep
pub mod test_mod {
pub trait TestTrait {
const SPECIAL_CONST: u8;
type HumbleType;
fn weird_function();
fn random_method(&self);
}
pub struct TestStruct {}
impl TestTrait for TestStruct {
const SPECIAL_CONST: u8 = 42;
type HumbleType = ();
fn weird_function() {}
fn random_method(&self) {}
}
}
//- /main.rs crate:main deps:dep
use dep::test_mod::TestStruct;
fn main() {
TestSt$0
}
"#,
expect![[r#""#]],
);
}
#[test]
fn does_not_propose_traits_in_scope() {
check(
r#"
//- /lib.rs crate:dep
pub mod test_mod {
pub trait TestTrait {
const SPECIAL_CONST: u8;
type HumbleType;
fn weird_function();
fn random_method(&self);
}
pub struct TestStruct {}
impl TestTrait for TestStruct {
const SPECIAL_CONST: u8 = 42;
type HumbleType = ();
fn weird_function() {}
fn random_method(&self) {}
}
}
//- /main.rs crate:main deps:dep
use dep::test_mod::{TestStruct, TestTrait};
fn main() {
dep::test_mod::TestStruct::hum$0
}
"#,
expect![[r#""#]],
);
}
#[test]
fn blanket_trait_impl_import() {
check_edit(
"another_function",
r#"
//- /lib.rs crate:dep
pub mod test_mod {
pub struct TestStruct {}
pub trait TestTrait {
fn another_function();
}
impl<T> TestTrait for T {
fn another_function() {}
}
}
//- /main.rs crate:main deps:dep
fn main() {
dep::test_mod::TestStruct::ano$0
}
"#,
r#"
use dep::test_mod::TestTrait;
fn main() {
dep::test_mod::TestStruct::another_function()$0
}
"#,
);
}
#[test]
fn zero_input_deprecated_assoc_item_completion() {
check(
r#"
//- /lib.rs crate:dep
pub mod test_mod {
#[deprecated]
pub trait TestTrait {
const SPECIAL_CONST: u8;
type HumbleType;
fn weird_function();
fn random_method(&self);
}
pub struct TestStruct {}
impl TestTrait for TestStruct {
const SPECIAL_CONST: u8 = 42;
type HumbleType = ();
fn weird_function() {}
fn random_method(&self) {}
}
}
//- /main.rs crate:main deps:dep
fn main() {
let test_struct = dep::test_mod::TestStruct {};
test_struct.$0
}
"#,
expect![[r#"
me random_method() (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
"#]],
);
check(
r#"
//- /lib.rs crate:dep
pub mod test_mod {
#[deprecated]
pub trait TestTrait {
const SPECIAL_CONST: u8;
type HumbleType;
fn weird_function();
fn random_method(&self);
}
pub struct TestStruct {}
impl TestTrait for TestStruct {
const SPECIAL_CONST: u8 = 42;
type HumbleType = ();
fn weird_function() {}
fn random_method(&self) {}
}
}
//- /main.rs crate:main deps:dep
fn main() {
dep::test_mod::TestStruct::$0
}
"#,
expect![[r#"
fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED
me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
"#]],
);
}
#[test]
fn no_completions_in_use_statements() {
check(
r#"
//- /lib.rs crate:dep
pub mod io {
pub fn stdin() {}
};
//- /main.rs crate:main deps:dep
use stdi$0
fn main() {}
"#,
expect![[]],
);
}
#[test]
fn prefix_config_usage() {
let fixture = r#"
mod foo {
pub mod bar {
pub struct Item;
}
}
use crate::foo::bar;
fn main() {
Ite$0
}"#;
let mut config = TEST_CONFIG;
config.insert_use.prefix_kind = hir::PrefixKind::ByCrate;
check_edit_with_config(
config.clone(),
"Item",
fixture,
r#"
mod foo {
pub mod bar {
pub struct Item;
}
}
use crate::foo::bar::{self, Item};
fn main() {
Item
}"#,
);
config.insert_use.prefix_kind = hir::PrefixKind::BySelf;
check_edit_with_config(
config.clone(),
"Item",
fixture,
r#"
mod foo {
pub mod bar {
pub struct Item;
}
}
use crate::foo::bar;
use self::foo::bar::Item;
fn main() {
Item
}"#,
);
config.insert_use.prefix_kind = hir::PrefixKind::Plain;
check_edit_with_config(
config,
"Item",
fixture,
r#"
mod foo {
pub mod bar {
pub struct Item;
}
}
use foo::bar::Item;
use crate::foo::bar;
fn main() {
Item
}"#,
);
}
#[test]
fn unresolved_qualifier() {
let fixture = r#"
mod foo {
pub mod bar {
pub mod baz {
pub struct Item;
}
}
}
fn main() {
bar::baz::Ite$0
}"#;
check(
fixture,
expect![[r#"
st Item (use foo::bar) Item
"#]],
);
check_edit(
"Item",
fixture,
r#"
use foo::bar;
mod foo {
pub mod bar {
pub mod baz {
pub struct Item;
}
}
}
fn main() {
bar::baz::Item
}"#,
);
}
#[test]
fn unresolved_assoc_item_container() {
let fixture = r#"
mod foo {
pub struct Item;
impl Item {
pub const TEST_ASSOC: usize = 3;
}
}
fn main() {
Item::TEST_A$0
}"#;
check(
fixture,
expect![[r#"
ct TEST_ASSOC (use foo::Item) usize
"#]],
);
check_edit(
"TEST_ASSOC",
fixture,
r#"
use foo::Item;
mod foo {
pub struct Item;
impl Item {
pub const TEST_ASSOC: usize = 3;
}
}
fn main() {
Item::TEST_ASSOC
}"#,
);
}
#[test]
fn unresolved_assoc_item_container_with_path() {
let fixture = r#"
mod foo {
pub mod bar {
pub struct Item;
impl Item {
pub const TEST_ASSOC: usize = 3;
}
}
}
fn main() {
bar::Item::TEST_A$0
}"#;
check(
fixture,
expect![[r#"
ct TEST_ASSOC (use foo::bar) usize
"#]],
);
check_edit(
"TEST_ASSOC",
fixture,
r#"
use foo::bar;
mod foo {
pub mod bar {
pub struct Item;
impl Item {
pub const TEST_ASSOC: usize = 3;
}
}
}
fn main() {
bar::Item::TEST_ASSOC
}"#,
);
}
#[test]
fn fuzzy_unresolved_path() {
check(
r#"
mod foo {
pub mod bar {
pub struct Item;
impl Item {
pub const TEST_ASSOC: usize = 3;
}
}
}
fn main() {
bar::ASS$0
}"#,
expect![[]],
)
}
#[test]
fn unqualified_assoc_items_are_omitted() {
check(
r#"
mod something {
pub trait BaseTrait {
fn test_function() -> i32;
}
pub struct Item1;
pub struct Item2;
impl BaseTrait for Item1 {
fn test_function() -> i32 {
1
}
}
impl BaseTrait for Item2 {
fn test_function() -> i32 {
2
}
}
}
fn main() {
test_f$0
}"#,
expect![[]],
)
}
#[test]
fn case_matters() {
check(
r#"
mod foo {
pub const TEST_CONST: usize = 3;
pub fn test_function() -> i32 {
4
}
}
fn main() {
TES$0
}"#,
expect![[r#"
ct TEST_CONST (use foo::TEST_CONST) usize
"#]],
);
check(
r#"
mod foo {
pub const TEST_CONST: usize = 3;
pub fn test_function() -> i32 {
4
}
}
fn main() {
tes$0
}"#,
expect![[r#"
ct TEST_CONST (use foo::TEST_CONST) usize
fn test_function() (use foo::test_function) fn() -> i32
"#]],
);
check(
r#"
mod foo {
pub const TEST_CONST: usize = 3;
pub fn test_function() -> i32 {
4
}
}
fn main() {
Tes$0
}"#,
expect![""],
);
}
#[test]
fn no_fuzzy_during_fields_of_record_lit_syntax() {
check(
r#"
mod m {
pub fn some_fn() -> i32 {
42
}
}
struct Foo {
some_field: i32,
}
fn main() {
let _ = Foo { so$0 };
}
"#,
expect![[]],
);
}
#[test]
fn fuzzy_after_fields_of_record_lit_syntax() {
check(
r#"
mod m {
pub fn some_fn() -> i32 {
42
}
}
struct Foo {
some_field: i32,
}
fn main() {
let _ = Foo { some_field: som$0 };
}
"#,
expect![[r#"
fn some_fn() (use m::some_fn) fn() -> i32
"#]],
);
}
#[test]
fn no_flyimports_in_traits_and_impl_declarations() {
check(
r#"
mod m {
pub fn some_fn() -> i32 {
42
}
}
trait Foo {
som$0
}
"#,
expect![[r#""#]],
);
check(
r#"
mod m {
pub fn some_fn() -> i32 {
42
}
}
struct Foo;
impl Foo {
som$0
}
"#,
expect![[r#""#]],
);
check(
r#"
mod m {
pub fn some_fn() -> i32 {
42
}
}
struct Foo;
trait Bar {}
impl Bar for Foo {
som$0
}
"#,
expect![[r#""#]],
);
}
#[test]
fn no_inherent_candidates_proposed() {
check(
r#"
mod baz {
pub trait DefDatabase {
fn method1(&self);
}
pub trait HirDatabase: DefDatabase {
fn method2(&self);
}
}
mod bar {
fn test(db: &dyn crate::baz::HirDatabase) {
db.metho$0
}
}
"#,
expect![[r#""#]],
);
check(
r#"
mod baz {
pub trait DefDatabase {
fn method1(&self);
}
pub trait HirDatabase: DefDatabase {
fn method2(&self);
}
}
mod bar {
fn test(db: &impl crate::baz::HirDatabase) {
db.metho$0
}
}
"#,
expect![[r#""#]],
);
check(
r#"
mod baz {
pub trait DefDatabase {
fn method1(&self);
}
pub trait HirDatabase: DefDatabase {
fn method2(&self);
}
}
mod bar {
fn test<T: crate::baz::HirDatabase>(db: T) {
db.metho$0
}
}
"#,
expect![[r#""#]],
);
}
#[test]
fn respects_doc_hidden() {
check(
r#"
//- /lib.rs crate:lib deps:dep
fn f() {
().fro$0
}
//- /dep.rs crate:dep
#[doc(hidden)]
pub trait Private {
fn frob(&self) {}
}
impl<T> Private for T {}
"#,
expect![[r#""#]],
);
check(
r#"
//- /lib.rs crate:lib deps:dep
fn f() {
().fro$0
}
//- /dep.rs crate:dep
pub trait Private {
#[doc(hidden)]
fn frob(&self) {}
}
impl<T> Private for T {}
"#,
expect![[r#""#]],
);
}
#[test]
fn regression_9760() {
check(
r#"
struct Struct;
fn main() {}
mod mud {
fn func() {
let struct_instance = Stru$0
}
}
"#,
expect![[r#"
st Struct (use crate::Struct) Struct
"#]],
);
}
#[test]
fn flyimport_pattern() {
check(
r#"
mod module {
pub struct FooStruct {}
pub const FooConst: () = ();
pub fn foo_fun() {}
}
fn function() {
let foo$0
}
"#,
expect![[r#"
ct FooConst (use module::FooConst)
st FooStruct (use module::FooStruct)
"#]],
);
}
#[test]
fn flyimport_pattern_no_unstable_item_on_stable() {
check(
r#"
//- /main.rs crate:main deps:std
fn function() {
let foo$0
}
//- /std.rs crate:std
#[unstable]
pub struct FooStruct {}
"#,
expect![""],
);
}
#[test]
fn flyimport_pattern_unstable_item_on_nightly() {
check(
r#"
//- toolchain:nightly
//- /main.rs crate:main deps:std
fn function() {
let foo$0
}
//- /std.rs crate:std
#[unstable]
pub struct FooStruct {}
"#,
expect![[r#"
st FooStruct (use std::FooStruct)
"#]],
);
}
#[test]
fn flyimport_item_name() {
check(
r#"
mod module {
pub struct Struct;
}
struct Str$0
"#,
expect![[r#""#]],
);
}
#[test]
fn flyimport_rename() {
check(
r#"
mod module {
pub struct Struct;
}
use self as Str$0;
"#,
expect![[r#""#]],
);
}
#[test]
fn flyimport_enum_variant() {
check(
r#"
mod foo {
pub struct Barbara;
}
enum Foo {
Barba$0()
}
}"#,
expect![[r#""#]],
);
check(
r#"
mod foo {
pub struct Barbara;
}
enum Foo {
Barba(Barba$0)
}
}"#,
expect![[r#"
st Barbara (use foo::Barbara) Barbara
"#]],
)
}
#[test]
fn flyimport_attribute() {
check(
r#"
//- proc_macros:identity
#[ide$0]
struct Foo;
"#,
expect![[r#"
at identity (use proc_macros::identity) proc_macro identity
"#]],
);
check_edit(
"identity",
r#"
//- proc_macros:identity
#[ide$0]
struct Foo;
"#,
r#"
use proc_macros::identity;
#[identity]
struct Foo;
"#,
);
}
#[test]
fn flyimport_in_type_bound_omits_types() {
check(
r#"
mod module {
pub struct CompletemeStruct;
pub type CompletemeType = ();
pub enum CompletemeEnum {}
pub trait CompletemeTrait {}
}
fn f<T>() where T: Comp$0
"#,
expect![[r#"
tt CompletemeTrait (use module::CompletemeTrait)
"#]],
);
}
#[test]
fn flyimport_source_file() {
check(
r#"
//- /main.rs crate:main deps:dep
def$0
//- /lib.rs crate:dep
#[macro_export]
macro_rules! define_struct {
() => {
pub struct Foo;
};
}
"#,
expect![[r#"
ma define_struct!(…) (use dep::define_struct) macro_rules! define_struct
"#]],
);
}
#[test]
fn macro_use_prelude_is_in_scope() {
check(
r#"
//- /main.rs crate:main deps:dep
#[macro_use]
extern crate dep;
fn main() {
print$0
}
//- /lib.rs crate:dep
#[macro_export]
macro_rules! println {
() => {}
}
"#,
expect![""],
)
}
#[test]
fn no_completions_for_external_doc_hidden_in_path() {
check(
r#"
//- /main.rs crate:main deps:dep
fn main() {
Span$0
}
//- /lib.rs crate:dep
#[doc(hidden)]
pub mod bridge {
pub mod server {
pub trait Span
}
}
pub mod bridge2 {
#[doc(hidden)]
pub mod server2 {
pub trait Span
}
}
"#,
expect![""],
);
// unless re-exported
check(
r#"
//- /main.rs crate:main deps:dep
fn main() {
Span$0
}
//- /lib.rs crate:dep
#[doc(hidden)]
pub mod bridge {
pub mod server {
pub trait Span
}
}
pub use bridge::server::Span;
pub mod bridge2 {
#[doc(hidden)]
pub mod server2 {
pub trait Span2
}
}
pub use bridge2::server2::Span2;
"#,
expect![[r#"
tt Span (use dep::Span)
tt Span2 (use dep::Span2)
"#]],
);
}