diff --git a/src/NerdBank.GitVersioning.Tests/AssemblyInfoTest.cs b/src/NerdBank.GitVersioning.Tests/AssemblyInfoTest.cs
new file mode 100644
index 00000000..1f0a0758
--- /dev/null
+++ b/src/NerdBank.GitVersioning.Tests/AssemblyInfoTest.cs
@@ -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 = @"//------------------------------------------------------------------------------
+//
+// 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.
+//
+//------------------------------------------------------------------------------
+
+namespace AssemblyInfo
+[]
+[]
+[]
+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);
+ }
+ }
+}
diff --git a/src/NerdBank.GitVersioning.Tests/NerdBank.GitVersioning.Tests.csproj b/src/NerdBank.GitVersioning.Tests/NerdBank.GitVersioning.Tests.csproj
index be755f37..36be883c 100644
--- a/src/NerdBank.GitVersioning.Tests/NerdBank.GitVersioning.Tests.csproj
+++ b/src/NerdBank.GitVersioning.Tests/NerdBank.GitVersioning.Tests.csproj
@@ -20,6 +20,7 @@
+
diff --git a/src/Nerdbank.GitVersioning.Tasks/AssemblyVersionInfo.cs b/src/Nerdbank.GitVersioning.Tasks/AssemblyVersionInfo.cs
index 86587db2..b928cd10 100644
--- a/src/Nerdbank.GitVersioning.Tasks/AssemblyVersionInfo.cs
+++ b/src/Nerdbank.GitVersioning.Tasks/AssemblyVersionInfo.cs
@@ -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;
@@ -22,7 +21,7 @@ public class AssemblyVersionInfo : Task
};
private CodeCompileUnit generatedFile;
-#else
+#endif
private const string FileHeaderComment = @"------------------------------------------------------------------------------
This code was generated by a tool.
@@ -36,8 +35,6 @@ the code is regenerated.
private CodeGenerator generator;
-#endif
-
[Required]
public string CodeLanguage { get; set; }
@@ -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;
@@ -205,24 +212,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);
@@ -240,7 +259,7 @@ private void CreateAssemblyAttributes()
}
}
- private void CreateThisAssemblyClass()
+ private void GenerateThisAssemblyClass()
{
this.generator.StartThisAssemblyClass();
@@ -280,6 +299,7 @@ private void CreateThisAssemblyClass()
this.generator.EndThisAssemblyClass();
}
+
private CodeGenerator CreateGenerator()
{
switch (this.CodeLanguage.ToLowerInvariant())
@@ -290,8 +310,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;
}
}
@@ -315,6 +336,12 @@ internal CodeGenerator()
internal abstract void EndThisAssemblyClass();
+ ///
+ /// Gives languages that *require* a namespace a chance to emit such.
+ ///
+ /// The RootNamespace of the project.
+ internal virtual void EmitNamespaceIfRequired(string ns) { }
+
internal string GetCode() => this.codeBuilder.ToString();
internal void AddBlankLine()
@@ -334,6 +361,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($"[]");
+ }
+
+ 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)
@@ -389,7 +449,6 @@ internal override void EndThisAssemblyClass()
this.codeBuilder.AppendLine("End Class");
}
}
-#endif
private static string ToHex(byte[] data)
{