1 //! Random assortment of ide helpers for high-level ide features that don't fit in any other module.
3 use std
::collections
::VecDeque
;
5 use base_db
::{FileId, SourceDatabaseExt}
;
6 use hir
::{Crate, ItemInNs, ModuleDef, Name, Semantics}
;
9 AstToken
, SyntaxKind
, SyntaxToken
, TokenAtOffset
,
12 use crate::{defs::Definition, generated, RootDatabase}
;
14 pub fn item_name(db
: &RootDatabase
, item
: ItemInNs
) -> Option
<Name
> {
16 ItemInNs
::Types(module_def_id
) => module_def_id
.name(db
),
17 ItemInNs
::Values(module_def_id
) => module_def_id
.name(db
),
18 ItemInNs
::Macros(macro_def_id
) => Some(macro_def_id
.name(db
)),
22 /// Picks the token with the highest rank returned by the passed in function.
23 pub fn pick_best_token(
24 tokens
: TokenAtOffset
<SyntaxToken
>,
25 f
: impl Fn(SyntaxKind
) -> usize,
26 ) -> Option
<SyntaxToken
> {
27 tokens
.max_by_key(move |t
| f(t
.kind()))
29 pub fn pick_token
<T
: AstToken
>(mut tokens
: TokenAtOffset
<SyntaxToken
>) -> Option
<T
> {
30 tokens
.find_map(T
::cast
)
33 /// Converts the mod path struct into its ast representation.
34 pub fn mod_path_to_ast(path
: &hir
::ModPath
) -> ast
::Path
{
35 let _p
= profile
::span("mod_path_to_ast");
37 let mut segments
= Vec
::new();
38 let mut is_abs
= false;
40 hir
::PathKind
::Plain
=> {}
41 hir
::PathKind
::Super(0) => segments
.push(make
::path_segment_self()),
42 hir
::PathKind
::Super(n
) => segments
.extend((0..n
).map(|_
| make
::path_segment_super())),
43 hir
::PathKind
::DollarCrate(_
) | hir
::PathKind
::Crate
=> {
44 segments
.push(make
::path_segment_crate())
46 hir
::PathKind
::Abs
=> is_abs
= true,
52 .map(|segment
| make
::path_segment(make
::name_ref(&segment
.to_smol_str()))),
54 make
::path_from_segments(segments
, is_abs
)
57 /// Iterates all `ModuleDef`s and `Impl` blocks of the given file.
58 pub fn visit_file_defs(
59 sema
: &Semantics
<'_
, RootDatabase
>,
61 cb
: &mut dyn FnMut(Definition
),
64 let module
= match sema
.to_module_def(file_id
) {
68 let mut defs
: VecDeque
<_
> = module
.declarations(db
).into();
69 while let Some(def
) = defs
.pop_front() {
70 if let ModuleDef
::Module(submodule
) = def
{
71 if let hir
::ModuleSource
::Module(_
) = submodule
.definition_source(db
).value
{
72 defs
.extend(submodule
.declarations(db
));
73 submodule
.impl_defs(db
).into_iter().for_each(|impl_
| cb(impl_
.into()));
78 module
.impl_defs(db
).into_iter().for_each(|impl_
| cb(impl_
.into()));
80 let is_root
= module
.is_crate_root(db
);
84 // don't show legacy macros declared in the crate-root that were already covered in declarations earlier
85 .filter(|it
| !(is_root
&& it
.is_macro_export(db
)))
86 .for_each(|mac
| cb(mac
.into()));
89 /// Checks if the given lint is equal or is contained by the other lint which may or may not be a group.
90 pub fn lint_eq_or_in_group(lint
: &str, lint_is
: &str) -> bool
{
95 if let Some(group
) = generated
::lints
::DEFAULT_LINT_GROUPS
97 .chain(generated
::lints
::CLIPPY_LINT_GROUPS
.iter())
98 .chain(generated
::lints
::RUSTDOC_LINT_GROUPS
.iter())
99 .find(|&check
| check
.lint
.label
== lint_is
)
101 group
.children
.contains(&lint
)
107 pub fn is_editable_crate(krate
: Crate
, db
: &RootDatabase
) -> bool
{
108 let root_file
= krate
.root_file(db
);
109 let source_root_id
= db
.file_source_root(root_file
);
110 !db
.source_root(source_root_id
).is_library