@@ -171,45 +171,56 @@ fn process_doc_item(item: Node, src: &[u8]) -> Result<Option<Item>, Box<dyn Erro
171171
172172 // Try to turn the previous sibling into a comment node. Some items may
173173 // require this to be Some(_) while others may allow None.
174- let ( comment, feat_requirement) = comment_and_requirement ( prev, src) ?;
174+ let ( comment, feat_requirement, deprecation ) = comment_and_requirement ( prev, src) ?;
175175
176176 let kind = item. kind ( ) ;
177177 // Based on the node kind, convert it to an appropriate Item.
178178 Ok ( Some ( match kind {
179179 "type_definition" => process_typedef_item ( comment, feat_requirement, item, src) ?,
180180 "enum_specifier" => Item :: from ( EnumItem :: new ( comment, feat_requirement, item, src) ?) ,
181- "declaration" => process_declaration_item ( comment, feat_requirement, item, src) ?,
181+ "declaration" => {
182+ process_declaration_item ( comment, feat_requirement, deprecation, item, src) ?
183+ }
182184 _ => return Err ( format ! ( "unexpected item kind: {kind}" ) . into ( ) ) ,
183185 } ) )
184186}
185187
186188fn comment_and_requirement (
187189 node : Node ,
188190 src : & [ u8 ] ,
189- ) -> Result < ( Option < Comment > , Option < Feature > ) , Box < dyn Error > > {
191+ ) -> Result < ( Option < Comment > , Option < Feature > , Option < Deprecation > ) , Box < dyn Error > > {
190192 // Node is a comment, potentially with a feature requirement ahead of it.
191193 if let Ok ( comment) = Comment :: new ( node, src) {
192194 return Ok ( match node. prev_named_sibling ( ) {
193- Some ( prev) => ( Some ( comment) , Feature :: new ( prev, src) . ok ( ) ) ,
194- None => ( Some ( comment) , None )
195+ Some ( prev) => ( Some ( comment) , Feature :: new ( prev, src) . ok ( ) , None ) ,
196+ None => ( Some ( comment) , None , None ) ,
195197 } ) ;
196198 }
197199
198- // If node wasn't a comment, see if it was an expression_statement
199- // that itself was preceded by a comment. This skips over
200- // expression-like preprocessor attributes on function decls.
201- if let ( "expression_statement" , Some ( prev) ) =
202- ( node. kind ( ) , node. prev_sibling ( ) ) {
203- return Ok ( match prev. prev_named_sibling ( ) {
204- // The comment may also be preceded by a feature requirement
205- Some ( prev_prev) => ( Comment :: new ( prev, src) . ok ( ) , Feature :: new ( prev_prev, src) . ok ( ) ) ,
206- None => ( Comment :: new ( prev, src) . ok ( ) , None ) ,
200+ // Node is a deprecation, optionally with a comment. If there was a comment, it
201+ // may itself have a feature requirement ahead of it.
202+ if let Ok ( deprecation) = Deprecation :: new ( node, src) {
203+ let Some ( comment) = node
204+ . prev_sibling ( )
205+ . and_then ( |prev| Comment :: new ( prev, src) . ok ( ) )
206+ else {
207+ // Undocumented deprecation. Produce an error.
208+ return Err ( node_error ( "undocumented deprecated item" , node, src) . into ( ) ) ;
209+ } ;
210+
211+ return Ok ( match node. prev_named_sibling ( ) {
212+ Some ( prev) => (
213+ Some ( comment) ,
214+ Feature :: new ( prev, src) . ok ( ) ,
215+ Some ( deprecation) ,
216+ ) ,
217+ None => ( Some ( comment) , None , Some ( deprecation) ) ,
207218 } ) ;
208219 }
209220
210221 // Node wasn't a comment or preprocessor attribute, might be a
211222 // bare feature requirement.
212- Ok ( ( None , Feature :: new ( node, src) . ok ( ) ) )
223+ Ok ( ( None , Feature :: new ( node, src) . ok ( ) , None ) )
213224}
214225
215226#[ derive( Debug , Default , Serialize ) ]
@@ -329,6 +340,38 @@ impl Display for Comment {
329340 }
330341}
331342
343+ #[ derive( Debug , Default , Serialize ) ]
344+ struct Deprecation ( String ) ;
345+
346+ impl Deprecation {
347+ fn new ( node : Node , src : & [ u8 ] ) -> Result < Self , Box < dyn Error > > {
348+ require_kind ( "expression_statement" , node, src) ?;
349+
350+ let query_str = r#"
351+ (call_expression
352+ function: (identifier) @func (#eq? @func "DEPRECATED_FUNC")
353+ arguments: (argument_list
354+ (string_literal (string_content) @content)
355+ )
356+ )
357+ "# ;
358+
359+ let mut query_cursor = QueryCursor :: new ( ) ;
360+ let language = tree_sitter_c:: LANGUAGE ;
361+ let query = Query :: new ( & language. into ( ) , query_str) ?;
362+
363+ let captures = query_cursor. captures ( & query, node, src) ;
364+ for ( mat, _) in captures {
365+ for capture in mat. captures {
366+ if query. capture_names ( ) [ capture. index as usize ] == "content" {
367+ return Ok ( Self ( node_text ( capture. node , src) ) ) ;
368+ }
369+ }
370+ }
371+
372+ Err ( node_error ( "DEPRECATED_FUNC call not found or malformed" , node, src) . into ( ) )
373+ }
374+ }
332375fn process_typedef_item (
333376 maybe_comment : Option < Comment > ,
334377 maybe_feature : Option < Feature > ,
@@ -410,6 +453,7 @@ fn process_typedef_item(
410453fn process_declaration_item (
411454 comment : Option < Comment > ,
412455 maybe_feature : Option < Feature > ,
456+ maybe_deprecation : Option < Deprecation > ,
413457 item : Node ,
414458 src : & [ u8 ] ,
415459) -> Result < Item , Box < dyn Error > > {
@@ -429,6 +473,7 @@ fn process_declaration_item(
429473 Ok ( Item :: from ( FunctionItem :: new (
430474 comment,
431475 maybe_feature,
476+ maybe_deprecation,
432477 item,
433478 src,
434479 ) ?) )
@@ -664,6 +709,7 @@ struct FunctionItem {
664709 anchor : String ,
665710 comment : Comment ,
666711 feature : Option < Feature > ,
712+ deprecation : Option < Deprecation > ,
667713 name : String ,
668714 text : String ,
669715}
@@ -672,6 +718,7 @@ impl FunctionItem {
672718 fn new (
673719 comment : Comment ,
674720 feature : Option < Feature > ,
721+ deprecation : Option < Deprecation > ,
675722 decl_node : Node ,
676723 src : & [ u8 ] ,
677724 ) -> Result < Self , Box < dyn Error > > {
@@ -682,6 +729,7 @@ impl FunctionItem {
682729 anchor : name. replace ( '_' , "-" ) . to_ascii_lowercase ( ) ,
683730 comment,
684731 feature,
732+ deprecation,
685733 name,
686734 text : markup_text ( decl_node, src) ,
687735 } )
0 commit comments