11namespace 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