@@ -23,12 +23,14 @@ template <typename Options>
23
23
void OptionsParser<Options>::AddOption(const char * name,
24
24
const char * help_text,
25
25
bool Options::* field,
26
- OptionEnvvarSettings env_setting) {
26
+ OptionEnvvarSettings env_setting,
27
+ bool default_is_true) {
27
28
options_.emplace (name,
28
29
OptionInfo{kBoolean ,
29
30
std::make_shared<SimpleOptionField<bool >>(field),
30
31
env_setting,
31
- help_text});
32
+ help_text,
33
+ default_is_true});
32
34
}
33
35
34
36
template <typename Options>
@@ -186,7 +188,8 @@ auto OptionsParser<Options>::Convert(
186
188
return OptionInfo{original.type ,
187
189
Convert (original.field , get_child),
188
190
original.env_setting ,
189
- original.help_text };
191
+ original.help_text ,
192
+ original.default_is_true };
190
193
}
191
194
192
195
template <typename Options>
@@ -225,6 +228,10 @@ inline std::string RequiresArgumentErr(const std::string& arg) {
225
228
return arg + " requires an argument" ;
226
229
}
227
230
231
+ inline std::string NegationImpliesBooleanError (const std::string& arg) {
232
+ return arg + " is an invalid negation because it is not a boolean option" ;
233
+ }
234
+
228
235
// We store some of the basic information around a single Parse call inside
229
236
// this struct, to separate storage of command line arguments and their
230
237
// handling. In particular, this makes it easier to introduce 'synthetic'
@@ -325,6 +332,13 @@ void OptionsParser<Options>::Parse(
325
332
name[i] = ' -' ;
326
333
}
327
334
335
+ // Convert --no-foo to --foo and keep in mind that we're negating.
336
+ bool is_negation = false ;
337
+ if (name.find (" --no-" ) == 0 ) {
338
+ name.erase (2 , 3 ); // remove no-
339
+ is_negation = true ;
340
+ }
341
+
328
342
{
329
343
auto it = aliases_.end ();
330
344
// Expand aliases:
@@ -367,7 +381,12 @@ void OptionsParser<Options>::Parse(
367
381
}
368
382
369
383
{
370
- auto implications = implications_.equal_range (name);
384
+ std::string implied_name = name;
385
+ if (is_negation) {
386
+ // Implications for negated options are defined with "--no-".
387
+ implied_name.insert (2 , " no-" );
388
+ }
389
+ auto implications = implications_.equal_range (implied_name);
371
390
for (auto it = implications.first ; it != implications.second ; ++it) {
372
391
if (it->second .type == kV8Option ) {
373
392
v8_args->push_back (it->second .name );
@@ -384,6 +403,13 @@ void OptionsParser<Options>::Parse(
384
403
}
385
404
386
405
const OptionInfo& info = it->second ;
406
+
407
+ // Some V8 options can be negated and they are validated by V8 later.
408
+ if (is_negation && info.type != kBoolean && info.type != kV8Option ) {
409
+ errors->push_back (NegationImpliesBooleanError (arg));
410
+ break ;
411
+ }
412
+
387
413
std::string value;
388
414
if (info.type != kBoolean && info.type != kNoOp && info.type != kV8Option ) {
389
415
if (equals_index != std::string::npos) {
@@ -412,7 +438,7 @@ void OptionsParser<Options>::Parse(
412
438
413
439
switch (info.type ) {
414
440
case kBoolean :
415
- *Lookup<bool >(info.field , options) = true ;
441
+ *Lookup<bool >(info.field , options) = !is_negation ;
416
442
break ;
417
443
case kInteger :
418
444
*Lookup<int64_t >(info.field , options) = std::atoll (value.c_str ());
0 commit comments