// 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;
}
}
}