Skip to content

Commit febbd65

Browse files
committed
Add support for custom attributes on generic constraints
1 parent 749710a commit febbd65

File tree

6 files changed

+131
-27
lines changed

6 files changed

+131
-27
lines changed

Mono.Cecil/AssemblyReader.cs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,27 +1993,31 @@ public bool HasGenericConstraints (GenericParameter generic_parameter)
19931993
{
19941994
InitializeGenericConstraints ();
19951995

1996-
Collection<MetadataToken> mapping;
1996+
Collection<Row<uint, MetadataToken>> mapping;
19971997
if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping))
19981998
return false;
19991999

20002000
return mapping.Count > 0;
20012001
}
20022002

2003-
public Collection<TypeReference> ReadGenericConstraints (GenericParameter generic_parameter)
2003+
public GenericParameterConstraintCollection ReadGenericConstraints (GenericParameter generic_parameter)
20042004
{
20052005
InitializeGenericConstraints ();
20062006

2007-
Collection<MetadataToken> mapping;
2007+
Collection<Row<uint, MetadataToken>> mapping;
20082008
if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping))
2009-
return new Collection<TypeReference> ();
2009+
return new GenericParameterConstraintCollection (generic_parameter);
20102010

2011-
var constraints = new Collection<TypeReference> (mapping.Count);
2011+
var constraints = new GenericParameterConstraintCollection (generic_parameter, mapping.Count);
20122012

20132013
this.context = (IGenericContext) generic_parameter.Owner;
20142014

2015-
for (int i = 0; i < mapping.Count; i++)
2016-
constraints.Add (GetTypeDefOrRef (mapping [i]));
2015+
for (int i = 0; i < mapping.Count; i++) {
2016+
constraints.Add (
2017+
new GenericParameterConstraint (
2018+
GetTypeDefOrRef (mapping [i].Col2),
2019+
new MetadataToken (TokenType.GenericParamConstraint, mapping [i].Col1)));
2020+
}
20172021

20182022
metadata.RemoveGenericConstraintMapping (generic_parameter);
20192023

@@ -2027,15 +2031,16 @@ void InitializeGenericConstraints ()
20272031

20282032
var length = MoveTo (Table.GenericParamConstraint);
20292033

2030-
metadata.GenericConstraints = new Dictionary<uint, Collection<MetadataToken>> (length);
2034+
metadata.GenericConstraints = new Dictionary<uint, Collection<Row<uint, MetadataToken>>> (length);
20312035

2032-
for (int i = 1; i <= length; i++)
2036+
for (uint i = 1; i <= length; i++) {
20332037
AddGenericConstraintMapping (
20342038
ReadTableIndex (Table.GenericParam),
2035-
ReadMetadataToken (CodedIndex.TypeDefOrRef));
2039+
new Row<uint, MetadataToken> (i, ReadMetadataToken (CodedIndex.TypeDefOrRef)));
2040+
}
20362041
}
20372042

2038-
void AddGenericConstraintMapping (uint generic_parameter, MetadataToken constraint)
2043+
void AddGenericConstraintMapping (uint generic_parameter, Row<uint, MetadataToken> constraint)
20392044
{
20402045
metadata.SetGenericConstraintMapping (
20412046
generic_parameter,

Mono.Cecil/AssemblyWriter.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,12 +1513,20 @@ void AddConstraints (GenericParameter generic_parameter, GenericParamConstraintT
15131513
{
15141514
var constraints = generic_parameter.Constraints;
15151515

1516-
var rid = generic_parameter.token.RID;
1516+
var gp_rid = generic_parameter.token.RID;
15171517

1518-
for (int i = 0; i < constraints.Count; i++)
1519-
table.AddRow (new GenericParamConstraintRow (
1520-
rid,
1521-
MakeCodedRID (GetTypeToken (constraints [i]), CodedIndex.TypeDefOrRef)));
1518+
for (int i = 0; i < constraints.Count; i++) {
1519+
var constraint = constraints [i];
1520+
1521+
var rid = table.AddRow (new GenericParamConstraintRow (
1522+
gp_rid,
1523+
MakeCodedRID (GetTypeToken (constraint.ConstraintType), CodedIndex.TypeDefOrRef)));
1524+
1525+
constraint.token = new MetadataToken (TokenType.GenericParamConstraint, rid);
1526+
1527+
if (constraint.HasCustomAttributes)
1528+
AddCustomAttributes (constraint);
1529+
}
15221530
}
15231531

15241532
void AddInterfaces (TypeDefinition type)

Mono.Cecil/GenericParameter.cs

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public sealed class GenericParameter : TypeReference, ICustomAttributeProvider {
2323
internal IGenericParameterProvider owner;
2424

2525
ushort attributes;
26-
Collection<TypeReference> constraints;
26+
GenericParameterConstraintCollection constraints;
2727
Collection<CustomAttribute> custom_attributes;
2828

2929
public GenericParameterAttributes Attributes {
@@ -52,15 +52,15 @@ public bool HasConstraints {
5252
}
5353
}
5454

55-
public Collection<TypeReference> Constraints {
55+
public Collection<GenericParameterConstraint> Constraints {
5656
get {
5757
if (constraints != null)
5858
return constraints;
5959

6060
if (HasImage)
6161
return Module.Read (ref constraints, this, (generic_parameter, reader) => reader.ReadGenericConstraints (generic_parameter));
6262

63-
return constraints = new Collection<TypeReference> ();
63+
return constraints = new GenericParameterConstraintCollection (this);
6464
}
6565
}
6666

@@ -265,4 +265,94 @@ protected override void OnRemove (GenericParameter item, int index)
265265
items[i].position = i - 1;
266266
}
267267
}
268+
269+
public sealed class GenericParameterConstraint : ICustomAttributeProvider {
270+
271+
internal GenericParameter generic_parameter;
272+
internal MetadataToken token;
273+
274+
TypeReference constraint_type;
275+
Collection<CustomAttribute> custom_attributes;
276+
277+
public TypeReference ConstraintType {
278+
get { return constraint_type; }
279+
set { constraint_type = value; }
280+
}
281+
282+
public bool HasCustomAttributes {
283+
get {
284+
if (custom_attributes != null)
285+
return custom_attributes.Count > 0;
286+
287+
if (generic_parameter == null)
288+
return false;
289+
290+
return this.GetHasCustomAttributes (generic_parameter.Module);
291+
}
292+
}
293+
294+
public Collection<CustomAttribute> CustomAttributes {
295+
get {
296+
if (generic_parameter == null)
297+
return custom_attributes = new Collection<CustomAttribute> ();
298+
299+
return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, generic_parameter.Module));
300+
}
301+
}
302+
303+
public MetadataToken MetadataToken {
304+
get { return token; }
305+
set { token = value; }
306+
}
307+
308+
internal GenericParameterConstraint (TypeReference constraintType, MetadataToken token)
309+
{
310+
this.constraint_type = constraintType;
311+
this.token = token;
312+
}
313+
314+
public GenericParameterConstraint (TypeReference constraintType)
315+
{
316+
Mixin.CheckType (constraintType, Mixin.Argument.constraintType);
317+
318+
this.constraint_type = constraintType;
319+
this.token = new MetadataToken (TokenType.GenericParamConstraint);
320+
}
321+
}
322+
323+
class GenericParameterConstraintCollection : Collection<GenericParameterConstraint>
324+
{
325+
readonly GenericParameter generic_parameter;
326+
327+
internal GenericParameterConstraintCollection (GenericParameter genericParameter)
328+
{
329+
this.generic_parameter = genericParameter;
330+
}
331+
332+
internal GenericParameterConstraintCollection (GenericParameter genericParameter, int length)
333+
: base (length)
334+
{
335+
this.generic_parameter = genericParameter;
336+
}
337+
338+
protected override void OnAdd (GenericParameterConstraint item, int index)
339+
{
340+
item.generic_parameter = generic_parameter;
341+
}
342+
343+
protected override void OnInsert (GenericParameterConstraint item, int index)
344+
{
345+
item.generic_parameter = generic_parameter;
346+
}
347+
348+
protected override void OnSet (GenericParameterConstraint item, int index)
349+
{
350+
item.generic_parameter = generic_parameter;
351+
}
352+
353+
protected override void OnRemove (GenericParameterConstraint item, int index)
354+
{
355+
item.generic_parameter = null;
356+
}
357+
}
268358
}

Mono.Cecil/MetadataSystem.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ sealed class MetadataSystem {
5656
internal Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> Semantics;
5757
internal Dictionary<uint, Row<PInvokeAttributes, uint, uint>> PInvokes;
5858
internal Dictionary<MetadataToken, Range []> GenericParameters;
59-
internal Dictionary<uint, Collection<MetadataToken>> GenericConstraints;
59+
internal Dictionary<uint, Collection<Row<uint, MetadataToken>>> GenericConstraints;
6060

6161
internal Document [] Documents;
6262
internal Dictionary<uint, Collection<Row<uint, Range, Range, uint, uint, uint>>> LocalScopes;
@@ -149,7 +149,7 @@ public void Clear ()
149149
if (Semantics != null) Semantics = new Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> (capacity: 0);
150150
if (PInvokes != null) PInvokes = new Dictionary<uint, Row<PInvokeAttributes, uint, uint>> (capacity: 0);
151151
if (GenericParameters != null) GenericParameters = new Dictionary<MetadataToken, Range []> (capacity: 0);
152-
if (GenericConstraints != null) GenericConstraints = new Dictionary<uint, Collection<MetadataToken>> (capacity: 0);
152+
if (GenericConstraints != null) GenericConstraints = new Dictionary<uint, Collection<Row<uint, MetadataToken>>> (capacity: 0);
153153

154154
Documents = Empty<Document>.Array;
155155
ImportScopes = Empty<ImportDebugInformation>.Array;
@@ -335,12 +335,12 @@ public void RemoveSecurityDeclarationRange (ISecurityDeclarationProvider owner)
335335
SecurityDeclarations.Remove (owner.MetadataToken);
336336
}
337337

338-
public bool TryGetGenericConstraintMapping (GenericParameter generic_parameter, out Collection<MetadataToken> mapping)
338+
public bool TryGetGenericConstraintMapping (GenericParameter generic_parameter, out Collection<Row<uint, MetadataToken>> mapping)
339339
{
340340
return GenericConstraints.TryGetValue (generic_parameter.token.RID, out mapping);
341341
}
342342

343-
public void SetGenericConstraintMapping (uint gp_rid, Collection<MetadataToken> mapping)
343+
public void SetGenericConstraintMapping (uint gp_rid, Collection<Row<uint, MetadataToken>> mapping)
344344
{
345345
GenericConstraints [gp_rid] = mapping;
346346
}

Mono.Cecil/ModuleDefinition.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,7 @@ public enum Argument {
11621162
returnType,
11631163
propertyType,
11641164
interfaceType,
1165+
constraintType,
11651166
}
11661167

11671168
public static void CheckName (object name)

Test/Mono.Cecil.Tests/TypeTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ public void ConstrainedGenericType ()
9898
Assert.IsTrue (t.HasConstraints);
9999
Assert.AreEqual (2, t.Constraints.Count);
100100

101-
Assert.AreEqual ("Zap", t.Constraints [0].FullName);
102-
Assert.AreEqual ("IZoom", t.Constraints [1].FullName);
101+
Assert.AreEqual ("Zap", t.Constraints [0].ConstraintType.FullName);
102+
Assert.AreEqual ("IZoom", t.Constraints [1].ConstraintType.FullName);
103103
});
104104
}
105105

@@ -132,8 +132,8 @@ public void GenericConstraintOnGenericParameter ()
132132
var t2 = duel.GenericParameters [1];
133133
var t3 = duel.GenericParameters [2];
134134

135-
Assert.AreEqual (t1, t2.Constraints [0]);
136-
Assert.AreEqual (t2, t3.Constraints [0]);
135+
Assert.AreEqual (t1, t2.Constraints [0].ConstraintType);
136+
Assert.AreEqual (t2, t3.Constraints [0].ConstraintType);
137137
});
138138
}
139139

0 commit comments

Comments
 (0)