// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics; using dnlib.Utils; using dnlib.DotNet.Pdb; namespace dnlib.DotNet.Emit { /// /// A collection of s /// [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(LocalList_CollectionDebugView))] public sealed class LocalList : IListListener, IList { readonly LazyList locals; /// /// Gets the number of locals /// public int Count => locals.Count; /// /// Gets the list of locals /// public IList Locals => locals; /// /// Gets the N'th local /// /// The local index public Local this[int index] { get => locals[index]; set => locals[index] = value; } /// /// Default constructor /// public LocalList() => locals = new LazyList(this); /// /// Constructor /// /// All locals that will be owned by this instance public LocalList(IList locals) { this.locals = new LazyList(this); for (int i = 0; i < locals.Count; i++) this.locals.Add(locals[i]); } /// /// Adds a new local and then returns it /// /// The local that should be added to the list /// The input is always returned public Local Add(Local local) { locals.Add(local); return local; } /// void IListListener.OnLazyAdd(int index, ref Local value) { } /// void IListListener.OnAdd(int index, Local value) => value.Index = index; /// void IListListener.OnRemove(int index, Local value) => value.Index = -1; /// void IListListener.OnResize(int index) { for (int i = index; i < locals.Count_NoLock; i++) locals.Get_NoLock(i).Index = i; } /// void IListListener.OnClear() { foreach (var local in locals.GetEnumerable_NoLock()) local.Index = -1; } /// public int IndexOf(Local item) => locals.IndexOf(item); /// public void Insert(int index, Local item) => locals.Insert(index, item); /// public void RemoveAt(int index) => locals.RemoveAt(index); void ICollection.Add(Local item) => locals.Add(item); /// public void Clear() => locals.Clear(); /// public bool Contains(Local item) => locals.Contains(item); /// public void CopyTo(Local[] array, int arrayIndex) => locals.CopyTo(array, arrayIndex); /// public bool IsReadOnly => false; /// public bool Remove(Local item) => locals.Remove(item); /// public LazyList.Enumerator GetEnumerator() => locals.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => locals.GetEnumerator(); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => ((IEnumerable)this).GetEnumerator(); } /// /// A method local /// public sealed class Local : IVariable { TypeSig typeSig; int index; string name; PdbLocalAttributes attributes; /// /// Gets/sets the type of the local /// public TypeSig Type { get => typeSig; set => typeSig = value; } /// /// Local index /// public int Index { get => index; internal set => index = value; } /// /// Gets the name. This property is obsolete, use to get/set the name stored in the PDB file. /// public string Name { get => name; set => name = value; } /// /// Gets the attributes. This property is obsolete, use to get/set the attributes stored in the PDB file. /// public PdbLocalAttributes Attributes { get => attributes; set => attributes = value; } internal void SetName(string name) => this.name = name; internal void SetAttributes(PdbLocalAttributes attributes) => this.attributes = attributes; /// /// Constructor /// /// The type public Local(TypeSig typeSig) => this.typeSig = typeSig; /// /// Constructor /// /// The type /// Name of local public Local(TypeSig typeSig, string name) { this.typeSig = typeSig; this.name = name; } /// /// Constructor /// /// The type /// Name of local /// Index, should only be used if you don't add it to the locals list public Local(TypeSig typeSig, string name, int index) { this.typeSig = typeSig; this.name = name; this.index = index; } /// public override string ToString() { var n = name; if (string.IsNullOrEmpty(n)) return $"V_{Index}"; return n; } } }