Skip to content

Commit a0e9cb7

Browse files
authored
Merge pull request #356 from anthonylangsworth/missing_author_NullReference
Fix for missing author null reference (#332)
2 parents 9ff3c90 + 13d8b58 commit a0e9cb7

File tree

7 files changed

+181
-3
lines changed

7 files changed

+181
-3
lines changed

‎.gitignore‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,6 @@ artifacts/*
3939
.vs/*
4040
*.xproj.user
4141
*.nuget.targets
42-
*.lock.json
42+
*.lock.json
43+
*.nuget.props
44+

‎src/CommandLine/Error.cs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ public abstract class TokenError : Error, IEquatable<TokenError>
157157
{
158158
privatereadonlystringtoken;
159159

160+
/// <summary>
161+
/// Initializes a new instance of the <see cref="CommandLine.TokenError"/> class.
162+
/// </summary>
163+
/// <param name="tag">Error type.</param>
164+
/// <param name="token">Problematic token.</param>
160165
protectedinternalTokenError(ErrorTypetag,stringtoken)
161166
:base(tag)
162167
{
@@ -232,6 +237,12 @@ public abstract class NamedError : Error, IEquatable<NamedError>
232237
{
233238
privatereadonlyNameInfonameInfo;
234239

240+
/// <summary>
241+
/// Initializes a new instance of the <see cref="CommandLine.NamedError"/> class.
242+
/// </summary>
243+
/// <param name="tag">Error type.</param>
244+
/// <param name="nameInfo">Problematic name.</param>
245+
235246
protectedinternalNamedError(ErrorTypetag,NameInfonameInfo)
236247
:base(tag)
237248
{

‎src/CommandLine/Infrastructure/ReflectionHelper.cs‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,57 @@
11
// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
22

33
usingSystem;
4+
usingSystem.Collections.Generic;
45
usingSystem.Linq;
56
usingSystem.Reflection;
7+
usingSystem.Runtime.Remoting.Messaging;
68
usingCommandLine.Core;
79
usingCSharpx;
810

911
namespaceCommandLine.Infrastructure
1012
{
1113
staticclassReflectionHelper
1214
{
15+
/// <summary>
16+
/// Per thread assembly attribute overrides for testing.
17+
/// </summary>
18+
[ThreadStatic]privatestaticIDictionary<Type,Attribute>_overrides;
19+
20+
/// <summary>
21+
/// Assembly attribute overrides for testing.
22+
/// </summary>
23+
/// <remarks>
24+
/// The implementation will fail if two or more attributes of the same type
25+
/// are included in <paramref name="overrides"/>.
26+
/// </remarks>
27+
/// <param name="overrides">
28+
/// Attributes that replace the existing assembly attributes or null,
29+
/// to clear any testing attributes.
30+
/// </param>
31+
publicstaticvoidSetAttributeOverride(IEnumerable<Attribute>overrides)
32+
{
33+
if(overrides!=null)
34+
{
35+
_overrides=overrides.ToDictionary(attr =>attr.GetType(), attr =>attr);
36+
}
37+
else
38+
{
39+
_overrides=null;
40+
}
41+
}
42+
1343
publicstaticMaybe<TAttribute>GetAttribute<TAttribute>()
1444
whereTAttribute:Attribute
1545
{
46+
// Test support
47+
if(_overrides!=null)
48+
{
49+
return
50+
_overrides.ContainsKey(typeof(TAttribute))?
51+
Maybe.Just((TAttribute)_overrides[typeof(TAttribute)]):
52+
Maybe.Nothing<TAttribute>();
53+
}
54+
1655
varassembly=GetExecutingOrEntryAssembly();
1756

1857
#if NET40

‎src/CommandLine/Text/CopyrightInfo.cs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
22

33
usingSystem;
4+
usingSystem.Dynamic;
45
usingSystem.Globalization;
56
usingSystem.Reflection;
67
usingSystem.Text;
@@ -24,6 +25,17 @@ public class CopyrightInfo
2425
privatereadonlystringauthor;
2526
privatereadonlyintbuilderSize;
2627

28+
/// <summary>
29+
/// An empty object used for initialization.
30+
/// </summary>
31+
publicstaticCopyrightInfoEmpty
32+
{
33+
get
34+
{
35+
returnnewCopyrightInfo("author",1);
36+
}
37+
}
38+
2739
/// <summary>
2840
/// Initializes a new instance of the <see cref="CommandLine.Text.CopyrightInfo"/> class
2941
/// specifying author and year.

‎src/CommandLine/Text/HeadingInfo.cs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ public HeadingInfo(string programName, string version = null)
3333
this.version=version;
3434
}
3535

36+
/// <summary>
37+
/// An empty object used for initialization.
38+
/// </summary>
39+
publicstaticHeadingInfoEmpty
40+
{
41+
get
42+
{
43+
returnnewHeadingInfo("");
44+
}
45+
}
46+
3647
/// <summary>
3748
/// Gets the default heading instance.
3849
/// The title is retrieved from <see cref="AssemblyTitleAttribute"/>,

‎src/CommandLine/Text/HelpText.cs‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,23 @@ public static HelpText AutoBuild<T>(
212212
{
213213
varauto=newHelpText
214214
{
215-
Heading=HeadingInfo.Default,
216-
Copyright=CopyrightInfo.Default,
215+
Heading=HeadingInfo.Empty,
216+
Copyright=CopyrightInfo.Empty,
217217
AdditionalNewLineAfterOption=true,
218218
AddDashesToOption=!verbsIndex,
219219
MaximumDisplayWidth=maxDisplayWidth
220220
};
221221

222+
try
223+
{
224+
auto.Heading=HeadingInfo.Default;
225+
auto.Copyright=CopyrightInfo.Default;
226+
}
227+
catch(Exception)
228+
{
229+
auto=onError(auto);
230+
}
231+
222232
varerrors=Enumerable.Empty<Error>();
223233

224234
if(onError!=null&&parserResult.Tag==ParserResultType.NotParsed)

‎tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs‎

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
usingSystem.Collections.Generic;
55
usingSystem.Globalization;
66
usingSystem.Linq;
7+
usingSystem.Reflection;
78
usingCommandLine.Core;
9+
usingCommandLine.Infrastructure;
810
usingCommandLine.Tests.Fakes;
11+
usingCommandLine.Tests.Unit.Infrastructure;
912
usingCommandLine.Text;
1013
usingFluentAssertions;
1114
usingXunit;
@@ -564,5 +567,95 @@ public void Default_set_to_sequence_should_be_properly_printed()
564567
// Teardown
565568
}
566569
#endif
570+
571+
[Fact]
572+
publicvoidAutoBuild_when_no_assembly_attributes()
573+
{
574+
try
575+
{
576+
stringexpectedCopyright="Copyright (C) 1 author";
577+
578+
ReflectionHelper.SetAttributeOverride(newAttribute[0]);
579+
580+
ParserResult<Simple_Options>fakeResult=newNotParsed<Simple_Options>(
581+
TypeInfo.Create(typeof(Simple_Options)),newError[0]);
582+
boolonErrorCalled=false;
583+
HelpTextactualResult=HelpText.AutoBuild(fakeResult, ht =>
584+
{
585+
onErrorCalled=true;
586+
returnht;
587+
}, ex =>ex);
588+
589+
onErrorCalled.Should().BeTrue();
590+
actualResult.Copyright.Should().Be(expectedCopyright);
591+
}
592+
finally
593+
{
594+
ReflectionHelper.SetAttributeOverride(null);
595+
}
596+
}
597+
598+
[Fact]
599+
publicvoidAutoBuild_with_assembly_title_and_version_attributes_only()
600+
{
601+
try
602+
{
603+
stringexpectedTitle="Title";
604+
stringexpectedVersion="1.2.3.4";
605+
606+
ReflectionHelper.SetAttributeOverride(newAttribute[]
607+
{
608+
newAssemblyTitleAttribute(expectedTitle),
609+
newAssemblyInformationalVersionAttribute(expectedVersion)
610+
});
611+
612+
ParserResult<Simple_Options>fakeResult=newNotParsed<Simple_Options>(
613+
TypeInfo.Create(typeof(Simple_Options)),newError[0]);
614+
boolonErrorCalled=false;
615+
HelpTextactualResult=HelpText.AutoBuild(fakeResult, ht =>
616+
{
617+
onErrorCalled=true;
618+
returnht;
619+
}, ex =>ex);
620+
621+
onErrorCalled.Should().BeTrue();
622+
actualResult.Heading.Should().Be(string.Format("{0}{1}",expectedTitle,expectedVersion));
623+
}
624+
finally
625+
{
626+
ReflectionHelper.SetAttributeOverride(null);
627+
}
628+
}
629+
630+
631+
[Fact]
632+
publicvoidAutoBuild_with_assembly_company_attribute_only()
633+
{
634+
try
635+
{
636+
stringexpectedCompany="Company";
637+
638+
ReflectionHelper.SetAttributeOverride(newAttribute[]
639+
{
640+
newAssemblyCompanyAttribute(expectedCompany)
641+
});
642+
643+
ParserResult<Simple_Options>fakeResult=newNotParsed<Simple_Options>(
644+
TypeInfo.Create(typeof(Simple_Options)),newError[0]);
645+
boolonErrorCalled=false;
646+
HelpTextactualResult=HelpText.AutoBuild(fakeResult, ht =>
647+
{
648+
onErrorCalled=true;
649+
returnht;
650+
}, ex =>ex);
651+
652+
onErrorCalled.Should().BeFalse();// Other attributes have fallback logic
653+
actualResult.Copyright.Should().Be(string.Format("Copyright (C){0}{1}",DateTime.Now.Year,expectedCompany));
654+
}
655+
finally
656+
{
657+
ReflectionHelper.SetAttributeOverride(null);
658+
}
659+
}
567660
}
568661
}

0 commit comments

Comments
(0)