Skip to content

Commit 19b2675

Browse files
committed
Add primitive code gen support for .NET Core
1 parent 0583248 commit 19b2675

File tree

1 file changed

+165
-4
lines changed

1 file changed

+165
-4
lines changed

src/Nerdbank.GitVersioning.Tasks/AssemblyVersionInfo.cs

Lines changed: 165 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace Nerdbank.GitVersioning.Tasks
22
{
3-
using System;
3+
using System;
44
using System.CodeDom;
55
using System.CodeDom.Compiler;
66
using System.Collections.Generic;
@@ -24,6 +24,21 @@ public class AssemblyVersionInfo : Task
2424
};
2525

2626
private CodeCompileUnit generatedFile;
27+
#else
28+
private const string FileHeaderComment = @"------------------------------------------------------------------------------
29+
<auto-generated>
30+
This code was generated by a tool.
31+
Runtime Version:4.0.30319.42000
32+
33+
Changes to this file may cause incorrect behavior and will be lost if
34+
the code is regenerated.
35+
</auto-generated>
36+
------------------------------------------------------------------------------
37+
";
38+
39+
private CodeGenerator generator;
40+
41+
#endif
2742

2843
[Required]
2944
public string CodeLanguage { get; set; }
@@ -55,6 +70,7 @@ public class AssemblyVersionInfo : Task
5570

5671
public string AssemblyConfiguration { get; set; }
5772

73+
#if NET45
5874
public override bool Execute()
5975
{
6076
if (CodeDomProvider.IsDefinedLanguage(this.CodeLanguage))
@@ -127,7 +143,7 @@ private CodeTypeDeclaration CreateThisAssemblyClass()
127143
return thisAssembly;
128144
}
129145

130-
private void ReadKeyInfo(out string publicKey, out string publicKeyToken)
146+
private void ReadKeyInfo(out string publicKey, out string publicKeyToken)
131147
{
132148
byte[] publicKeyBytes = null;
133149
if (!string.IsNullOrEmpty(this.AssemblyOriginatorKeyFile) && File.Exists(this.AssemblyOriginatorKeyFile))
@@ -213,11 +229,156 @@ private static CodeAttributeDeclaration DeclareAttribute(Type attributeType, par
213229
attributeType,
214230
arguments.Select(a => new CodeAttributeArgument(new CodePrimitiveExpression(a))).ToArray());
215231
}
232+
216233
#else
234+
217235
public override bool Execute()
218236
{
219-
this.Log.LogError("Not yet implemented.");
220-
return false;
237+
this.generator = this.CreateGenerator();
238+
if (this.generator != null)
239+
{
240+
this.generator.AddComment(FileHeaderComment);
241+
this.generator.AddBlankLine();
242+
this.CreateAssemblyAttributes();
243+
this.CreateThisAssemblyClass();
244+
245+
Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile));
246+
File.WriteAllText(this.OutputFile, this.generator.GetCode());
247+
}
248+
249+
return !this.Log.HasLoggedErrors;
250+
}
251+
252+
private void CreateAssemblyAttributes()
253+
{
254+
this.generator.DeclareAttribute(typeof(AssemblyVersionAttribute), this.AssemblyVersion);
255+
this.generator.DeclareAttribute(typeof(AssemblyFileVersionAttribute), this.AssemblyFileVersion);
256+
this.generator.DeclareAttribute(typeof(AssemblyInformationalVersionAttribute), this.AssemblyInformationalVersion);
257+
if (!string.IsNullOrEmpty(this.AssemblyTitle))
258+
this.generator.DeclareAttribute(typeof(AssemblyTitleAttribute), this.AssemblyTitle);
259+
if (!string.IsNullOrEmpty(this.AssemblyProduct))
260+
this.generator.DeclareAttribute(typeof(AssemblyProductAttribute), this.AssemblyProduct);
261+
if (!string.IsNullOrEmpty(this.AssemblyCompany))
262+
this.generator.DeclareAttribute(typeof(AssemblyCompanyAttribute), this.AssemblyCompany);
263+
if (!string.IsNullOrEmpty(this.AssemblyCopyright))
264+
this.generator.DeclareAttribute(typeof(AssemblyCopyrightAttribute), this.AssemblyCopyright);
265+
}
266+
267+
private void CreateThisAssemblyClass()
268+
{
269+
this.generator.StartThisAssemblyClass();
270+
271+
////// Determine information about the public key used in the assembly name.
272+
////string publicKey, publicKeyToken;
273+
////this.ReadKeyInfo(out publicKey, out publicKeyToken);
274+
275+
// Define the constants.
276+
var fields = new Dictionary<string, string>
277+
{
278+
{ "AssemblyVersion", this.AssemblyVersion },
279+
{ "AssemblyFileVersion", this.AssemblyFileVersion },
280+
{ "AssemblyInformationalVersion", this.AssemblyInformationalVersion },
281+
{ "AssemblyName", this.AssemblyName },
282+
////{ "PublicKey", publicKey },
283+
////{ "PublicKeyToken", publicKeyToken },
284+
{ "AssemblyTitle", this.AssemblyTitle },
285+
{ "AssemblyProduct", this.AssemblyProduct },
286+
{ "AssemblyCopyright", this.AssemblyCopyright },
287+
{ "AssemblyCompany", this.AssemblyCompany },
288+
{ "AssemblyConfiguration", this.AssemblyConfiguration }
289+
};
290+
foreach (var pair in fields)
291+
{
292+
if (!string.IsNullOrEmpty(pair.Value))
293+
{
294+
this.generator.AddThisAssemblyMember(pair.Key, pair.Value);
295+
}
296+
}
297+
298+
// These properties should be defined even if they are empty.
299+
this.generator.AddThisAssemblyMember("RootNamespace", this.RootNamespace);
300+
301+
this.generator.EndThisAssemblyClass();
302+
}
303+
private CodeGenerator CreateGenerator()
304+
{
305+
switch (this.CodeLanguage.ToLowerInvariant())
306+
{
307+
case "c#":
308+
return new CSharpCodeGenerator();
309+
case "visual basic":
310+
case "visualbasic":
311+
case "vb":
312+
default:
313+
this.Log.LogError("Code provider not available for language: {0}. No version info will be embedded into assembly.", this.CodeLanguage);
314+
return null;
315+
}
316+
}
317+
318+
private abstract class CodeGenerator
319+
{
320+
protected readonly StringBuilder codeBuilder;
321+
322+
internal CodeGenerator()
323+
{
324+
this.codeBuilder = new StringBuilder();
325+
}
326+
327+
internal abstract void AddComment(string comment);
328+
329+
internal abstract void DeclareAttribute(Type type, string arg);
330+
331+
internal abstract void StartThisAssemblyClass();
332+
333+
internal abstract void AddThisAssemblyMember(string name, string value);
334+
335+
internal abstract void EndThisAssemblyClass();
336+
337+
internal string GetCode() => this.codeBuilder.ToString();
338+
339+
internal void AddBlankLine()
340+
{
341+
this.codeBuilder.AppendLine();
342+
}
343+
344+
protected void AddCodeComment(string comment, string token)
345+
{
346+
var sr = new StringReader(comment);
347+
string line;
348+
while ((line = sr.ReadLine()) != null)
349+
{
350+
this.codeBuilder.Append(token);
351+
this.codeBuilder.AppendLine(line);
352+
}
353+
}
354+
}
355+
356+
private class CSharpCodeGenerator : CodeGenerator
357+
{
358+
internal override void AddComment(string comment)
359+
{
360+
this.AddCodeComment(comment, "//");
361+
}
362+
363+
internal override void DeclareAttribute(Type type, string arg)
364+
{
365+
this.codeBuilder.AppendLine($"[assembly: {type.FullName}(\"{arg}\")]");
366+
}
367+
368+
internal override void StartThisAssemblyClass()
369+
{
370+
this.codeBuilder.AppendLine("internal static partial class ThisAssembly {");
371+
}
372+
373+
internal override void AddThisAssemblyMember(string name, string value)
374+
{
375+
this.codeBuilder.AppendLine($" internal const string {name} = \"{value}\";");
376+
}
377+
378+
internal override void EndThisAssemblyClass()
379+
{
380+
this.codeBuilder.AppendLine("}");
381+
}
221382
}
222383
#endif
223384
}

0 commit comments

Comments
 (0)