Skip to content

Commit 6b85295

Browse files
authored
Global options fixes (#958)
1 parent efc6127 commit 6b85295

File tree

3 files changed

+120
-50
lines changed

3 files changed

+120
-50
lines changed

src/System.CommandLine.Tests/CommandTests.cs

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -321,53 +321,6 @@ public void When_multiple_options_are_configured_then_they_must_differ_by_name()
321321
.Be("Alias '--same' is already in use.");
322322
}
323323

324-
[Fact]
325-
public void Global_options_may_be_added_with_aliases_that_conflict_with_local_options()
326-
{
327-
var command = new Command("the-command")
328-
{
329-
new Option("--same")
330-
};
331-
332-
command
333-
.Invoking(c => c.AddGlobalOption(new Option("--same")))
334-
.Should()
335-
.NotThrow<ArgumentException>();
336-
}
337-
338-
[Fact]
339-
public void Global_options_may_not_have_aliases_conflicting_with_other_global_option_aliases()
340-
{
341-
var command = new Command("the-command");
342-
343-
command.AddGlobalOption(new Option("--same"));
344-
345-
command
346-
.Invoking(c => c.AddGlobalOption(new Option("--same")))
347-
.Should()
348-
.Throw<ArgumentException>()
349-
.Which
350-
.Message
351-
.Should()
352-
.Be("Alias '--same' is already in use.");
353-
}
354-
355-
[Fact]
356-
public void When_local_options_are_added_then_they_must_differ_from_global_options_by_name()
357-
{
358-
var command = new Command("the-command");
359-
command.AddGlobalOption(new Option("--same"));
360-
361-
command
362-
.Invoking(c => c.Add(new Option("--same")))
363-
.Should()
364-
.Throw<ArgumentException>()
365-
.And
366-
.Message
367-
.Should()
368-
.Be("Alias '--same' is already in use.");
369-
}
370-
371324
protected override Symbol CreateSymbol(string name) => new Command(name);
372325
}
373326
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
5+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
6+
7+
using FluentAssertions;
8+
using Xunit;
9+
10+
namespace System.CommandLine.Tests
11+
{
12+
public class GlobalOptionTests
13+
{
14+
[Fact]
15+
public void Global_options_may_be_added_with_aliases_that_conflict_with_local_options()
16+
{
17+
var command = new Command("the-command")
18+
{
19+
new Option("--same")
20+
};
21+
22+
command
23+
.Invoking(c => c.AddGlobalOption(new Option("--same")))
24+
.Should()
25+
.NotThrow<ArgumentException>();
26+
}
27+
28+
[Fact]
29+
public void Global_options_may_not_have_aliases_conflicting_with_other_global_option_aliases()
30+
{
31+
var command = new Command("the-command");
32+
33+
command.AddGlobalOption(new Option("--same"));
34+
35+
command
36+
.Invoking(c => c.AddGlobalOption(new Option("--same")))
37+
.Should()
38+
.Throw<ArgumentException>()
39+
.Which
40+
.Message
41+
.Should()
42+
.Be("Alias '--same' is already in use.");
43+
}
44+
45+
[Fact]
46+
public void When_local_options_are_added_then_they_must_differ_from_global_options_by_name()
47+
{
48+
var command = new Command("the-command");
49+
50+
command.AddGlobalOption(new Option("--same"));
51+
52+
command
53+
.Invoking(c => c.Add(new Option("--same")))
54+
.Should()
55+
.Throw<ArgumentException>()
56+
.And
57+
.Message
58+
.Should()
59+
.Be("Alias '--same' is already in use.");
60+
}
61+
62+
[Fact]
63+
public void Global_options_appear_in_options_list()
64+
{
65+
var root = new Command("parent");
66+
67+
var option = new Option<int>("--global");
68+
69+
root.AddGlobalOption(option);
70+
71+
var child = new Command("child");
72+
73+
root.AddCommand(child);
74+
75+
root.Options.Should().Contain(option);
76+
}
77+
78+
[Fact]
79+
public void Global_options_appear_in_child_command_options_list()
80+
{
81+
var root = new Command("parent");
82+
83+
var option = new Option<int>("--global");
84+
85+
root.AddGlobalOption(option);
86+
87+
var child = new Command("child");
88+
89+
root.AddCommand(child);
90+
91+
child.Options.Should().Contain(option);
92+
}
93+
94+
[Fact]
95+
public void Subcommands_added_after_a_global_option_is_added_to_parent_will_recognize_the_global_option()
96+
{
97+
var root = new Command("parent");
98+
99+
var option = new Option<int>("--global");
100+
101+
root.AddGlobalOption(option);
102+
103+
var child = new Command("child");
104+
105+
root.AddCommand(child);
106+
107+
root.Parse("child --global 123").ValueForOption(option).Should().Be(123);
108+
109+
child.Parse("--global 123").ValueForOption(option).Should().Be(123);
110+
}
111+
}
112+
}

src/System.CommandLine/Command.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@ public Command(string name, string? description = null) : base(new[] { name }, d
1818
{
1919
}
2020

21-
public IEnumerable<Argument> Arguments => Children.OfType<Argument>();
22-
23-
public IEnumerable<Option> Options => Children.OfType<Option>();
21+
public IEnumerable<Argument> Arguments =>
22+
Children.OfType<Argument>();
23+
24+
public IEnumerable<Option> Options =>
25+
Children.OfType<Option>()
26+
.Concat(Parents
27+
.OfType<Command>()
28+
.SelectMany(c => c.GlobalOptions));
2429

2530
public IEnumerable<Option> GlobalOptions => _globalOptions.OfType<Option>();
2631

0 commit comments

Comments
 (0)