Skip to content

Commit

Permalink
Merge pull request #255 from kwpatrick/fix/149
Browse files Browse the repository at this point in the history
Fix for issue #149 - Adding F# support for AssemblyInfo generation
  • Loading branch information
AArnott authored Nov 24, 2018
2 parents fb1ec38 + cf0dd1a commit 8ec9808
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 16 deletions.
49 changes: 49 additions & 0 deletions src/NerdBank.GitVersioning.Tests/AssemblyInfoTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nerdbank.GitVersioning.Tasks;
using Xunit;

namespace NerdBank.GitVersioning.Tests
{
public class AssemblyInfoTest
{
[Fact]
public void FSharpGenerator()
{
var info = new AssemblyVersionInfo();
info.AssemblyCompany = "company";
info.AssemblyFileVersion = "1.3.1.0";
info.AssemblyVersion = "1.3.0.0";
info.CodeLanguage = "f#";

var built = info.BuildCode();

var expected = @"//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace AssemblyInfo
[<assembly: System.Reflection.AssemblyVersionAttribute(""1.3.0.0"")>]
[<assembly: System.Reflection.AssemblyFileVersionAttribute(""1.3.1.0"")>]
[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("""")>]
do()
type internal ThisAssembly() =
static member internal AssemblyVersion = ""1.3.0.0""
static member internal AssemblyFileVersion = ""1.3.1.0""
static member internal AssemblyCompany = ""company""
static member internal RootNamespace = """"
do()
";
Assert.Equal(expected, built);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<EmbeddedResource Include="repos\submodules.7z" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MSBuildExtensionTask\MSBuildExtensionTask.csproj" />
<ProjectReference Include="..\Nerdbank.GitVersioning.Tasks\Nerdbank.GitVersioning.Tasks.csproj" />
<ProjectReference Include="..\NerdBank.GitVersioning\NerdBank.GitVersioning.csproj" />
</ItemGroup>
Expand Down
91 changes: 75 additions & 16 deletions src/Nerdbank.GitVersioning.Tasks/AssemblyVersionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
Expand All @@ -22,7 +21,7 @@ public class AssemblyVersionInfo : Task
};

private CodeCompileUnit generatedFile;
#else
#endif
private const string FileHeaderComment = @"------------------------------------------------------------------------------
<auto-generated>
This code was generated by a tool.
Expand All @@ -36,8 +35,6 @@ the code is regenerated.

private CodeGenerator generator;

#endif

[Required]
public string CodeLanguage { get; set; }

Expand Down Expand Up @@ -101,7 +98,17 @@ public override bool Execute()
}
else
{
this.Log.LogError("CodeDomProvider not available for language: {0}. No version info will be embedded into assembly.", this.CodeLanguage);
// attempt to use local codegen
string fileContent = this.BuildCode();
if (fileContent != null)
{
Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile));
Utilities.FileOperationWithRetry(() => File.WriteAllText(this.OutputFile, fileContent));
}
else
{
this.Log.LogError("CodeDomProvider not available for language: {0}. No version info will be embedded into assembly.", this.CodeLanguage);
}
}

return !this.Log.HasLoggedErrors;
Expand Down Expand Up @@ -216,24 +223,36 @@ private static CodeAttributeDeclaration DeclareAttribute(Type attributeType, par
#else

public override bool Execute()
{
string fileContent = this.BuildCode();
if (fileContent != null)
{
Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile));
Utilities.FileOperationWithRetry(() => File.WriteAllText(this.OutputFile, fileContent));
}

return !this.Log.HasLoggedErrors;
}

#endif

public string BuildCode()
{
this.generator = this.CreateGenerator();
if (this.generator != null)
{
this.generator.AddComment(FileHeaderComment);
this.generator.AddBlankLine();
this.CreateAssemblyAttributes();
this.CreateThisAssemblyClass();

Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile));
string fileContent = this.generator.GetCode();
Utilities.FileOperationWithRetry(() => File.WriteAllText(this.OutputFile, fileContent));
this.generator.EmitNamespaceIfRequired(this.RootNamespace ?? "AssemblyInfo");
this.GenerateAssemblyAttributes();
this.GenerateThisAssemblyClass();
return this.generator.GetCode();
}

return !this.Log.HasLoggedErrors;
return null;
}

private void CreateAssemblyAttributes()
private void GenerateAssemblyAttributes()
{
this.generator.DeclareAttribute(typeof(AssemblyVersionAttribute), this.AssemblyVersion);
this.generator.DeclareAttribute(typeof(AssemblyFileVersionAttribute), this.AssemblyFileVersion);
Expand Down Expand Up @@ -262,7 +281,7 @@ private void CreateAssemblyAttributes()
}
}

private void CreateThisAssemblyClass()
private void GenerateThisAssemblyClass()
{
this.generator.StartThisAssemblyClass();

Expand Down Expand Up @@ -302,6 +321,7 @@ private void CreateThisAssemblyClass()

this.generator.EndThisAssemblyClass();
}

private CodeGenerator CreateGenerator()
{
switch (this.CodeLanguage.ToLowerInvariant())
Expand All @@ -312,8 +332,9 @@ private CodeGenerator CreateGenerator()
case "visualbasic":
case "vb":
return new VisualBasicCodeGenerator();
case "f#":
return new FSharpCodeGenerator();
default:
this.Log.LogError("Code provider not available for language: {0}. No version info will be embedded into assembly.", this.CodeLanguage);
return null;
}
}
Expand All @@ -337,6 +358,12 @@ internal CodeGenerator()

internal abstract void EndThisAssemblyClass();

/// <summary>
/// Gives languages that *require* a namespace a chance to emit such.
/// </summary>
/// <param name="ns">The RootNamespace of the project.</param>
internal virtual void EmitNamespaceIfRequired(string ns) { }

internal string GetCode() => this.codeBuilder.ToString();

internal void AddBlankLine()
Expand All @@ -356,6 +383,39 @@ protected void AddCodeComment(string comment, string token)
}
}

private class FSharpCodeGenerator : CodeGenerator
{
internal override void AddComment(string comment)
{
this.AddCodeComment(comment, "//");
}

internal override void AddThisAssemblyMember(string name, string value)
{
this.codeBuilder.AppendLine($" static member internal {name} = \"{value}\"");
}

internal override void EmitNamespaceIfRequired(string ns)
{
this.codeBuilder.AppendLine($"namespace {ns}");
}

internal override void DeclareAttribute(Type type, string arg)
{
this.codeBuilder.AppendLine($"[<assembly: {type.FullName}(\"{arg}\")>]");
}

internal override void EndThisAssemblyClass()
{
this.codeBuilder.AppendLine("do()");
}

internal override void StartThisAssemblyClass()
{
this.codeBuilder.AppendLine("do()\r\ntype internal ThisAssembly() =");
}
}

private class CSharpCodeGenerator : CodeGenerator
{
internal override void AddComment(string comment)
Expand Down Expand Up @@ -411,7 +471,6 @@ internal override void EndThisAssemblyClass()
this.codeBuilder.AppendLine("End Class");
}
}
#endif

private static string ToHex(byte[] data)
{
Expand Down

0 comments on commit 8ec9808

Please sign in to comment.