예제 #1
0
        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);
        }
예제 #2
0
        // 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);
        }
예제 #3
0
        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());
        }
예제 #4
0
 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;
        }
예제 #6
0
        internal static bool IsTypeName(this GeneratedNameKind kind)
        {
            switch (kind)
            {
            case GeneratedNameKind.LambdaDisplayClass:
            case GeneratedNameKind.StateMachineType:
            case GeneratedNameKind.DynamicCallSiteContainerType:
                return(true);

            default:
                return(false);
            }
        }
예제 #7
0
        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());
        }
예제 #8
0
        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;
        }
예제 #9
0
        // 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;
        }
예제 #10
0
        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();
        }
예제 #11
0
        // 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);
        }
예제 #12
0
 public static bool TryParseSourceMethodNameFromGeneratedName(string generatedName, GeneratedNameKind requiredKind, out string methodName) => Impl.TryParseSourceMethodNameFromGeneratedName(generatedName, requiredKind, out methodName);
예제 #13
0
 public static bool TryParseGeneratedName(
     string name,
     out GeneratedNameKind kind,
     out int openBracketOffset,
     out int closeBracketOffset) => Impl.TryParseGeneratedName(name, out kind, out openBracketOffset, out closeBracketOffset);
예제 #14
0
 internal static bool IsTypeName(this GeneratedNameKind kind)
 => kind is GeneratedNameKind.LambdaDisplayClass
예제 #15
0
 internal static bool IsTypeName(this GeneratedNameKind kind)
 => kind is GeneratedNameKind.LambdaDisplayClass or GeneratedNameKind.StateMachineType or GeneratedNameKind.DynamicCallSiteContainerType;