Adding a rule that turns off assembly info generation for attributes already defined when migrating.
This commit is contained in:
parent
4aa1c1bfb4
commit
f863630fd8
6 changed files with 336 additions and 1 deletions
14
TestAssets/TestProjects/AppWithAssemblyInfo/Program.cs
Normal file
14
TestAssets/TestProjects/AppWithAssemblyInfo/Program.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ConsoleApp1
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("ConsoleApp1")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCopyright("")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyFileVersion("")]
|
||||||
|
[assembly: AssemblyInformationalVersion("")]
|
||||||
|
[assembly: AssemblyTitle("")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0")]
|
||||||
|
[assembly: NeutralResourcesLanguage("")]
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("ab699746-eb43-467d-ab46-6095b4de9722")]
|
19
TestAssets/TestProjects/AppWithAssemblyInfo/project.json
Normal file
19
TestAssets/TestProjects/AppWithAssemblyInfo/project.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"buildOptions": {
|
||||||
|
"emitEntryPoint": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.NETCore.App": {
|
||||||
|
"type": "platform",
|
||||||
|
"version": "1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"frameworks": {
|
||||||
|
"netcoreapp1.0": {
|
||||||
|
"imports": "dnxcore50"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Build.Construction;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using Microsoft.DotNet.ProjectJsonMigration;
|
||||||
|
using Microsoft.DotNet.ProjectJsonMigration.Transforms;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
using Microsoft.DotNet.ProjectModel.Files;
|
||||||
|
using Microsoft.DotNet.Tools.Common;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
|
{
|
||||||
|
public class MigrateAssemblyInfoRule : IMigrationRule
|
||||||
|
{
|
||||||
|
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>()
|
||||||
|
{
|
||||||
|
"AssemblyCompany",
|
||||||
|
"AssemblyConfiguration",
|
||||||
|
"AssemblyCopyright",
|
||||||
|
"AssemblyDescription",
|
||||||
|
"AssemblyFileVersion",
|
||||||
|
"AssemblyInformationalVersion",
|
||||||
|
"AssemblyProduct",
|
||||||
|
"AssemblyTitle",
|
||||||
|
"AssemblyVersion",
|
||||||
|
"NeutralResourcesLanguage"
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ITransformApplicator _transformApplicator;
|
||||||
|
|
||||||
|
public MigrateAssemblyInfoRule(ITransformApplicator transformApplicator = null)
|
||||||
|
{
|
||||||
|
_transformApplicator = transformApplicator ?? new TransformApplicator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
|
||||||
|
{
|
||||||
|
var projectContext = migrationRuleInputs.DefaultProjectContext;
|
||||||
|
var compilationOptions = ResolveCompilationOptions(projectContext, "Debug");
|
||||||
|
var sources = GetCompilationSources(projectContext, compilationOptions);
|
||||||
|
var assemblyInfoList = GetAssemblyInfo(sources);
|
||||||
|
|
||||||
|
foreach(var assemblyInfo in assemblyInfoList)
|
||||||
|
{
|
||||||
|
var propertyTransform = new AddPropertyTransform<string>(
|
||||||
|
$"Generate{assemblyInfo}Attribute",
|
||||||
|
a => "false",
|
||||||
|
a => true);
|
||||||
|
|
||||||
|
_transformApplicator.Execute(
|
||||||
|
propertyTransform.Transform(assemblyInfo),
|
||||||
|
migrationRuleInputs.CommonPropertyGroup,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> GetCompilationSources(ProjectContext project, CommonCompilerOptions compilerOptions)
|
||||||
|
{
|
||||||
|
if (compilerOptions.CompileInclude == null)
|
||||||
|
{
|
||||||
|
return project.ProjectFile.Files.SourceFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
var includeFiles = IncludeFilesResolver.GetIncludeFiles(compilerOptions.CompileInclude, "/", diagnostics: null);
|
||||||
|
|
||||||
|
return includeFiles.Select(f => f.SourcePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> GetAssemblyInfo(IEnumerable<string> sourceFiles)
|
||||||
|
{
|
||||||
|
var assemblyInfoList = new List<string>();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return assemblyInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// used in incremental compilation for the key file
|
||||||
|
private CommonCompilerOptions ResolveCompilationOptions(ProjectContext context, string configuration)
|
||||||
|
{
|
||||||
|
var compilerOptions = GetLanguageSpecificCompilerOptions(context, context.TargetFramework, configuration);
|
||||||
|
|
||||||
|
// Path to strong naming key in environment variable overrides path in project.json
|
||||||
|
var environmentKeyFile = Environment.GetEnvironmentVariable(EnvironmentNames.StrongNameKeyFile);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(environmentKeyFile))
|
||||||
|
{
|
||||||
|
compilerOptions.KeyFile = environmentKeyFile;
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(compilerOptions.KeyFile))
|
||||||
|
{
|
||||||
|
// Resolve full path to key file
|
||||||
|
compilerOptions.KeyFile =
|
||||||
|
Path.GetFullPath(Path.Combine(context.ProjectFile.ProjectDirectory, compilerOptions.KeyFile));
|
||||||
|
}
|
||||||
|
return compilerOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CommonCompilerOptions GetLanguageSpecificCompilerOptions(
|
||||||
|
ProjectContext context,
|
||||||
|
NuGetFramework framework,
|
||||||
|
string configurationName)
|
||||||
|
{
|
||||||
|
var baseOption = context.ProjectFile.GetCompilerOptions(framework, configurationName);
|
||||||
|
|
||||||
|
IReadOnlyList<string> defaultSuppresses;
|
||||||
|
var compilerName = baseOption.CompilerName ?? "csc";
|
||||||
|
if (Suppresses.TryGetValue(compilerName, out defaultSuppresses))
|
||||||
|
{
|
||||||
|
baseOption.SuppressWarnings = (baseOption.SuppressWarnings ?? Enumerable.Empty<string>()).Concat(defaultSuppresses).Distinct();
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseOption;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,8 @@
|
||||||
"Microsoft.DotNet.ProjectModel": {
|
"Microsoft.DotNet.ProjectModel": {
|
||||||
"target": "project"
|
"target": "project"
|
||||||
},
|
},
|
||||||
"Microsoft.Build": "15.1.319-preview5"
|
"Microsoft.Build": "15.1.319-preview5",
|
||||||
|
"Microsoft.CodeAnalysis.CSharp": "2.0.0-beta6-60922-08"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"netcoreapp1.0": { }
|
"netcoreapp1.0": { }
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.Build.Construction;
|
||||||
|
using Microsoft.DotNet.ProjectJsonMigration;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
using Microsoft.DotNet.Tools.Test.Utilities;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
using System.Linq;
|
||||||
|
using Xunit;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Microsoft.DotNet.ProjectJsonMigration.Rules;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
|
{
|
||||||
|
public class GivenThatIWantToMigrateAssemblyInfo : TestBase
|
||||||
|
{
|
||||||
|
private ProjectRootElement _mockProject;
|
||||||
|
|
||||||
|
public GivenThatIWantToMigrateAssemblyInfo()
|
||||||
|
{
|
||||||
|
var projectDirectory =
|
||||||
|
TestAssetsManager.CreateTestInstance("AppWithAssemblyInfo", callingMethod: "i").Path;
|
||||||
|
var projectContext =
|
||||||
|
ProjectContext.Create(projectDirectory, FrameworkConstants.CommonFrameworks.NetCoreApp10);
|
||||||
|
_mockProject = ProjectRootElement.Create();
|
||||||
|
var testSettings = new MigrationSettings(projectDirectory, projectDirectory, "1.0.0", _mockProject, null);
|
||||||
|
var testInputs = new MigrationRuleInputs(
|
||||||
|
new[] {projectContext},
|
||||||
|
_mockProject,
|
||||||
|
_mockProject.AddItemGroup(),
|
||||||
|
_mockProject.AddPropertyGroup());
|
||||||
|
|
||||||
|
new MigrateAssemblyInfoRule().Apply(testSettings, testInputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateAssemblyCompanyAttributeToFalseWhenAssemblyCompanyExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateAssemblyCompanyAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateAssemblyConfigurationAttributeToFalseWhenAssemblyConfigurationExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateAssemblyConfigurationAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateAssemblyCopyrightAttributeToFalseWhenAssemblyCopyrightExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateAssemblyCopyrightAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateAssemblyDescriptionAttributeToFalseWhenAssemblyDescriptionExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateAssemblyDescriptionAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateAssemblyFileVersionAttributeToFalseWhenAssemblyFileVersionExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateAssemblyFileVersionAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateAssemblyInformationalVersionAttributeToFalseWhenAssemblyInformationalVersionExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateAssemblyInformationalVersionAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateAssemblyProductAttributeToFalseWhenAssemblyProductExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateAssemblyProductAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateAssemblyTitleAttributeToFalseWhenAssemblyTitleExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateAssemblyTitleAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateAssemblyVersionAttributeToFalseWhenAssemblyVersionExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateAssemblyVersionAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItSetsGenerateNeutralResourcesLanguageAttributeToFalseWhenNeutralResourcesLanguageExists()
|
||||||
|
{
|
||||||
|
var generateAssemblyAttributes =
|
||||||
|
_mockProject.Properties.Where(p => p.Name.Equals("GenerateNeutralResourcesLanguageAttribute", StringComparison.Ordinal));
|
||||||
|
generateAssemblyAttributes.Count().Should().Be(1);
|
||||||
|
generateAssemblyAttributes.First().Value.Should().Be("false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue