Skip to content

Commit 5168ab1

Browse files
Add rustdocs and use better names
1 parent dccbb38 commit 5168ab1

File tree

3 files changed

+64
-40
lines changed

3 files changed

+64
-40
lines changed

crates/ide_assists/src/handlers/auto_import.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use ide_db::helpers::{
22
import_assets::{ImportAssets, ImportCandidate},
33
insert_use::{insert_use, ImportScope},
4-
mod_path_to_ast,
4+
item_name, mod_path_to_ast,
55
};
66
use syntax::{ast, AstNode, SyntaxNode};
77

@@ -93,7 +93,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
9393
let group = import_group_message(import_assets.import_candidate());
9494
let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?;
9595
for import in proposed_imports {
96-
let name = match import.original_item_name(ctx.db()) {
96+
let name = match item_name(ctx.db(), import.original_item) {
9797
Some(name) => name,
9898
None => continue,
9999
};
@@ -130,10 +130,10 @@ fn import_group_message(import_candidate: &ImportCandidate) -> GroupLabel {
130130
let name = match import_candidate {
131131
ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()),
132132
ImportCandidate::TraitAssocItem(candidate) => {
133-
format!("Import a trait for item {}", candidate.name.text())
133+
format!("Import a trait for item {}", candidate.assoc_item_name.text())
134134
}
135135
ImportCandidate::TraitMethod(candidate) => {
136-
format!("Import a trait for method {}", candidate.name.text())
136+
format!("Import a trait for method {}", candidate.assoc_item_name.text())
137137
}
138138
};
139139
GroupLabel(name)

crates/ide_assists/src/handlers/qualify_path.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::iter;
22

33
use hir::AsAssocItem;
44
use ide_db::helpers::{
5-
import_assets::{ImportCandidate, LocatedImport, Qualifier},
6-
mod_path_to_ast,
5+
import_assets::{ImportCandidate, LocatedImport},
6+
item_name, mod_path_to_ast,
77
};
88
use ide_db::RootDatabase;
99
use syntax::{
@@ -48,7 +48,7 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
4848

4949
let qualify_candidate = match candidate {
5050
ImportCandidate::Path(candidate) => {
51-
if !matches!(candidate.qualifier, Qualifier::Absent) {
51+
if candidate.qualifier.is_some() {
5252
cov_mark::hit!(qualify_path_qualifier_start);
5353
let path = ast::Path::cast(syntax_under_caret)?;
5454
let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?);
@@ -191,20 +191,22 @@ fn item_as_trait(db: &RootDatabase, item: hir::ItemInNs) -> Option<hir::Trait> {
191191
fn group_label(candidate: &ImportCandidate) -> GroupLabel {
192192
let name = match candidate {
193193
ImportCandidate::Path(it) => &it.name,
194-
ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => &it.name,
194+
ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => {
195+
&it.assoc_item_name
196+
}
195197
}
196198
.text();
197199
GroupLabel(format!("Qualify {}", name))
198200
}
199201

200202
fn label(db: &RootDatabase, candidate: &ImportCandidate, import: &LocatedImport) -> String {
201-
let display_path = match import.original_item_name(db) {
203+
let display_path = match item_name(db, import.original_item) {
202204
Some(display_path) => display_path.to_string(),
203205
None => "{unknown}".to_string(),
204206
};
205207
match candidate {
206208
ImportCandidate::Path(candidate) => {
207-
if !matches!(candidate.qualifier, Qualifier::Absent) {
209+
if candidate.qualifier.is_some() {
208210
format!("Qualify with `{}`", display_path)
209211
} else {
210212
format!("Qualify as `{}`", display_path)

crates/ide_db/src/helpers/import_assets.rs

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Look up accessible paths for items.
22
use hir::{
33
AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module,
4-
ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, Type,
4+
ModuleDef, PathResolution, PrefixKind, ScopeDef, Semantics, Type,
55
};
66
use itertools::Itertools;
77
use rustc_hash::FxHashSet;
@@ -14,11 +14,16 @@ use crate::{
1414

1515
use super::item_name;
1616

17+
/// A candidate for import, derived during various IDE activities:
18+
/// * completion with imports on the fly proposals
19+
/// * completion edit resolve requests
20+
/// * assists
21+
/// * etc.
1722
#[derive(Debug)]
1823
pub enum ImportCandidate {
19-
// A path, qualified (`std::collections::HashMap`) or not (`HashMap`).
24+
/// A path, qualified (`std::collections::HashMap`) or not (`HashMap`).
2025
Path(PathImportCandidate),
21-
/// A trait associated function (with no self parameter) or associated constant.
26+
/// A trait associated function (with no self parameter) or an associated constant.
2227
/// For 'test_mod::TestEnum::test_function', `ty` is the `test_mod::TestEnum` expression type
2328
/// and `name` is the `test_function`
2429
TraitAssocItem(TraitImportCandidate),
@@ -28,27 +33,40 @@ pub enum ImportCandidate {
2833
TraitMethod(TraitImportCandidate),
2934
}
3035

36+
/// A trait import needed for a given associated item access.
37+
/// For `some::path::SomeStruct::ASSOC_`, contains the
38+
/// type of `some::path::SomeStruct` and `ASSOC_` as the item name.
3139
#[derive(Debug)]
3240
pub struct TraitImportCandidate {
41+
/// A type of the item that has the associated item accessed at.
3342
pub receiver_ty: Type,
34-
pub name: NameToImport,
43+
/// The associated item name that the trait to import should contain.
44+
pub assoc_item_name: NameToImport,
3545
}
3646

47+
/// Path import for a given name, qualified or not.
3748
#[derive(Debug)]
3849
pub struct PathImportCandidate {
39-
pub qualifier: Qualifier,
50+
/// Optional qualifier before name.
51+
pub qualifier: Option<FirstSegmentUnresolved>,
52+
/// The name the item (struct, trait, enum, etc.) should have.
4053
pub name: NameToImport,
4154
}
4255

56+
/// A qualifier that has a first segment and it's unresolved.
4357
#[derive(Debug)]
44-
pub enum Qualifier {
45-
Absent,
46-
FirstSegmentUnresolved(ast::NameRef, ModPath),
58+
pub struct FirstSegmentUnresolved {
59+
fist_segment: ast::NameRef,
60+
full_qualifier: ModPath,
4761
}
4862

63+
/// A name that will be used during item lookups.
4964
#[derive(Debug)]
5065
pub enum NameToImport {
66+
/// Requires items with names that exactly match the given string, case-sensitive.
5167
Exact(String),
68+
/// Requires items with names that case-insensitively contain all letters from the string,
69+
/// in the same order, but not necessary adjacent.
5270
Fuzzy(String),
5371
}
5472

@@ -61,6 +79,7 @@ impl NameToImport {
6179
}
6280
}
6381

82+
/// A struct to find imports in the project, given a certain name (or its part) and the context.
6483
#[derive(Debug)]
6584
pub struct ImportAssets {
6685
import_candidate: ImportCandidate,
@@ -119,19 +138,30 @@ impl ImportAssets {
119138
Some(Self {
120139
import_candidate: ImportCandidate::TraitMethod(TraitImportCandidate {
121140
receiver_ty,
122-
name: NameToImport::Fuzzy(fuzzy_method_name),
141+
assoc_item_name: NameToImport::Fuzzy(fuzzy_method_name),
123142
}),
124143
module_with_candidate: module_with_method_call,
125144
candidate_node,
126145
})
127146
}
128147
}
129148

149+
/// An import (not necessary the only one) that corresponds a certain given [`PathImportCandidate`].
150+
/// (the structure is not entirely correct, since there can be situations requiring two imports, see FIXME below for the details)
130151
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
131152
pub struct LocatedImport {
153+
/// The path to use in the `use` statement for a given candidate to be imported.
132154
pub import_path: ModPath,
155+
/// An item that will be imported with the import path given.
133156
pub item_to_import: ItemInNs,
157+
/// The path import candidate, resolved.
158+
///
159+
/// Not necessary matches the import:
160+
/// For any associated constant from the trait, we try to access as `some::path::SomeStruct::ASSOC_`
161+
/// the original item is the associated constant, but the import has to be a trait that
162+
/// defines this constant.
134163
pub original_item: ItemInNs,
164+
/// A path of the original item.
135165
pub original_path: Option<ModPath>,
136166
}
137167

@@ -144,15 +174,6 @@ impl LocatedImport {
144174
) -> Self {
145175
Self { import_path, item_to_import, original_item, original_path }
146176
}
147-
148-
pub fn original_item_name(&self, db: &RootDatabase) -> Option<Name> {
149-
match self.original_item {
150-
ItemInNs::Types(module_def_id) | ItemInNs::Values(module_def_id) => {
151-
ModuleDef::from(module_def_id).name(db)
152-
}
153-
ItemInNs::Macros(macro_def_id) => MacroDef::from(macro_def_id).name(db),
154-
}
155-
}
156177
}
157178

158179
impl ImportAssets {
@@ -229,7 +250,7 @@ impl ImportAssets {
229250
match &self.import_candidate {
230251
ImportCandidate::Path(candidate) => &candidate.name,
231252
ImportCandidate::TraitAssocItem(candidate)
232-
| ImportCandidate::TraitMethod(candidate) => &candidate.name,
253+
| ImportCandidate::TraitMethod(candidate) => &candidate.assoc_item_name,
233254
}
234255
}
235256

@@ -279,17 +300,18 @@ fn path_applicable_imports(
279300
let _p = profile::span("import_assets::path_applicable_imports");
280301

281302
let (unresolved_first_segment, unresolved_qualifier) = match &path_candidate.qualifier {
282-
Qualifier::Absent => {
303+
None => {
283304
return items_with_candidate_name
284305
.into_iter()
285306
.filter_map(|item| {
286307
Some(LocatedImport::new(mod_path(item)?, item, item, mod_path(item)))
287308
})
288309
.collect();
289310
}
290-
Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => {
291-
(first_segment.to_string(), qualifier.to_string())
292-
}
311+
Some(first_segment_unresolved) => (
312+
first_segment_unresolved.fist_segment.to_string(),
313+
first_segment_unresolved.full_qualifier.to_string(),
314+
),
293315
};
294316

295317
items_with_candidate_name
@@ -516,7 +538,7 @@ impl ImportCandidate {
516538
Some(_) => None,
517539
None => Some(Self::TraitMethod(TraitImportCandidate {
518540
receiver_ty: sema.type_of_expr(&method_call.receiver()?)?,
519-
name: NameToImport::Exact(method_call.name_ref()?.to_string()),
541+
assoc_item_name: NameToImport::Exact(method_call.name_ref()?.to_string()),
520542
})),
521543
}
522544
}
@@ -559,10 +581,10 @@ fn path_import_candidate(
559581
qualifier_start.syntax().ancestors().find_map(ast::Path::cast)?;
560582
if sema.resolve_path(&qualifier_start_path).is_none() {
561583
ImportCandidate::Path(PathImportCandidate {
562-
qualifier: Qualifier::FirstSegmentUnresolved(
563-
qualifier_start,
564-
ModPath::from_src_unhygienic(qualifier)?,
565-
),
584+
qualifier: Some(FirstSegmentUnresolved {
585+
fist_segment: qualifier_start,
586+
full_qualifier: ModPath::from_src_unhygienic(qualifier)?,
587+
}),
566588
name,
567589
})
568590
} else {
@@ -572,12 +594,12 @@ fn path_import_candidate(
572594
Some(PathResolution::Def(ModuleDef::Adt(assoc_item_path))) => {
573595
ImportCandidate::TraitAssocItem(TraitImportCandidate {
574596
receiver_ty: assoc_item_path.ty(sema.db),
575-
name,
597+
assoc_item_name: name,
576598
})
577599
}
578600
Some(_) => return None,
579601
},
580-
None => ImportCandidate::Path(PathImportCandidate { qualifier: Qualifier::Absent, name }),
602+
None => ImportCandidate::Path(PathImportCandidate { qualifier: None, name }),
581603
})
582604
}
583605

0 commit comments

Comments
 (0)