Skip to content

Commit 254430e

Browse files
committed
check option names conflict on debug build
1 parent 8e64f97 commit 254430e

File tree

2 files changed

+52
-14
lines changed

2 files changed

+52
-14
lines changed

src/lib.rs

Lines changed: 24 additions & 14 deletions
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,6 +673,23 @@ impl Options {
680673

681674
Box::new(rows)
682675
}
676+
677+
fn push_group(&mut self, group: OptGroup) {
678+
validate_names(&group.short_name, &group.long_name);
679+
#[cfg(debug_assertions)]
680+
self.check_conflict(&group);
681+
self.grps.push(group);
682+
}
683+
684+
#[cfg(debug_assertions)]
685+
fn check_conflict(&self, group: &OptGroup) {
686+
if !group.short_name.is_empty() && self.grps.iter().any(|g| g.short_name == group.short_name) {
687+
panic!("the short option name -{} caused conflict among multiple options", group.short_name);
688+
}
689+
if !group.long_name.is_empty() && self.grps.iter().any(|g| g.long_name == group.long_name) {
690+
panic!("the long option name --{} caused conflict among multiple options", group.long_name);
691+
}
692+
}
683693
}
684694

685695
fn validate_names(short_name: &str, long_name: &str) {

src/tests/mod.rs

Lines changed: 28 additions & 0 deletions
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)