From ff63f91711b5f1ed2ea71e52aee7c78e99165459 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Sat, 9 Mar 2019 17:00:58 -0800 Subject: [PATCH 1/3] Fix identifiers generated from resx resource names --- .../GenerateResxSourceTests.cs | 14 ++++ .../src/GenerateResxSource.cs | 84 +++++++++++++------ 2 files changed, 72 insertions(+), 26 deletions(-) diff --git a/src/Microsoft.DotNet.Arcade.Sdk.Tests/GenerateResxSourceTests.cs b/src/Microsoft.DotNet.Arcade.Sdk.Tests/GenerateResxSourceTests.cs index 7007b839990..6edec3e0b2c 100644 --- a/src/Microsoft.DotNet.Arcade.Sdk.Tests/GenerateResxSourceTests.cs +++ b/src/Microsoft.DotNet.Arcade.Sdk.Tests/GenerateResxSourceTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +<<<<<<< HEAD using System; using System.IO; using Microsoft.DotNet.Arcade.Sdk.Tests.Utilities; @@ -59,5 +60,18 @@ public void GeneratesCSharp(bool emitFormatMethods, bool asConstants, bool omitG _output.WriteLine(actualFileContents); Assert.Equal(File.ReadAllText(expectedFile), actualFileContents, ignoreLineEndingDifferences: true); } + + [Theory] + [InlineData("a", "a")] + [InlineData("A", "A")] + [InlineData("_A", "_A")] + [InlineData(".A", "_A")] + [InlineData("4A", "_4A")] + [InlineData("4(.-)A", "_4____A")] + [InlineData("A\u0660\u2040\u0601\u0300\u0903", "A\u0660\u2040\u0601\u0300\u0903")] + public void GetIdentifierFromResourceName(string name, string expectedIdentifier) + { + Assert.Equal(expectedIdentifier, GenerateResxSource.GetIdentifierFromResourceName(name)); + } } } diff --git a/src/Microsoft.DotNet.Arcade.Sdk/src/GenerateResxSource.cs b/src/Microsoft.DotNet.Arcade.Sdk/src/GenerateResxSource.cs index 3d55135ccb3..301fd120cda 100644 --- a/src/Microsoft.DotNet.Arcade.Sdk/src/GenerateResxSource.cs +++ b/src/Microsoft.DotNet.Arcade.Sdk/src/GenerateResxSource.cs @@ -70,27 +70,6 @@ private enum Lang CSharp, VisualBasic, } - - private bool IsLetterChar(UnicodeCategory cat) - { - // letter-character: - // A Unicode character of classes Lu, Ll, Lt, Lm, Lo, or Nl - // A Unicode-escape-sequence representing a character of classes Lu, Ll, Lt, Lm, Lo, or Nl - - switch (cat) - { - case UnicodeCategory.UppercaseLetter: - case UnicodeCategory.LowercaseLetter: - case UnicodeCategory.TitlecaseLetter: - case UnicodeCategory.ModifierLetter: - case UnicodeCategory.OtherLetter: - case UnicodeCategory.LetterNumber: - return true; - } - - return false; - } - public override bool Execute() { string namespaceName; @@ -151,7 +130,7 @@ public override bool Execute() RenderDocComment(language, memberIndent, strings, docCommentString); - string identifier = IsLetterChar(CharUnicodeInfo.GetUnicodeCategory(name[0])) ? name : "_" + name; + string identifier = GetIdentifierFromResourceName(name); string defaultValue = IncludeDefaultValues ? ", " + CreateStringLiteral(value, language) : string.Empty; @@ -160,11 +139,11 @@ public override bool Execute() case Lang.CSharp: if (AsConstants) { - strings.AppendLine($"{memberIndent}internal const string {name} = nameof({name});"); + strings.AppendLine($"{memberIndent}internal const string @{identifier} = \"{name}\");"); } else { - strings.AppendLine($"{memberIndent}internal static string {identifier} => GetResourceString(\"{name}\"{defaultValue});"); + strings.AppendLine($"{memberIndent}internal static string @{identifier} => GetResourceString(\"{name}\"{defaultValue});"); } if (EmitFormatMethods) @@ -182,11 +161,11 @@ public override bool Execute() case Lang.VisualBasic: if (AsConstants) { - strings.AppendLine($"{memberIndent}Friend Const {name} As String = \"{name}\""); + strings.AppendLine($"{memberIndent}Friend Const [{identifier}] As String = \"{name}\""); } else { - strings.AppendLine($"{memberIndent}Friend Shared ReadOnly Property {identifier} As String"); + strings.AppendLine($"{memberIndent}Friend Shared ReadOnly Property [{identifier}] As String"); strings.AppendLine($"{memberIndent} Get"); strings.AppendLine($"{memberIndent} Return GetResourceString(\"{name}\"{defaultValue})"); strings.AppendLine($"{memberIndent} End Get"); @@ -387,6 +366,59 @@ Imports System.Reflection return true; } + internal static string GetIdentifierFromResourceName(string name) + { + if (name.All(IsIdentifierPartCharacter)) + { + return IsIdentifierStartCharacter(name[0]) ? name : "_" + name; + } + + var builder = new StringBuilder(name.Length); + + char f = name[0]; + if (IsIdentifierPartCharacter(f) && !IsIdentifierStartCharacter(f)) + { + builder.Append('_'); + } + + foreach (char c in name) + { + builder.Append(IsIdentifierPartCharacter(c) ? c : '_'); + } + + return builder.ToString(); + + bool IsIdentifierStartCharacter(char ch) + => ch == '_' || IsLetterChar(CharUnicodeInfo.GetUnicodeCategory(ch)); + + bool IsIdentifierPartCharacter(char ch) + { + var cat = CharUnicodeInfo.GetUnicodeCategory(ch); + return IsLetterChar(cat) + || cat == UnicodeCategory.DecimalDigitNumber + || cat == UnicodeCategory.ConnectorPunctuation + || cat == UnicodeCategory.Format + || cat == UnicodeCategory.NonSpacingMark + || cat == UnicodeCategory.SpacingCombiningMark; + } + + bool IsLetterChar(UnicodeCategory cat) + { + switch (cat) + { + case UnicodeCategory.UppercaseLetter: + case UnicodeCategory.LowercaseLetter: + case UnicodeCategory.TitlecaseLetter: + case UnicodeCategory.ModifierLetter: + case UnicodeCategory.OtherLetter: + case UnicodeCategory.LetterNumber: + return true; + } + + return false; + } + } + private static void RenderDocComment(Lang language, string memberIndent, StringBuilder strings, string value) { string docCommentStart = language == Lang.CSharp From 9b5a001a1f4be1c14fb134eec13f62ea7a2ad9c6 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Sun, 29 Dec 2019 11:40:00 +0100 Subject: [PATCH 2/3] Make AggressiveInlining NET20 conditional --- .../src/GenerateResxSource.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.DotNet.Arcade.Sdk/src/GenerateResxSource.cs b/src/Microsoft.DotNet.Arcade.Sdk/src/GenerateResxSource.cs index 301fd120cda..bd150cf1e45 100644 --- a/src/Microsoft.DotNet.Arcade.Sdk/src/GenerateResxSource.cs +++ b/src/Microsoft.DotNet.Arcade.Sdk/src/GenerateResxSource.cs @@ -194,8 +194,9 @@ public override bool Execute() { case Lang.CSharp: getStringMethod = $@"{memberIndent}internal static global::System.Globalization.CultureInfo Culture {{ get; set; }} - +#if !NET20 {memberIndent}[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif {memberIndent}internal static string GetResourceString(string resourceKey, string defaultValue = null) => ResourceManager.GetString(resourceKey, Culture);"; if (EmitFormatMethods) { @@ -219,8 +220,9 @@ public override bool Execute() case Lang.VisualBasic: getStringMethod = $@"{memberIndent}Friend Shared Property Culture As Global.System.Globalization.CultureInfo - +#If Not NET20 Then {memberIndent} +#End If {memberIndent}Friend Shared Function GetResourceString(ByVal resourceKey As String, Optional ByVal defaultValue As String = Nothing) As String {memberIndent} Return ResourceManager.GetString(resourceKey, Culture) {memberIndent}End Function"; @@ -388,10 +390,10 @@ internal static string GetIdentifierFromResourceName(string name) return builder.ToString(); - bool IsIdentifierStartCharacter(char ch) + static bool IsIdentifierStartCharacter(char ch) => ch == '_' || IsLetterChar(CharUnicodeInfo.GetUnicodeCategory(ch)); - bool IsIdentifierPartCharacter(char ch) + static bool IsIdentifierPartCharacter(char ch) { var cat = CharUnicodeInfo.GetUnicodeCategory(ch); return IsLetterChar(cat) @@ -402,7 +404,7 @@ bool IsIdentifierPartCharacter(char ch) || cat == UnicodeCategory.SpacingCombiningMark; } - bool IsLetterChar(UnicodeCategory cat) + static bool IsLetterChar(UnicodeCategory cat) { switch (cat) { From a08cec99e19b349b19efb3c3225792a806267a74 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Sun, 29 Dec 2019 13:22:35 +0100 Subject: [PATCH 3/3] Fix --- src/Microsoft.DotNet.Arcade.Sdk.Tests/GenerateResxSourceTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.DotNet.Arcade.Sdk.Tests/GenerateResxSourceTests.cs b/src/Microsoft.DotNet.Arcade.Sdk.Tests/GenerateResxSourceTests.cs index 6edec3e0b2c..afffb0d5bbe 100644 --- a/src/Microsoft.DotNet.Arcade.Sdk.Tests/GenerateResxSourceTests.cs +++ b/src/Microsoft.DotNet.Arcade.Sdk.Tests/GenerateResxSourceTests.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -<<<<<<< HEAD using System; using System.IO; using Microsoft.DotNet.Arcade.Sdk.Tests.Utilities;