@@ -11,6 +11,8 @@ struct NodeField {
1111 name : String ,
1212 c_type : String ,
1313 c_name : Option < String > ,
14+ #[ serde( default ) ]
15+ optional : bool ,
1416}
1517
1618impl NodeField {
@@ -109,6 +111,42 @@ fn convert_name(name: &str, identifier: CIdentifier) -> String {
109111 out
110112}
111113
114+ fn write_node_field_accessor (
115+ file : & mut File ,
116+ field : & NodeField ,
117+ rust_type : & str ,
118+ ) -> std:: io:: Result < ( ) > {
119+ if field. optional {
120+ writeln ! (
121+ file,
122+ " pub fn {}(&self) -> Option<{}> {{" ,
123+ field. name, rust_type
124+ ) ?;
125+ writeln ! (
126+ file,
127+ " let ptr = unsafe {{ (*self.pointer).{} }};" ,
128+ field. c_name( )
129+ ) ?;
130+ writeln ! ( file, " if ptr.is_null() {{" ) ?;
131+ writeln ! ( file, " None" ) ?;
132+ writeln ! ( file, " }} else {{" ) ?;
133+ writeln ! (
134+ file,
135+ " Some({rust_type} {{ parser: self.parser, pointer: ptr }})"
136+ ) ?;
137+ writeln ! ( file, " }}" ) ?;
138+ } else {
139+ writeln ! ( file, " pub fn {}(&self) -> {} {{" , field. name, rust_type) ?;
140+ writeln ! (
141+ file,
142+ " {} {{ parser: self.parser, pointer: unsafe {{ (*self.pointer).{} }} }}" ,
143+ rust_type,
144+ field. c_name( )
145+ ) ?;
146+ }
147+ writeln ! ( file, " }}" )
148+ }
149+
112150fn write_visit_trait ( file : & mut File , config : & Config ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
113151 writeln ! ( file, "/// A trait for traversing the AST using a visitor" ) ?;
114152 writeln ! ( file, "pub trait Visit {{" ) ?;
@@ -206,128 +244,62 @@ fn generate(config: &Config) -> Result<(), Box<dyn Error>> {
206244 writeln ! ( file, " }}" ) ?;
207245 }
208246 "rbs_ast_comment" => {
209- writeln ! ( file, " pub fn {}(&self) -> CommentNode {{" , field. name) ?;
210- writeln ! (
211- file,
212- " CommentNode {{ parser: self.parser, pointer: unsafe {{ (*self.pointer).{} }} }}" ,
213- field. c_name( )
214- ) ?;
215- writeln ! ( file, " }}" ) ?;
247+ write_node_field_accessor ( & mut file, field, "CommentNode" ) ?
216248 }
217249 "rbs_ast_declarations_class_super" => {
218- writeln ! (
219- file,
220- " pub fn {}(&self) -> ClassSuperNode {{" ,
221- field. name
222- ) ?;
223- writeln ! (
224- file,
225- " ClassSuperNode {{ parser: self.parser, pointer: unsafe {{ (*self.pointer).{} }} }}" ,
226- field. c_name( )
227- ) ?;
228- writeln ! ( file, " }}" ) ?;
229- }
230- "rbs_ast_symbol" => {
231- writeln ! ( file, " pub fn {}(&self) -> SymbolNode {{" , field. name) ?;
232- writeln ! (
233- file,
234- " SymbolNode {{ parser: self.parser, pointer: unsafe {{ (*self.pointer).{} }} }}" ,
235- field. c_name( )
236- ) ?;
237- writeln ! ( file, " }}" ) ?;
250+ write_node_field_accessor ( & mut file, field, "ClassSuperNode" ) ?
238251 }
252+ "rbs_ast_symbol" => write_node_field_accessor ( & mut file, field, "SymbolNode" ) ?,
239253 "rbs_hash" => {
240- writeln ! ( file, " pub fn {}(&self) -> RBSHash {{" , field. name) ?;
241- writeln ! (
242- file,
243- " RBSHash::new(self.parser, unsafe {{ (*self.pointer).{} }})" ,
244- field. c_name( )
245- ) ?;
246- writeln ! ( file, " }}" ) ?;
254+ write_node_field_accessor ( & mut file, field, "RBSHash" ) ?;
247255 }
248256 "rbs_location" => {
249- writeln ! ( file, " pub fn {}(&self) -> RBSLocation {{" , field. name) ?;
250- writeln ! (
251- file,
252- " RBSLocation::new(unsafe {{ (*self.pointer).{} }}, self.parser)" ,
253- field. c_name( )
254- ) ?;
255- writeln ! ( file, " }}" ) ?;
257+ write_node_field_accessor ( & mut file, field, "RBSLocation" ) ?;
256258 }
257259 "rbs_location_list" => {
258- writeln ! (
259- file,
260- " pub fn {}(&self) -> RBSLocationList {{" ,
261- field. name
262- ) ?;
263- writeln ! (
264- file,
265- " RBSLocationList::new(unsafe {{ (*self.pointer).{} }}, self.parser)" ,
266- field. c_name( )
267- ) ?;
268- writeln ! ( file, " }}" ) ?;
260+ write_node_field_accessor ( & mut file, field, "RBSLocationList" ) ?;
269261 }
270262 "rbs_namespace" => {
271- writeln ! ( file, " pub fn {}(&self) -> NamespaceNode {{" , field. name) ?;
272- writeln ! (
273- file,
274- " NamespaceNode {{ parser: self.parser, pointer: unsafe {{ (*self.pointer).{} }} }}" ,
275- field. c_name( )
276- ) ?;
277- writeln ! ( file, " }}" ) ?;
263+ write_node_field_accessor ( & mut file, field, "NamespaceNode" ) ?;
278264 }
279265 "rbs_node" => {
280266 let name = if field. name == "type" {
281267 "type_"
282268 } else {
283269 field. name . as_str ( )
284270 } ;
285-
286- writeln ! ( file, " pub fn {}(&self) -> Node {{" , name) ?;
287- writeln ! (
288- file,
289- " unsafe {{ Node::new(self.parser, (*self.pointer).{}) }}" ,
290- field. c_name( )
291- ) ?;
271+ if field. optional {
272+ writeln ! ( file, " pub fn {name}(&self) -> Option<Node> {{" ) ?;
273+ writeln ! (
274+ file,
275+ " let ptr = unsafe {{ (*self.pointer).{} }};" ,
276+ field. c_name( )
277+ ) ?;
278+ writeln ! (
279+ file,
280+ " if ptr.is_null() {{ None }} else {{ Some(Node::new(self.parser, ptr)) }}"
281+ ) ?;
282+ } else {
283+ writeln ! ( file, " pub fn {name}(&self) -> Node {{" ) ?;
284+ writeln ! (
285+ file,
286+ " unsafe {{ Node::new(self.parser, (*self.pointer).{}) }}" ,
287+ field. c_name( )
288+ ) ?;
289+ }
292290 writeln ! ( file, " }}" ) ?;
293291 }
294292 "rbs_node_list" => {
295- writeln ! ( file, " pub fn {}(&self) -> NodeList {{" , field. name) ?;
296- writeln ! (
297- file,
298- " NodeList::new(self.parser, unsafe {{ (*self.pointer).{} }})" ,
299- field. c_name( )
300- ) ?;
301- writeln ! ( file, " }}" ) ?;
302- }
303- "rbs_keyword" => {
304- writeln ! ( file, " pub fn {}(&self) -> KeywordNode {{" , field. name) ?;
305- writeln ! (
306- file,
307- " KeywordNode {{ parser: self.parser, pointer: unsafe {{ (*self.pointer).{} }} }}" ,
308- field. c_name( )
309- ) ?;
310- writeln ! ( file, " }}" ) ?;
293+ write_node_field_accessor ( & mut file, field, "NodeList" ) ?;
311294 }
295+ "rbs_keyword" => write_node_field_accessor ( & mut file, field, "KeywordNode" ) ?,
312296 "rbs_type_name" => {
313- writeln ! ( file, " pub fn {}(&self) -> TypeNameNode {{" , field. name) ?;
314- writeln ! (
315- file,
316- " TypeNameNode {{ parser: self.parser, pointer: unsafe {{ (*self.pointer).{} }} }}" ,
317- field. c_name( )
318- ) ?;
319- writeln ! ( file, " }}" ) ?;
297+ write_node_field_accessor ( & mut file, field, "TypeNameNode" ) ?;
320298 }
321299 "rbs_types_block" => {
322- writeln ! ( file, " pub fn {}(&self) -> BlockTypeNode {{" , field. name) ?;
323- writeln ! (
324- file,
325- " BlockTypeNode {{ parser: self.parser, pointer: unsafe {{ (*self.pointer).{} }} }}" ,
326- field. c_name( )
327- ) ?;
328- writeln ! ( file, " }}" ) ?;
300+ write_node_field_accessor ( & mut file, field, "BlockTypeNode" ) ?
329301 }
330- _ => eprintln ! ( "Unknown field type: {}" , field. c_type) ,
302+ _ => panic ! ( "Unknown field type: {}" , field. c_type) ,
331303 }
332304 }
333305 }
@@ -351,7 +323,7 @@ fn generate(config: &Config) -> Result<(), Box<dyn Error>> {
351323 writeln ! ( file, " #[allow(clippy::missing_safety_doc)]" ) ?;
352324 writeln ! (
353325 file,
354- " pub unsafe fn new(parser: *mut rbs_parser_t, node: *mut rbs_node_t) -> Self {{"
326+ " fn new(parser: *mut rbs_parser_t, node: *mut rbs_node_t) -> Self {{"
355327 ) ?;
356328 writeln ! ( file, " match unsafe {{ (*node).type_ }} {{" ) ?;
357329 for node in & config. nodes {
0 commit comments