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
.