Permalink
Browse files

Add support for unbound generic parameters

  • Loading branch information...
1 parent 92c7f45 commit ba4a57fb33891aaa5200f91dea890bb5647d3a10 @jbevain committed Jul 24, 2011
@@ -1798,11 +1798,11 @@ public Collection<GenericParameter> ReadGenericParameters (IGenericParameterProv
Range range;
if (!metadata.TryGetGenericParameterRange (provider, out range)
|| !MoveTo (Table.GenericParam, range.Start))
- return new Collection<GenericParameter> ();
+ return new GenericParameterCollection (provider);
metadata.RemoveGenericParameterRange (provider);
- var generic_parameters = new Collection<GenericParameter> ((int) range.Length);
+ var generic_parameters = new GenericParameterCollection (provider, (int) range.Length);
for (uint i = 0; i < range.Length; i++) {
ReadUInt16 (); // index
@@ -2647,9 +2647,10 @@ MetadataToken ReadTypeTokenSignature ()
GenericParameter GetGenericParameter (GenericParameterType type, uint var)
{
var context = reader.context;
+ int index = (int) var;
if (context == null)
- throw new NotSupportedException ();
+ return GetUnboundGenericParameter (type, index);
IGenericParameterProvider provider;
@@ -2664,14 +2665,20 @@ GenericParameter GetGenericParameter (GenericParameterType type, uint var)
throw new NotSupportedException ();
}
- int index = (int) var;
-
if (!context.IsDefinition)
CheckGenericContext (provider, index);
+ if (index >= provider.GenericParameters.Count)
+ return GetUnboundGenericParameter (type, index);
+
return provider.GenericParameters [index];
}
+ static GenericParameter GetUnboundGenericParameter (GenericParameterType type, int index)
+ {
+ return new GenericParameter (index, type);
+ }
+
static void CheckGenericContext (IGenericParameterProvider owner, int index)
{
var owner_parameters = owner.GenericParameters;
@@ -36,7 +36,9 @@ namespace Mono.Cecil {
public sealed class GenericParameter : TypeReference, ICustomAttributeProvider {
- readonly IGenericParameterProvider owner;
+ internal int position;
+ internal GenericParameterType type;
+ internal IGenericParameterProvider owner;
ushort attributes;
Collection<TypeReference> constraints;
@@ -48,12 +50,11 @@ public sealed class GenericParameter : TypeReference, ICustomAttributeProvider {
}
public int Position {
- get {
- if (owner == null)
- return -1;
+ get { return position; }
+ }
- return owner.GenericParameters.IndexOf (this);
- }
+ public GenericParameterType Type {
+ get { return type; }
}
public IGenericParameterProvider Owner {
@@ -99,23 +100,25 @@ public sealed class GenericParameter : TypeReference, ICustomAttributeProvider {
public override IMetadataScope Scope {
get {
- if (owner.GenericParameterType == GenericParameterType.Method)
- return ((MethodReference) owner).DeclaringType.Scope;
+ if (owner == null)
+ return null;
- return ((TypeReference) owner).Scope;
+ return owner.GenericParameterType == GenericParameterType.Method
+ ? ((MethodReference) owner).DeclaringType.Scope
+ : ((TypeReference) owner).Scope;
}
}
public override ModuleDefinition Module {
- get { return ((MemberReference) owner).Module; }
+ get { return owner != null ? owner.Module : null; }
}
public override string Name {
get {
if (!string.IsNullOrEmpty (base.Name))
return base.Name;
- return base.Name = (owner.GenericParameterType == GenericParameterType.Type ? "!" : "!!") + Position;
+ return base.Name = (type == GenericParameterType.Method ? "!!" : "!") + position;
}
}
@@ -185,13 +188,86 @@ public GenericParameter (string name, IGenericParameterProvider owner)
if (owner == null)
throw new ArgumentNullException ();
+ this.position = -1;
this.owner = owner;
- this.etype = owner.GenericParameterType == GenericParameterType.Type ? ElementType.Var : ElementType.MVar;
+ this.type = owner.GenericParameterType;
+ this.etype = ConvertGenericParameterType (this.type);
+ }
+
+ public GenericParameter (int position, GenericParameterType type)
+ : base (string.Empty, string.Empty)
+ {
+ this.position = position;
+ this.type = type;
+ this.etype = ConvertGenericParameterType (type);
+ }
+
+ static ElementType ConvertGenericParameterType (GenericParameterType type)
+ {
+ switch (type) {
+ case GenericParameterType.Type:
+ return ElementType.Var;
+ case GenericParameterType.Method:
+ return ElementType.MVar;
+ }
+
+ throw new ArgumentOutOfRangeException ();
}
public override TypeDefinition Resolve ()
{
return null;
}
}
+
+ sealed class GenericParameterCollection : Collection<GenericParameter> {
+
+ readonly IGenericParameterProvider owner;
+
+ internal GenericParameterCollection (IGenericParameterProvider owner)
+ {
+ this.owner = owner;
+ }
+
+ internal GenericParameterCollection (IGenericParameterProvider owner, int capacity)
+ : base (capacity)
+ {
+ this.owner = owner;
+ }
+
+ protected override void OnAdd (GenericParameter item, int index)
+ {
+ UpdateGenericParameter (item, index);
+ }
+
+ protected override void OnInsert (GenericParameter item, int index)
+ {
+ UpdateGenericParameter (item, index);
+
+ for (int i = index; i < size; i++)
+ items[i].position = i + 1;
+ }
+
+ protected override void OnSet (GenericParameter item, int index)
+ {
+ UpdateGenericParameter (item, index);
+ }
+
+ void UpdateGenericParameter (GenericParameter item, int index)
+ {
+ item.owner = owner;
+ item.position = index;
+ item.type = owner.GenericParameterType;
+ }
+
+ protected override void OnRemove (GenericParameter item, int index)
+ {
+ item.owner = null;
+ item.position = -1;
+ item.type = GenericParameterType.Type;
+
+ for (int i = index + 1; i < size; i++)
+ items[i].position = i - 1;
+ }
+ }
}
@@ -67,7 +67,7 @@ static partial class Mixin {
{
return module.HasImage ()
? module.Read (self, (provider, reader) => reader.ReadGenericParameters (provider))
- : new Collection<GenericParameter> ();
+ : new GenericParameterCollection (self);
}
}
}
@@ -99,7 +99,7 @@ public class MethodReference : MemberReference, IMethodSignature, IGenericParame
if (generic_parameters != null)
return generic_parameters;
- return generic_parameters = new Collection<GenericParameter> ();
+ return generic_parameters = new GenericParameterCollection (this);
}
}
@@ -135,7 +135,7 @@ public class TypeReference : MemberReference, IGenericParameterProvider, IGeneri
if (generic_parameters != null)
return generic_parameters;
- return generic_parameters = new Collection<GenericParameter> ();
+ return generic_parameters = new GenericParameterCollection (this);
}
}

0 comments on commit ba4a57f

Please sign in to comment.