SymbolDocument[] ReadDocuments()
        {
            Debug.Assert(module is not null);
            var docTbl     = pdbMetadata.TablesStream.DocumentTable;
            var docs       = new SymbolDocument[docTbl.Rows];
            var nameReader = new DocumentNameReader(pdbMetadata.BlobStream);
            var custInfos  = ListCache <PdbCustomDebugInfo> .AllocList();

            var gpContext = new GenericParamContext();

            for (int i = 0; i < docs.Length; i++)
            {
                bool b = pdbMetadata.TablesStream.TryReadDocumentRow((uint)i + 1, out var row);
                Debug.Assert(b);
                var url                 = nameReader.ReadDocumentName(row.Name);
                var language            = pdbMetadata.GuidStream.Read(row.Language) ?? Guid.Empty;
                var languageVendor      = GetLanguageVendor(language);
                var documentType        = PdbDocumentConstants.DocumentTypeText;
                var checkSumAlgorithmId = pdbMetadata.GuidStream.Read(row.HashAlgorithm) ?? Guid.Empty;
                var checkSum            = pdbMetadata.BlobStream.ReadNoNull(row.Hash);

                var token = new MDToken(Table.Document, i + 1).ToInt32();
                custInfos.Clear();
                GetCustomDebugInfos(token, gpContext, custInfos);
                var custInfosArray = custInfos.Count == 0 ? Array2.Empty <PdbCustomDebugInfo>() : custInfos.ToArray();

                docs[i] = new SymbolDocumentImpl(url, language, languageVendor, documentType, checkSumAlgorithmId, checkSum, custInfosArray);
            }
            ListCache <PdbCustomDebugInfo> .Free(ref custInfos);

            return(docs);
        }
        SymbolScopeImpl ReadScope(uint methodRid, GenericParamContext gpContext)
        {
            var             scopesRidList   = pdbMetadata.GetLocalScopeRidList(methodRid);
            SymbolScopeImpl rootScopeOrNull = null;

            if (scopesRidList.Count != 0)
            {
                var custInfos = ListCache <PdbCustomDebugInfo> .AllocList();

                var stack = ListCache <SymbolScopeImpl> .AllocList();

                var importScopeBlobReader = new ImportScopeBlobReader(module, pdbMetadata.BlobStream);
                for (int i = 0; i < scopesRidList.Count; i++)
                {
                    var  rid   = scopesRidList[i];
                    int  token = new MDToken(Table.LocalScope, rid).ToInt32();
                    bool b     = pdbMetadata.TablesStream.TryReadLocalScopeRow(rid, out var row);
                    Debug.Assert(b);
                    uint startOffset = row.StartOffset;
                    uint endOffset   = startOffset + row.Length;

                    SymbolScopeImpl parent = null;
                    while (stack.Count > 0)
                    {
                        var nextParent = stack[stack.Count - 1];
                        if (startOffset >= nextParent.StartOffset && endOffset <= nextParent.EndOffset)
                        {
                            parent = nextParent;
                            break;
                        }
                        stack.RemoveAt(stack.Count - 1);
                    }

                    Debug.Assert(parent is not null || rootScopeOrNull is null);
                    custInfos.Clear();
                    GetCustomDebugInfos(token, gpContext, custInfos);
                    var customDebugInfos = custInfos.Count == 0 ? Array2.Empty <PdbCustomDebugInfo>() : custInfos.ToArray();
                    var scope            = new SymbolScopeImpl(this, parent, (int)startOffset, (int)endOffset, customDebugInfos);
                    if (rootScopeOrNull is null)
                    {
                        rootScopeOrNull = scope;
                    }
                    stack.Add(scope);
                    if (parent is not null)
                    {
                        parent.childrenList.Add(scope);
                    }

                    scope.importScope = ReadPdbImportScope(ref importScopeBlobReader, row.ImportScope, gpContext);
                    ReadVariables(scope, gpContext, pdbMetadata.GetLocalVariableRidList(rid));
                    ReadConstants(scope, pdbMetadata.GetLocalConstantRidList(rid));
                }

                ListCache <SymbolScopeImpl> .Free(ref stack);

                ListCache <PdbCustomDebugInfo> .Free(ref custInfos);
            }
            return(rootScopeOrNull ?? new SymbolScopeImpl(this, null, 0, int.MaxValue, Array2.Empty <PdbCustomDebugInfo>()));
        }
        void ReadVariables(SymbolScopeImpl scope, GenericParamContext gpContext, RidList rids)
        {
            if (rids.Count == 0)
            {
                return;
            }
            var table     = pdbMetadata.TablesStream.LocalVariableTable;
            var custInfos = ListCache <PdbCustomDebugInfo> .AllocList();

            for (int i = 0; i < rids.Count; i++)
            {
                var rid   = rids[i];
                int token = new MDToken(Table.LocalVariable, rid).ToInt32();
                custInfos.Clear();
                GetCustomDebugInfos(token, gpContext, custInfos);
                var  customDebugInfos = custInfos.Count == 0 ? Array2.Empty <PdbCustomDebugInfo>() : custInfos.ToArray();
                bool b = pdbMetadata.TablesStream.TryReadLocalVariableRow(rid, out var row);
                Debug.Assert(b);
                var name = pdbMetadata.StringsStream.Read(row.Name);
                scope.localsList.Add(new SymbolVariableImpl(name, ToSymbolVariableAttributes(row.Attributes), row.Index, customDebugInfos));
            }
            ListCache <PdbCustomDebugInfo> .Free(ref custInfos);
        }