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 18 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
51 changes: 51 additions & 0 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,23 @@ args = "horizontal"
# default: nothing is emitted for must_use functions
must_use = "MUST_USE_FUNC"

# An optional string that should prefix function declarations which have been
# marked as `#[deprecated]` without note. For instance, "__attribute__((deprecated))"
# would be a reasonable value if targeting gcc/clang. A more portable solution
# would involve emitting the name of a macro which you define in a
# platform-specific way. e.g. "DEPRECATED_FUNC"
# default: nothing is emitted for deprecated functions
deprecated = "DEPRECATED_FUNC"

# An optional string that should prefix function declarations which have been
# marked as `#[deprecated(note = "reason")]`. `{}` will be replaced with the
# double-quoted string. For instance, "__attribute__((deprecated({})))"
# would be a reasonable value if targeting gcc/clang. A more portable solution
# would involve emitting the name of a macro which you define in a
# platform-specific way. e.g. "DEPRECATED_FUNC_WITH_NOTE(note)"
# default: nothing is emitted for deprecated functions
deprecated_with_notes = "DEPRECATED_FUNC_WITH_NOTE"

# An optional string that will be used in the attribute position for functions
# that don't return (that return `!` in Rust).
#
Expand Down Expand Up @@ -752,6 +769,23 @@ rename_fields = "PascalCase"
# default: nothing is emitted for must_use structs
must_use = "MUST_USE_STRUCT"

# An optional string that should come before the name of any struct which has been
# marked as `#[deprecated]` without note. For instance, "__attribute__((deprecated))"
# would be a reasonable value if targeting gcc/clang. A more portable solution
# would involve emitting the name of a macro which you define in a
# platform-specific way. e.g. "DEPRECATED_STRUCT"
# default: nothing is emitted for deprecated structs
deprecated = "DEPRECATED_STRUCT"

# An optional string that should come before the name of any struct which has been
# marked as `#[deprecated(note = "reason")]`. `{}` will be replaced with the
# double-quoted string. For instance, "__attribute__((deprecated({})))"
# would be a reasonable value if targeting gcc/clang. A more portable solution
# would involve emitting the name of a macro which you define in a
# platform-specific way. e.g. "DEPRECATED_STRUCT_WITH_NOTE(note)"
# default: nothing is emitted for deprecated structs
deprecated_with_notes = "DEPRECATED_STRUCT_WITH_NOTE"

# Whether a Rust type with associated consts should emit those consts inside the
# type's body. Otherwise they will be emitted trailing and with the type's name
# prefixed. This does nothing if the target is C, or if
Expand Down Expand Up @@ -865,6 +899,23 @@ cast_assert_name = "MOZ_RELEASE_ASSERT"
# default: nothing is emitted for must_use enums
must_use = "MUST_USE_ENUM"

# An optional string that should come before the name of any enum which has been
# marked as `#[deprecated]` without note. For instance, "__attribute__((deprecated))"
# would be a reasonable value if targeting gcc/clang. A more portable solution
# would involve emitting the name of a macro which you define in a
# platform-specific way. e.g. "DEPRECATED_ENUM"
# default: nothing is emitted for deprecated enums
deprecated = "DEPRECATED_ENUM"

# An optional string that should come before the name of any enum which has been
# marked as `#[deprecated(note = "reason")]`. `{}` will be replaced with the
# double-quoted string. For instance, "__attribute__((deprecated({})))"
# would be a reasonable value if targeting gcc/clang. A more portable solution
# would involve emitting the name of a macro which you define in a
# platform-specific way. e.g. "DEPRECATED_ENUM_WITH_NOTE(note)"
# default: nothing is emitted for deprecated enums
deprecated_with_notes = "DEPRECATED_ENUM_WITH_NOTE"

# Whether enums with fields should generate destructors. This exists so that generic
# enums can be properly instantiated with payloads that are C++ types with
# destructors. This isn't necessary for structs because C++ has rules to
Expand Down
3 changes: 3 additions & 0 deletions src/bindgen/cdecl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct CDecl {
type_generic_args: Vec<GenericArgument>,
declarators: Vec<CDeclarator>,
type_ctype: Option<DeclarationType>,
deprecated: Option<String>,
}

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

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

Expand Down
16 changes: 16 additions & 0 deletions src/bindgen/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ pub struct FunctionConfig {
pub postfix: Option<String>,
/// The way to annotation this function as #[must_use]
pub must_use: Option<String>,
/// The way to annotation this function as #[deprecated] without notes
pub deprecated: Option<String>,
/// The way to annotation this function as #[deprecated] with notes
pub deprecated_with_note: Option<String>,
/// The style to layout the args
pub args: Layout,
/// The rename rule to apply to function args
Expand All @@ -443,6 +447,8 @@ impl Default for FunctionConfig {
prefix: None,
postfix: None,
must_use: None,
deprecated: None,
deprecated_with_note: None,
args: Layout::Auto,
rename_args: RenameRule::None,
swift_name_macro: None,
Expand Down Expand Up @@ -498,6 +504,10 @@ pub struct StructConfig {
pub associated_constants_in_body: bool,
/// The way to annotate this struct as #[must_use].
pub must_use: Option<String>,
/// The way to annotation this function as #[deprecated] without notes
pub deprecated: Option<String>,
/// The way to annotation this function as #[deprecated] with notes
pub deprecated_with_note: Option<String>,
}

impl StructConfig {
Expand Down Expand Up @@ -581,6 +591,10 @@ pub struct EnumConfig {
pub cast_assert_name: Option<String>,
/// The way to annotation this enum as #[must_use].
pub must_use: Option<String>,
/// The way to annotation this function as #[deprecated] without notes
pub deprecated: Option<String>,
/// The way to annotation this function as #[deprecated] with notes
pub deprecated_with_note: Option<String>,
/// Whether to generate destructors of tagged enums.
pub derive_tagged_enum_destructor: bool,
/// Whether to generate copy-constructors of tagged enums.
Expand Down Expand Up @@ -612,6 +626,8 @@ impl Default for EnumConfig {
derive_mut_casts: false,
cast_assert_name: None,
must_use: None,
deprecated: None,
deprecated_with_note: None,
derive_tagged_enum_destructor: false,
derive_tagged_enum_copy_constructor: false,
derive_tagged_enum_copy_assignment: false,
Expand Down
26 changes: 25 additions & 1 deletion 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 @@ -53,6 +55,27 @@ impl AnnotationSet {
self.must_use && config.language != Language::Cython
}

pub(crate) fn deprecated_note(&self, config: &Config) -> Option<String> {
sevenc-nanashi marked this conversation as resolved.
Show resolved Hide resolved
if config.language == Language::Cython {
return None;
}

self.deprecated.clone()
sevenc-nanashi marked this conversation as resolved.
Show resolved Hide resolved
}

pub(crate) fn format_deprecated_note(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have no idea around where to put these utilities.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This doesn't use self, so at the very least should be a static function right?

&self,
format_without_note: Option<&str>,
format_with_note: Option<&str>,
note: &str,
) -> Option<String> {
if note.is_empty() {
return format_without_note.map(|x| x.to_string());
}
format_with_note
.map(|format_with_note| format_with_note.replace("{}", format!("{:?}", note).as_str()))
}

pub fn load(attrs: &[syn::Attribute]) -> Result<AnnotationSet, String> {
let lines = attrs.get_comment_lines();
let lines: Vec<&str> = lines
Expand All @@ -68,7 +91,7 @@ impl AnnotationSet {
.collect();

let must_use = attrs.has_attr_word("must_use");

let deprecated = attrs.find_deprecated_note()?;
let mut annotations = HashMap::new();

// Look at each line for an annotation
Expand Down Expand Up @@ -118,6 +141,7 @@ impl AnnotationSet {
Ok(AnnotationSet {
annotations,
must_use,
deprecated,
})
}

Expand Down
53 changes: 52 additions & 1 deletion src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,21 @@ impl Enum {
if let Some(prim) = size {
// If we need to specify size, then we have no choice but to create a typedef,
// so `config.style` is not respected.
write!(out, "enum {}", tag_name);
write!(out, "enum");
if let Some(note) = self.annotations.deprecated_note(config) {
if note.is_empty() {
if let Some(ref anno) = config.structure.deprecated {
write!(out, " {}", anno);
}
} else if let Some(ref anno) = config.structure.deprecated_with_note {
write!(
out,
" {}",
anno.replace("{}", format!("{:?}", note).as_str())
);
}
}
write!(out, " {}", tag_name);

if config.cpp_compatible_c() {
out.new_line();
Expand All @@ -769,6 +783,19 @@ impl Enum {
out.write("typedef ");
}
out.write("enum");
if let Some(note) = self.annotations.deprecated_note(config) {
if note.is_empty() {
if let Some(ref anno) = config.structure.deprecated {
write!(out, " {}", anno);
}
} else if let Some(ref anno) = config.structure.deprecated_with_note {
write!(
out,
" {}",
anno.replace("{}", format!("{:?}", note).as_str())
);
}
}
if config.style.generate_tag() {
write!(out, " {}", tag_name);
}
Expand All @@ -787,6 +814,20 @@ impl Enum {
}
}

if let Some(note) = self.annotations.deprecated_note(config) {
if note.is_empty() {
if let Some(ref anno) = config.structure.deprecated {
write!(out, " {}", anno);
}
} else if let Some(ref anno) = config.structure.deprecated_with_note {
write!(
out,
" {}",
anno.replace("{}", format!("{:?}", note).as_str())
);
}
}

write!(out, " {}", tag_name);
if let Some(prim) = size {
write!(out, " : {}", prim);
Expand Down Expand Up @@ -865,6 +906,16 @@ impl Enum {
}
}

if let Some(note) = self.annotations.deprecated_note(config) {
if let Some(note) = self.annotations.format_deprecated_note(
config.enumeration.deprecated.as_deref(),
config.enumeration.deprecated_with_note.as_deref(),
&note,
) {
write!(out, " {} ", note);
}
}

if config.language != Language::C || config.style.generate_tag() {
write!(out, " {}", self.export_name());
}
Expand Down
24 changes: 24 additions & 0 deletions src/bindgen/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,15 @@ impl Source for Function {
write!(out, "{} ", anno);
}
}
if let Some(note) = func.annotations.deprecated_note(config) {
if let Some(note) = func.annotations.format_deprecated_note(
config.function.deprecated.as_deref(),
config.function.deprecated_with_note.as_deref(),
&note,
) {
write!(out, "{} ", note);
}
}
}
cdecl::write_func(out, func, Layout::Horizontal, config);

Expand Down Expand Up @@ -284,6 +293,21 @@ impl Source for Function {
out.new_line();
}
}
if let Some(note) = func.annotations.deprecated_note(config) {
if note.is_empty() {
if let Some(ref anno) = config.function.deprecated {
write!(out, "{}", anno);
out.new_line();
}
} else if let Some(ref anno) = config.function.deprecated_with_note {
sevenc-nanashi marked this conversation as resolved.
Show resolved Hide resolved
write!(
out,
"{}",
anno.replace("{}", format!("{:?}", note).as_str())
);
out.new_line();
}
}
}
cdecl::write_func(out, func, Layout::Vertical, config);
if !func.extern_decl {
Expand Down
9 changes: 9 additions & 0 deletions src/bindgen/ir/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,15 @@ impl Source for Struct {
write!(out, " {}", anno);
}
}
if let Some(note) = self.annotations.deprecated_note(config) {
if let Some(note) = self.annotations.format_deprecated_note(
config.structure.deprecated.as_deref(),
config.structure.deprecated_with_note.as_deref(),
&note,
) {
write!(out, " {}", note);
}
}

if config.language != Language::C || config.style.generate_tag() {
write!(out, " {}", self.export_name());
Expand Down