Skip to content

Commit 49a2074

Browse files
committed
PRE-MERGE #18915 Add reflection to the ActionArgs in the settings model
2 parents 42ef28a + 72e9b64 commit 49a2074

16 files changed

+892
-173
lines changed

src/cascadia/TerminalSettingsModel/ActionArgs.h

Lines changed: 213 additions & 106 deletions
Large diffs are not rendered by default.

src/cascadia/TerminalSettingsModel/ActionArgs.idl

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,32 @@ import "Command.idl";
55

66
namespace Microsoft.Terminal.Settings.Model
77
{
8+
enum ArgTag
9+
{
10+
None = 0,
11+
FilePath,
12+
ColorScheme
13+
};
14+
15+
struct ArgDescription
16+
{
17+
String Name;
18+
String Type;
19+
Boolean Required;
20+
ArgTag Tag;
21+
};
22+
823
interface IActionArgs
924
{
1025
Boolean Equals(IActionArgs other);
1126
String GenerateName();
1227
IActionArgs Copy();
1328
UInt64 Hash();
29+
30+
UInt32 GetArgCount();
31+
ArgDescription GetArgDescriptionAt(UInt32 index);
32+
IInspectable GetArgAt(UInt32 index);
33+
void SetArgAt(UInt32 index, Object value);
1434
};
1535

1636
interface IActionEventArgs
@@ -168,6 +188,11 @@ namespace Microsoft.Terminal.Settings.Model
168188
UInt64 ContentId{ get; set; };
169189

170190
String ToCommandline();
191+
192+
UInt32 GetArgCount();
193+
ArgDescription GetArgDescriptionAt(UInt32 index);
194+
IInspectable GetArgAt(UInt32 index);
195+
void SetArgAt(UInt32 index, Object value);
171196
};
172197

173198
[default_interface] runtimeclass ActionEventArgs : IActionEventArgs
@@ -230,7 +255,7 @@ namespace Microsoft.Terminal.Settings.Model
230255
{
231256
SendInputArgs(String input);
232257

233-
String Input { get; };
258+
String Input;
234259
};
235260

236261
[default_interface] runtimeclass SplitPaneArgs : IActionArgs
@@ -309,7 +334,7 @@ namespace Microsoft.Terminal.Settings.Model
309334
[default_interface] runtimeclass CloseTabArgs : IActionArgs
310335
{
311336
CloseTabArgs(UInt32 tabIndex);
312-
Windows.Foundation.IReference<UInt32> Index { get; };
337+
Windows.Foundation.IReference<UInt32> Index;
313338
};
314339

315340
[default_interface] runtimeclass MoveTabArgs : IActionArgs

src/cascadia/TerminalSettingsModel/ActionArgsMagic.h

Lines changed: 144 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -54,50 +54,81 @@ struct InitListPlaceholder
5454
// expanded. Pretty critical for tracking down extraneous commas, etc.
5555

5656
// Property definitions, and JSON keys
57-
#define DECLARE_ARGS(type, name, jsonKey, required, ...) \
58-
static constexpr std::string_view name##Key{ jsonKey }; \
57+
#define DECLARE_ARGS(type, name, jsonKey, required, tag, ...) \
58+
static constexpr std::string_view name##Key{ jsonKey }; \
5959
ACTION_ARG(type, name, ##__VA_ARGS__);
6060

6161
// Parameters to the non-default ctor
62-
#define CTOR_PARAMS(type, name, jsonKey, required, ...) \
62+
#define CTOR_PARAMS(type, name, jsonKey, required, tag, ...) \
6363
const type &name##Param,
6464

6565
// initializers in the ctor
66-
#define CTOR_INIT(type, name, jsonKey, required, ...) \
66+
#define CTOR_INIT(type, name, jsonKey, required, tag, ...) \
6767
_##name{ name##Param },
6868

69+
// append this argument's description to the internal vector
70+
#define APPEND_ARG_DESCRIPTION(type, name, jsonKey, required, tag, ...) \
71+
_argDescriptions.push_back({ L## #name, L## #type, std::wstring_view(L## #required) != L"false", tag });
72+
6973
// check each property in the Equals() method. You'll note there's a stray
7074
// `true` in the definition of Equals() below, that's to deal with trailing
7175
// commas
72-
#define EQUALS_ARGS(type, name, jsonKey, required, ...) \
76+
#define EQUALS_ARGS(type, name, jsonKey, required, tag, ...) \
7377
&&(otherAsUs->_##name == _##name)
7478

79+
// getter and setter for each property by index
80+
#define GET_ARG_BY_INDEX(type, name, jsonKey, required, tag, ...) \
81+
if (index == curIndex++) \
82+
{ \
83+
if (_##name.has_value()) \
84+
{ \
85+
return winrt::box_value(_##name.value()); \
86+
} \
87+
else \
88+
{ \
89+
return winrt::box_value(static_cast<type>(__VA_ARGS__)); \
90+
} \
91+
}
92+
93+
#define SET_ARG_BY_INDEX(type, name, jsonKey, required, tag, ...) \
94+
if (index == curIndex++) \
95+
{ \
96+
if (value) \
97+
{ \
98+
_##name = winrt::unbox_value<type>(value); \
99+
} \
100+
else \
101+
{ \
102+
_##name = std::nullopt; \
103+
} \
104+
}
105+
75106
// JSON deserialization. If the parameter is required to pass any validation,
76107
// add that as the `required` parameter here, as the body of a conditional
77108
// EX: For the RESIZE_PANE_ARGS
78109
// X(Model::ResizeDirection, ResizeDirection, "direction", args->ResizeDirection() == ResizeDirection::None, Model::ResizeDirection::None)
79110
// the bit
80111
// args->ResizeDirection() == ResizeDirection::None
81112
// is used as the conditional for the validation here.
82-
#define FROM_JSON_ARGS(type, name, jsonKey, required, ...) \
113+
#define FROM_JSON_ARGS(type, name, jsonKey, required, tag, ...) \
83114
JsonUtils::GetValueForKey(json, jsonKey, args->_##name); \
84115
if (required) \
85116
{ \
86117
return { nullptr, { SettingsLoadWarnings::MissingRequiredParameter } }; \
87118
}
88119

89120
// JSON serialization
90-
#define TO_JSON_ARGS(type, name, jsonKey, required, ...) \
121+
#define TO_JSON_ARGS(type, name, jsonKey, required, tag, ...) \
91122
JsonUtils::SetValueForKey(json, jsonKey, args->_##name);
92123

93124
// Copy each property in the Copy() method
94-
#define COPY_ARGS(type, name, jsonKey, required, ...) \
125+
#define COPY_ARGS(type, name, jsonKey, required, tag, ...) \
95126
copy->_##name = _##name;
96127

97128
// hash each property in Hash(). You'll note there's a stray `0` in the
98129
// definition of Hash() below, that's to deal with trailing commas (or in this
99130
// case, leading.)
100-
#define HASH_ARGS(type, name, jsonKey, required, ...) \
131+
#define HASH_ARGS(type, name, jsonKey, required, tag, ...) \
101132
h.write(name());
102133

103134
// Use ACTION_ARGS_STRUCT when you've got no other customizing to do.
@@ -111,53 +142,108 @@ struct InitListPlaceholder
111142
// * NewTerminalArgs has a ToCommandline method it needs to additionally declare.
112143
// * GlobalSummonArgs has the QuakeModeFromJson helper
113144

114-
#define ACTION_ARG_BODY(className, argsMacro) \
115-
className() = default; \
116-
className( \
117-
argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \
118-
argsMacro(CTOR_INIT) _placeholder{} {}; \
119-
argsMacro(DECLARE_ARGS); \
120-
\
121-
private: \
122-
InitListPlaceholder _placeholder; \
123-
\
124-
public: \
125-
hstring GenerateName() const; \
126-
bool Equals(const IActionArgs& other) \
127-
{ \
128-
auto otherAsUs = other.try_as<className>(); \
129-
if (otherAsUs) \
130-
{ \
131-
return true argsMacro(EQUALS_ARGS); \
132-
} \
133-
return false; \
134-
}; \
135-
static FromJsonResult FromJson(const Json::Value& json) \
136-
{ \
137-
auto args = winrt::make_self<className>(); \
138-
argsMacro(FROM_JSON_ARGS); \
139-
return { *args, {} }; \
140-
} \
141-
static Json::Value ToJson(const IActionArgs& val) \
142-
{ \
143-
if (!val) \
144-
{ \
145-
return {}; \
146-
} \
147-
Json::Value json{ Json::ValueType::objectValue }; \
148-
const auto args{ get_self<className>(val) }; \
149-
argsMacro(TO_JSON_ARGS); \
150-
return json; \
151-
} \
152-
IActionArgs Copy() const \
153-
{ \
154-
auto copy{ winrt::make_self<className>() }; \
155-
argsMacro(COPY_ARGS); \
156-
return *copy; \
157-
} \
158-
size_t Hash() const \
159-
{ \
160-
til::hasher h; \
161-
argsMacro(HASH_ARGS); \
162-
return h.finalize(); \
145+
#define ACTION_ARG_BODY(className, argsMacro) \
146+
className(){ argsMacro(APPEND_ARG_DESCRIPTION) }; \
147+
className( \
148+
argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \
149+
argsMacro(CTOR_INIT) _placeholder{} { \
150+
argsMacro(APPEND_ARG_DESCRIPTION) \
151+
}; \
152+
argsMacro(DECLARE_ARGS); \
153+
\
154+
private: \
155+
InitListPlaceholder _placeholder; \
156+
std::vector<ArgDescription> _argDescriptions; \
157+
\
158+
public: \
159+
hstring GenerateName() const; \
160+
bool Equals(const IActionArgs& other) \
161+
{ \
162+
auto otherAsUs = other.try_as<className>(); \
163+
if (otherAsUs) \
164+
{ \
165+
return true argsMacro(EQUALS_ARGS); \
166+
} \
167+
return false; \
168+
}; \
169+
static FromJsonResult FromJson(const Json::Value& json) \
170+
{ \
171+
auto args = winrt::make_self<className>(); \
172+
argsMacro(FROM_JSON_ARGS); \
173+
return { *args, {} }; \
174+
} \
175+
static Json::Value ToJson(const IActionArgs& val) \
176+
{ \
177+
if (!val) \
178+
{ \
179+
return {}; \
180+
} \
181+
Json::Value json{ Json::ValueType::objectValue }; \
182+
const auto args{ get_self<className>(val) }; \
183+
argsMacro(TO_JSON_ARGS); \
184+
return json; \
185+
} \
186+
IActionArgs Copy() const \
187+
{ \
188+
auto copy{ winrt::make_self<className>() }; \
189+
argsMacro(COPY_ARGS); \
190+
copy->_argDescriptions = _argDescriptions; \
191+
return *copy; \
192+
} \
193+
size_t Hash() const \
194+
{ \
195+
til::hasher h; \
196+
argsMacro(HASH_ARGS); \
197+
return h.finalize(); \
198+
} \
199+
uint32_t GetArgCount() const \
200+
{ \
201+
return gsl::narrow<uint32_t>(_argDescriptions.size()); \
202+
} \
203+
ArgDescription GetArgDescriptionAt(uint32_t index) const \
204+
{ \
205+
return _argDescriptions.at(index); \
206+
} \
207+
IInspectable GetArgAt(uint32_t index) const \
208+
{ \
209+
uint32_t curIndex{ 0 }; \
210+
argsMacro(GET_ARG_BY_INDEX) return nullptr; \
211+
} \
212+
void SetArgAt(uint32_t index, IInspectable value) \
213+
{ \
214+
uint32_t curIndex{ 0 }; \
215+
argsMacro(SET_ARG_BY_INDEX) \
216+
}
217+
218+
#define PARTIAL_ACTION_ARG_BODY(className, argsMacro) \
219+
className(){ argsMacro(APPEND_ARG_DESCRIPTION) }; \
220+
className( \
221+
argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \
222+
argsMacro(CTOR_INIT) _placeholder{} { \
223+
argsMacro(APPEND_ARG_DESCRIPTION) \
224+
}; \
225+
argsMacro(DECLARE_ARGS); \
226+
\
227+
private: \
228+
InitListPlaceholder _placeholder; \
229+
std::vector<ArgDescription> _argDescriptions; \
230+
\
231+
public: \
232+
uint32_t GetArgCount() const \
233+
{ \
234+
return gsl::narrow<uint32_t>(_argDescriptions.size()); \
235+
} \
236+
ArgDescription GetArgDescriptionAt(uint32_t index) const \
237+
{ \
238+
return _argDescriptions.at(index); \
239+
} \
240+
IInspectable GetArgAt(uint32_t index) const \
241+
{ \
242+
uint32_t curIndex{ 0 }; \
243+
argsMacro(GET_ARG_BY_INDEX) return nullptr; \
244+
} \
245+
void SetArgAt(uint32_t index, IInspectable value) \
246+
{ \
247+
uint32_t curIndex{ 0 }; \
248+
argsMacro(SET_ARG_BY_INDEX) \
163249
}

0 commit comments

Comments
 (0)