diff options
author | jbevain <jbevain@gmail.com> | 2011-07-24 17:03:45 +0400 |
---|---|---|
committer | jbevain <jbevain@gmail.com> | 2011-07-24 17:03:45 +0400 |
commit | ba4a57fb33891aaa5200f91dea890bb5647d3a10 (patch) | |
tree | 881a529c85fa0ec62651b5991011f82bd88ec5e9 /Mono.Cecil | |
parent | 92c7f45243a945886863dc8bfd24d6e52cde1e54 (diff) |
Add support for unbound generic parameters
Diffstat (limited to 'Mono.Cecil')
-rw-r--r-- | Mono.Cecil/AssemblyReader.cs | 17 | ||||
-rw-r--r-- | Mono.Cecil/GenericParameter.cs | 100 | ||||
-rw-r--r-- | Mono.Cecil/IGenericParameterProvider.cs | 2 | ||||
-rw-r--r-- | Mono.Cecil/MethodReference.cs | 2 | ||||
-rw-r--r-- | Mono.Cecil/TypeReference.cs | 2 |
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); } } |