Skip to content

Commit 343542c

Browse files
committed
check option names conflict on debug build
1 parent 8e64f97 commit 343542c

File tree

2 files changed

+67
-28
lines changed

2 files changed

+67
-28
lines changed

src/lib.rs

+39-28
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,7 @@ impl Options {
178178
hasarg: HasArg,
179179
occur: Occur,
180180
) -> &mut Options {
181-
validate_names(short_name, long_name);
182-
self.grps.push(OptGroup {
181+
self.push_group(OptGroup {
183182
short_name: short_name.to_string(),
184183
long_name: long_name.to_string(),
185184
hint: hint.to_string(),
@@ -207,8 +206,7 @@ impl Options {
207206
/// assert!(matches.opt_present("h"));
208207
/// ```
209208
pub fn optflag(&mut self, short_name: &str, long_name: &str, desc: &str) -> &mut Options {
210-
validate_names(short_name, long_name);
211-
self.grps.push(OptGroup {
209+
self.push_group(OptGroup {
212210
short_name: short_name.to_string(),
213211
long_name: long_name.to_string(),
214212
hint: "".to_string(),
@@ -237,8 +235,7 @@ impl Options {
237235
/// assert_eq!(2, matches.opt_count("v"));
238236
/// ```
239237
pub fn optflagmulti(&mut self, short_name: &str, long_name: &str, desc: &str) -> &mut Options {
240-
validate_names(short_name, long_name);
241-
self.grps.push(OptGroup {
238+
self.push_group(OptGroup {
242239
short_name: short_name.to_string(),
243240
long_name: long_name.to_string(),
244241
hint: "".to_string(),
@@ -277,8 +274,7 @@ impl Options {
277274
desc: &str,
278275
hint: &str,
279276
) -> &mut Options {
280-
validate_names(short_name, long_name);
281-
self.grps.push(OptGroup {
277+
self.push_group(OptGroup {
282278
short_name: short_name.to_string(),
283279
long_name: long_name.to_string(),
284280
hint: hint.to_string(),
@@ -319,8 +315,7 @@ impl Options {
319315
desc: &str,
320316
hint: &str,
321317
) -> &mut Options {
322-
validate_names(short_name, long_name);
323-
self.grps.push(OptGroup {
318+
self.push_group(OptGroup {
324319
short_name: short_name.to_string(),
325320
long_name: long_name.to_string(),
326321
hint: hint.to_string(),
@@ -360,8 +355,7 @@ impl Options {
360355
desc: &str,
361356
hint: &str,
362357
) -> &mut Options {
363-
validate_names(short_name, long_name);
364-
self.grps.push(OptGroup {
358+
self.push_group(OptGroup {
365359
short_name: short_name.to_string(),
366360
long_name: long_name.to_string(),
367361
hint: hint.to_string(),
@@ -403,8 +397,7 @@ impl Options {
403397
desc: &str,
404398
hint: &str,
405399
) -> &mut Options {
406-
validate_names(short_name, long_name);
407-
self.grps.push(OptGroup {
400+
self.push_group(OptGroup {
408401
short_name: short_name.to_string(),
409402
long_name: long_name.to_string(),
410403
hint: hint.to_string(),
@@ -680,21 +673,39 @@ impl Options {
680673

681674
Box::new(rows)
682675
}
683-
}
684676

685-
fn validate_names(short_name: &str, long_name: &str) {
686-
let len = short_name.len();
687-
assert!(
688-
len == 1 || len == 0,
689-
"the short_name (first argument) should be a single character, \
690-
or an empty string for none"
691-
);
692-
let len = long_name.len();
693-
assert!(
694-
len == 0 || len > 1,
695-
"the long_name (second argument) should be longer than a single \
696-
character, or an empty string for none"
697-
);
677+
fn push_group(&mut self, group: OptGroup) {
678+
self.validate_names(&group);
679+
self.grps.push(group);
680+
}
681+
682+
fn validate_names(&self, group: &OptGroup) {
683+
let len = group.short_name.len();
684+
assert!(
685+
len == 1 || len == 0,
686+
"the short_name (first argument) should be a single character, \
687+
or an empty string for none"
688+
);
689+
let len = group.long_name.len();
690+
assert!(
691+
len == 0 || len > 1,
692+
"the long_name (second argument) should be longer than a single \
693+
character, or an empty string for none"
694+
);
695+
696+
debug_assert!(
697+
group.short_name.is_empty()
698+
|| self.grps.iter().all(|g| g.short_name != group.short_name),
699+
"the short option name -{} caused conflict among multiple options",
700+
group.short_name,
701+
);
702+
debug_assert!(
703+
group.long_name.is_empty()
704+
|| self.grps.iter().all(|g| g.long_name != group.long_name),
705+
"the long option name --{} caused conflict among multiple options",
706+
group.long_name,
707+
);
708+
}
698709
}
699710

700711
/// What parsing style to use when parsing arguments.

src/tests/mod.rs

+28
Original file line numberDiff line numberDiff line change
@@ -1319,3 +1319,31 @@ fn test_opt_strs_pos() {
13191319
]
13201320
);
13211321
}
1322+
1323+
#[cfg(debug_assertions)]
1324+
#[test]
1325+
#[should_panic(expected = "the short option name -s caused conflict among multiple options")]
1326+
fn test_check_conflicts_in_short_name() {
1327+
let mut opts = Options::new();
1328+
opts.optflag("s", "long", "");
1329+
opts.optflag("s", "other", "");
1330+
}
1331+
1332+
#[cfg(debug_assertions)]
1333+
#[test]
1334+
#[should_panic(expected = "the long option name --long caused conflict among multiple options")]
1335+
fn test_check_conflicts_in_long_name() {
1336+
let mut opts = Options::new();
1337+
opts.optflag("a", "long", "");
1338+
opts.optflag("b", "long", "");
1339+
}
1340+
1341+
#[cfg(debug_assertions)]
1342+
#[test]
1343+
fn test_empty_names_should_not_cause_conflict() {
1344+
let mut opts = Options::new();
1345+
opts.optflag("", "long1", "");
1346+
opts.optflag("", "long2", "");
1347+
opts.optflag("a", "", "");
1348+
opts.optflag("b", "", "");
1349+
}

0 commit comments

Comments
 (0)