internal static bool TryParseSourceMethodNameFromGeneratedName( string generatedName, GeneratedNameKind requiredKind, out string methodName) { GeneratedNameKind kind; int openBracketOffset; int closeBracketOffset; if (!GeneratedNames.TryParseGeneratedName(generatedName, out kind, out openBracketOffset, out closeBracketOffset)) { methodName = null; return(false); } if (requiredKind != GeneratedNameKind.None && kind != requiredKind) { methodName = null; return(false); } methodName = generatedName.Substring(openBracketOffset + 1, closeBracketOffset - openBracketOffset - 1); if (kind.IsTypeName()) { methodName = methodName.Replace('-', '.'); } return(true); }
// Parse the generated name. Returns true for names of the form // [CS$]<[middle]>c[__[suffix]] where [CS$] is included for certain // generated names, where [middle] and [__[suffix]] are optional, // and where c is a single character in [1-9a-z] // (csharp\LanguageAnalysis\LIB\SpecialName.cpp). internal static bool TryParseGeneratedName( string name, out GeneratedNameKind kind, out int openBracketOffset, out int closeBracketOffset) { openBracketOffset = -1; if (name.StartsWith("CS$<", StringComparison.Ordinal)) { openBracketOffset = 3; } else if (name.StartsWith("<", StringComparison.Ordinal)) { openBracketOffset = 0; } if (openBracketOffset >= 0) { closeBracketOffset = name.IndexOfBalancedParenthesis(openBracketOffset, '>'); if (closeBracketOffset >= 0 && closeBracketOffset + 1 < name.Length) { int c = name[closeBracketOffset + 1]; if ((c >= '1' && c <= '9') || (c >= 'a' && c <= 'z')) // Note '0' is not special. { kind = (GeneratedNameKind)c; return(true); } } } kind = GeneratedNameKind.None; openBracketOffset = -1; closeBracketOffset = -1; return(false); }
private static string MakeMethodScopedSynthesizedName(GeneratedNameKind kind, int methodOrdinal, int generation, string methodNameOpt = null, string suffix = null, int uniqueId = -1, bool isTypeName = false) { Debug.Assert(methodOrdinal >= -1); Debug.Assert(generation >= 0 || generation == -1 && methodOrdinal == -1); Debug.Assert(uniqueId >= -1); var result = PooledStringBuilder.GetInstance(); var builder = result.Builder; builder.Append('<'); if (methodNameOpt != null) { builder.Append(methodNameOpt); // CLR generally allows names with dots, however some APIs like IMetaDataImport // can only return full type names combined with namespaces. // see: http://msdn.microsoft.com/en-us/library/ms230143.aspx (IMetaDataImport::GetTypeDefProps) // When working with such APIs, names with dots become ambiguous since metadata // consumer cannot figure where namespace ends and actual type name starts. // Therefore it is a good practice to avoid type names with dots. // As a replacement use a character not allowed in C# identifier to avoid conflicts. if (kind.IsTypeName()) { builder.Replace('.', DotReplacementInTypeNames); } } builder.Append('>'); builder.Append((char)kind); if (suffix != null || methodOrdinal >= 0 || uniqueId >= 0) { builder.Append(SuffixSeparator); builder.Append(suffix); if (methodOrdinal >= 0) { builder.Append(methodOrdinal); if (generation > 0) { builder.Append(GenerationSeparator); builder.Append(generation); } } if (uniqueId >= 0) { if (methodOrdinal >= 0) { builder.Append(IdSeparator); } builder.Append(uniqueId); } } return(result.ToStringAndFree()); }
internal static bool TryParseGeneratedName( string name, out GeneratedNameKind kind, out int openBracketOffset, out int closeBracketOffset) { openBracketOffset = -1; if (name.StartsWith("CS$<", StringComparison.Ordinal)) { openBracketOffset = 3; } else if (name.StartsWith("<", StringComparison.Ordinal)) { openBracketOffset = 0; } if (openBracketOffset >= 0) { closeBracketOffset = name.IndexOfBalancedParenthesis(openBracketOffset, '>'); if (closeBracketOffset >= 0 && closeBracketOffset + 1 < name.Length) { int num = name[closeBracketOffset + 1]; if (num >= 49 && num <= 57 || num >= 97 && num <= 122) { kind = (GeneratedNameKind)num; return(true); } } } kind = GeneratedNameKind.None; openBracketOffset = -1; closeBracketOffset = -1; return(false); }
// Parse the generated name. Returns true for names of the form // [CS$]<[middle]>c__[suffix] where [CS$] is included for certain // generated names, where [middle] and [suffix] are optional, // and where c is a single character in [1-9a-z]. internal static bool TryParseGeneratedName( string name, out GeneratedNameKind kind, out int openBracketOffset, out int closeBracketOffset) { openBracketOffset = -1; if (name.StartsWith("CS$<", StringComparison.Ordinal)) { openBracketOffset = 3; } else if (name.StartsWith("<", StringComparison.Ordinal)) { openBracketOffset = 0; } if (openBracketOffset >= 0) { closeBracketOffset = -1; int depth = 1; // Find matching '>'. Since a valid generated name // ends with ">c__[suffix]" we only need to search // up to 3 characters from the end. for (int i = openBracketOffset + 1; i < name.Length - 3; i++) { switch (name[i]) { case '<': depth++; break; case '>': depth--; if (depth == 0) { closeBracketOffset = i; goto found; } break; } } found: if (closeBracketOffset > openBracketOffset && name[closeBracketOffset + 2] == '_' && name[closeBracketOffset + 3] == '_') // Not out of range since loop ended early. { int c = name[closeBracketOffset + 1]; if ((c >= '1' && c <= '9') || (c >= 'a' && c <= 'z')) // Note '0' is not special. { kind = (GeneratedNameKind)c; return true; } } } kind = GeneratedNameKind.None; openBracketOffset = -1; closeBracketOffset = -1; return false; }
internal static bool IsTypeName(this GeneratedNameKind kind) { switch (kind) { case GeneratedNameKind.LambdaDisplayClass: case GeneratedNameKind.StateMachineType: case GeneratedNameKind.DynamicCallSiteContainerType: return(true); default: return(false); } }
private static string MakeMethodScopedSynthesizedName( GeneratedNameKind kind, int methodOrdinal, int methodGeneration, string methodNameOpt = null, string suffix = null, char suffixTerminator = '\0', int entityOrdinal = -1, int entityGeneration = -1) { StringBuilder builder = new StringBuilder(); builder.Append('<'); if (methodNameOpt != null) { builder.Append(methodNameOpt); if (kind.IsTypeName()) { builder.Replace('.', '-'); } } builder.Append('>'); builder.Append((char)kind); if (suffix != null || methodOrdinal >= 0 || entityOrdinal >= 0) { builder.Append("__"); builder.Append(suffix); if (suffixTerminator != char.MinValue) { builder.Append(suffixTerminator); } if (methodOrdinal >= 0) { builder.Append(methodOrdinal); GeneratedNames.AppendOptionalGeneration(builder, methodGeneration); } if (entityOrdinal >= 0) { if (methodOrdinal >= 0) { builder.Append('_'); } builder.Append(entityOrdinal); GeneratedNames.AppendOptionalGeneration(builder, entityGeneration); } } return(builder.ToString()); }
internal static bool TryParseSourceMethodNameFromGeneratedName(string generatedName, GeneratedNameKind requiredKind, out string methodName) { int openBracketOffset; int closeBracketOffset; GeneratedNameKind kind; if (!TryParseGeneratedName(generatedName, out kind, out openBracketOffset, out closeBracketOffset)) { methodName = null; return false; } if (requiredKind != 0 && kind != requiredKind) { methodName = null; return false; } methodName = generatedName.Substring(openBracketOffset + 1, closeBracketOffset - openBracketOffset - 1); if (kind.IsTypeName()) { methodName = methodName.Replace(DotReplacementInTypeNames, '.'); } return true; }
// Parse the generated name. Returns true for names of the form // [CS$]<[middle]>c[__[suffix]] where [CS$] is included for certain // generated names, where [middle] and [__[suffix]] are optional, // and where c is a single character in [1-9a-z] // (csharp\LanguageAnalysis\LIB\SpecialName.cpp). internal static bool TryParseGeneratedName( string name, out GeneratedNameKind kind, out int openBracketOffset, out int closeBracketOffset) { openBracketOffset = -1; if (name.StartsWith("CS$<", StringComparison.Ordinal)) { openBracketOffset = 3; } else if (name.StartsWith("<", StringComparison.Ordinal)) { openBracketOffset = 0; } if (openBracketOffset >= 0) { closeBracketOffset = name.IndexOfBalancedParenthesis(openBracketOffset, '>'); if (closeBracketOffset >= 0 && closeBracketOffset + 1 < name.Length) { int c = name[closeBracketOffset + 1]; if ((c >= '1' && c <= '9') || (c >= 'a' && c <= 'z')) // Note '0' is not special. { kind = (GeneratedNameKind)c; return true; } } } kind = GeneratedNameKind.None; openBracketOffset = -1; closeBracketOffset = -1; return false; }
private static string MakeMethodScopedSynthesizedName( GeneratedNameKind kind, int methodOrdinal, int methodGeneration, string methodNameOpt = null, string suffix = null, int entityOrdinal = -1, int entityGeneration = -1, bool isTypeName = false) { Debug.Assert(methodOrdinal >= -1); Debug.Assert(methodGeneration >= 0 || methodGeneration == -1 && methodOrdinal == -1); Debug.Assert(entityOrdinal >= -1); Debug.Assert(entityGeneration >= 0 || entityGeneration == -1 && entityOrdinal == -1); Debug.Assert(entityGeneration == -1 || entityGeneration >= methodGeneration); var result = PooledStringBuilder.GetInstance(); var builder = result.Builder; builder.Append('<'); if (methodNameOpt != null) { builder.Append(methodNameOpt); // CLR generally allows names with dots, however some APIs like IMetaDataImport // can only return full type names combined with namespaces. // see: http://msdn.microsoft.com/en-us/library/ms230143.aspx (IMetaDataImport::GetTypeDefProps) // When working with such APIs, names with dots become ambiguous since metadata // consumer cannot figure where namespace ends and actual type name starts. // Therefore it is a good practice to avoid type names with dots. // As a replacement use a character not allowed in C# identifier to avoid conflicts. if (kind.IsTypeName()) { builder.Replace('.', DotReplacementInTypeNames); } } builder.Append('>'); builder.Append((char)kind); if (suffix != null || methodOrdinal >= 0 || entityOrdinal >= 0) { builder.Append(SuffixSeparator); builder.Append(suffix); if (methodOrdinal >= 0) { builder.Append(methodOrdinal); if (methodGeneration > 0) { builder.Append(GenerationSeparator); builder.Append(methodGeneration); } } if (entityOrdinal >= 0) { if (methodOrdinal >= 0) { builder.Append(IdSeparator); } builder.Append(entityOrdinal); if (entityGeneration > 0) { builder.Append(GenerationSeparator); builder.Append(entityGeneration); } } } return result.ToStringAndFree(); }
// Parse the generated name. Returns true for names of the form // [CS$]<[middle]>c__[suffix] where [CS$] is included for certain // generated names, where [middle] and [suffix] are optional, // and where c is a single character in [1-9a-z]. internal static bool TryParseGeneratedName( string name, out GeneratedNameKind kind, out int openBracketOffset, out int closeBracketOffset) { openBracketOffset = -1; if (name.StartsWith("CS$<", StringComparison.Ordinal)) { openBracketOffset = 3; } else if (name.StartsWith("<", StringComparison.Ordinal)) { openBracketOffset = 0; } if (openBracketOffset >= 0) { closeBracketOffset = -1; int depth = 1; // Find matching '>'. Since a valid generated name // ends with ">c__[suffix]" we only need to search // up to 3 characters from the end. for (int i = openBracketOffset + 1; i < name.Length - 3; i++) { switch (name[i]) { case '<': depth++; break; case '>': depth--; if (depth == 0) { closeBracketOffset = i; goto found; } break; } } found: if ((closeBracketOffset > openBracketOffset) && (name[closeBracketOffset + 2] == '_') && (name[closeBracketOffset + 3] == '_')) // Not out of range since loop ended early. { int c = name[closeBracketOffset + 1]; if ((c >= '1') && (c <= '9')) // Note '0' is not special. { kind = (GeneratedNameKind)(c - '0'); return(true); } else if ((c >= 'a') && (c <= 'z')) { kind = (GeneratedNameKind)(c - 'a' + 10); return(true); } } } kind = GeneratedNameKind.None; openBracketOffset = -1; closeBracketOffset = -1; return(false); }
public static bool TryParseSourceMethodNameFromGeneratedName(string generatedName, GeneratedNameKind requiredKind, out string methodName) => Impl.TryParseSourceMethodNameFromGeneratedName(generatedName, requiredKind, out methodName);
public static bool TryParseGeneratedName( string name, out GeneratedNameKind kind, out int openBracketOffset, out int closeBracketOffset) => Impl.TryParseGeneratedName(name, out kind, out openBracketOffset, out closeBracketOffset);
internal static bool IsTypeName(this GeneratedNameKind kind) => kind is GeneratedNameKind.LambdaDisplayClass
internal static bool IsTypeName(this GeneratedNameKind kind) => kind is GeneratedNameKind.LambdaDisplayClass or GeneratedNameKind.StateMachineType or GeneratedNameKind.DynamicCallSiteContainerType;