Skip to content

Instantly share code, notes, and snippets.

@robgha01
Last active October 1, 2019 09:26
Show Gist options
  • Save robgha01/bd980037ab484a0f23b2911b2dae063b to your computer and use it in GitHub Desktop.
Save robgha01/bd980037ab484a0f23b2911b2dae063b to your computer and use it in GitHub Desktop.
Cake AssemblyInfo Code
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by Cake.
// </auto-generated>
//------------------------------------------------------------------------------
using System.Reflection;
using System.Runtime.InteropServices;
using System;
using BlueLeet.Core.Attributes;
[assembly: AssemblyTitle("BlueLeet.UCodeFirst")]
[assembly: AssemblyDescription("BlueLeet.UCodeFirst is a Code-First solution to Umbraco")]
[assembly: AssemblyCompany("BlueLeet")]
[assembly: AssemblyProduct("BlueLeet.UCodeFirst")]
[assembly: AssemblyVersion("0.9.8.0")]
[assembly: AssemblyFileVersion("0.9.8.0")]
[assembly: AssemblyInformationalVersion("0.9.8+Branch.dev-8.1.Sha.91baf2bfd78c9da9cfd935bbe7a6c10272b5ea54")]
[assembly: AssemblyCopyright("Copyright (c) BlueLeet 2015 - 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyConfiguration("")]
[assembly: Guid("2ACBE7CB-7DC7-4E27-94A0-B537B1F0296B")]
[assembly: ComVisible(true)]
[assembly: CLSCompliant(false)]
[assembly: BlueLeetModule] // This is what gets stripped out.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Cake.Core;
using Cake.Core.IO;
namespace Cake.Common.Solution.Project.Properties
{
/// <summary>
/// The assembly info parser.
/// </summary>
public sealed class AssemblyInfoParser
{
private const string CSharpNonQuotedPattern = @"^\s*\[assembly: (?:System\.Reflection\.)?{0}(?:Attribute)? ?\((?<attributeValue>.*)\)";
private const string CSharpQuotedPattern = @"^\s*\[assembly: (?:System\.Reflection\.)?{0}(?:Attribute)? ?\(""(?<attributeValue>.*)""\)";
private const string VBNonQuotedPattern = @"^\s*\<Assembly: (?:System\.Reflection\.)?{0}(?:Attribute)? ?\((?<attributeValue>.*)\)";
private const string VBQuotedPattern = @"^\s*\<Assembly: (?:System\.Reflection\.)?{0}(?:Attribute)? ?\(""(?<attributeValue>.*)""\)";
private const string CSharpCustomAttributePattern = @"^\[assembly: (?:System\.Reflection\.)?(?<attributeName>\w*)(?:Attribute)? ?\((?<attributeValue>.*)\)";
private const string DefaultVersion = "1.0.0.0";
private readonly IFileSystem _fileSystem;
private readonly ICakeEnvironment _environment;
/// <summary>
/// Initializes a new instance of the <see cref="AssemblyInfoParser"/> class.
/// </summary>
/// <param name="fileSystem">The file system.</param>
/// <param name="environment">The environment.</param>
public AssemblyInfoParser(IFileSystem fileSystem, ICakeEnvironment environment)
{
if (fileSystem == null)
{
throw new ArgumentNullException(nameof(fileSystem));
}
if (environment == null)
{
throw new ArgumentNullException(nameof(environment));
}
_fileSystem = fileSystem;
_environment = environment;
}
/// <summary>
/// Parses information from an assembly info file.
/// </summary>
/// <param name="assemblyInfoPath">The file path.</param>
/// <returns>Information about the assembly info content.</returns>
public AssemblyInfoParseResult Parse(FilePath assemblyInfoPath)
{
if (assemblyInfoPath == null)
{
throw new ArgumentNullException(nameof(assemblyInfoPath));
}
if (assemblyInfoPath.IsRelative)
{
assemblyInfoPath = assemblyInfoPath.MakeAbsolute(_environment);
}
string nonQuotedPattern = CSharpNonQuotedPattern;
string quotedPattern = CSharpQuotedPattern;
// Get the release notes file.
var file = _fileSystem.GetFile(assemblyInfoPath);
if (!file.Exists)
{
const string format = "Assembly info file '{0}' does not exist.";
var message = string.Format(CultureInfo.InvariantCulture, format, assemblyInfoPath.FullPath);
throw new CakeException(message);
}
if (file.Path.GetExtension() == ".vb")
{
nonQuotedPattern = VBNonQuotedPattern;
quotedPattern = VBQuotedPattern;
}
using (var reader = new StreamReader(file.OpenRead()))
{
var content = reader.ReadToEnd();
return new AssemblyInfoParseResult(
ParseSingle(nonQuotedPattern, "CLSCompliant", content),
ParseSingle(quotedPattern, "AssemblyCompany", content),
ParseSingle(nonQuotedPattern, "ComVisible", content),
ParseSingle(quotedPattern, "AssemblyConfiguration", content),
ParseSingle(quotedPattern, "AssemblyCopyright", content),
ParseSingle(quotedPattern, "AssemblyDescription", content),
ParseSingle(quotedPattern, "AssemblyFileVersion", content) ?? DefaultVersion,
ParseSingle(quotedPattern, "Guid", content),
ParseSingle(quotedPattern, "AssemblyInformationalVersion", content) ?? DefaultVersion,
ParseSingle(quotedPattern, "AssemblyProduct", content),
ParseSingle(quotedPattern, "AssemblyTitle", content),
ParseSingle(quotedPattern, "AssemblyTrademark", content),
ParseSingle(quotedPattern, "AssemblyVersion", content) ?? DefaultVersion,
ParseMultiple(quotedPattern, "InternalsVisibleTo", content),
ParseCustomAttributes(content, "CLSCompliant", "AssemblyCompany", "ComVisible", "AssemblyConfiguration", "AssemblyCopyright", "AssemblyDescription", "AssemblyFileVersion", "Guid", "AssemblyInformationalVersion", "AssemblyProduct", "AssemblyTitle", "AssemblyTrademark", "AssemblyVersion", "InternalsVisibleTo"));
}
}
private static string ParseSingle(string pattern, string attributeName, string content)
{
return ParseMultiple(pattern, attributeName, content).SingleOrDefault();
}
private static IEnumerable<string> ParseMultiple(string pattern, string attributeName, string content)
{
var regex = new Regex(string.Format(CultureInfo.InvariantCulture, pattern, attributeName), RegexOptions.Multiline);
foreach (Match match in regex.Matches(content))
{
if (match.Groups.Count > 0)
{
var value = match.Groups["attributeValue"].Value;
if (!string.IsNullOrWhiteSpace(value))
{
yield return value;
}
}
}
}
private IEnumerable<AssemblyInfoCustomAttribute> ParseCustomAttributes(string content, params string[] ignoreAttributeNames)
{
// ^\[assembly: (?<attributeName>\w*)(?:Attribute)? ?\((?:""(?<attributeQuotedValue>.*)""|(?<attributeValue>.*))\)
var regexNonQuotedPattern = @"^\[assembly: (?<attributeName>\w*)(?:Attribute)? ?\((?<attributeValue>.*)\)";
var regexQuotedPattern = @"^\[assembly: (?<attributeName>\w*)(?:Attribute)? ?\(""(?<attributeValue>.*)""\)";
var ignoredAttributes = new StringBuilder();
foreach (var name in ignoreAttributeNames)
{
ignoredAttributes.AppendFormat("(?!{0})", name);
}
var regexNonQuoted = new Regex(string.Format(CultureInfo.InvariantCulture, regexNonQuotedPattern, ignoredAttributes.ToString()), RegexOptions.Multiline);
foreach (Match match in regexNonQuoted.Matches(content))
{
if (match.Groups.Count > 0)
{
var name = match.Groups["attributeName"].Value;
var value = match.Groups["attributeValue"].Value;
if (!string.IsNullOrWhiteSpace(value))
{
yield return new AssemblyInfoCustomAttribute { Name = name, Value = value };
}
}
}
//var regexQuoted = new Regex(string.Format(CultureInfo.InvariantCulture, regexQuotedPattern, ignoredAttributes.ToString()), RegexOptions.Multiline);
//foreach (Match match in regexQuoted.Matches(content))
//{
// if (match.Groups.Count > 0)
// {
// var name = match.Groups["attributeName"].Value;
// var value = match.Groups["attributeValue"].Value;
// if (!string.IsNullOrWhiteSpace(value))
// {
// yield return new AssemblyInfoCustomAttribute { Name = name, Value = value };
// }
// }
//}
}
}
}
Task("Patch-Assembly-Info")
.Does(() =>
{
var assemblyInfoFile = srcDir + File("/Properties/AssemblyInfo.cs");
var assemblyInfo = ParseAssemblyInfo(assemblyInfoFile);
CreateAssemblyInfo(assemblyInfoFile, new AssemblyInfoSettings {
InternalsVisibleTo = InternalsVisibleTo,
Product = assemblyInfo.Product,
Version = assemblyInfo.AssemblyVersion,
FileVersion = assemblyInfo.AssemblyFileVersion,
InformationalVersion = assemblyInfo.AssemblyInformationalVersion,
Copyright = assemblyInfo.Copyright,
CLSCompliant = assemblyInfo.ClsCompliant,
Company = assemblyInfo.Company,
ComVisible = assemblyInfo.ComVisible,
Configuration = assemblyInfo.Configuration,
Description = assemblyInfo.Description,
Guid = assemblyInfo.Guid,
Title = assemblyInfo.Title,
Trademark = assemblyInfo.Trademark
});
});
* The ParseAssemblyInfo as we all know dont have capability to parse CustomAttributes.
Tried to fix this yesterday but to do it cleanly one need to load the attribute and check
type data for every parameter or am i overthinking this
* The AssemblyInfoSettings have CustomAttributes but it wont allow adding a attribute with no value and can only
handle a single string value no numbers bools etc and multiple values.
Expected behavior:
* Support for ParseAssemblyInfo to parse all data that AssemblyInfoSettings has.
* AssemblyInfoSettings.CustomAttributes AssemblyInfoCustomAttribute.Value should be of type Object to allow any possible value
a attribute can have.
* private void AddCustomAttribute(string name, string @namespace, string value) should allow empty values now it skips it
if (value != null)
I changed the string value to object value in AssemblyInfoCustomAttribute and added CustomAttributes to AssemblyInfoParseResult.
In AssemblyInfoParser i added "ParseCustomAttributes" method that took in string content and all the attribute names that had already
ben worked on. (so we could skip em)
I then use this regex to filter out custom assembly attributes:
var regexNonQuotedPattern = @"^\[assembly: (?<attributeName>\w*)(?:Attribute)? ?\((?<attributeValue>.*)\)";
this matches the values see https://regexr.com/4lt4j
What we need to make this work is now to somehow read the custom attribute reflection data for every parameter and parse the string
value to its real value as everyting is string.
@robgha01
Copy link
Author

robgha01 commented Oct 1, 2019

The AddCustomAttribute method in AssemblyInfoCreatorData.cs

private void AddCustomAttribute(string name, string @namespace, object value)
        {
            if (value != null)
            {
                if (value is string)
                {
                    AddAttributeCore(CustomAttributes, name, @namespace, string.Concat("\"", value, "\""));
                }
                else
                {
                    var ms = new MemoryStream();
                    var ser = new DataContractJsonSerializer(value.GetType());
                    ser.WriteObject(ms, value);
                    byte[] json = ms.ToArray();
                    ms.Close();
                    var v = Encoding.UTF8.GetString(json, 0, json.Length);
                    AddAttributeCore(CustomAttributes, name, @namespace, v);
                }
            }
        }

Here i tried to serialize the value to string if we only do ToString() a bool true becomes True xD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment