Merge pull request #4777 from dasMulli/bugfix/assembly-attributes-migration

Migration: Handle different variations of specifying assembly attributes.
This commit is contained in:
Livar 2016-11-18 13:56:30 -08:00 committed by GitHub
commit dd2fe2fac5
2 changed files with 59 additions and 37 deletions

View file

@ -1,5 +1,4 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -7,16 +6,15 @@ using System.Runtime.InteropServices;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ConsoleApp1")]
[assembly: AssemblyCompanyAttribute("")]
[assembly: System.Reflection.AssemblyProduct("ConsoleApp1")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyFileVersion("")]
[assembly: AssemblyInformationalVersion("")]
[assembly: AssemblyTitle("")]
[assembly: AssemblyVersion("1.0.0")]
[assembly: NeutralResourcesLanguage("")]
[assembly: System.Reflection.AssemblyTitleAttribute("")]
[assembly: AssemblyVersion("1.0.0"), System.Resources.NeutralResourcesLanguageAttribute("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from

View file

@ -19,23 +19,26 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
{
internal class MigrateAssemblyInfoRule : IMigrationRule
{
private const string SystemReflectionNamespace = "System.Reflection";
private const string SystemResourcesNamespace = "System.Resources";
private static IReadOnlyDictionary<string, IReadOnlyList<string>> Suppresses { get; } = new Dictionary<string, IReadOnlyList<string>>
{
{ "csc", new string[] {"CS1701", "CS1702", "CS1705" } }
};
private static IReadOnlyList<string> GenerateAssemblyInfoWhitelist = new List<string>()
private static IReadOnlyList<KnownAssemblyAttribute> GenerateAssemblyInfoWhitelist = new List<KnownAssemblyAttribute>()
{
"AssemblyCompany",
"AssemblyConfiguration",
"AssemblyCopyright",
"AssemblyDescription",
"AssemblyFileVersion",
"AssemblyInformationalVersion",
"AssemblyProduct",
"AssemblyTitle",
"AssemblyVersion",
"NeutralResourcesLanguage"
new KnownAssemblyAttribute(SystemReflectionNamespace, "AssemblyCompany"),
new KnownAssemblyAttribute(SystemReflectionNamespace, "AssemblyConfiguration"),
new KnownAssemblyAttribute(SystemReflectionNamespace, "AssemblyCopyright"),
new KnownAssemblyAttribute(SystemReflectionNamespace, "AssemblyDescription"),
new KnownAssemblyAttribute(SystemReflectionNamespace, "AssemblyFileVersion"),
new KnownAssemblyAttribute(SystemReflectionNamespace, "AssemblyInformationalVersion"),
new KnownAssemblyAttribute(SystemReflectionNamespace, "AssemblyProduct"),
new KnownAssemblyAttribute(SystemReflectionNamespace, "AssemblyTitle"),
new KnownAssemblyAttribute(SystemReflectionNamespace, "AssemblyVersion"),
new KnownAssemblyAttribute(SystemResourcesNamespace, "NeutralResourcesLanguage")
};
private readonly ITransformApplicator _transformApplicator;
@ -50,23 +53,23 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
var projectContext = migrationRuleInputs.DefaultProjectContext;
var compilationOptions = ResolveCompilationOptions(projectContext, "Debug");
var sources = GetCompilationSources(projectContext, compilationOptions);
var assemblyInfoList = GetAssemblyInfo(sources);
var assemblyAttributeList = GetWhitelistedKnownAssemblyAttributes(sources);
foreach(var assemblyInfo in assemblyInfoList)
foreach(var assemblyAttribute in assemblyAttributeList)
{
var propertyTransform = new AddPropertyTransform<string>(
$"Generate{assemblyInfo}Attribute",
assemblyAttribute.GenerateAssemblyAttributePropertyName,
a => "false",
a => true);
_transformApplicator.Execute(
propertyTransform.Transform(assemblyInfo),
propertyTransform.Transform(assemblyAttribute.AttributeName),
migrationRuleInputs.CommonPropertyGroup,
true);
}
}
public IEnumerable<string> GetCompilationSources(ProjectContext project, CommonCompilerOptions compilerOptions)
private IEnumerable<string> GetCompilationSources(ProjectContext project, CommonCompilerOptions compilerOptions)
{
if (compilerOptions.CompileInclude == null)
{
@ -78,28 +81,28 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
return includeFiles.Select(f => f.SourcePath);
}
public List<string> GetAssemblyInfo(IEnumerable<string> sourceFiles)
private List<KnownAssemblyAttribute> GetWhitelistedKnownAssemblyAttributes(IEnumerable<string> sourceFiles)
{
var assemblyInfoList = new List<string>();
var assemblyInfoList = new List<KnownAssemblyAttribute>();
foreach (var sourceFile in sourceFiles)
{
var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(sourceFile));
var root = tree.GetRoot();
// assembly attributes can be only on first level
foreach (var attributeListSyntax in root.ChildNodes().OfType<AttributeListSyntax>())
{
if (attributeListSyntax.Target.Identifier.Kind() == SyntaxKind.AssemblyKeyword)
{
foreach (var attributeSyntax in attributeListSyntax
.Attributes
.Select(a => a.Name.ToString())
.Where(a => GenerateAssemblyInfoWhitelist.Contains(a)))
{
assemblyInfoList.Add(attributeSyntax);
}
}
}
var attributeListSyntaxNodes = root.ChildNodes().OfType<AttributeListSyntax>();
assemblyInfoList.AddRange(
attributeListSyntaxNodes
.Where(node => node.Target.Identifier.Kind() == SyntaxKind.AssemblyKeyword)
.SelectMany(node => node.Attributes)
.Select(attribute => attribute.Name.ToString())
.Select(name =>
GenerateAssemblyInfoWhitelist
.FirstOrDefault(b => b.MatchNames.Contains(name))
)
.Where(knownAttribute => knownAttribute != null)
);
}
return assemblyInfoList;
@ -142,5 +145,26 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
return baseOption;
}
private class KnownAssemblyAttribute
{
public string Namespace { get; }
public string AttributeName { get; }
public IList<string> MatchNames { get; }
public string GenerateAssemblyAttributePropertyName { get; }
public KnownAssemblyAttribute(string namespaceName, string attributeName)
{
Namespace = namespaceName;
AttributeName = attributeName;
GenerateAssemblyAttributePropertyName = $"Generate{attributeName}Attribute";
MatchNames = new [] {
attributeName,
$"{attributeName}Attribute",
$"{namespaceName}.{attributeName}",
$"{namespaceName}.{attributeName}Attribute"
};
}
}
}
}