Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: Support #[deprecated] attribute #860

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f86d749
WIP:
sevenc-nanashi Jul 22, 2023
87561a4
Add: Add deprecated
sevenc-nanashi Jul 23, 2023
e001222
Fix: Fix it generates invalid python code
sevenc-nanashi Jul 23, 2023
d75abe9
Fix: Support quotes
sevenc-nanashi Jul 23, 2023
19845d8
Change: Move creation of [[deprecated]]
sevenc-nanashi Jul 23, 2023
608a31e
Add: Support enum
sevenc-nanashi Jul 23, 2023
ff164fb
Change: Add deprecate if c23
sevenc-nanashi Jul 23, 2023
6c29ff7
Update: Update test
sevenc-nanashi Jul 23, 2023
5733bf8
Add: Add test exceptation
sevenc-nanashi Jul 23, 2023
b5ae00e
Code: Use out.write
sevenc-nanashi Jul 23, 2023
a9587bb
Fix: Fix condition
sevenc-nanashi Jul 23, 2023
fbe51c6
(WIP) Change: make it like must_use
sevenc-nanashi Jul 28, 2023
6bfb3ff
Change: make it like must_use
sevenc-nanashi Jul 28, 2023
31fff88
Fix: Fix formatting
sevenc-nanashi Jul 28, 2023
a439a3a
Update: Update template.toml
sevenc-nanashi Jul 28, 2023
bb39e3a
Change: deprecated -> deprecated_node
sevenc-nanashi Aug 25, 2023
1a3f566
Change: move finding deperecation node to outer side of a function
sevenc-nanashi Aug 25, 2023
81bf4ca
Refactor: Move to a new function to avoid copy-pasting
sevenc-nanashi Aug 25, 2023
50b6171
Change: Option<String> -> Option<&str>
sevenc-nanashi Aug 27, 2023
05d7035
Change: Result<Option<String>, String> -> Option<String> and warn!
sevenc-nanashi Aug 27, 2023
19db2a4
Change: Use helper
sevenc-nanashi Aug 27, 2023
d13bb58
Merge: master -> add/deprecated
sevenc-nanashi Aug 27, 2023
5b119db
Change: Use helper
sevenc-nanashi Aug 27, 2023
507eaa5
Change: Remove let-else
sevenc-nanashi Aug 27, 2023
5809afc
Fix: Use Some(
sevenc-nanashi Aug 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ serde = { version = "1.0.103", default-features = false, features = ["derive"] }
serde_json = "1.0"
tempfile = "3"
toml = "0.5"
proc-macro2 = "1"
proc-macro2 = "1.0.60"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ref: #859

quote = "1"
heck = "0.4"

Expand Down
20 changes: 19 additions & 1 deletion src/bindgen/cdecl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::io::Write;
use crate::bindgen::config::Layout;
use crate::bindgen::declarationtyperesolver::DeclarationType;
use crate::bindgen::ir::{ConstExpr, Function, GenericArgument, Type};
use crate::bindgen::utilities::create_deprecate_attribute;
use crate::bindgen::writer::{ListType, SourceWriter};
use crate::bindgen::{Config, Language};

Expand Down Expand Up @@ -40,6 +41,7 @@ struct CDecl {
type_generic_args: Vec<GenericArgument>,
declarators: Vec<CDeclarator>,
type_ctype: Option<DeclarationType>,
deprecated: Option<String>,
}

impl CDecl {
Expand All @@ -50,6 +52,7 @@ impl CDecl {
type_generic_args: Vec::new(),
declarators: Vec::new(),
type_ctype: None,
deprecated: None,
}
}

Expand Down Expand Up @@ -99,6 +102,7 @@ impl CDecl {
layout,
never_return: f.never_return,
});
self.deprecated = f.annotations.deprecated.clone();
self.build_type(&f.ret, false, config);
}

Expand Down Expand Up @@ -189,7 +193,21 @@ impl CDecl {
}

fn write<F: Write>(&self, out: &mut SourceWriter<F>, ident: Option<&str>, config: &Config) {
// Write the type-specifier and type-qualifier first
// Write deprecated attribute
if config.language != Language::Cython {
if let Some(ref deprecated) = self.deprecated {
if config.language == Language::Cxx {
writeln!(out, "{}", create_deprecate_attribute(deprecated));
} else {
out.write("#if __STDC_VERSION__ >= 202311L");
out.new_line();
writeln!(out, "{}", create_deprecate_attribute(deprecated));
out.write("#endif // __STDC_VERSION__ >= 202311L");
out.new_line();
}
}
}
// Write the type-specifier and type-qualifier
if !self.type_qualifers.is_empty() {
write!(out, "{} ", self.type_qualifers);
}
Expand Down
33 changes: 33 additions & 0 deletions src/bindgen/ir/annotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ pub enum AnnotationValue {
pub struct AnnotationSet {
annotations: HashMap<String, AnnotationValue>,
pub must_use: bool,
pub deprecated: Option<String>,
}

impl AnnotationSet {
pub fn new() -> AnnotationSet {
AnnotationSet {
annotations: HashMap::new(),
must_use: false,
deprecated: None,
}
}

Expand All @@ -68,6 +70,36 @@ impl AnnotationSet {
.collect();

let must_use = attrs.has_attr_word("must_use");
let deprecated = if let Some(note) = attrs.attr_name_value_lookup("deprecated") {
sevenc-nanashi marked this conversation as resolved.
Show resolved Hide resolved
Some(note)
} else if attrs.has_attr_word("deprecated") {
Some("".to_string())
} else if let Some(attr) = attrs.iter().find(|attr| {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this code-path tested?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be.

if let Ok(syn::Meta::List(list)) = attr.parse_meta() {
list.path.is_ident("deprecated")
} else {
false
}
}) {
let args: syn::punctuated::Punctuated<syn::MetaNameValue, Token![,]> = attr
.parse_args_with(syn::punctuated::Punctuated::parse_terminated)
.map_err(|e| format!("Couldn't parse deprecated attribute: {}", e.to_string()))?;
let Some(lit) = args
.iter()
.find(|arg| arg.path.is_ident("note"))
.map(|arg| &arg.lit)
else {
return Err("Couldn't parse deprecated attribute: no `note` field".to_string());
};

if let syn::Lit::Str(lit) = lit {
Some(lit.value())
} else {
return Err("deprecated attribute must be a string".to_string());
}
} else {
None
};

let mut annotations = HashMap::new();

Expand Down Expand Up @@ -118,6 +150,7 @@ impl AnnotationSet {
Ok(AnnotationSet {
annotations,
must_use,
deprecated,
})
}

Expand Down
21 changes: 21 additions & 0 deletions src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::bindgen::mangle;
use crate::bindgen::monomorph::Monomorphs;
use crate::bindgen::rename::{IdentifierType, RenameRule};
use crate::bindgen::reserved;
use crate::bindgen::utilities::create_deprecate_attribute;
use crate::bindgen::writer::{ListType, Source, SourceWriter};

#[allow(clippy::large_enum_variant)]
Expand Down Expand Up @@ -769,6 +770,22 @@ impl Enum {
out.write("typedef ");
}
out.write("enum");
if let Some(ref note) = self.annotations.deprecated {
if config.cpp_compatible_c() {
out.write("#if defined(__cplusplus) || __STDC_VERSION__ >= 202311L");
} else {
out.write("#if __STDC_VERSION__ >= 201112L");
}
out.new_line();

write!(out, " {}", create_deprecate_attribute(note));
if config.cpp_compatible_c() {
out.write("#endif // defined(__cplusplus) || __STDC_VERSION__ >= 202311L");
} else {
out.write("#endif // __STDC_VERSION__ >= 201112L");
}
out.new_line();
}
if config.style.generate_tag() {
write!(out, " {}", tag_name);
}
Expand All @@ -781,6 +798,10 @@ impl Enum {
out.write("enum");
}

if let Some(ref note) = self.annotations.deprecated {
write!(out, " {}", create_deprecate_attribute(note));
}

if self.annotations.must_use(config) {
if let Some(ref anno) = config.enumeration.must_use {
write!(out, " {}", anno)
Expand Down
9 changes: 9 additions & 0 deletions src/bindgen/utilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,12 @@ fn split_doc_attr(input: &str) -> Vec<String> {
.map(|s| s.trim_end().to_string())
.collect()
}

pub fn create_deprecate_attribute(deprecated: &String) -> String {
if deprecated.is_empty() {
"[[deprecated]]".to_string()
} else {
// FIXME: I used {:?} to escape the string, but there should be much better way
sevenc-nanashi marked this conversation as resolved.
Show resolved Hide resolved
format!("[[deprecated({:?})]]", deprecated)
}
}
40 changes: 40 additions & 0 deletions tests/expectations/deprecated.both.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

enum DeprecatedEnum {
A = 0,
};
typedef int32_t DeprecatedEnum;

typedef struct DeprecatedStruct {
int32_t a;
} DeprecatedStruct;

#if __STDC_VERSION__ >= 202311L
[[deprecated]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_without_note(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_without_bracket(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note_and_since(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This quote \" requires to be quoted, and this [\n] requires to be escaped")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note_which_requires_to_be_escaped(void);

void dummy(DeprecatedEnum a, struct DeprecatedStruct b);
54 changes: 54 additions & 0 deletions tests/expectations/deprecated.both.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

enum DeprecatedEnum
#ifdef __cplusplus
: int32_t
#endif // __cplusplus
{
A = 0,
};
#ifndef __cplusplus
typedef int32_t DeprecatedEnum;
#endif // __cplusplus

typedef struct DeprecatedStruct {
int32_t a;
} DeprecatedStruct;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#if __STDC_VERSION__ >= 202311L
[[deprecated]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_without_note(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_without_bracket(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note_and_since(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This quote \" requires to be quoted, and this [\n] requires to be escaped")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note_which_requires_to_be_escaped(void);

void dummy(DeprecatedEnum a, struct DeprecatedStruct b);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
40 changes: 40 additions & 0 deletions tests/expectations/deprecated.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

enum DeprecatedEnum {
A = 0,
};
typedef int32_t DeprecatedEnum;

typedef struct {
int32_t a;
} DeprecatedStruct;

#if __STDC_VERSION__ >= 202311L
[[deprecated]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_without_note(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_without_bracket(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note_and_since(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This quote \" requires to be quoted, and this [\n] requires to be escaped")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note_which_requires_to_be_escaped(void);

void dummy(DeprecatedEnum a, DeprecatedStruct b);
54 changes: 54 additions & 0 deletions tests/expectations/deprecated.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

enum DeprecatedEnum
#ifdef __cplusplus
: int32_t
#endif // __cplusplus
{
A = 0,
};
#ifndef __cplusplus
typedef int32_t DeprecatedEnum;
#endif // __cplusplus

typedef struct {
int32_t a;
} DeprecatedStruct;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#if __STDC_VERSION__ >= 202311L
[[deprecated]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_without_note(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_without_bracket(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This is a note")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note_and_since(void);

#if __STDC_VERSION__ >= 202311L
[[deprecated("This quote \" requires to be quoted, and this [\n] requires to be escaped")]]
#endif // __STDC_VERSION__ >= 202311L
void deprecated_with_note_which_requires_to_be_escaped(void);

void dummy(DeprecatedEnum a, DeprecatedStruct b);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus