From 18ed6a4e490cf386801a431185d2c8917b1f1fc1 Mon Sep 17 00:00:00 2001 From: Gary Ewan Park Date: Tue, 15 Oct 2019 13:28:01 +0100 Subject: [PATCH 1/2] (GH-2637) Fix string rendering of boolean value There is a difference between how C# and VB interpret a boolean value. C# uses true/false, where as VB uses True/False --- .../Project/Properties/AssemblyInfoCreatorTests_VB.cs | 6 +++--- .../Project/Properties/AssemblyInfoCreator.cs | 8 ++++++-- .../Project/Properties/AssemblyInfoCreatorData.cs | 11 ++++++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests_VB.cs b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests_VB.cs index e24c7f0257..579684029e 100644 --- a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests_VB.cs +++ b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests_VB.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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. @@ -222,7 +222,7 @@ public void Should_Add_ComVisible_Attribute_If_Set() // Then Assert.Contains("Imports System.Runtime.InteropServices", result); - Assert.Contains("", result); + Assert.Contains("", result); } [Fact] @@ -237,7 +237,7 @@ public void Should_Add_CLSCompliant_Attribute_If_Set() // Then Assert.Contains("Imports System", result); - Assert.Contains("", result); + Assert.Contains("", result); } [Fact] diff --git a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreator.cs b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreator.cs index b2ffc8612d..55e53542ef 100644 --- a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreator.cs +++ b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreator.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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. @@ -78,15 +78,19 @@ public void Create(FilePath outputPath, AssemblyInfoSettings settings) string attributeWithValueFormat = CSharpAttributeWithValueFormat; string attributeWithKeyValueFormat = CSharpAttributeWithKeyValueFormat; + var isVisualBasicAssemblyInfoFile = false; + if (outputPath.GetExtension() == ".vb") { + isVisualBasicAssemblyInfoFile = true; comment = VBComment; usingFormat = VBUsingFormat; attributeFormat = VBAttributeFormat; attributeWithValueFormat = VBAttributeWithValueFormat; attributeWithKeyValueFormat = VBAttributeWithKeyValueFormat; } - var data = new AssemblyInfoCreatorData(settings); + + var data = new AssemblyInfoCreatorData(settings, isVisualBasicAssemblyInfoFile); outputPath = outputPath.MakeAbsolute(_environment); _log.Verbose("Creating assembly info file: {0}", outputPath); diff --git a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreatorData.cs b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreatorData.cs index 237c7c0161..63665078b4 100644 --- a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreatorData.cs +++ b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreatorData.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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. @@ -16,6 +16,8 @@ internal sealed class AssemblyInfoCreatorData private readonly Dictionary _metadatattributes; private readonly HashSet _namespaces; private readonly HashSet _internalVisibleTo; + private readonly string _trueStringValue; + private readonly string _falseStringValue; public IDictionary Attributes => _dictionary; @@ -27,7 +29,7 @@ internal sealed class AssemblyInfoCreatorData public ISet InternalVisibleTo => _internalVisibleTo; - public AssemblyInfoCreatorData(AssemblyInfoSettings settings) + public AssemblyInfoCreatorData(AssemblyInfoSettings settings, bool isVisualBasicAssemblyInfoFile) { _dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); _customAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -35,6 +37,9 @@ public AssemblyInfoCreatorData(AssemblyInfoSettings settings) _namespaces = new HashSet(StringComparer.OrdinalIgnoreCase); _internalVisibleTo = new HashSet(StringComparer.OrdinalIgnoreCase); + _falseStringValue = isVisualBasicAssemblyInfoFile ? "False" : "false"; + _trueStringValue = isVisualBasicAssemblyInfoFile ? "True" : "true"; + // Add attributes. AddAttribute("AssemblyTitle", "System.Reflection", settings.Title); AddAttribute("AssemblyDescription", "System.Reflection", settings.Description); @@ -82,7 +87,7 @@ private void AddAttribute(string name, string @namespace, bool? value) { if (value != null) { - AddAttributeCore(Attributes, name, @namespace, value.Value ? "true" : "false"); + AddAttributeCore(Attributes, name, @namespace, value.Value ? _trueStringValue : _falseStringValue); } } From 8546aa359199467cfd4a16c9c6f6b85dda8a76fd Mon Sep 17 00:00:00 2001 From: Gary Ewan Park Date: Tue, 15 Oct 2019 13:30:51 +0100 Subject: [PATCH 2/2] (GH-2638) Add ability to pass bool and null values When creating CustomAttributes for AssemblyInfo files, it is useful to be able to generate attributes with boolean values, as well as attributes that don't have a value. This is a "simple" solution to allow this to happen, a broader fix would be to use Roslyn to fully understand all attributes in the file. --- .../Properties/AssemblyInfoCreatorTests.cs | 45 +++++++++++++++++++ .../Properties/AssemblyInfoCreatorTests_VB.cs | 45 +++++++++++++++++++ .../Properties/AssemblyInfoCreatorData.cs | 31 +++++++++++-- .../Properties/AssemblyInfoCustomAttribute.cs | 4 +- 4 files changed, 120 insertions(+), 5 deletions(-) diff --git a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests.cs b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests.cs index 1ccea6b5b5..2b66e294d4 100644 --- a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests.cs +++ b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests.cs @@ -347,6 +347,51 @@ public void Should_Add_CustomAttributes_If_Set() Assert.Contains("[assembly: TestAttribute(\"TestValue\")]", result); } + [Fact] + public void Should_Add_CustomAttributes_If_Set_With_Boolean_Value() + { + // Given + var fixture = new AssemblyInfoFixture(); + fixture.Settings.CustomAttributes = new Collection { new AssemblyInfoCustomAttribute { Name = "TestAttribute", NameSpace = "Test.NameSpace", Value = true } }; + + // When + var result = fixture.CreateAndReturnContent(); + + // Then + Assert.Contains("using Test.NameSpace;", result); + Assert.Contains("[assembly: TestAttribute(true)]", result); + } + + [Fact] + public void Should_Add_CustomAttributes_If_Set_With_Null_Value() + { + // Given + var fixture = new AssemblyInfoFixture(); + fixture.Settings.CustomAttributes = new Collection { new AssemblyInfoCustomAttribute { Name = "TestAttribute", NameSpace = "Test.NameSpace", Value = null } }; + + // When + var result = fixture.CreateAndReturnContent(); + + // Then + Assert.Contains("using Test.NameSpace;", result); + Assert.Contains("[assembly: TestAttribute()]", result); + } + + [Fact] + public void Should_Add_CustomAttributes_If_Set_With_Empty_Value() + { + // Given + var fixture = new AssemblyInfoFixture(); + fixture.Settings.CustomAttributes = new Collection { new AssemblyInfoCustomAttribute { Name = "TestAttribute", NameSpace = "Test.NameSpace", Value = string.Empty } }; + + // When + var result = fixture.CreateAndReturnContent(); + + // Then + Assert.Contains("using Test.NameSpace;", result); + Assert.Contains("[assembly: TestAttribute()]", result); + } + [Fact] public void Should_Add_MetadataAttributes_If_Set() { diff --git a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests_VB.cs b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests_VB.cs index 579684029e..1ecf09ae98 100644 --- a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests_VB.cs +++ b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoCreatorTests_VB.cs @@ -301,6 +301,51 @@ public void Should_Add_CustomAttributes_If_Set() Assert.Contains("Imports Test.NameSpace", result); Assert.Contains("", result); } + + [Fact] + public void Should_Add_CustomAttributes_If_Set_With_Boolean_Value() + { + // Given + var fixture = new AssemblyInfoFixture_VB(); + fixture.Settings.CustomAttributes = new Collection { new AssemblyInfoCustomAttribute { Name = "TestAttribute", NameSpace = "Test.NameSpace", Value = true } }; + + // When + var result = fixture.CreateAndReturnContent(); + + // Then + Assert.Contains("Imports Test.NameSpace", result); + Assert.Contains("", result); + } + + [Fact] + public void Should_Add_CustomAttributes_If_Set_With_Null_Value() + { + // Given + var fixture = new AssemblyInfoFixture_VB(); + fixture.Settings.CustomAttributes = new Collection { new AssemblyInfoCustomAttribute { Name = "TestAttribute", NameSpace = "Test.NameSpace", Value = null } }; + + // When + var result = fixture.CreateAndReturnContent(); + + // Then + Assert.Contains("Imports Test.NameSpace", result); + Assert.Contains("", result); + } + + [Fact] + public void Should_Add_CustomAttributes_If_Set_With_Empty_Value() + { + // Given + var fixture = new AssemblyInfoFixture_VB(); + fixture.Settings.CustomAttributes = new Collection { new AssemblyInfoCustomAttribute { Name = "TestAttribute", NameSpace = "Test.NameSpace", Value = string.Empty } }; + + // When + var result = fixture.CreateAndReturnContent(); + + // Then + Assert.Contains("Imports Test.NameSpace", result); + Assert.Contains("", result); + } } } } \ No newline at end of file diff --git a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreatorData.cs b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreatorData.cs index 63665078b4..02b079e015 100644 --- a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreatorData.cs +++ b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreatorData.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Cake.Core; @@ -99,11 +100,35 @@ private void AddAttribute(string name, string @namespace, string value) } } - private void AddCustomAttribute(string name, string @namespace, string value) + private void AddCustomAttribute(string name, string @namespace, object value) { - if (value != null) + var attributeValue = AttributeValueToString(value); + + AddAttributeCore(CustomAttributes, name, @namespace, attributeValue); + } + + private string AttributeValueToString(object value) + { + switch (value) { - AddAttributeCore(CustomAttributes, name, @namespace, string.Concat("\"", value, "\"")); + case null: + { + return string.Empty; + } + case bool boolValue: + { + return boolValue ? _trueStringValue : _falseStringValue; + } + case string stringValue: + { + return stringValue == string.Empty + ? string.Empty + : string.Concat("\"", value, "\""); + } + default: + { + return Convert.ToString(value, CultureInfo.InvariantCulture); + } } } diff --git a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCustomAttribute.cs b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCustomAttribute.cs index 0aa60ff3b3..368722111f 100644 --- a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCustomAttribute.cs +++ b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCustomAttribute.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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. @@ -25,6 +25,6 @@ public sealed class AssemblyInfoCustomAttribute /// Gets or sets the value. /// /// The value for the attribute. - public string Value { get; set; } + public object Value { get; set; } } } \ No newline at end of file