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

feat: support #[deprecated] on enum variants #933

Merged
merged 1 commit into from
Apr 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,23 @@ deprecated = "DEPRECATED_ENUM"
# default: nothing is emitted for deprecated enums
deprecated_with_notes = "DEPRECATED_ENUM_WITH_NOTE"

# An optional string that should come after the name of any enum variant 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_VARIANT"
# default: nothing is emitted for deprecated enum variants
deprecated_variant = "DEPRECATED_ENUM_VARIANT"

# An optional string that should come after the name of any enum variant 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 enum variants
deprecated_variant_with_notes = "DEPRECATED_ENUM_VARIANT_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
6 changes: 6 additions & 0 deletions src/bindgen/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,10 @@ pub struct EnumConfig {
pub deprecated: Option<String>,
/// The way to annotation this function as #[deprecated] with notes
pub deprecated_with_note: Option<String>,
/// The way to annotate this enum variant as #[deprecated] without notes
pub deprecated_variant: Option<String>,
/// The way to annotate this enum variant as #[deprecated] with notes
pub deprecated_variant_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 @@ -619,6 +623,8 @@ impl Default for EnumConfig {
must_use: None,
deprecated: None,
deprecated_with_note: None,
deprecated_variant: None,
deprecated_variant_with_note: None,
derive_tagged_enum_destructor: false,
derive_tagged_enum_copy_constructor: false,
derive_tagged_enum_copy_assignment: false,
Expand Down
5 changes: 5 additions & 0 deletions src/bindgen/ir/annotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub enum DeprecatedNoteKind {
Function,
Struct,
Enum,
EnumVariant,
}

impl AnnotationSet {
Expand Down Expand Up @@ -76,13 +77,17 @@ impl AnnotationSet {
if note.is_empty() {
return Some(Cow::Borrowed(match kind {
DeprecatedNoteKind::Enum => config.enumeration.deprecated.as_deref()?,
DeprecatedNoteKind::EnumVariant => {
config.enumeration.deprecated_variant.as_deref()?
}
DeprecatedNoteKind::Function => config.function.deprecated.as_deref()?,
DeprecatedNoteKind::Struct => config.structure.deprecated.as_deref()?,
}));
}

let format = match kind {
DeprecatedNoteKind::Enum => &config.enumeration.deprecated_with_note,
DeprecatedNoteKind::EnumVariant => &config.enumeration.deprecated_variant_with_note,
DeprecatedNoteKind::Function => &config.function.deprecated_with_note,
DeprecatedNoteKind::Struct => &config.structure.deprecated_with_note,
}
Expand Down
9 changes: 9 additions & 0 deletions src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,15 @@ impl Source for EnumVariant {
}
self.documentation.write(config, out);
write!(out, "{}", self.export_name);

if let Some(note) = self
.body
.annotations()
.deprecated_note(config, DeprecatedNoteKind::EnumVariant)
{
write!(out, " {}", note);
}

if let Some(discriminant) = &self.discriminant {
if config.language == Language::Cython {
// For extern Cython declarations the enumerator value is ignored,
Expand Down
45 changes: 43 additions & 2 deletions tests/expectations/deprecated.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#define DEPRECATED_FUNC __attribute__((deprecated))
#define DEPRECATED_STRUCT __attribute__((deprecated))
#define DEPRECATED_ENUM __attribute__((deprecated))
#define DEPRECATED_ENUM_VARIANT __attribute__((deprecated))
#define DEPRECATED_FUNC_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_STRUCT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_ENUM_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_ENUM_VARIANT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))


#include <stdarg.h>
Expand All @@ -21,6 +23,14 @@ enum DEPRECATED_ENUM_WITH_NOTE("This is a note") DeprecatedEnumWithNote {
};
typedef int32_t DeprecatedEnumWithNote;

enum EnumWithDeprecatedVariants {
C = 0,
D DEPRECATED_ENUM_VARIANT = 1,
E DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 2,
F DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 3,
};
typedef int32_t EnumWithDeprecatedVariants;

typedef struct DEPRECATED_STRUCT {
int32_t a;
} DeprecatedStruct;
Expand All @@ -29,6 +39,35 @@ typedef struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") {
int32_t a;
} DeprecatedStructWithNote;

enum EnumWithDeprecatedStructVariants_Tag {
Foo,
Bar DEPRECATED_ENUM_VARIANT,
Baz DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note"),
};
typedef uint8_t EnumWithDeprecatedStructVariants_Tag;

typedef struct DEPRECATED_STRUCT {
EnumWithDeprecatedStructVariants_Tag tag;
uint8_t x;
int16_t y;
} Bar_Body;

typedef struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") {
EnumWithDeprecatedStructVariants_Tag tag;
uint8_t x;
uint8_t y;
} Baz_Body;

typedef union {
EnumWithDeprecatedStructVariants_Tag tag;
struct {
EnumWithDeprecatedStructVariants_Tag foo_tag;
int16_t foo;
};
Bar_Body bar;
Baz_Body baz;
} EnumWithDeprecatedStructVariants;

DEPRECATED_FUNC void deprecated_without_note(void);

DEPRECATED_FUNC_WITH_NOTE("This is a note") void deprecated_without_bracket(void);
Expand All @@ -42,5 +81,7 @@ void deprecated_with_note_which_requires_to_be_escaped(void);

void dummy(DeprecatedEnum a,
DeprecatedEnumWithNote b,
DeprecatedStruct c,
DeprecatedStructWithNote d);
EnumWithDeprecatedVariants c,
DeprecatedStruct d,
DeprecatedStructWithNote e,
EnumWithDeprecatedStructVariants f);
57 changes: 55 additions & 2 deletions tests/expectations/deprecated.compat.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#define DEPRECATED_FUNC __attribute__((deprecated))
#define DEPRECATED_STRUCT __attribute__((deprecated))
#define DEPRECATED_ENUM __attribute__((deprecated))
#define DEPRECATED_ENUM_VARIANT __attribute__((deprecated))
#define DEPRECATED_FUNC_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_STRUCT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_ENUM_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_ENUM_VARIANT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))


#include <stdarg.h>
Expand Down Expand Up @@ -33,6 +35,20 @@ enum DEPRECATED_ENUM_WITH_NOTE("This is a note") DeprecatedEnumWithNote
typedef int32_t DeprecatedEnumWithNote;
#endif // __cplusplus

enum EnumWithDeprecatedVariants
#ifdef __cplusplus
: int32_t
#endif // __cplusplus
{
C = 0,
D DEPRECATED_ENUM_VARIANT = 1,
E DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 2,
F DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 3,
};
#ifndef __cplusplus
typedef int32_t EnumWithDeprecatedVariants;
#endif // __cplusplus

typedef struct DEPRECATED_STRUCT {
int32_t a;
} DeprecatedStruct;
Expand All @@ -41,6 +57,41 @@ typedef struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") {
int32_t a;
} DeprecatedStructWithNote;

enum EnumWithDeprecatedStructVariants_Tag
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
Foo,
Bar DEPRECATED_ENUM_VARIANT,
Baz DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note"),
};
#ifndef __cplusplus
typedef uint8_t EnumWithDeprecatedStructVariants_Tag;
#endif // __cplusplus

typedef struct DEPRECATED_STRUCT {
EnumWithDeprecatedStructVariants_Tag tag;
uint8_t x;
int16_t y;
} Bar_Body;

typedef struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") {
EnumWithDeprecatedStructVariants_Tag tag;
uint8_t x;
uint8_t y;
} Baz_Body;

typedef union {
EnumWithDeprecatedStructVariants_Tag tag;
struct {
EnumWithDeprecatedStructVariants_Tag foo_tag;
int16_t foo;
};
Bar_Body bar;
Baz_Body baz;
} EnumWithDeprecatedStructVariants;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
Expand All @@ -58,8 +109,10 @@ void deprecated_with_note_which_requires_to_be_escaped(void);

void dummy(DeprecatedEnum a,
DeprecatedEnumWithNote b,
DeprecatedStruct c,
DeprecatedStructWithNote d);
EnumWithDeprecatedVariants c,
DeprecatedStruct d,
DeprecatedStructWithNote e,
EnumWithDeprecatedStructVariants f);

#ifdef __cplusplus
} // extern "C"
Expand Down
47 changes: 45 additions & 2 deletions tests/expectations/deprecated.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#define DEPRECATED_FUNC __attribute__((deprecated))
#define DEPRECATED_STRUCT __attribute__((deprecated))
#define DEPRECATED_ENUM __attribute__((deprecated))
#define DEPRECATED_ENUM_VARIANT __attribute__((deprecated))
#define DEPRECATED_FUNC_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_STRUCT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_ENUM_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_ENUM_VARIANT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))


#include <cstdarg>
Expand All @@ -20,6 +22,13 @@ enum class DEPRECATED_ENUM_WITH_NOTE("This is a note") DeprecatedEnumWithNote :
B = 0,
};

enum class EnumWithDeprecatedVariants : int32_t {
C = 0,
D DEPRECATED_ENUM_VARIANT = 1,
E DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 2,
F DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 3,
};

struct DEPRECATED_STRUCT DeprecatedStruct {
int32_t a;
};
Expand All @@ -28,6 +37,38 @@ struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") DeprecatedStructWithNote {
int32_t a;
};

union EnumWithDeprecatedStructVariants {
enum class Tag : uint8_t {
Foo,
Bar DEPRECATED_ENUM_VARIANT,
Baz DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note"),
};

struct Foo_Body {
Tag tag;
int16_t _0;
};

struct DEPRECATED_STRUCT Bar_Body {
Tag tag;
uint8_t x;
int16_t y;
};

struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") Baz_Body {
Tag tag;
uint8_t x;
uint8_t y;
};

struct {
Tag tag;
};
Foo_Body foo;
Bar_Body bar;
Baz_Body baz;
};

extern "C" {

DEPRECATED_FUNC void deprecated_without_note();
Expand All @@ -43,7 +84,9 @@ void deprecated_with_note_which_requires_to_be_escaped();

void dummy(DeprecatedEnum a,
DeprecatedEnumWithNote b,
DeprecatedStruct c,
DeprecatedStructWithNote d);
EnumWithDeprecatedVariants c,
DeprecatedStruct d,
DeprecatedStructWithNote e,
EnumWithDeprecatedStructVariants f);

} // extern "C"
37 changes: 35 additions & 2 deletions tests/expectations/deprecated.pyx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#define DEPRECATED_FUNC __attribute__((deprecated))
#define DEPRECATED_STRUCT __attribute__((deprecated))
#define DEPRECATED_ENUM __attribute__((deprecated))
#define DEPRECATED_ENUM_VARIANT __attribute__((deprecated))
#define DEPRECATED_FUNC_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_STRUCT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_ENUM_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
#define DEPRECATED_ENUM_VARIANT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))


from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t
Expand All @@ -22,12 +24,41 @@ cdef extern from *:
B # = 0,
ctypedef int32_t DeprecatedEnumWithNote;

cdef enum:
C # = 0,
D # = 1,
E # = 2,
F # = 3,
ctypedef int32_t EnumWithDeprecatedVariants;

ctypedef struct DeprecatedStruct:
int32_t a;

ctypedef struct DeprecatedStructWithNote:
int32_t a;

cdef enum:
Foo,
Bar,
Baz,
ctypedef uint8_t EnumWithDeprecatedStructVariants_Tag;

ctypedef struct Bar_Body:
EnumWithDeprecatedStructVariants_Tag tag;
uint8_t x;
int16_t y;

ctypedef struct Baz_Body:
EnumWithDeprecatedStructVariants_Tag tag;
uint8_t x;
uint8_t y;

ctypedef union EnumWithDeprecatedStructVariants:
EnumWithDeprecatedStructVariants_Tag tag;
int16_t foo;
Bar_Body bar;
Baz_Body baz;

void deprecated_without_note();

void deprecated_without_bracket();
Expand All @@ -40,5 +71,7 @@ cdef extern from *:

void dummy(DeprecatedEnum a,
DeprecatedEnumWithNote b,
DeprecatedStruct c,
DeprecatedStructWithNote d);
EnumWithDeprecatedVariants c,
DeprecatedStruct d,
DeprecatedStructWithNote e,
EnumWithDeprecatedStructVariants f);
Loading
Loading