Skip to content

Commit e008b08

Browse files
Support associated consts
1 parent 3ccf8b7 commit e008b08

File tree

1 file changed

+133
-18
lines changed

1 file changed

+133
-18
lines changed

crates/ra_assists/src/handlers/auto_import.rs

Lines changed: 133 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use crate::{
44
};
55
use hir::{
66
db::{DefDatabase, HirDatabase},
7-
AsAssocItem, AssocItem, AssocItemContainer, Crate, Function, ModPath, Module, ModuleDef,
8-
PathResolution, SourceAnalyzer, Trait, Type,
7+
AsAssocItem, AssocItem, AssocItemContainer, Crate, ModPath, Module, ModuleDef, PathResolution,
8+
SourceAnalyzer, Trait, Type,
99
};
1010
use ra_ide_db::{imports_locator::ImportsLocator, RootDatabase};
1111
use ra_prof::profile;
@@ -115,7 +115,7 @@ impl AutoImportAssets {
115115
match &self.import_candidate {
116116
ImportCandidate::UnqualifiedName(name) => name,
117117
ImportCandidate::QualifierStart(qualifier_start) => qualifier_start,
118-
ImportCandidate::TraitAssocItem(_, trait_function_name) => trait_function_name,
118+
ImportCandidate::TraitAssocItem(_, trait_assoc_item_name) => trait_assoc_item_name,
119119
ImportCandidate::TraitMethod(_, trait_method_name) => trait_method_name,
120120
}
121121
}
@@ -126,8 +126,8 @@ impl AutoImportAssets {
126126
ImportCandidate::QualifierStart(qualifier_start) => {
127127
format!("Import {}", qualifier_start)
128128
}
129-
ImportCandidate::TraitAssocItem(_, trait_function_name) => {
130-
format!("Import a trait for item {}", trait_function_name)
129+
ImportCandidate::TraitAssocItem(_, trait_assoc_item_name) => {
130+
format!("Import a trait for item {}", trait_assoc_item_name)
131131
}
132132
ImportCandidate::TraitMethod(_, trait_method_name) => {
133133
format!("Import a trait for method {}", trait_method_name)
@@ -142,16 +142,24 @@ impl AutoImportAssets {
142142
.find_imports(&self.get_search_query())
143143
.into_iter()
144144
.map(|module_def| match &self.import_candidate {
145-
ImportCandidate::TraitAssocItem(function_callee, _) => {
145+
ImportCandidate::TraitAssocItem(assoc_item_type, _) => {
146+
let located_assoc_item = match module_def {
147+
ModuleDef::Function(located_function) => {
148+
Some(AssocItem::Function(located_function))
149+
}
150+
ModuleDef::Const(located_const) => Some(AssocItem::Const(located_const)),
151+
_ => None,
152+
};
153+
146154
let mut applicable_traits = Vec::new();
147-
if let ModuleDef::Function(located_function) = module_def {
155+
if let Some(located_assoc_item) = located_assoc_item {
148156
let trait_candidates: FxHashSet<_> =
149-
Self::get_trait_candidates(db, located_function, current_crate)
157+
Self::get_trait_candidates(db, located_assoc_item, current_crate)
150158
.into_iter()
151159
.map(|trait_candidate| trait_candidate.into())
152160
.collect();
153161
if !trait_candidates.is_empty() {
154-
function_callee.iterate_path_candidates(
162+
assoc_item_type.iterate_path_candidates(
155163
db,
156164
current_crate,
157165
&trait_candidates,
@@ -175,11 +183,14 @@ impl AutoImportAssets {
175183
ImportCandidate::TraitMethod(function_callee, _) => {
176184
let mut applicable_traits = Vec::new();
177185
if let ModuleDef::Function(located_function) = module_def {
178-
let trait_candidates: FxHashSet<_> =
179-
Self::get_trait_candidates(db, located_function, current_crate)
180-
.into_iter()
181-
.map(|trait_candidate| trait_candidate.into())
182-
.collect();
186+
let trait_candidates: FxHashSet<_> = Self::get_trait_candidates(
187+
db,
188+
AssocItem::Function(located_function),
189+
current_crate,
190+
)
191+
.into_iter()
192+
.map(|trait_candidate| trait_candidate.into())
193+
.collect();
183194
if !trait_candidates.is_empty() {
184195
function_callee.iterate_method_candidates(
185196
db,
@@ -215,7 +226,7 @@ impl AutoImportAssets {
215226

216227
fn get_trait_candidates(
217228
db: &RootDatabase,
218-
called_function: Function,
229+
called_assoc_item: AssocItem,
219230
root_crate: Crate,
220231
) -> FxHashSet<Trait> {
221232
let _p = profile("auto_import::get_trait_candidates");
@@ -235,7 +246,7 @@ impl AutoImportAssets {
235246
if trait_candidate
236247
.items(db)
237248
.into_iter()
238-
.any(|item| item == AssocItem::Function(called_function)) =>
249+
.any(|item| item == called_assoc_item) =>
239250
{
240251
Some(trait_candidate)
241252
}
@@ -302,9 +313,9 @@ impl ImportCandidate {
302313
} else {
303314
source_analyzer.resolve_path(db, &qualifier)?
304315
};
305-
if let PathResolution::Def(ModuleDef::Adt(function_callee)) = qualifier_resolution {
316+
if let PathResolution::Def(ModuleDef::Adt(assoc_item_path)) = qualifier_resolution {
306317
Some(ImportCandidate::TraitAssocItem(
307-
function_callee.ty(db),
318+
assoc_item_path.ty(db),
308319
segment.syntax().to_string(),
309320
))
310321
} else {
@@ -580,6 +591,39 @@ mod tests {
580591
);
581592
}
582593

594+
#[test]
595+
fn associated_struct_const() {
596+
check_assist(
597+
auto_import,
598+
r"
599+
mod test_mod {
600+
pub struct TestStruct {}
601+
impl TestStruct {
602+
const TEST_CONST: u8 = 42;
603+
}
604+
}
605+
606+
fn main() {
607+
TestStruct::TEST_CONST<|>
608+
}
609+
",
610+
r"
611+
use test_mod::TestStruct;
612+
613+
mod test_mod {
614+
pub struct TestStruct {}
615+
impl TestStruct {
616+
const TEST_CONST: u8 = 42;
617+
}
618+
}
619+
620+
fn main() {
621+
TestStruct::TEST_CONST<|>
622+
}
623+
",
624+
);
625+
}
626+
583627
#[test]
584628
fn associated_trait_function() {
585629
check_assist(
@@ -651,6 +695,77 @@ mod tests {
651695
)
652696
}
653697

698+
#[test]
699+
fn associated_trait_const() {
700+
check_assist(
701+
auto_import,
702+
r"
703+
mod test_mod {
704+
pub trait TestTrait {
705+
const TEST_CONST: u8;
706+
}
707+
pub struct TestStruct {}
708+
impl TestTrait for TestStruct {
709+
const TEST_CONST: u8 = 42;
710+
}
711+
}
712+
713+
fn main() {
714+
test_mod::TestStruct::TEST_CONST<|>
715+
}
716+
",
717+
r"
718+
use test_mod::TestTrait;
719+
720+
mod test_mod {
721+
pub trait TestTrait {
722+
const TEST_CONST: u8;
723+
}
724+
pub struct TestStruct {}
725+
impl TestTrait for TestStruct {
726+
const TEST_CONST: u8 = 42;
727+
}
728+
}
729+
730+
fn main() {
731+
test_mod::TestStruct::TEST_CONST<|>
732+
}
733+
",
734+
);
735+
}
736+
737+
#[test]
738+
fn not_applicable_for_imported_trait_for_const() {
739+
check_assist_not_applicable(
740+
auto_import,
741+
r"
742+
mod test_mod {
743+
pub trait TestTrait {
744+
const TEST_CONST: u8;
745+
}
746+
pub trait TestTrait2 {
747+
const TEST_CONST: f64;
748+
}
749+
pub enum TestEnum {
750+
One,
751+
Two,
752+
}
753+
impl TestTrait2 for TestEnum {
754+
const TEST_CONST: f64 = 42.0;
755+
}
756+
impl TestTrait for TestEnum {
757+
const TEST_CONST: u8 = 42;
758+
}
759+
}
760+
761+
use test_mod::TestTrait2;
762+
fn main() {
763+
test_mod::TestEnum::TEST_CONST<|>;
764+
}
765+
",
766+
)
767+
}
768+
654769
#[test]
655770
fn trait_method() {
656771
check_assist(

0 commit comments

Comments
 (0)