@@ -4,8 +4,8 @@ use crate::{
44} ;
55use 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} ;
1010use ra_ide_db:: { imports_locator:: ImportsLocator , RootDatabase } ;
1111use 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