Skip to content

Commit 210a3e7

Browse files
committed
tools/docgen: parse function deprecation messages
The `api.json` data is updated to add the parsed deprecation messages.
1 parent 947d8b1 commit 210a3e7

File tree

2 files changed

+254
-11
lines changed

2 files changed

+254
-11
lines changed

tools/src/bin/docgen/main.rs

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ struct ItemMetadata {
145145
comment: Option<Comment>,
146146
/// A feature requirement that must be enabled for the item
147147
feature: Option<Feature>,
148+
/// A deprecation message for the item
149+
deprecation: Option<Deprecation>,
148150
}
149151

150152
impl ItemMetadata {
@@ -158,15 +160,17 @@ impl ItemMetadata {
158160
/// * `prev` is not a comment, and not a feature requirement.
159161
/// * `prev` is a Comment, and has no feature requirement before it.
160162
/// * `prev` is a Comment, and has a feature requirement before it.
163+
/// * `prev` is a Deprecation, and has a comment and feature requirement before it.
164+
/// * `prev` is a Deprecation, and has a comment and no feature requirement before it.
161165
/// * `prev` is a bare feature requirement
162166
///
163-
/// cbindgen won't create a comment before a feature requirement so we don't have to
164-
/// consider that case.
167+
/// cbindgen won't create other permutations (e.g. comment before a feature requirement, or
168+
/// a deprecation before a feature requirement) so we don't have to consider those cases.
165169
fn new(prev: Node, src: &[u8]) -> Result<Self, Box<dyn Error>> {
166170
let prev_prev = prev.prev_named_sibling();
167171

168172
// In the simple case, `prev` is a comment and `prev_prev` may
169-
// be a feature requirement.
173+
// be a feature requirement. Deprecations aren't in play.
170174
if let Ok(comment) = Comment::new(prev, src) {
171175
let feature = match prev_prev {
172176
Some(prev_prev) => Feature::new(prev_prev, src).ok(),
@@ -175,24 +179,36 @@ impl ItemMetadata {
175179
return Ok(ItemMetadata {
176180
comment: Some(comment),
177181
feature,
182+
deprecation: None,
178183
});
179184
}
180185

181-
// If `prev` wasn't a comment, see if it was an expression_statement
182-
// that itself was preceded by a comment. This skips over
183-
// expression-like preprocessor attributes on function decls.
184-
if prev.kind() == "expression_statement" {
185-
return match prev_prev {
186-
Some(prev_prev) => Self::new(prev_prev, src),
187-
None => Ok(ItemMetadata::default()),
186+
// `prev` is a deprecation, `prev_prev` may be a comment, and `prev_prev_prev`
187+
// may be a feature requirement.
188+
if let Ok(deprecation) = Deprecation::new(prev, src) {
189+
let comment = match prev_prev {
190+
Some(prev_prev) => Comment::new(prev_prev, src).ok(),
191+
None => None,
192+
};
193+
let prev_prev_prev = prev_prev.and_then(|prev_prev| prev_prev.prev_named_sibling());
194+
let feature = match prev_prev_prev {
195+
Some(prev_prev_prev) => Feature::new(prev_prev_prev, src).ok(),
196+
None => None,
188197
};
198+
return Ok(ItemMetadata {
199+
comment,
200+
feature,
201+
deprecation: Some(deprecation),
202+
});
189203
}
190204

191205
// If `prev` wasn't a comment, or an expression_statement preceded by a comment,
192-
// then it's either a bare feature requirement or we have no metadata to return.
206+
// then it's either a bare feature requirement without a deprecation or we have no
207+
// metadata to return.
193208
Ok(ItemMetadata {
194209
comment: None,
195210
feature: Feature::new(prev, src).ok(),
211+
deprecation: None,
196212
})
197213
}
198214

@@ -322,6 +338,39 @@ impl Display for Comment {
322338
}
323339
}
324340

341+
#[derive(Debug, Default, Serialize)]
342+
struct Deprecation(String);
343+
344+
impl Deprecation {
345+
fn new(node: Node, src: &[u8]) -> Result<Self, Box<dyn Error>> {
346+
require_kind("expression_statement", node, src)?;
347+
348+
let query_str = r#"
349+
(call_expression
350+
function: (identifier) @func (#eq? @func "DEPRECATED_FUNC")
351+
arguments: (argument_list
352+
(string_literal (string_content) @content)
353+
)
354+
)
355+
"#;
356+
357+
let mut query_cursor = QueryCursor::new();
358+
let language = tree_sitter_c::LANGUAGE;
359+
let query = Query::new(&language.into(), query_str)?;
360+
361+
let captures = query_cursor.captures(&query, node, src);
362+
for (mat, _) in captures {
363+
for capture in mat.captures {
364+
if query.capture_names()[capture.index as usize] == "content" {
365+
return Ok(Self(node_text(capture.node, src)));
366+
}
367+
}
368+
}
369+
370+
Err(node_error("DEPRECATED_FUNC call not found or malformed", node, src).into())
371+
}
372+
}
373+
325374
fn process_typedef_item(
326375
mut metadata: ItemMetadata,
327376
item: Node,

0 commit comments

Comments
 (0)