Skip to content

Commit dbf1815

Browse files
committed
docgen: parse function deprecation messages
The `api.json` data is updated to add the newly parsed deprecation messages.
1 parent 0002f04 commit dbf1815

File tree

2 files changed

+255
-11
lines changed

2 files changed

+255
-11
lines changed

tools/src/bin/docgen/main.rs

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

149151
impl ItemMetadata {
@@ -157,35 +159,50 @@ impl ItemMetadata {
157159
/// * `prev` is not a comment, and not a feature requirement.
158160
/// * `prev` is a Comment, and has no feature requirement before it.
159161
/// * `prev` is a Comment, and has a feature requirement before it.
162+
/// * `prev` is a Deprecation, and has a comment and feature requirement before it.
163+
/// * `prev` is a Deprecation, and has a comment and no feature requirement before it.
160164
/// * `prev` is a bare feature requirement
161165
///
162-
/// cbindgen won't create a comment before a feature requirement so we don't have to
163-
/// consider that case.
166+
/// cbindgen won't create other permutations (e.g. comment before a feature requirement, or
167+
/// a deprecation before a feature requirement) so we don't have to consider those cases.
164168
fn new(prev: Node, src: &[u8]) -> Result<Self, Box<dyn Error>> {
165169
let prev_prev = prev.prev_named_sibling();
166170
// In the simple case, `prev` is a comment and `prev_prev` may be a feature requirement.
171+
// Deprecations aren't in play in this case based on how cbindgen works.
167172
if let Ok(comment) = Comment::new(prev, src) {
168173
return Ok(Self {
169174
comment: Some(comment),
170175
feature: prev_prev.and_then(|prev_prev| Feature::new(prev_prev, src).ok()),
176+
deprecation: None,
171177
});
172178
}
173179

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

184199
// If `prev` wasn't a comment, or an expression_statement preceded by a comment,
185-
// then it's either a bare feature requirement or we have no metadata to return.
200+
// then it's either a bare feature requirement without a deprecation or we have no
201+
// metadata to return.
186202
Ok(Self {
187203
comment: None,
188204
feature: Feature::new(prev, src).ok(),
205+
deprecation: None,
189206
})
190207
}
191208

@@ -315,6 +332,39 @@ impl Display for Comment {
315332
}
316333
}
317334

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

0 commit comments

Comments
 (0)