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:
authorMarek Safar <marek.safar@gmail.com>2022-02-22 15:47:18 +0300
committerMarek Safar <marek.safar@gmail.com>2022-02-22 15:47:18 +0300
commitfcbb234133cf1ffba99373b46b5f21edb3bc3787 (patch)
tree84bf6642559bbe1564ab01d02bfa9300aa5bc2bd
parent0780d4e15ef42b56a4e40dafac0d5486f09ce005 (diff)
parentf7b64f756021c546d303e55413f10967728ad8ba (diff)
Merge remote-tracking branch 'upstream/master'
-rw-r--r--Mono.Cecil/AssemblyReader.cs6
-rw-r--r--Mono.Cecil/AssemblyWriter.cs12
-rw-r--r--Test/Mono.Cecil.Tests/CompilationService.cs2
-rw-r--r--Test/Mono.Cecil.Tests/CustomAttributesTests.cs101
-rw-r--r--Test/Resources/cs/CustomAttributes.cs37
5 files changed, 156 insertions, 2 deletions
diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs
index b66c162..ee2c229 100644
--- a/Mono.Cecil/AssemblyReader.cs
+++ b/Mono.Cecil/AssemblyReader.cs
@@ -3598,6 +3598,12 @@ namespace Mono.Cecil {
object ReadCustomAttributeElementValue (TypeReference type)
{
var etype = type.etype;
+ if (etype == ElementType.GenericInst) {
+ // The only way to get a generic here is that it's an enum on a generic type
+ // so for enum we don't need to know the generic arguments (they have no effect)
+ type = type.GetElementType ();
+ etype = type.etype;
+ }
switch (etype) {
case ElementType.String:
diff --git a/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/AssemblyWriter.cs
index 5799f07..3843e85 100644
--- a/Mono.Cecil/AssemblyWriter.cs
+++ b/Mono.Cecil/AssemblyWriter.cs
@@ -2999,6 +2999,10 @@ namespace Mono.Cecil {
else
WriteCustomAttributeEnumValue (type, value);
break;
+ case ElementType.GenericInst:
+ // Generic instantiation can only happen for an enum (no other generic like types can appear in attribute value)
+ WriteCustomAttributeEnumValue (type, value);
+ break;
default:
WritePrimitiveValue (value);
break;
@@ -3105,6 +3109,14 @@ namespace Mono.Cecil {
WriteTypeReference (type);
}
return;
+ case ElementType.GenericInst:
+ // Generic instantiation can really only happen if it's an enum type since no other
+ // types are allowed in the attribute value.
+ // Enums are special in attribute data, they're encoded as ElementType.Enum followed by a typeref
+ // followed by the value.
+ WriteElementType (ElementType.Enum);
+ WriteTypeReference (type);
+ return;
default:
WriteElementType (etype);
return;
diff --git a/Test/Mono.Cecil.Tests/CompilationService.cs b/Test/Mono.Cecil.Tests/CompilationService.cs
index 0c9d35c..f7ecc4c 100644
--- a/Test/Mono.Cecil.Tests/CompilationService.cs
+++ b/Test/Mono.Cecil.Tests/CompilationService.cs
@@ -186,7 +186,7 @@ namespace Mono.Cecil.Tests {
case ".cs":
return CS.CSharpCompilation.Create (
assemblyName,
- new [] { CS.SyntaxFactory.ParseSyntaxTree (source) },
+ new [] { CS.SyntaxFactory.ParseSyntaxTree (source, new CS.CSharpParseOptions (preprocessorSymbols: new string [] { "NET_CORE" })) },
references,
new CS.CSharpCompilationOptions (OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Release));
default:
diff --git a/Test/Mono.Cecil.Tests/CustomAttributesTests.cs b/Test/Mono.Cecil.Tests/CustomAttributesTests.cs
index 0c8524a..a406c41 100644
--- a/Test/Mono.Cecil.Tests/CustomAttributesTests.cs
+++ b/Test/Mono.Cecil.Tests/CustomAttributesTests.cs
@@ -546,6 +546,105 @@ namespace Mono.Cecil.Tests {
module.Dispose ();
}
+#if NET_CORE
+ [Test]
+ public void BoxedEnumOnGenericArgumentOnType ()
+ {
+ TestCSharp ("CustomAttributes.cs", module => {
+ var valueEnumGenericType = module.GetType ("BoxedValueEnumOnGenericType");
+
+ Assert.IsTrue (valueEnumGenericType.HasCustomAttributes);
+ Assert.AreEqual (1, valueEnumGenericType.CustomAttributes.Count);
+
+ var attribute = valueEnumGenericType.CustomAttributes [0];
+ Assert.AreEqual ("System.Void FooAttribute::.ctor(System.Object,System.Object)",
+ attribute.Constructor.FullName);
+
+ Assert.IsTrue (attribute.HasConstructorArguments);
+ Assert.AreEqual (2, attribute.ConstructorArguments.Count);
+
+ AssertCustomAttributeArgument ("(Object:(GenericWithEnum`1/OnGenericNumber<System.Int32>:0))", attribute.ConstructorArguments [0]);
+ AssertCustomAttributeArgument ("(Object:(GenericWithEnum`1/OnGenericNumber<System.String>:1))", attribute.ConstructorArguments [1]);
+ });
+ }
+
+ [Test]
+ public void EnumOnGenericArgumentOnType ()
+ {
+ TestCSharp ("CustomAttributes.cs", module => {
+ var valueEnumGenericType = module.GetType ("ValueEnumOnGenericType");
+
+ Assert.IsTrue (valueEnumGenericType.HasCustomAttributes);
+ Assert.AreEqual (1, valueEnumGenericType.CustomAttributes.Count);
+
+ var attribute = valueEnumGenericType.CustomAttributes [0];
+ Assert.AreEqual ("System.Void FooAttribute::.ctor(GenericWithEnum`1/OnGenericNumber<Bingo>)",
+ attribute.Constructor.FullName);
+
+ Assert.IsTrue (attribute.HasConstructorArguments);
+ Assert.AreEqual (1, attribute.ConstructorArguments.Count);
+
+ AssertCustomAttributeArgument ("(GenericWithEnum`1/OnGenericNumber<Bingo>:1)", attribute.ConstructorArguments [0]);
+ });
+ }
+
+ [Test]
+ public void EnumOnGenericFieldOnType ()
+ {
+ TestCSharp ("CustomAttributes.cs", module => {
+ var valueEnumGenericType = module.GetType ("FieldEnumOnGenericType");
+
+ Assert.IsTrue (valueEnumGenericType.HasCustomAttributes);
+ Assert.AreEqual (1, valueEnumGenericType.CustomAttributes.Count);
+
+ var attribute = valueEnumGenericType.CustomAttributes [0];
+ var argument = attribute.Fields.Where (a => a.Name == "NumberEnumField").First ().Argument;
+
+ AssertCustomAttributeArgument ("(GenericWithEnum`1/OnGenericNumber<System.Byte>:0)", argument);
+ });
+ }
+
+ [Test]
+ public void EnumOnGenericPropertyOnType ()
+ {
+ TestCSharp ("CustomAttributes.cs", module => {
+ var valueEnumGenericType = module.GetType ("PropertyEnumOnGenericType");
+
+ Assert.IsTrue (valueEnumGenericType.HasCustomAttributes);
+ Assert.AreEqual (1, valueEnumGenericType.CustomAttributes.Count);
+
+ var attribute = valueEnumGenericType.CustomAttributes [0];
+ var argument = attribute.Properties.Where (a => a.Name == "NumberEnumProperty").First ().Argument;
+
+ AssertCustomAttributeArgument ("(GenericWithEnum`1/OnGenericNumber<System.Byte>:1)", argument);
+ });
+ }
+
+ [Test]
+ public void EnumDeclaredInGenericTypeArray ()
+ {
+ TestCSharp ("CustomAttributes.cs", module => {
+ var type = module.GetType ("WithAttributeUsingNestedEnumArray");
+ var attributes = type.CustomAttributes;
+ Assert.AreEqual (1, attributes.Count);
+ var attribute = attributes [0];
+ Assert.AreEqual (1, attribute.Fields.Count);
+ var arg = attribute.Fields [0].Argument;
+ Assert.AreEqual ("System.Object", arg.Type.FullName);
+
+ var argumentValue = (CustomAttributeArgument)arg.Value;
+ Assert.AreEqual ("GenericWithEnum`1/OnGenericNumber<System.String>[]", argumentValue.Type.FullName);
+ var argumentValues = (CustomAttributeArgument [])argumentValue.Value;
+
+ Assert.AreEqual ("GenericWithEnum`1/OnGenericNumber<System.String>", argumentValues [0].Type.FullName);
+ Assert.AreEqual (0, (int)argumentValues [0].Value);
+
+ Assert.AreEqual ("GenericWithEnum`1/OnGenericNumber<System.String>", argumentValues [1].Type.FullName);
+ Assert.AreEqual (1, (int)argumentValues [1].Value);
+ });
+ }
+#endif
+
static void AssertCustomAttribute (string expected, CustomAttribute attribute)
{
Assert.AreEqual (expected, PrettyPrint (attribute));
@@ -643,7 +742,7 @@ namespace Mono.Cecil.Tests {
if (type.IsArray) {
ArrayType array = (ArrayType) type;
signature.AppendFormat ("{0}[]", array.ElementType.etype.ToString ());
- } else if (type.etype == ElementType.None) {
+ } else if (type.etype == ElementType.None || type.etype == ElementType.GenericInst) {
signature.Append (type.FullName);
} else
signature.Append (type.etype.ToString ());
diff --git a/Test/Resources/cs/CustomAttributes.cs b/Test/Resources/cs/CustomAttributes.cs
index 11939ed..530d654 100644
--- a/Test/Resources/cs/CustomAttributes.cs
+++ b/Test/Resources/cs/CustomAttributes.cs
@@ -11,6 +11,14 @@ enum Bingo : short {
Binga = 4,
}
+class GenericWithEnum<T> {
+ public enum OnGenericNumber
+ {
+ One,
+ Two
+ }
+}
+
/*
in System.Security.AccessControl
@@ -70,6 +78,10 @@ class FooAttribute : Attribute {
{
}
+ public FooAttribute (GenericWithEnum<Bingo>.OnGenericNumber number)
+ {
+ }
+
public int Bang { get { return 0; } set {} }
public string Fiou { get { return "fiou"; } set {} }
@@ -77,6 +89,9 @@ class FooAttribute : Attribute {
public string [] PanPan;
public Type Chose;
+
+ public GenericWithEnum<byte>.OnGenericNumber NumberEnumField;
+ public GenericWithEnum<byte>.OnGenericNumber NumberEnumProperty { get; set; }
}
[Foo ("bar")]
@@ -160,3 +175,25 @@ class Parent {
[Foo ("Foo\0Bar\0")]
class NullCharInString {
}
+
+#if NET_CORE
+[Foo (GenericWithEnum<int>.OnGenericNumber.One, GenericWithEnum<string>.OnGenericNumber.Two)]
+class BoxedValueEnumOnGenericType {
+}
+
+[Foo (GenericWithEnum<Bingo>.OnGenericNumber.Two)]
+class ValueEnumOnGenericType {
+}
+
+[Foo (NumberEnumField = GenericWithEnum<byte>.OnGenericNumber.One)]
+class FieldEnumOnGenericType {
+}
+
+[Foo(NumberEnumProperty = GenericWithEnum<byte>.OnGenericNumber.Two)]
+class PropertyEnumOnGenericType {
+}
+
+[Foo(Pan = new[] { GenericWithEnum<string>.OnGenericNumber.One, GenericWithEnum<string>.OnGenericNumber.Two })]
+class WithAttributeUsingNestedEnumArray {
+}
+#endif \ No newline at end of file