Skip to content

Commit be59618

Browse files
committed
feat: support #[deprecated] on enum variants
While the #[deprecated] attribute was already used on structs, fns and enums, it was not implemented for enum variants. The information about enum variants is already available via `variant.body.annotations`, so the support for the #[deprecated] attribute on enum-variant level is more or less only another pair of entries within the `EnumConfig`. This commit adds two new options within the `[enum]` settings: - deprecated_variant, and - deprecated_variant_with_notes Both get active only on #[deprecated] variants, e.g., #[repr(u8)] enum ApiLevel { #[deprecated(note = "Legacy Support until 2025")] L1 = 1, #[deprecated] L2 = 2, L3 = 3, L4 = 4, } For enums with struct variants, the current struct deprecation methods are already working good enough (see tests/expecations/deprecated*).
1 parent f1d5801 commit be59618

15 files changed

+474
-20
lines changed

docs.md

+17
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,23 @@ deprecated = "DEPRECATED_ENUM"
933933
# default: nothing is emitted for deprecated enums
934934
deprecated_with_notes = "DEPRECATED_ENUM_WITH_NOTE"
935935

936+
# An optional string that should come after the name of any enum variant which has been
937+
# marked as `#[deprecated]` without note. For instance, "__attribute__((deprecated))"
938+
# would be a reasonable value if targeting gcc/clang. A more portable solution would
939+
# involve emitting the name of a macro which you define in a platform-specific
940+
# way. e.g. "DEPRECATED_ENUM_VARIANT"
941+
# default: nothing is emitted for deprecated enum variants
942+
deprecated_variant = "DEPRECATED_ENUM_VARIANT"
943+
944+
# An optional string that should come after the name of any enum variant which has been
945+
# marked as `#[deprecated(note = "reason")]`. `{}` will be replaced with the
946+
# double-quoted string. For instance, "__attribute__((deprecated({})))" would be a
947+
# reasonable value if targeting gcc/clang. A more portable solution would involve
948+
# emitting the name of a macro which you define in a platform-specific
949+
# way. e.g. "DEPRECATED_ENUM_WITH_NOTE(note)"
950+
# default: nothing is emitted for deprecated enum variants
951+
deprecated_variant_with_notes = "DEPRECATED_ENUM_VARIANT_WITH_NOTE({})"
952+
936953
# Whether enums with fields should generate destructors. This exists so that generic
937954
# enums can be properly instantiated with payloads that are C++ types with
938955
# destructors. This isn't necessary for structs because C++ has rules to

src/bindgen/config.rs

+6
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,10 @@ pub struct EnumConfig {
586586
pub deprecated: Option<String>,
587587
/// The way to annotation this function as #[deprecated] with notes
588588
pub deprecated_with_note: Option<String>,
589+
/// The way to annotate this enum variant as #[deprecated] without notes
590+
pub deprecated_variant: Option<String>,
591+
/// The way to annotate this enum variant as #[deprecated] with notes
592+
pub deprecated_variant_with_note: Option<String>,
589593
/// Whether to generate destructors of tagged enums.
590594
pub derive_tagged_enum_destructor: bool,
591595
/// Whether to generate copy-constructors of tagged enums.
@@ -619,6 +623,8 @@ impl Default for EnumConfig {
619623
must_use: None,
620624
deprecated: None,
621625
deprecated_with_note: None,
626+
deprecated_variant: None,
627+
deprecated_variant_with_note: None,
622628
derive_tagged_enum_destructor: false,
623629
derive_tagged_enum_copy_constructor: false,
624630
derive_tagged_enum_copy_assignment: false,

src/bindgen/ir/annotation.rs

+5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub enum DeprecatedNoteKind {
4343
Function,
4444
Struct,
4545
Enum,
46+
EnumVariant,
4647
}
4748

4849
impl AnnotationSet {
@@ -76,13 +77,17 @@ impl AnnotationSet {
7677
if note.is_empty() {
7778
return Some(Cow::Borrowed(match kind {
7879
DeprecatedNoteKind::Enum => config.enumeration.deprecated.as_deref()?,
80+
DeprecatedNoteKind::EnumVariant => {
81+
config.enumeration.deprecated_variant.as_deref()?
82+
}
7983
DeprecatedNoteKind::Function => config.function.deprecated.as_deref()?,
8084
DeprecatedNoteKind::Struct => config.structure.deprecated.as_deref()?,
8185
}));
8286
}
8387

8488
let format = match kind {
8589
DeprecatedNoteKind::Enum => &config.enumeration.deprecated_with_note,
90+
DeprecatedNoteKind::EnumVariant => &config.enumeration.deprecated_variant_with_note,
8691
DeprecatedNoteKind::Function => &config.function.deprecated_with_note,
8792
DeprecatedNoteKind::Struct => &config.structure.deprecated_with_note,
8893
}

src/bindgen/ir/enumeration.rs

+9
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,15 @@ impl Source for EnumVariant {
301301
}
302302
self.documentation.write(config, out);
303303
write!(out, "{}", self.export_name);
304+
305+
if let Some(note) = self
306+
.body
307+
.annotations()
308+
.deprecated_note(config, DeprecatedNoteKind::EnumVariant)
309+
{
310+
write!(out, " {}", note);
311+
}
312+
304313
if let Some(discriminant) = &self.discriminant {
305314
if config.language == Language::Cython {
306315
// For extern Cython declarations the enumerator value is ignored,

tests/expectations/deprecated.c

+43-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#define DEPRECATED_FUNC __attribute__((deprecated))
22
#define DEPRECATED_STRUCT __attribute__((deprecated))
33
#define DEPRECATED_ENUM __attribute__((deprecated))
4+
#define DEPRECATED_ENUM_VARIANT __attribute__((deprecated))
45
#define DEPRECATED_FUNC_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
56
#define DEPRECATED_STRUCT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
67
#define DEPRECATED_ENUM_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
8+
#define DEPRECATED_ENUM_VARIANT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
79

810

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

26+
enum EnumWithDeprecatedVariants {
27+
C = 0,
28+
D DEPRECATED_ENUM_VARIANT = 1,
29+
E DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 2,
30+
F DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 3,
31+
};
32+
typedef int32_t EnumWithDeprecatedVariants;
33+
2434
typedef struct DEPRECATED_STRUCT {
2535
int32_t a;
2636
} DeprecatedStruct;
@@ -29,6 +39,35 @@ typedef struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") {
2939
int32_t a;
3040
} DeprecatedStructWithNote;
3141

42+
enum EnumWithDeprecatedStructVariants_Tag {
43+
Foo,
44+
Bar DEPRECATED_ENUM_VARIANT,
45+
Baz DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note"),
46+
};
47+
typedef uint8_t EnumWithDeprecatedStructVariants_Tag;
48+
49+
typedef struct DEPRECATED_STRUCT {
50+
EnumWithDeprecatedStructVariants_Tag tag;
51+
uint8_t x;
52+
int16_t y;
53+
} Bar_Body;
54+
55+
typedef struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") {
56+
EnumWithDeprecatedStructVariants_Tag tag;
57+
uint8_t x;
58+
uint8_t y;
59+
} Baz_Body;
60+
61+
typedef union {
62+
EnumWithDeprecatedStructVariants_Tag tag;
63+
struct {
64+
EnumWithDeprecatedStructVariants_Tag foo_tag;
65+
int16_t foo;
66+
};
67+
Bar_Body bar;
68+
Baz_Body baz;
69+
} EnumWithDeprecatedStructVariants;
70+
3271
DEPRECATED_FUNC void deprecated_without_note(void);
3372

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

4382
void dummy(DeprecatedEnum a,
4483
DeprecatedEnumWithNote b,
45-
DeprecatedStruct c,
46-
DeprecatedStructWithNote d);
84+
EnumWithDeprecatedVariants c,
85+
DeprecatedStruct d,
86+
DeprecatedStructWithNote e,
87+
EnumWithDeprecatedStructVariants f);

tests/expectations/deprecated.compat.c

+55-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#define DEPRECATED_FUNC __attribute__((deprecated))
22
#define DEPRECATED_STRUCT __attribute__((deprecated))
33
#define DEPRECATED_ENUM __attribute__((deprecated))
4+
#define DEPRECATED_ENUM_VARIANT __attribute__((deprecated))
45
#define DEPRECATED_FUNC_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
56
#define DEPRECATED_STRUCT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
67
#define DEPRECATED_ENUM_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
8+
#define DEPRECATED_ENUM_VARIANT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
79

810

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

38+
enum EnumWithDeprecatedVariants
39+
#ifdef __cplusplus
40+
: int32_t
41+
#endif // __cplusplus
42+
{
43+
C = 0,
44+
D DEPRECATED_ENUM_VARIANT = 1,
45+
E DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 2,
46+
F DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 3,
47+
};
48+
#ifndef __cplusplus
49+
typedef int32_t EnumWithDeprecatedVariants;
50+
#endif // __cplusplus
51+
3652
typedef struct DEPRECATED_STRUCT {
3753
int32_t a;
3854
} DeprecatedStruct;
@@ -41,6 +57,41 @@ typedef struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") {
4157
int32_t a;
4258
} DeprecatedStructWithNote;
4359

60+
enum EnumWithDeprecatedStructVariants_Tag
61+
#ifdef __cplusplus
62+
: uint8_t
63+
#endif // __cplusplus
64+
{
65+
Foo,
66+
Bar DEPRECATED_ENUM_VARIANT,
67+
Baz DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note"),
68+
};
69+
#ifndef __cplusplus
70+
typedef uint8_t EnumWithDeprecatedStructVariants_Tag;
71+
#endif // __cplusplus
72+
73+
typedef struct DEPRECATED_STRUCT {
74+
EnumWithDeprecatedStructVariants_Tag tag;
75+
uint8_t x;
76+
int16_t y;
77+
} Bar_Body;
78+
79+
typedef struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") {
80+
EnumWithDeprecatedStructVariants_Tag tag;
81+
uint8_t x;
82+
uint8_t y;
83+
} Baz_Body;
84+
85+
typedef union {
86+
EnumWithDeprecatedStructVariants_Tag tag;
87+
struct {
88+
EnumWithDeprecatedStructVariants_Tag foo_tag;
89+
int16_t foo;
90+
};
91+
Bar_Body bar;
92+
Baz_Body baz;
93+
} EnumWithDeprecatedStructVariants;
94+
4495
#ifdef __cplusplus
4596
extern "C" {
4697
#endif // __cplusplus
@@ -58,8 +109,10 @@ void deprecated_with_note_which_requires_to_be_escaped(void);
58109

59110
void dummy(DeprecatedEnum a,
60111
DeprecatedEnumWithNote b,
61-
DeprecatedStruct c,
62-
DeprecatedStructWithNote d);
112+
EnumWithDeprecatedVariants c,
113+
DeprecatedStruct d,
114+
DeprecatedStructWithNote e,
115+
EnumWithDeprecatedStructVariants f);
63116

64117
#ifdef __cplusplus
65118
} // extern "C"

tests/expectations/deprecated.cpp

+45-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#define DEPRECATED_FUNC __attribute__((deprecated))
22
#define DEPRECATED_STRUCT __attribute__((deprecated))
33
#define DEPRECATED_ENUM __attribute__((deprecated))
4+
#define DEPRECATED_ENUM_VARIANT __attribute__((deprecated))
45
#define DEPRECATED_FUNC_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
56
#define DEPRECATED_STRUCT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
67
#define DEPRECATED_ENUM_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
8+
#define DEPRECATED_ENUM_VARIANT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
79

810

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

25+
enum class EnumWithDeprecatedVariants : int32_t {
26+
C = 0,
27+
D DEPRECATED_ENUM_VARIANT = 1,
28+
E DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 2,
29+
F DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note") = 3,
30+
};
31+
2332
struct DEPRECATED_STRUCT DeprecatedStruct {
2433
int32_t a;
2534
};
@@ -28,6 +37,38 @@ struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") DeprecatedStructWithNote {
2837
int32_t a;
2938
};
3039

40+
union EnumWithDeprecatedStructVariants {
41+
enum class Tag : uint8_t {
42+
Foo,
43+
Bar DEPRECATED_ENUM_VARIANT,
44+
Baz DEPRECATED_ENUM_VARIANT_WITH_NOTE("This is a note"),
45+
};
46+
47+
struct Foo_Body {
48+
Tag tag;
49+
int16_t _0;
50+
};
51+
52+
struct DEPRECATED_STRUCT Bar_Body {
53+
Tag tag;
54+
uint8_t x;
55+
int16_t y;
56+
};
57+
58+
struct DEPRECATED_STRUCT_WITH_NOTE("This is a note") Baz_Body {
59+
Tag tag;
60+
uint8_t x;
61+
uint8_t y;
62+
};
63+
64+
struct {
65+
Tag tag;
66+
};
67+
Foo_Body foo;
68+
Bar_Body bar;
69+
Baz_Body baz;
70+
};
71+
3172
extern "C" {
3273

3374
DEPRECATED_FUNC void deprecated_without_note();
@@ -43,7 +84,9 @@ void deprecated_with_note_which_requires_to_be_escaped();
4384

4485
void dummy(DeprecatedEnum a,
4586
DeprecatedEnumWithNote b,
46-
DeprecatedStruct c,
47-
DeprecatedStructWithNote d);
87+
EnumWithDeprecatedVariants c,
88+
DeprecatedStruct d,
89+
DeprecatedStructWithNote e,
90+
EnumWithDeprecatedStructVariants f);
4891

4992
} // extern "C"

tests/expectations/deprecated.pyx

+35-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#define DEPRECATED_FUNC __attribute__((deprecated))
22
#define DEPRECATED_STRUCT __attribute__((deprecated))
33
#define DEPRECATED_ENUM __attribute__((deprecated))
4+
#define DEPRECATED_ENUM_VARIANT __attribute__((deprecated))
45
#define DEPRECATED_FUNC_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
56
#define DEPRECATED_STRUCT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
67
#define DEPRECATED_ENUM_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
8+
#define DEPRECATED_ENUM_VARIANT_WITH_NOTE(...) __attribute__((deprecated(__VA_ARGS__)))
79

810

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

27+
cdef enum:
28+
C # = 0,
29+
D # = 1,
30+
E # = 2,
31+
F # = 3,
32+
ctypedef int32_t EnumWithDeprecatedVariants;
33+
2534
ctypedef struct DeprecatedStruct:
2635
int32_t a;
2736

2837
ctypedef struct DeprecatedStructWithNote:
2938
int32_t a;
3039

40+
cdef enum:
41+
Foo,
42+
Bar,
43+
Baz,
44+
ctypedef uint8_t EnumWithDeprecatedStructVariants_Tag;
45+
46+
ctypedef struct Bar_Body:
47+
EnumWithDeprecatedStructVariants_Tag tag;
48+
uint8_t x;
49+
int16_t y;
50+
51+
ctypedef struct Baz_Body:
52+
EnumWithDeprecatedStructVariants_Tag tag;
53+
uint8_t x;
54+
uint8_t y;
55+
56+
ctypedef union EnumWithDeprecatedStructVariants:
57+
EnumWithDeprecatedStructVariants_Tag tag;
58+
int16_t foo;
59+
Bar_Body bar;
60+
Baz_Body baz;
61+
3162
void deprecated_without_note();
3263

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

4172
void dummy(DeprecatedEnum a,
4273
DeprecatedEnumWithNote b,
43-
DeprecatedStruct c,
44-
DeprecatedStructWithNote d);
74+
EnumWithDeprecatedVariants c,
75+
DeprecatedStruct d,
76+
DeprecatedStructWithNote e,
77+
EnumWithDeprecatedStructVariants f);

0 commit comments

Comments
 (0)