Skip to content

Commit aaf7fe6

Browse files
committed
Touch-up on AssemblyVersionInfo changes
1 parent e3cd90f commit aaf7fe6

File tree

1 file changed

+59
-84
lines changed

1 file changed

+59
-84
lines changed

src/Nerdbank.GitVersioning.Tasks/AssemblyVersionInfo.cs

Lines changed: 59 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Text;
1111
using Microsoft.Build.Framework;
1212
using Microsoft.Build.Utilities;
13+
using Validation;
1314

1415
public class AssemblyVersionInfo : Task
1516
{
@@ -112,7 +113,7 @@ public override bool Execute()
112113
{
113114
// attempt to use local codegen
114115
string fileContent = this.BuildCode();
115-
if (fileContent != null)
116+
if (fileContent is object)
116117
{
117118
Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile));
118119
Utilities.FileOperationWithRetry(() => File.WriteAllText(this.OutputFile, fileContent));
@@ -179,6 +180,13 @@ private CodeTypeDeclaration CreateThisAssemblyClass()
179180
{
180181
switch (pair.Value.Value)
181182
{
183+
case null:
184+
if (pair.Value.EmitIfEmpty)
185+
{
186+
thisAssembly.Members.Add(CreateField(pair.Key, (string)null));
187+
}
188+
189+
break;
182190
case string stringValue:
183191
if (pair.Value.EmitIfEmpty || !string.IsNullOrEmpty(stringValue))
184192
{
@@ -190,12 +198,12 @@ private CodeTypeDeclaration CreateThisAssemblyClass()
190198
thisAssembly.Members.Add(CreateField(pair.Key, boolValue));
191199
break;
192200

193-
case long ticksValue:
194-
thisAssembly.Members.AddRange(CreateField(pair.Key, ticksValue).ToArray());
201+
case DateTime dateValue:
202+
thisAssembly.Members.AddRange(CreateDateTimeField(pair.Key, dateValue).ToArray());
195203
break;
196204

197205
default:
198-
throw new NotImplementedException();
206+
throw new NotSupportedException($"Value type {pair.Value.Value.GetType().Name} as found for the \"{pair.Key}\" property is not supported.");
199207
}
200208
}
201209

@@ -240,45 +248,15 @@ private static CodeMemberField CreateField<T>(string name, T value)
240248
};
241249
}
242250

243-
private static IEnumerable<CodeTypeMember> CreateField(string name, long ticks)
251+
private static IEnumerable<CodeTypeMember> CreateDateTimeField(string name, DateTime value)
244252
{
245-
if ( string.IsNullOrWhiteSpace(name))
246-
{
247-
throw new ArgumentNullException(nameof(name));
248-
}
253+
Requires.NotNullOrEmpty(name, nameof(name));
249254

250-
// internal static System.DateTime GitCommitDate {{ get; }} = new System.DateTime({ticks}, System.DateTimeKind.Utc);");
251-
252-
// For backing field name, try to use name with first char converted to lower case, or otherwise suffix with underscore.
253-
string fieldName = null;
254-
var char0 = name[0];
255-
256-
if ( char.IsUpper( char0) )
257-
{
258-
fieldName =
259-
name.Length == 1
260-
? new string(char.ToLowerInvariant(char0), 1)
261-
: new string(char.ToLowerInvariant(char0), 1) + name.Substring(1);
262-
}
263-
else
264-
{
265-
fieldName = name + "_";
266-
}
267-
268-
yield return new CodeMemberField(typeof(DateTime), fieldName)
269-
{
270-
Attributes = MemberAttributes.Private,
271-
InitExpression = new CodeObjectCreateExpression(
272-
typeof(DateTime),
273-
new CodePrimitiveExpression(ticks),
274-
new CodePropertyReferenceExpression(
275-
new CodeTypeReferenceExpression(typeof(DateTimeKind)),
276-
nameof(DateTimeKind.Utc)))
277-
};
255+
// internal static System.DateTime GitCommitDate => new System.DateTime({ticks}, System.DateTimeKind.Utc);");
278256

279257
var property = new CodeMemberProperty()
280258
{
281-
Attributes = MemberAttributes.Assembly,
259+
Attributes = MemberAttributes.Assembly | MemberAttributes.Static | MemberAttributes.Final,
282260
Type = new CodeTypeReference(typeof(DateTime)),
283261
Name = name,
284262
HasGet = true,
@@ -287,9 +265,12 @@ private static IEnumerable<CodeTypeMember> CreateField(string name, long ticks)
287265

288266
property.GetStatements.Add(
289267
new CodeMethodReturnStatement(
290-
new CodeFieldReferenceExpression(
291-
null,
292-
fieldName)));
268+
new CodeObjectCreateExpression(
269+
typeof(DateTime),
270+
new CodePrimitiveExpression(value.Ticks),
271+
new CodePropertyReferenceExpression(
272+
new CodeTypeReferenceExpression(typeof(DateTimeKind)),
273+
nameof(DateTimeKind.Utc)))));
293274

294275
yield return property;
295276
}
@@ -312,7 +293,7 @@ private static CodeAttributeDeclaration DeclareAttribute(Type attributeType, par
312293
public override bool Execute()
313294
{
314295
string fileContent = this.BuildCode();
315-
if (fileContent != null)
296+
if (fileContent is object)
316297
{
317298
Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile));
318299
Utilities.FileOperationWithRetry(() => File.WriteAllText(this.OutputFile, fileContent));
@@ -330,7 +311,7 @@ public override bool Execute()
330311
public string BuildCode()
331312
{
332313
this.generator = this.CreateGenerator();
333-
if (this.generator != null)
314+
if (this.generator is object)
334315
{
335316
this.generator.AddComment(FileHeaderComment);
336317
this.generator.AddBlankLine();
@@ -411,89 +392,83 @@ private void GenerateAssemblyAttributes()
411392

412393
if (long.TryParse(this.GitCommitDateTicks, out long gitCommitDateTicks))
413394
{
414-
fields.Add("GitCommitDate", (gitCommitDateTicks, true));
395+
fields.Add("GitCommitDate", (new DateTime(gitCommitDateTicks, DateTimeKind.Utc), true));
415396
}
416397

417-
if (this.AdditionalThisAssemblyFields != null && this.AdditionalThisAssemblyFields.Length > 0)
398+
if (this.AdditionalThisAssemblyFields is object)
418399
{
419400
foreach (var item in this.AdditionalThisAssemblyFields)
420401
{
421-
if (item == null)
422-
continue;
423-
424402
var name = item.ItemSpec.Trim();
425-
var metaClone = item.CloneCustomMetadata();
426-
var meta = new Dictionary<string, string>(metaClone.Count, StringComparer.OrdinalIgnoreCase);
427-
var iter = metaClone.GetEnumerator();
428-
429-
while ( iter.MoveNext() )
403+
var meta = new Dictionary<string, string>(item.MetadataCount, StringComparer.OrdinalIgnoreCase);
404+
foreach (string metadataName in item.MetadataNames)
430405
{
431-
meta.Add((string)iter.Key, (string)iter.Value);
406+
meta.Add(metadataName, item.GetMetadata(metadataName));
432407
}
433408

434409
object value = null;
435410
bool emitIfEmpty = false;
436411

437-
if (meta.TryGetValue("String", out var stringValue))
412+
if (meta.TryGetValue("String", out string stringValue))
438413
{
439414
value = stringValue;
440-
if (meta.TryGetValue("EmitIfEmpty", out var emitIfEmptyString))
415+
if (meta.TryGetValue("EmitIfEmpty", out string emitIfEmptyString))
441416
{
442417
if (!bool.TryParse(emitIfEmptyString, out emitIfEmpty))
443418
{
444-
this.Log.LogError("The value '{0}' for EmitIfEmpty metadata for item '{1}' in AdditionalThisAssemblyFields is not valid.", emitIfEmptyString, name);
419+
this.Log.LogError($"The value '{emitIfEmptyString}' for EmitIfEmpty metadata for item '{name}' in {nameof(this.AdditionalThisAssemblyFields)} is not valid.");
445420
continue;
446421
}
447422
}
448423
}
449424

450-
if (meta.TryGetValue("Boolean", out var boolText))
425+
if (meta.TryGetValue("Boolean", out string boolText))
451426
{
452-
if (value != null)
427+
if (value is object)
453428
{
454-
this.Log.LogError("The metadata for item '{0}' in AdditionalThisAssemblyFields specifies more than one kind of value.", name);
429+
this.Log.LogError($"The metadata for item '{name}' in {nameof(this.AdditionalThisAssemblyFields)} specifies more than one kind of value.");
455430
continue;
456431
}
457432

458-
if (bool.TryParse(boolText, out var boolValue))
433+
if (bool.TryParse(boolText, out bool boolValue))
459434
{
460435
value = boolValue;
461436
}
462437
else
463438
{
464-
this.Log.LogError("The Boolean value '{0}' for item '{1}' in AdditionalThisAssemblyFields is not valid.", boolText, name);
439+
this.Log.LogError($"The Boolean value '{boolText}' for item '{name}' in AdditionalThisAssemblyFields is not valid.");
465440
continue;
466441
}
467442
}
468443

469-
if (meta.TryGetValue("Ticks", out var ticksText))
444+
if (meta.TryGetValue("Ticks", out string ticksText))
470445
{
471-
if (value != null)
446+
if (value is object)
472447
{
473-
this.Log.LogError("The metadata for item '{0}' in AdditionalThisAssemblyFields specifies more than one kind of value.", name);
448+
this.Log.LogError($"The metadata for item '{name}' in {nameof(this.AdditionalThisAssemblyFields)} specifies more than one kind of value.");
474449
continue;
475450
}
476451

477-
if (long.TryParse(ticksText, out var ticksValue))
452+
if (long.TryParse(ticksText, out long ticksValue))
478453
{
479-
value = ticksValue;
454+
value = new DateTime(ticksValue, DateTimeKind.Utc);
480455
}
481456
else
482457
{
483-
this.Log.LogError("The Ticks value '{0}' for item '{1}' in AdditionalThisAssemblyFields is not valid.", ticksText, name);
458+
this.Log.LogError($"The Ticks value '{ticksText}' for item '{name}' in {nameof(this.AdditionalThisAssemblyFields)} is not valid.");
484459
continue;
485460
}
486461
}
487462

488-
if ( value == null )
463+
if (value is null)
489464
{
490-
this.Log.LogWarning("Field '{0}' in AdditionalThisAssemblyFields has no value and will be ignored.", name);
465+
this.Log.LogWarning($"Field '{name}' in {nameof(this.AdditionalThisAssemblyFields)} has no value and will be ignored.");
491466
continue;
492467
}
493468

494469
if (fields.ContainsKey(name))
495470
{
496-
this.Log.LogError("Field name '{0}' in AdditionalThisAssemblyFields has already been defined.", name);
471+
this.Log.LogError($"Field name '{name}' in {nameof(this.AdditionalThisAssemblyFields)} is defined multiple times.");
497472
continue;
498473
}
499474

@@ -532,12 +507,12 @@ private void GenerateThisAssemblyClass()
532507
this.generator.AddThisAssemblyMember(pair.Key, boolValue);
533508
break;
534509

535-
case long ticksValue:
536-
this.generator.AddThisAssemblyMember(pair.Key, ticksValue);
510+
case DateTime datetimeValue:
511+
this.generator.AddThisAssemblyMember(pair.Key, datetimeValue);
537512
break;
538513

539514
default:
540-
throw new NotImplementedException();
515+
throw new NotSupportedException($"Value type {pair.Value.Value.GetType().Name} as found for the \"{pair.Key}\" property is not supported.");
541516
}
542517
}
543518

@@ -580,7 +555,7 @@ internal CodeGenerator()
580555

581556
internal abstract void AddThisAssemblyMember(string name, bool value);
582557

583-
internal abstract void AddThisAssemblyMember(string name, long ticks);
558+
internal abstract void AddThisAssemblyMember(string name, DateTime value);
584559

585560
internal abstract void EndThisAssemblyClass();
586561

@@ -601,7 +576,7 @@ protected void AddCodeComment(string comment, string token)
601576
{
602577
var sr = new StringReader(comment);
603578
string line;
604-
while ((line = sr.ReadLine()) != null)
579+
while ((line = sr.ReadLine()) is object)
605580
{
606581
this.codeBuilder.Append(token);
607582
this.codeBuilder.AppendLine(line);
@@ -626,9 +601,9 @@ internal override void AddThisAssemblyMember(string name, bool value)
626601
this.codeBuilder.AppendLine($" static member internal {name} = {(value ? "true" : "false")}");
627602
}
628603

629-
internal override void AddThisAssemblyMember(string name, long ticks)
604+
internal override void AddThisAssemblyMember(string name, DateTime value)
630605
{
631-
this.codeBuilder.AppendLine($" static member internal {name} = new System.DateTime({ticks}L, System.DateTimeKind.Utc)");
606+
this.codeBuilder.AppendLine($" static member internal {name} = new System.DateTime({value.Ticks}L, System.DateTimeKind.Utc)");
632607
}
633608

634609
internal override void EmitNamespaceIfRequired(string ns)
@@ -692,9 +667,9 @@ internal override void AddThisAssemblyMember(string name, bool value)
692667
this.codeBuilder.AppendLine($" internal const bool {name} = {(value ? "true" : "false")};");
693668
}
694669

695-
internal override void AddThisAssemblyMember(string name, long ticks)
670+
internal override void AddThisAssemblyMember(string name, DateTime value)
696671
{
697-
this.codeBuilder.AppendLine($" internal static readonly System.DateTime {name} = new System.DateTime({ticks}L, System.DateTimeKind.Utc);");
672+
this.codeBuilder.AppendLine($" internal static readonly System.DateTime {name} = new System.DateTime({value.Ticks}L, System.DateTimeKind.Utc);");
698673
}
699674

700675
internal override void EndThisAssemblyClass()
@@ -739,9 +714,9 @@ internal override void AddThisAssemblyMember(string name, bool value)
739714
this.codeBuilder.AppendLine($" Friend Const {name} As Boolean = {(value ? "True" : "False")}");
740715
}
741716

742-
internal override void AddThisAssemblyMember(string name, long ticks)
717+
internal override void AddThisAssemblyMember(string name, DateTime value)
743718
{
744-
this.codeBuilder.AppendLine($" Friend Shared ReadOnly {name} As System.DateTime = New System.DateTime({ticks}L, System.DateTimeKind.Utc)");
719+
this.codeBuilder.AppendLine($" Friend Shared ReadOnly {name} As System.DateTime = New System.DateTime({value.Ticks}L, System.DateTimeKind.Utc)");
745720
}
746721

747722
internal override void EndThisAssemblyClass()
@@ -797,14 +772,14 @@ private bool TryReadKeyInfo(out string publicKey, out string publicKeyToken)
797772
publicKeyBytes = GetPublicKeyFromKeyContainer(this.AssemblyKeyContainerName);
798773
}
799774

800-
if (publicKeyBytes != null && publicKeyBytes.Length > 0) // If .NET 2.0 isn't installed, we get byte[0] back.
775+
if (publicKeyBytes is object && publicKeyBytes.Length > 0) // If .NET 2.0 isn't installed, we get byte[0] back.
801776
{
802777
publicKey = ToHex(publicKeyBytes);
803778
publicKeyToken = ToHex(CryptoBlobParser.GetStrongNameTokenFromPublicKey(publicKeyBytes));
804779
}
805780
else
806781
{
807-
if (publicKeyBytes != null)
782+
if (publicKeyBytes is object)
808783
{
809784
this.Log.LogWarning("Unable to emit public key fields in ThisAssembly class because .NET 2.0 isn't installed.");
810785
}

0 commit comments

Comments
 (0)