22//! file.
33
44use hir_def:: {
5- child_by_source:: ChildBySource , dyn_map:: DynMap , keys, keys:: Key , nameres:: ModuleSource ,
6- ConstId , DefWithBodyId , EnumId , EnumVariantId , FunctionId , GenericDefId , ImplId , ModuleId ,
7- StaticId , StructId , TraitId , TypeAliasId , UnionId , VariantId ,
5+ child_by_source:: ChildBySource , keys, nameres:: ModuleSource , GenericDefId , ModuleId ,
86} ;
9- use hir_expand:: { name:: AsName , AstId , MacroDefId , MacroDefKind } ;
7+ use hir_expand:: name:: AsName ;
108use ra_db:: FileId ;
119use ra_prof:: profile;
1210use ra_syntax:: {
1311 ast:: { self , AstNode , NameOwner } ,
14- match_ast, SyntaxNode ,
12+ match_ast,
1513} ;
1614
1715use crate :: {
1816 db:: { DefDatabase , HirDatabase } ,
19- Const , DefWithBody , Enum , EnumVariant , FieldSource , Function , ImplBlock , InFile , Local ,
20- MacroDef , Module , Static , Struct , StructField , Trait , TypeAlias , TypeParam , Union ,
17+ Const , DefWithBody , Enum , Function , ImplBlock , InFile , Local , Module , SourceBinder , Static ,
18+ Struct , Trait , TypeAlias , TypeParam ,
2119} ;
2220
23- pub ( crate ) trait FromSource : Sized {
24- type Ast ;
25- fn from_source ( db : & impl DefDatabase , src : InFile < Self :: Ast > ) -> Option < Self > ;
26- }
27-
28- pub trait FromSourceByContainer : Sized {
29- type Ast : AstNode + ' static ;
30- type Id : Copy + ' static ;
31- const KEY : Key < Self :: Ast , Self :: Id > ;
32- }
33-
34- impl < T : FromSourceByContainer > FromSource for T
35- where
36- T : From < <T as FromSourceByContainer >:: Id > ,
37- {
38- type Ast = <T as FromSourceByContainer >:: Ast ;
39- fn from_source ( db : & impl DefDatabase , src : InFile < Self :: Ast > ) -> Option < Self > {
40- analyze_container ( db, src. as_ref ( ) . map ( |it| it. syntax ( ) ) ) [ T :: KEY ]
41- . get ( & src)
42- . copied ( )
43- . map ( Self :: from)
44- }
45- }
46-
47- macro_rules! from_source_by_container_impls {
48- ( $( ( $hir: ident, $id: ident, $ast: path, $key: path) ) ,* , ) => { $(
49- impl FromSourceByContainer for $hir {
50- type Ast = $ast;
51- type Id = $id;
52- const KEY : Key <Self :: Ast , Self :: Id > = $key;
53- }
54- ) * }
55- }
56-
57- from_source_by_container_impls ! [
58- ( Struct , StructId , ast:: StructDef , keys:: STRUCT ) ,
59- ( Union , UnionId , ast:: UnionDef , keys:: UNION ) ,
60- ( Enum , EnumId , ast:: EnumDef , keys:: ENUM ) ,
61- ( Trait , TraitId , ast:: TraitDef , keys:: TRAIT ) ,
62- ( Function , FunctionId , ast:: FnDef , keys:: FUNCTION ) ,
63- ( Static , StaticId , ast:: StaticDef , keys:: STATIC ) ,
64- ( Const , ConstId , ast:: ConstDef , keys:: CONST ) ,
65- ( TypeAlias , TypeAliasId , ast:: TypeAliasDef , keys:: TYPE_ALIAS ) ,
66- ( ImplBlock , ImplId , ast:: ImplBlock , keys:: IMPL ) ,
67- ] ;
68-
69- impl FromSource for MacroDef {
70- type Ast = ast:: MacroCall ;
71- fn from_source ( db : & impl DefDatabase , src : InFile < Self :: Ast > ) -> Option < Self > {
72- let kind = MacroDefKind :: Declarative ;
73-
74- let module_src = ModuleSource :: from_child_node ( db, src. as_ref ( ) . map ( |it| it. syntax ( ) ) ) ;
75- let module = Module :: from_definition ( db, InFile :: new ( src. file_id , module_src) ) ?;
76- let krate = Some ( module. krate ( ) . id ) ;
77-
78- let ast_id = Some ( AstId :: new ( src. file_id , db. ast_id_map ( src. file_id ) . ast_id ( & src. value ) ) ) ;
79-
80- let id: MacroDefId = MacroDefId { krate, ast_id, kind } ;
81- Some ( MacroDef { id } )
82- }
83- }
84-
85- impl FromSource for EnumVariant {
86- type Ast = ast:: EnumVariant ;
87- fn from_source ( db : & impl DefDatabase , src : InFile < Self :: Ast > ) -> Option < Self > {
88- let parent_enum = src. value . parent_enum ( ) ;
89- let src_enum = InFile { file_id : src. file_id , value : parent_enum } ;
90- let parent_enum = Enum :: from_source ( db, src_enum) ?;
91- parent_enum. id . child_by_source ( db) [ keys:: ENUM_VARIANT ]
92- . get ( & src)
93- . copied ( )
94- . map ( EnumVariant :: from)
95- }
96- }
97-
98- impl FromSource for StructField {
99- type Ast = FieldSource ;
100- fn from_source ( db : & impl DefDatabase , src : InFile < Self :: Ast > ) -> Option < Self > {
101- let src = src. as_ref ( ) ;
102-
103- // FIXME this is buggy
104- let variant_id: VariantId = match src. value {
105- FieldSource :: Named ( field) => {
106- let value = field. syntax ( ) . ancestors ( ) . find_map ( ast:: StructDef :: cast) ?;
107- let src = InFile { file_id : src. file_id , value } ;
108- let def = Struct :: from_source ( db, src) ?;
109- def. id . into ( )
110- }
111- FieldSource :: Pos ( field) => {
112- let value = field. syntax ( ) . ancestors ( ) . find_map ( ast:: EnumVariant :: cast) ?;
113- let src = InFile { file_id : src. file_id , value } ;
114- let def = EnumVariant :: from_source ( db, src) ?;
115- EnumVariantId :: from ( def) . into ( )
116- }
117- } ;
118-
119- let dyn_map = variant_id. child_by_source ( db) ;
120- match src. value {
121- FieldSource :: Pos ( it) => dyn_map[ keys:: TUPLE_FIELD ] . get ( & src. with_value ( it. clone ( ) ) ) ,
122- FieldSource :: Named ( it) => dyn_map[ keys:: RECORD_FIELD ] . get ( & src. with_value ( it. clone ( ) ) ) ,
123- }
124- . copied ( )
125- . map ( StructField :: from)
126- }
127- }
128-
12921impl Local {
13022 pub fn from_source ( db : & impl HirDatabase , src : InFile < ast:: BindPat > ) -> Option < Self > {
23+ let mut sb = SourceBinder :: new ( db) ;
13124 let file_id = src. file_id ;
13225 let parent: DefWithBody = src. value . syntax ( ) . ancestors ( ) . find_map ( |it| {
13326 let res = match_ast ! {
13427 match it {
135- ast:: ConstDef ( value) => { Const :: from_source ( db , InFile { value, file_id} ) ?. into( ) } ,
136- ast:: StaticDef ( value) => { Static :: from_source ( db , InFile { value, file_id} ) ?. into( ) } ,
137- ast:: FnDef ( value) => { Function :: from_source ( db , InFile { value, file_id} ) ?. into( ) } ,
28+ ast:: ConstDef ( value) => { sb . to_def :: < Const , _> ( InFile { value, file_id} ) ?. into( ) } ,
29+ ast:: StaticDef ( value) => { sb . to_def :: < Static , _> ( InFile { value, file_id} ) ?. into( ) } ,
30+ ast:: FnDef ( value) => { sb . to_def :: < Function , _> ( InFile { value, file_id} ) ?. into( ) } ,
13831 _ => return None ,
13932 }
14033 } ;
@@ -149,16 +42,17 @@ impl Local {
14942
15043impl TypeParam {
15144 pub fn from_source ( db : & impl HirDatabase , src : InFile < ast:: TypeParam > ) -> Option < Self > {
45+ let mut sb = SourceBinder :: new ( db) ;
15246 let file_id = src. file_id ;
15347 let parent: GenericDefId = src. value . syntax ( ) . ancestors ( ) . find_map ( |it| {
15448 let res = match_ast ! {
15549 match it {
156- ast:: FnDef ( value) => { Function :: from_source ( db , InFile { value, file_id} ) ?. id. into( ) } ,
157- ast:: StructDef ( value) => { Struct :: from_source ( db , InFile { value, file_id} ) ?. id. into( ) } ,
158- ast:: EnumDef ( value) => { Enum :: from_source ( db , InFile { value, file_id} ) ?. id. into( ) } ,
159- ast:: TraitDef ( value) => { Trait :: from_source ( db , InFile { value, file_id} ) ?. id. into( ) } ,
160- ast:: TypeAliasDef ( value) => { TypeAlias :: from_source ( db , InFile { value, file_id} ) ?. id. into( ) } ,
161- ast:: ImplBlock ( value) => { ImplBlock :: from_source ( db , InFile { value, file_id} ) ?. id. into( ) } ,
50+ ast:: FnDef ( value) => { sb . to_def :: < Function , _> ( InFile { value, file_id} ) ?. id. into( ) } ,
51+ ast:: StructDef ( value) => { sb . to_def :: < Struct , _> ( InFile { value, file_id} ) ?. id. into( ) } ,
52+ ast:: EnumDef ( value) => { sb . to_def :: < Enum , _> ( InFile { value, file_id} ) ?. id. into( ) } ,
53+ ast:: TraitDef ( value) => { sb . to_def :: < Trait , _> ( InFile { value, file_id} ) ?. id. into( ) } ,
54+ ast:: TypeAliasDef ( value) => { sb . to_def :: < TypeAlias , _> ( InFile { value, file_id} ) ?. id. into( ) } ,
55+ ast:: ImplBlock ( value) => { sb . to_def :: < ImplBlock , _> ( InFile { value, file_id} ) ?. id. into( ) } ,
16256 _ => return None ,
16357 }
16458 } ;
@@ -220,46 +114,3 @@ impl Module {
220114 Some ( Module { id : ModuleId { krate, local_id } } )
221115 }
222116}
223-
224- fn analyze_container ( db : & impl DefDatabase , src : InFile < & SyntaxNode > ) -> DynMap {
225- let _p = profile ( "analyze_container" ) ;
226- return child_by_source ( db, src) . unwrap_or_default ( ) ;
227-
228- fn child_by_source ( db : & impl DefDatabase , src : InFile < & SyntaxNode > ) -> Option < DynMap > {
229- for container in src. value . ancestors ( ) . skip ( 1 ) {
230- let res = match_ast ! {
231- match container {
232- ast:: TraitDef ( it) => {
233- let def = Trait :: from_source( db, src. with_value( it) ) ?;
234- def. id. child_by_source( db)
235- } ,
236- ast:: ImplBlock ( it) => {
237- let def = ImplBlock :: from_source( db, src. with_value( it) ) ?;
238- def. id. child_by_source( db)
239- } ,
240- ast:: FnDef ( it) => {
241- let def = Function :: from_source( db, src. with_value( it) ) ?;
242- DefWithBodyId :: from( def. id)
243- . child_by_source( db)
244- } ,
245- ast:: StaticDef ( it) => {
246- let def = Static :: from_source( db, src. with_value( it) ) ?;
247- DefWithBodyId :: from( def. id)
248- . child_by_source( db)
249- } ,
250- ast:: ConstDef ( it) => {
251- let def = Const :: from_source( db, src. with_value( it) ) ?;
252- DefWithBodyId :: from( def. id)
253- . child_by_source( db)
254- } ,
255- _ => { continue } ,
256- }
257- } ;
258- return Some ( res) ;
259- }
260-
261- let module_source = ModuleSource :: from_child_node ( db, src) ;
262- let c = Module :: from_definition ( db, src. with_value ( module_source) ) ?;
263- Some ( c. id . child_by_source ( db) )
264- }
265- }
0 commit comments