// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Portable { sealed class SymbolScopeImpl : SymbolScope { readonly PortablePdbReader owner; internal SymbolMethod method; readonly SymbolScopeImpl parent; readonly int startOffset; readonly int endOffset; internal readonly List childrenList; internal readonly List localsList; internal PdbImportScope importScope; readonly PdbCustomDebugInfo[] customDebugInfos; public override SymbolMethod Method { get { if (method is not null) return method; var p = parent; if (p is null) return method; for (;;) { if (p.parent is null) return method = p.method; p = p.parent; } } } public override SymbolScope Parent => parent; public override int StartOffset => startOffset; public override int EndOffset => endOffset; public override IList Children => childrenList; public override IList Locals => localsList; public override IList Namespaces => Array2.Empty(); public override IList CustomDebugInfos => customDebugInfos; public override PdbImportScope ImportScope => importScope; public SymbolScopeImpl(PortablePdbReader owner, SymbolScopeImpl parent, int startOffset, int endOffset, PdbCustomDebugInfo[] customDebugInfos) { this.owner = owner; method = null; this.parent = parent; this.startOffset = startOffset; this.endOffset = endOffset; childrenList = new List(); localsList = new List(); this.customDebugInfos = customDebugInfos; } Metadata constantsMetadata; RidList constantRidList; internal void SetConstants(Metadata metadata, RidList rids) { constantsMetadata = metadata; constantRidList = rids; } public override IList GetConstants(ModuleDef module, GenericParamContext gpContext) { if (constantRidList.Count == 0) return Array2.Empty(); Debug.Assert(constantsMetadata is not null); var res = new PdbConstant[constantRidList.Count]; int w = 0; for (int i = 0; i < res.Length; i++) { uint rid = constantRidList[i]; bool b = constantsMetadata.TablesStream.TryReadLocalConstantRow(rid, out var row); Debug.Assert(b); var name = constantsMetadata.StringsStream.Read(row.Name); if (!constantsMetadata.BlobStream.TryCreateReader(row.Signature, out var reader)) continue; var localConstantSigBlobReader = new LocalConstantSigBlobReader(module, ref reader, gpContext); b = localConstantSigBlobReader.Read(out var type, out object value); Debug.Assert(b); if (b) { var pdbConstant = new PdbConstant(name, type, value); int token = new MDToken(Table.LocalConstant, rid).ToInt32(); owner.GetCustomDebugInfos(token, gpContext, pdbConstant.CustomDebugInfos); res[w++] = pdbConstant; } } if (res.Length != w) Array.Resize(ref res, w); return res; } } }