| File: UnicodeCharacterUtilities.cs | Web Access |
| Project: src\sdk\src\TemplateEngine\Microsoft.TemplateEngine.Orchestrator.RunnableProjects\Microsoft.TemplateEngine.Orchestrator.RunnableProjects.csproj (Microsoft.TemplateEngine.Orchestrator.RunnableProjects) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; namespace Microsoft.TemplateEngine.Orchestrator.RunnableProjects.Utilities { /// <summary> /// Defines a set of helper methods to classify Unicode characters. /// </summary> internal static partial class UnicodeCharacterUtilities { public static bool IsIdentifierStartCharacter(char ch) { // identifier-start-character: // letter-character // _ (the underscore character U+005F) if (ch < 'a') // '\u0061' { if (ch < 'A') // '\u0041' { return false; } return ch is <= 'Z' // '\u005A' or '_'; // '\u005F' } if (ch <= 'z') // '\u007A' { return true; } if (ch <= '\u007F') // max ASCII { return false; } return IsLetterChar(CharUnicodeInfo.GetUnicodeCategory(ch)); } /// <summary> /// Returns true if the Unicode character can be a part of an identifier. /// </summary> /// <param name="ch">The Unicode character.</param> public static bool IsIdentifierPartCharacter(char ch) { // identifier-part-character: // letter-character // decimal-digit-character // connecting-character // combining-character // formatting-character if (ch < 'a') // '\u0061' { if (ch < 'A') // '\u0041' { return ch is >= '0' // '\u0030' and <= '9'; // '\u0039' } return ch is <= 'Z' // '\u005A' or '_'; // '\u005F' } if (ch <= 'z') // '\u007A' { return true; } if (ch <= '\u007F') // max ASCII { return false; } UnicodeCategory cat = CharUnicodeInfo.GetUnicodeCategory(ch); return IsLetterChar(cat) || IsDecimalDigitChar(cat) || IsConnectingChar(cat) || IsCombiningChar(cat) || IsFormattingChar(cat); } /// <summary> /// Check that the name is a valid Unicode identifier. /// </summary> public static bool IsValidIdentifier(string? name) { if (string.IsNullOrEmpty(name)) { return false; } if (!IsIdentifierStartCharacter(name![0])) { return false; } int nameLength = name.Length; for (int i = 1; i < nameLength; i++) //NB: start at 1 { if (!IsIdentifierPartCharacter(name[i])) { return false; } } return true; } /// <summary> /// Returns true if the Unicode character is a formatting character (Unicode class Cf). /// </summary> /// <param name="ch">The Unicode character.</param> internal static bool IsFormattingChar(char ch) { // There are no FormattingChars in ASCII range return ch > 127 && IsFormattingChar(CharUnicodeInfo.GetUnicodeCategory(ch)); } private static 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 return cat switch { UnicodeCategory.UppercaseLetter or UnicodeCategory.LowercaseLetter or UnicodeCategory.TitlecaseLetter or UnicodeCategory.ModifierLetter or UnicodeCategory.OtherLetter or UnicodeCategory.LetterNumber => true, _ => false, }; } private static bool IsCombiningChar(UnicodeCategory cat) { // combining-character: // A Unicode character of classes Mn or Mc // A Unicode-escape-sequence representing a character of classes Mn or Mc return cat switch { UnicodeCategory.NonSpacingMark or UnicodeCategory.SpacingCombiningMark => true, _ => false, }; } private static bool IsDecimalDigitChar(UnicodeCategory cat) { // decimal-digit-character: // A Unicode character of the class Nd // A unicode-escape-sequence representing a character of the class Nd return cat == UnicodeCategory.DecimalDigitNumber; } private static bool IsConnectingChar(UnicodeCategory cat) { // connecting-character: // A Unicode character of the class Pc // A unicode-escape-sequence representing a character of the class Pc return cat == UnicodeCategory.ConnectorPunctuation; } /// <summary> /// Returns true if the Unicode character is a formatting character (Unicode class Cf). /// </summary> /// <param name="cat">The Unicode character.</param> private static bool IsFormattingChar(UnicodeCategory cat) { // formatting-character: // A Unicode character of the class Cf // A unicode-escape-sequence representing a character of the class Cf return cat == UnicodeCategory.Format; } } }