Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/cecil.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjbevain <jbevain@gmail.com>2011-07-24 17:03:45 +0400
committerjbevain <jbevain@gmail.com>2011-07-24 17:03:45 +0400
commitba4a57fb33891aaa5200f91dea890bb5647d3a10 (patch)
tree881a529c85fa0ec62651b5991011f82bd88ec5e9 /Mono.Cecil
parent92c7f45243a945886863dc8bfd24d6e52cde1e54 (diff)
Add support for unbound generic parameters
Diffstat (limited to 'Mono.Cecil')
-rw-r--r--Mono.Cecil/AssemblyReader.cs17
-rw-r--r--Mono.Cecil/GenericParameter.cs100
-rw-r--r--Mono.Cecil/IGenericParameterProvider.cs2
-rw-r--r--Mono.Cecil/MethodReference.cs2
-rw-r--r--Mono.Cecil/TypeReference.cs2
5 files changed, 103 insertions, 20 deletions
diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs
index d7007e1..f412d74 100644
--- a/Mono.Cecil/AssemblyReader.cs
+++ b/Mono.Cecil/AssemblyReader.cs
@@ -1798,11 +1798,11 @@ namespace Mono.Cecil {
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 @@ namespace Mono.Cecil {
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 @@ namespace Mono.Cecil {
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;
diff --git a/Mono.Cecil/GenericParameter.cs b/Mono.Cecil/GenericParameter.cs
index 2d0c190..664f00a 100644
--- a/Mono.Cecil/GenericParameter.cs
+++ b/Mono.Cecil/GenericParameter.cs
@@ -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 @@ namespace Mono.Cecil {
}
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,15 +100,17 @@ namespace Mono.Cecil {
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 {
@@ -115,7 +118,7 @@ namespace Mono.Cecil {
if (!string.IsNullOrEmpty (base.Name))
return base.Name;
- return base.Name = (owner.GenericParameterType == GenericParameterType.Type ? "!" : "!!") + Position;
+ return base.Name = (type == GenericParameterType.Method ? "!!" : "!") + position;
}
}
@@ -185,8 +188,30 @@ namespace Mono.Cecil {
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 ()
@@ -194,4 +219,55 @@ namespace Mono.Cecil {
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;
+ }
+ }
}
diff --git a/Mono.Cecil/IGenericParameterProvider.cs b/Mono.Cecil/IGenericParameterProvider.cs
index 7f499bb..d41b7f6 100644
--- a/Mono.Cecil/IGenericParameterProvider.cs
+++ b/Mono.Cecil/IGenericParameterProvider.cs
@@ -67,7 +67,7 @@ namespace Mono.Cecil {
{
return module.HasImage ()
? module.Read (self, (provider, reader) => reader.ReadGenericParameters (provider))
- : new Collection<GenericParameter> ();
+ : new GenericParameterCollection (self);
}
}
}
diff --git a/Mono.Cecil/MethodReference.cs b/Mono.Cecil/MethodReference.cs
index 21de336..0adab45 100644
--- a/Mono.Cecil/MethodReference.cs
+++ b/Mono.Cecil/MethodReference.cs
@@ -99,7 +99,7 @@ namespace Mono.Cecil {
if (generic_parameters != null)
return generic_parameters;
- return generic_parameters = new Collection<GenericParameter> ();
+ return generic_parameters = new GenericParameterCollection (this);
}
}
diff --git a/Mono.Cecil/TypeReference.cs b/Mono.Cecil/TypeReference.cs
index f486124..757c83a 100644
--- a/Mono.Cecil/TypeReference.cs
+++ b/Mono.Cecil/TypeReference.cs
@@ -135,7 +135,7 @@ namespace Mono.Cecil {
if (generic_parameters != null)
return generic_parameters;
- return generic_parameters = new Collection<GenericParameter> ();
+ return generic_parameters = new GenericParameterCollection (this);
}
}