BadScript 2
Loading...
Searching...
No Matches
SpecificationPropertyRules.cs
Go to the documentation of this file.
1// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
2
3using System;
4using System.Collections.Generic;
5using System.Linq;
6
7using CSharpx;
8
9namespace CommandLine.Core
10{
11 internal static class SpecificationPropertyRules
12 {
13 public static IEnumerable<Func<IEnumerable<SpecificationProperty>, IEnumerable<Error>>>
14 Lookup(IEnumerable<Token> tokens)
15 {
16 return Lookup(tokens, false);
17 }
18
19 public static IEnumerable<Func<IEnumerable<SpecificationProperty>, IEnumerable<Error>>>
20 Lookup(IEnumerable<Token> tokens,
21 bool allowMultiInstance)
22 {
23 return new List<Func<IEnumerable<SpecificationProperty>, IEnumerable<Error>>>
24 {
30 EnforceSingle(tokens, allowMultiInstance),
31 };
32 }
33
34 private static Func<IEnumerable<SpecificationProperty>, IEnumerable<Error>>
36 {
37 return specProps =>
38 {
39 IEnumerable<OptionSpecification> options =
40 from sp in specProps
41 where sp.Specification.IsOption()
42 let o = (OptionSpecification)sp.Specification
43 where o.SetName.Length > 0
44 where o.Group.Length > 0
45 select o;
46
47 if (options.Any())
48 {
49 return from o in options
50 select new GroupOptionAmbiguityError(new NameInfo(o.ShortName, o.LongName));
51 }
52
53 return Enumerable.Empty<Error>();
54 };
55 }
56
57 private static Func<IEnumerable<SpecificationProperty>, IEnumerable<Error>> EnforceGroup()
58 {
59 return specProps =>
60 {
61 var optionsValues =
62 from sp in specProps
63 where sp.Specification.IsOption()
64 let o = (OptionSpecification)sp.Specification
65 where o.Group.Length > 0
66 select new { Option = o, sp.Value, sp.Specification.DefaultValue };
67
68 var groups = from o in optionsValues
69 group o by o.Option.Group
70 into g
71 select g;
72
73 var errorGroups = groups.Where(gr => gr.All(g => g.Value.IsNothing() && g.DefaultValue.IsNothing()));
74
75 if (errorGroups.Any())
76 {
77 return errorGroups.Select(gr => new MissingGroupOptionError(gr.Key,
78 gr.Select(g =>
79 new NameInfo(g.Option
80 .ShortName,
81 g.Option.LongName
82 )
83 )
84 )
85 );
86 }
87
88 return Enumerable.Empty<Error>();
89 };
90 }
91
92 private static Func<IEnumerable<SpecificationProperty>, IEnumerable<Error>> EnforceMutuallyExclusiveSet()
93 {
94 return specProps =>
95 {
96 IEnumerable<OptionSpecification> options =
97 from sp in specProps
98 where sp.Specification.IsOption()
99 where sp.Value.IsJust()
100 let o = (OptionSpecification)sp.Specification
101 where o.SetName.Length > 0
102 select o;
103
104 IEnumerable<IGrouping<string, OptionSpecification>> groups = from o in options
105 group o by o.SetName
106 into g
107 select g;
108
109 if (groups.Count() > 1)
110 {
111 return
112 from o in options
113 select new MutuallyExclusiveSetError(o.FromOptionSpecification(), o.SetName);
114 }
115
116 return Enumerable.Empty<Error>();
117 };
118 }
119
120 private static Func<IEnumerable<SpecificationProperty>, IEnumerable<Error>> EnforceRequired()
121 {
122 return specProps =>
123 {
124 IEnumerable<Specification> requiredWithValue = from sp in specProps
125 where sp.Specification.IsOption()
126 where sp.Specification.Required
127 where sp.Value.IsJust()
128 let o = (OptionSpecification)sp.Specification
129 where o.SetName.Length > 0
130 select sp.Specification;
131
132 IEnumerable<string> setWithRequiredValue = (
133 from s in requiredWithValue
134 let o = (OptionSpecification)s
135 where o.SetName.Length > 0
136 select o.SetName)
137 .Distinct();
138
139 IEnumerable<Specification> requiredWithoutValue = from sp in specProps
140 where sp.Specification.IsOption()
141 where sp.Specification.Required
142 where sp.Value.IsNothing()
143 let o = (OptionSpecification)sp.Specification
144 where o.SetName.Length > 0
145 where o.Group.Length == 0
146 where setWithRequiredValue
147 .ContainsIfNotEmpty(o.SetName)
148 select sp.Specification;
149
150 IEnumerable<Specification> missing =
151 requiredWithoutValue
152 .Except(requiredWithValue)
153 .Concat(from sp in specProps
154 where sp.Specification.IsOption()
155 where sp.Specification.Required
156 where sp.Value.IsNothing()
157 let o = (OptionSpecification)sp.Specification
158 where o.SetName.Length == 0
159 where o.Group.Length == 0
160 select sp.Specification
161 )
162 .Concat(from sp in specProps
163 where sp.Specification.IsValue()
164 where sp.Specification.Required
165 where sp.Value.IsNothing()
166 select sp.Specification
167 );
168
169 return
170 from sp in missing
171 select new MissingRequiredOptionError(sp.FromSpecification());
172 };
173 }
174
175 private static Func<IEnumerable<SpecificationProperty>, IEnumerable<Error>> EnforceRange()
176 {
177 return specProps =>
178 {
179 IEnumerable<SpecificationProperty> options = specProps
180 .Where(sp => sp.Specification.TargetType ==
181 TargetType.Sequence
182 )
183 .Where(sp => sp.Value.IsJust())
184 .Where(sp =>
185 (sp.Specification.Min.IsJust() &&
186 ((Array)sp.Value.FromJustOrFail()).Length <
187 sp.Specification.Min.FromJustOrFail()) ||
188 (sp.Specification.Max.IsJust() &&
189 ((Array)sp.Value.FromJustOrFail()).Length >
190 sp.Specification.Max.FromJustOrFail())
191 );
192
193 if (options.Any())
194 {
195 return
196 from s in options
197 select new SequenceOutOfRangeError(s.Specification.FromSpecification());
198 }
199
200 return Enumerable.Empty<Error>();
201 };
202 }
203
204 private static Func<IEnumerable<SpecificationProperty>, IEnumerable<Error>> EnforceSingle(
205 IEnumerable<Token> tokens,
206 bool allowMultiInstance)
207 {
208 return specProps =>
209 {
210 if (allowMultiInstance)
211 {
212 return Enumerable.Empty<Error>();
213 }
214
215 IEnumerable<OptionSpecification> specs = from sp in specProps
216 where sp.Specification.IsOption()
217 where sp.Value.IsJust()
218 select (OptionSpecification)sp.Specification;
219
220 var shortOptions = from t in tokens
221 where t.IsName()
222 join o in specs on t.Text equals o.ShortName into to
223 from o in to.DefaultIfEmpty()
224 where o != null
225 select new { o.ShortName, o.LongName };
226
227 var longOptions = from t in tokens
228 where t.IsName()
229 join o in specs on t.Text equals o.LongName into to
230 from o in to.DefaultIfEmpty()
231 where o != null
232 select new { o.ShortName, o.LongName };
233
234 var groups = from x in shortOptions.Concat(longOptions)
235 group x by x
236 into g
237 let count = g.Count()
238 select new { Value = g.Key, Count = count };
239
240 IEnumerable<RepeatedOptionError> errors = from y in groups
241 where y.Count > 1
242 select new RepeatedOptionError(new NameInfo(y.Value.ShortName,
243 y.Value.LongName
244 )
245 );
246
247 return errors;
248 };
249 }
250
251 private static bool ContainsIfNotEmpty<T>(this IEnumerable<T> sequence, T value)
252 {
253 if (sequence.Any())
254 {
255 return sequence.Contains(value);
256 }
257
258 return true;
259 }
260 }
261}
static Func< IEnumerable< SpecificationProperty >, IEnumerable< Error > > EnforceRequired()
static IEnumerable< Func< IEnumerable< SpecificationProperty >, IEnumerable< Error > > > Lookup(IEnumerable< Token > tokens)
static IEnumerable< Func< IEnumerable< SpecificationProperty >, IEnumerable< Error > > > Lookup(IEnumerable< Token > tokens, bool allowMultiInstance)
static Func< IEnumerable< SpecificationProperty >, IEnumerable< Error > > EnforceRange()
static Func< IEnumerable< SpecificationProperty >, IEnumerable< Error > > EnforceMutuallyExclusiveSetAndGroupAreNotUsedTogether()
static Func< IEnumerable< SpecificationProperty >, IEnumerable< Error > > EnforceSingle(IEnumerable< Token > tokens, bool allowMultiInstance)
static Func< IEnumerable< SpecificationProperty >, IEnumerable< Error > > EnforceGroup()
static Func< IEnumerable< SpecificationProperty >, IEnumerable< Error > > EnforceMutuallyExclusiveSet()
Base type of all errors.
Definition Error.cs:110
Models an error generated when a required option is required.
Definition Error.cs:392
Models an error generated when a an option from another set is defined.
Definition Error.cs:401
Models name information, used in CommandLine.Error instances.
Definition NameInfo.cs:11
Models an error generated when an option is repeated two or more times.
Definition Error.cs:436
Models an error generated when a sequence value lacks elements.
Definition Error.cs:427