Skip to content

Commit e17c060

Browse files
committed
Add rfl::Deprecated, which adds deprecated and deprecationMessage to json schema fields.
1 parent f0af706 commit e17c060

7 files changed

Lines changed: 317 additions & 23 deletions

File tree

include/rfl/Deprecated.hpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#ifndef RFL_DEPRECATED_HPP_
2+
#define RFL_DEPRECATED_HPP_
3+
4+
#include <algorithm>
5+
#include <string_view>
6+
#include <tuple>
7+
#include <type_traits>
8+
#include <utility>
9+
10+
#include "Literal.hpp"
11+
#include "default.hpp"
12+
#include "internal/StringLiteral.hpp"
13+
14+
namespace rfl {
15+
16+
/// Used to mark a field as deprecated in the JSON schema, replacing
17+
/// rfl::Description for deprecated fields. Includes both a deprecation message
18+
/// and a description:
19+
/// rfl::Deprecated<"use X instead", "description of field", T>
20+
template <internal::StringLiteral _deprecation_message,
21+
internal::StringLiteral _description, class T>
22+
struct Deprecated {
23+
/// The underlying type.
24+
using Type = T;
25+
26+
/// The deprecation message.
27+
using DeprecationMessage = rfl::Literal<_deprecation_message>;
28+
29+
/// The description of the field (same role as Description::Content).
30+
using Content = rfl::Literal<_description>;
31+
32+
using ReflectionType = Type;
33+
34+
Deprecated() : value_(Type()) {}
35+
36+
Deprecated(const Type& _value) : value_(_value) {}
37+
38+
Deprecated(Type&& _value) noexcept : value_(std::move(_value)) {}
39+
40+
Deprecated(Deprecated&& _field) noexcept = default;
41+
42+
Deprecated(const Deprecated& _field) = default;
43+
44+
template <class U>
45+
Deprecated(const Deprecated<_deprecation_message, _description, U>& _field)
46+
: value_(_field.get()) {}
47+
48+
template <class U>
49+
Deprecated(Deprecated<_deprecation_message, _description, U>&& _field)
50+
: value_(_field.get()) {}
51+
52+
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
53+
bool>::type = true>
54+
Deprecated(const U& _value) : value_(_value) {}
55+
56+
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
57+
bool>::type = true>
58+
Deprecated(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
59+
60+
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
61+
bool>::type = true>
62+
Deprecated(const Deprecated<_deprecation_message, _description, U>& _field)
63+
: value_(_field.value()) {}
64+
65+
/// Assigns the underlying object to its default value.
66+
template <class U = Type,
67+
typename std::enable_if<std::is_default_constructible_v<U>,
68+
bool>::type = true>
69+
Deprecated(const Default&) : value_(Type()) {}
70+
71+
~Deprecated() = default;
72+
73+
/// The deprecation message, for internal use.
74+
constexpr static const internal::StringLiteral deprecation_message_ =
75+
_deprecation_message;
76+
77+
/// The description, for internal use.
78+
constexpr static const internal::StringLiteral description_ = _description;
79+
80+
/// Returns the underlying object.
81+
const Type& get() const { return value_; }
82+
83+
/// Returns the underlying object.
84+
Type& operator()() { return value_; }
85+
86+
/// Returns the underlying object.
87+
const Type& operator()() const { return value_; }
88+
89+
/// Assigns the underlying object.
90+
auto& operator=(const Type& _value) {
91+
value_ = _value;
92+
return *this;
93+
}
94+
95+
/// Assigns the underlying object.
96+
auto& operator=(Type&& _value) noexcept {
97+
value_ = std::move(_value);
98+
return *this;
99+
}
100+
101+
/// Assigns the underlying object.
102+
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
103+
bool>::type = true>
104+
auto& operator=(const U& _value) {
105+
value_ = _value;
106+
return *this;
107+
}
108+
109+
/// Assigns the underlying object to its default value.
110+
template <class U = Type,
111+
typename std::enable_if<std::is_default_constructible_v<U>,
112+
bool>::type = true>
113+
auto& operator=(const Default&) {
114+
value_ = Type();
115+
return *this;
116+
}
117+
118+
/// Assigns the underlying object.
119+
Deprecated& operator=(const Deprecated& _field) = default;
120+
121+
/// Assigns the underlying object.
122+
Deprecated& operator=(Deprecated&& _field) = default;
123+
124+
/// Assigns the underlying object.
125+
template <class U>
126+
auto& operator=(
127+
const Deprecated<_deprecation_message, _description, U>& _field) {
128+
value_ = _field.get();
129+
return *this;
130+
}
131+
132+
/// Assigns the underlying object.
133+
template <class U>
134+
auto& operator=(Deprecated<_deprecation_message, _description, U>&& _field) {
135+
value_ = std::forward<T>(_field.value_);
136+
return *this;
137+
}
138+
139+
/// Returns the underlying object - necessary for the reflection to work.
140+
const Type& reflection() const { return value_; }
141+
142+
/// Assigns the underlying object.
143+
void set(const Type& _value) { value_ = _value; }
144+
145+
/// Assigns the underlying object.
146+
void set(Type&& _value) { value_ = std::move(_value); }
147+
148+
/// Returns the underlying object.
149+
Type& value() { return value_; }
150+
151+
/// Returns the underlying object.
152+
const Type& value() const { return value_; }
153+
154+
/// The underlying value.
155+
Type value_;
156+
};
157+
158+
} // namespace rfl
159+
160+
#endif
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef RFL_INTERNAL_ISDEPRECATED_HPP_
2+
#define RFL_INTERNAL_ISDEPRECATED_HPP_
3+
4+
#include <type_traits>
5+
6+
#include "../Deprecated.hpp"
7+
#include "StringLiteral.hpp"
8+
9+
namespace rfl {
10+
namespace internal {
11+
12+
template <class T>
13+
class is_deprecated;
14+
15+
template <class T>
16+
class is_deprecated : public std::false_type {};
17+
18+
template <StringLiteral _message, StringLiteral _description, class Type>
19+
class is_deprecated<Deprecated<_message, _description, Type>>
20+
: public std::true_type {};
21+
22+
template <class T>
23+
constexpr bool is_deprecated_v =
24+
is_deprecated<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
25+
26+
} // namespace internal
27+
} // namespace rfl
28+
29+
#endif

include/rfl/json/schema/Type.hpp

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <optional>
66
#include <string>
77

8+
#include "../../Flatten.hpp"
89
#include "../../Literal.hpp"
910
#include "../../Object.hpp"
1011
#include "../../Ref.hpp"
@@ -15,123 +16,130 @@ namespace rfl::json::schema {
1516

1617
/// The JSON representation of internal::schema::Type.
1718
struct Type {
18-
struct Boolean {
19+
/// Common annotation fields shared by all schema subtypes.
20+
struct Annotations {
1921
std::optional<std::string> description{};
22+
std::optional<bool> deprecated{};
23+
std::optional<std::string> deprecationMessage{};
24+
};
25+
26+
struct Boolean {
27+
rfl::Flatten<Annotations> annotations{};
2028
Literal<"boolean"> type{};
2129
};
2230

2331
struct Integer {
2432
Literal<"integer"> type{};
25-
std::optional<std::string> description{};
33+
rfl::Flatten<Annotations> annotations{};
2634
};
2735

2836
struct Number {
2937
Literal<"number"> type{};
30-
std::optional<std::string> description{};
38+
rfl::Flatten<Annotations> annotations{};
3139
};
3240

3341
struct String {
3442
Literal<"string"> type{};
35-
std::optional<std::string> description{};
43+
rfl::Flatten<Annotations> annotations{};
3644
rfl::Rename<"minLength", std::optional<size_t>> minSize{};
3745
rfl::Rename<"maxLength", std::optional<size_t>> maxSize{};
3846
};
3947

4048
using NumericType = rfl::Variant<Integer, Number>;
4149

4250
struct AllOf {
43-
std::optional<std::string> description{};
51+
rfl::Flatten<Annotations> annotations{};
4452
std::vector<Type> allOf{};
4553
};
4654

4755
struct AnyOf {
48-
std::optional<std::string> description{};
56+
rfl::Flatten<Annotations> annotations{};
4957
std::vector<Type> anyOf{};
5058
};
5159

5260
struct ExclusiveMaximum {
53-
std::optional<std::string> description{};
61+
rfl::Flatten<Annotations> annotations{};
5462
rfl::Variant<double, int> exclusiveMaximum{};
5563
std::string type{};
5664
};
5765

5866
struct ExclusiveMinimum {
59-
std::optional<std::string> description{};
67+
rfl::Flatten<Annotations> annotations{};
6068
rfl::Variant<double, int> exclusiveMinimum{};
6169
std::string type{};
6270
};
6371

6472
struct FixedSizeTypedArray {
6573
Literal<"array"> type{};
66-
std::optional<std::string> description{};
74+
rfl::Flatten<Annotations> annotations{};
6775
rfl::Ref<Type> items{};
6876
size_t minItems{};
6977
size_t maxItems{};
7078
};
7179

7280
struct Maximum {
73-
std::optional<std::string> description{};
81+
rfl::Flatten<Annotations> annotations{};
7482
rfl::Variant<double, int> maximum{};
7583
std::string type{};
7684
};
7785

7886
struct Minimum {
79-
std::optional<std::string> description{};
87+
rfl::Flatten<Annotations> annotations{};
8088
rfl::Variant<double, int> minimum{};
8189
std::string type{};
8290
};
8391

8492
struct Null {
8593
Literal<"null"> type{};
86-
std::optional<std::string> description{};
94+
rfl::Flatten<Annotations> annotations{};
8795
};
8896

8997
struct Object {
9098
Literal<"object"> type{};
91-
std::optional<std::string> description{};
99+
rfl::Flatten<Annotations> annotations{};
92100
rfl::Object<Type> properties{};
93101
std::vector<std::string> required{};
94102
std::shared_ptr<Type> additionalProperties{};
95103
};
96104

97105
struct OneOf {
98-
std::optional<std::string> description{};
106+
rfl::Flatten<Annotations> annotations{};
99107
std::vector<Type> oneOf{};
100108
};
101109

102110
struct Reference {
103111
Rename<"$ref", std::optional<std::string>> ref{};
104-
std::optional<std::string> description{};
112+
rfl::Flatten<Annotations> annotations{};
105113
};
106114

107115
struct Regex {
108116
Literal<"string"> type{};
109-
std::optional<std::string> description{};
117+
rfl::Flatten<Annotations> annotations{};
110118
std::string pattern{};
111119
};
112120

113121
struct StringEnum {
114122
Literal<"string"> type{};
115-
std::optional<std::string> description{};
123+
rfl::Flatten<Annotations> annotations{};
116124
rfl::Rename<"enum", std::vector<std::string>> values{};
117125
};
118126

119127
struct StringMap {
120128
Literal<"object"> type{};
121-
std::optional<std::string> description{};
129+
rfl::Flatten<Annotations> annotations{};
122130
rfl::Ref<Type> additionalProperties{};
123131
};
124132

125133
struct Tuple {
126134
Literal<"array"> type{};
127-
std::optional<std::string> description{};
135+
rfl::Flatten<Annotations> annotations{};
128136
std::vector<Type> prefixItems{};
129137
bool items = false;
130138
};
131139

132140
struct TypedArray {
133141
Literal<"array"> type{};
134-
std::optional<std::string> description{};
142+
rfl::Flatten<Annotations> annotations{};
135143
rfl::Ref<Type> items{};
136144
rfl::Rename<"minItems", std::optional<size_t>> minSize{};
137145
rfl::Rename<"maxItems", std::optional<size_t>> maxSize{};

include/rfl/parsing/Parser_default.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "../internal/has_reflection_type_v.hpp"
1414
#include "../internal/has_reflector.hpp"
1515
#include "../internal/is_basic_type.hpp"
16+
#include "../internal/is_deprecated.hpp"
1617
#include "../internal/is_description.hpp"
1718
#include "../internal/is_literal.hpp"
1819
#include "../internal/is_underlying_enums_v.hpp"
@@ -127,6 +128,8 @@ struct Parser {
127128
if constexpr (rfl::internal::is_description_v<U>) {
128129
return make_description<U>(_definitions);
129130

131+
} else if constexpr (rfl::internal::is_deprecated_v<U>) {
132+
return make_deprecated<U>(_definitions);
130133
} else if constexpr (std::is_class_v<U> && std::is_aggregate_v<U>) {
131134
return make_reference<U>(_definitions);
132135

@@ -147,6 +150,18 @@ struct Parser {
147150
}
148151

149152
private:
153+
template <class U>
154+
static schema::Type make_deprecated(
155+
std::map<std::string, schema::Type>* _definitions) {
156+
using Type = schema::Type;
157+
return Type{Type::Deprecated{
158+
.deprecation_message_ = typename U::DeprecationMessage().str(),
159+
.description_ = typename U::Content().str(),
160+
.type_ =
161+
Ref<Type>::make(Parser<R, W, std::remove_cvref_t<typename U::Type>,
162+
ProcessorsType>::to_schema(_definitions))}};
163+
}
164+
150165
template <class U>
151166
static schema::Type make_description(
152167
std::map<std::string, schema::Type>* _definitions) {

0 commit comments

Comments
 (0)