Rust's crates/modules also serve as namespaces, allowing to give simpler names to types/traits/functions because the namespace already has some of their context. Even if my struct Foo only makes sense in the context of the module bar, because I can refer to it as bar::Foo I don't have to name it BarFoo just to give readers of the code easy time understanding what it means.
The problem is that if I use Rust Analyzer (or any other similar tool that may exist in the future) I'm going to have a hard time sticking to referring to it as bar::Foo. When I try to use autocompletion, Rust Analyzer will prefer to add a use bar::Foo; instead of adding the namespace. With code actions it would at offer to use the full qualified name, but if bar is a submodule of a crate baz the options will either be to import Foo or to use baz::bar::Foo - it won't offer to add use baz::bar; and then use bar::Foo.
A crate's author is the best suited to decide how the items of the crates should be imported, so I suggest adding attributes that crates can use to tell Rust Analyzer how to handle imports.
#[import_assist(namespace = ...)]
When Rust Analyzer sees something like this:
pub mod bar {
#[import_assist(namespace = crate::bar)]
pub struct Foo;
}
It should know that when the user tries to autocomplete Foo, it should add a use declaration to import bar from whatever crate it's in and then compelte the expression to bar::Foo.
This should also work for multi-levels:
pub mod baz {
pub mod bar {
#[import_assist(namespace = crate::baz::bar)]
pub struct Foo;
#[import_assist(namespace = crate::baz)]
pub struct Qux;
}
}
With this, Rust Analyzer will complete Foo to bar::Foo and Qux to baz::bar::Qux. After adding the appropriate use declarations, of course..
#[import_assist(prelude = ...)]
It is a standard practice for Rust crates to offer a prelude module that users can star-import to get the typical items needed to use the crate. The annotations support this as well:
pub mod bar {
#[import_assist(prelude = crate::prelude)]
pub struct Foo;
}
pub mod prelude {
pub use crate::bar::Foo;
}
With this, Rust Analyzer should know that it can do use <crate-name>::prelude::*; in order to import Foo.
This may be a bit dangerous for autocompletion-generated import, so maybe it should be limited to code actions?
Also, maybe it would be better to put the attribute on the prelude module instead of every item that goes into it.
#[import_assist(underscore)] (maybe this one needs a better name?)
Rust supports underscore imports where a trait gets brought into the scope so that its methods may be used without needlessly polluting the namespace with it. We should have support that as well:
#[import_assist(underscore)]
trait Foo { ... }
With this, when Rust Analyzer offers to import Foo because you used one of its methods, it'll import it as _.
#[import(rename = ...)]
This one is placed on the module itself:
#[import_assist(rename = "b")]`
pub mod bar {
#[import_assist(namespace = crate::bar)]
pub struct Foo;
}
When autocompleting Foo, or when running a code action to import it, Rust Analyzer will add an use <crate_name>::bar as b; and refer to Foo as b::Foo.