11use crate :: db:: ScarbDocDatabase ;
2+ use crate :: docs_generation:: markdown:: context:: IncludedItems ;
3+ use crate :: docs_generation:: markdown:: traits:: WithPath ;
4+ use crate :: location_links:: DocLocationLink ;
5+ use crate :: types:: item_data:: ItemData ;
26use crate :: types:: module_type:: is_doc_hidden_attr;
37use crate :: types:: other_types:: doc_full_path;
4- use crate :: types:: item_data:: ItemData ;
58use cairo_lang_defs:: ids:: {
69 LanguageElementId , LookupItemId , MemberId , ModuleItemId , NamedLanguageElementId , StructId ,
10+ TopLevelLanguageElementId ,
711} ;
812use cairo_lang_diagnostics:: Maybe ;
13+ use cairo_lang_doc:: db:: DocGroup ;
914use cairo_lang_doc:: documentable_item:: DocumentableItemId ;
15+ use cairo_lang_doc:: helpers:: {
16+ get_generic_params, get_struct_attributes_syntax, get_syntactic_visibility,
17+ } ;
18+ use cairo_lang_doc:: location_links:: { LocationLink , format_signature} ;
19+ use cairo_lang_doc:: signature_data:: SignatureDataRetriever ;
1020use cairo_lang_semantic:: items:: structure:: StructSemantic ;
1121use cairo_lang_semantic:: items:: visibility:: Visibility ;
1222use cairo_lang_syntax:: node:: ast;
1323use serde:: Serialize ;
14- use crate :: docs_generation:: markdown:: context:: IncludedItems ;
15- use crate :: docs_generation:: markdown:: traits:: WithPath ;
1624
1725#[ derive( Serialize , Clone ) ]
1826pub struct Struct < ' db > {
@@ -30,31 +38,19 @@ impl<'db> Struct<'db> {
3038 id : StructId < ' db > ,
3139 include_private_items : bool ,
3240 ) -> Maybe < Self > {
33- let members = db. struct_members ( id) ?;
34-
35- let item_data = ItemData :: new (
41+ let mut item_data = ItemData :: new_without_signature (
3642 db,
3743 id,
3844 LookupItemId :: ModuleItem ( ModuleItemId :: Struct ( id) ) . into ( ) ,
39- doc_full_path ( & id. parent_module ( db) , db) ,
4045 ) ;
41- let members = members
42- . iter ( )
43- . filter_map ( |( _, semantic_member) | {
44- let visible = matches ! ( semantic_member. visibility, Visibility :: Public ) ;
45- let syntax_node = & semantic_member. id . stable_location ( db) . syntax_node ( db) ;
46- if ( include_private_items || visible) && !is_doc_hidden_attr ( db, syntax_node) {
47- Some ( Ok ( Member :: new ( db, semantic_member. id ) ) )
48- } else {
49- None
50- }
51- } )
52- . collect :: < Maybe < Vec < _ > > > ( ) ?;
46+ let mut signature_builder = StructSignatureBuilder :: new ( db, id, include_private_items) ;
47+ let ( signature, location_links, members) = signature_builder. build_signature ( db) ;
48+ item_data. signature = Some ( signature) ;
49+ item_data. doc_location_links = location_links;
5350
54- let node = id. stable_ptr ( db) ;
5551 Ok ( Self {
5652 id,
57- node,
53+ node : id . stable_ptr ( db ) ,
5854 members,
5955 item_data,
6056 } )
@@ -68,6 +64,158 @@ impl<'db> Struct<'db> {
6864 }
6965}
7066
67+ struct MemberDataHelper < ' db > {
68+ signature : Option < String > ,
69+ member_id : MemberId < ' db > ,
70+ location_links : Vec < LocationLink < ' db > > ,
71+ }
72+
73+ impl < ' db > MemberDataHelper < ' db > {
74+ fn new ( member_id : MemberId < ' db > , db : & ' db ScarbDocDatabase ) -> Self {
75+ let ( signature, location_links) =
76+ db. get_item_signature_with_links ( DocumentableItemId :: Member ( member_id) ) ;
77+ Self {
78+ signature,
79+ member_id,
80+ location_links,
81+ }
82+ }
83+ }
84+
85+ struct StructSignatureBuilder < ' a > {
86+ members_data : Vec < MemberDataHelper < ' a > > ,
87+ has_private_members : bool ,
88+ has_public_members : bool ,
89+ buff : String ,
90+ location_links : Vec < LocationLink < ' a > > ,
91+ }
92+
93+ impl < ' db > StructSignatureBuilder < ' db > {
94+ const INDENT : & ' static str = " " ;
95+ const PRIVATE_MEMBERS : & ' static str = "/* private fields */" ;
96+
97+ fn new ( db : & ' db ScarbDocDatabase , id : StructId < ' db > , include_private_items : bool ) -> Self {
98+ let members = db. struct_members ( id) . expect ( & format ! (
99+ "Failed to get members of struct: {}" ,
100+ id. full_path( db)
101+ ) ) ;
102+ let signature_data = StructId :: retrieve_signature_data ( db, id) . expect ( & format ! (
103+ "Failed to get signature data for struct: {}" ,
104+ id. full_path( db)
105+ ) ) ;
106+
107+ let mut buff = String :: new ( ) ;
108+ let mut location_links = Vec :: new ( ) ;
109+
110+ if let Some ( attributes) = signature_data. attributes {
111+ let attributes_syntax = get_struct_attributes_syntax ( attributes, db) . expect ( & format ! (
112+ "Failed to format attributes syntax for struct: {}" ,
113+ id. full_path( db)
114+ ) ) ;
115+
116+ buff. push_str ( & attributes_syntax) ;
117+ }
118+ buff. push_str ( & format ! (
119+ "{}struct {}" ,
120+ get_syntactic_visibility( & signature_data. visibility) ,
121+ signature_data. name. long( db)
122+ ) ) ;
123+
124+ if let Some ( generic_params) = signature_data. generic_params {
125+ let ( stx, _location_links) = get_generic_params ( generic_params, db) . expect ( & format ! (
126+ "Failed to get format params for struct: {}" ,
127+ id. full_path( db)
128+ ) ) ;
129+
130+ buff. push_str ( & stx) ;
131+ location_links. extend ( _location_links) ;
132+ }
133+ let mut has_private_members = false ;
134+ let mut has_public_members = false ;
135+
136+ let members_data: Vec < MemberDataHelper > = members
137+ . iter ( )
138+ . filter_map ( |( _, semantic_member) | {
139+ let visible = matches ! ( semantic_member. visibility, Visibility :: Public ) ;
140+ let syntax_node = & semantic_member. id . stable_location ( db) . syntax_node ( db) ;
141+
142+ if ( include_private_items || visible) && !is_doc_hidden_attr ( db, syntax_node) {
143+ let mdh = MemberDataHelper :: new ( semantic_member. id , db) ;
144+ has_public_members = true ;
145+ Some ( Ok ( mdh) )
146+ } else {
147+ has_private_members = true ;
148+ None
149+ }
150+ } )
151+ . collect :: < Maybe < Vec < _ > > > ( )
152+ . expect ( & format ! (
153+ "Failed to collect members data for struct: {}" ,
154+ id. full_path( db)
155+ ) ) ;
156+
157+ StructSignatureBuilder {
158+ members_data,
159+ has_private_members,
160+ has_public_members,
161+ buff,
162+ location_links,
163+ }
164+ }
165+
166+ fn build_signature (
167+ & mut self ,
168+ db : & ' db ScarbDocDatabase ,
169+ ) -> ( String , Vec < DocLocationLink > , Vec < Member < ' db > > ) {
170+ let mut members = Vec :: new ( ) ;
171+ self . buff . push_str ( " {" ) ;
172+
173+ for mdh in & self . members_data {
174+ members. push ( Member :: new ( db, mdh. member_id ) ) ;
175+ let mut offset = self . buff . len ( ) ;
176+ offset += "\n " . len ( ) + Self :: INDENT . len ( ) ;
177+
178+ let formatted_member_signature = format ! (
179+ "\n {}{}," ,
180+ Self :: INDENT ,
181+ mdh. signature. clone( ) . unwrap_or_default( )
182+ ) ;
183+ self . buff . push_str ( & formatted_member_signature) ;
184+ self . location_links . extend (
185+ mdh. location_links
186+ . iter ( )
187+ . map ( |link| LocationLink :: new ( link. start , link. end , link. item_id , offset) )
188+ . collect :: < Vec < _ > > ( ) ,
189+ ) ;
190+ }
191+
192+ if !& self . members_data . is_empty ( ) {
193+ self . buff . push ( '\n' ) ;
194+ }
195+
196+ if self . has_private_members {
197+ let ( prefix, postfix) = if self . has_public_members {
198+ ( Self :: INDENT , "\n " )
199+ } else {
200+ ( " " , " " )
201+ } ;
202+ self . buff
203+ . push_str ( & format ! ( "{prefix}{}{postfix}" , Self :: PRIVATE_MEMBERS ) ) ;
204+ }
205+ self . buff . push ( '}' ) ;
206+
207+ let ( new_sig_formatted, formatted_location_links) =
208+ format_signature ( db, self . buff . clone ( ) , self . location_links . clone ( ) ) ;
209+
210+ let doc_location_links = formatted_location_links
211+ . iter ( )
212+ . map ( |link| DocLocationLink :: new ( link. start , link. end , link. item_id , db) )
213+ . collect :: < Vec < _ > > ( ) ;
214+
215+ ( new_sig_formatted, doc_location_links, members)
216+ }
217+ }
218+
71219#[ derive( Serialize , Clone ) ]
72220pub struct Member < ' db > {
73221 #[ serde( skip) ]
0 commit comments