|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using Basic.Reference.Assemblies;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols.Metadata.PE
{
public class LoadingAttributes : CSharpTestBase
{
[Fact]
public void TestAssemblyAttributes()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.MDTestAttributeApplicationLib,
TestReferences.SymbolsTests.Metadata.MDTestAttributeDefLib,
Net40.References.mscorlib
});
var assembly0 = assemblies[0];
var assembly1 = assemblies[1];
//<Assembly:ABoolean(True)>
//<Assembly:AByte(1)>
//<Assembly:AChar("a"c)>
//<Assembly:ADouble(3.1415926)>
//<Assembly:AInt16(16)>
//<Assembly:AInt32(32)>
//<Assembly:AInt64(64)>
//<Assembly:AObject("object")>
//<Assembly:ASingle(3.14159)>
//<Assembly:AString("assembly")>
//<Assembly:AType(GetType(String))>
var aBoolClass = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("ABooleanAttribute") as NamedTypeSymbol;
var aByteClass = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("AByteAttribute") as NamedTypeSymbol;
var aCharClass = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("ACharAttribute") as NamedTypeSymbol;
var aSingleClass = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("ASingleAttribute") as NamedTypeSymbol;
var aDoubleClass = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("ADoubleAttribute") as NamedTypeSymbol;
var aInt16Class = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("AInt16Attribute") as NamedTypeSymbol;
var aInt32Class = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("AInt32Attribute") as NamedTypeSymbol;
var aInt64Class = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("AInt64Attribute") as NamedTypeSymbol;
var aObjectClass = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("AObjectAttribute") as NamedTypeSymbol;
var aStringClass = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("AStringAttribute") as NamedTypeSymbol;
var aTypeClass = assembly1.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>("ATypeAttribute") as NamedTypeSymbol;
// Check attributes on assembly
var aBoolInst = assembly0.GetAttribute(aBoolClass);
aBoolInst.VerifyValue(0, TypedConstantKind.Primitive, true);
var aByteInst = assembly0.GetAttribute(aByteClass);
aByteInst.VerifyValue(0, TypedConstantKind.Primitive, Convert.ToByte(1));
var aCharInst = assembly0.GetAttribute(aCharClass);
aCharInst.VerifyValue(0, TypedConstantKind.Primitive, 'a');
var aSingleInst = assembly0.GetAttribute(aSingleClass);
aSingleInst.VerifyValue(0, TypedConstantKind.Primitive, 3.14159f);
var aDoubleInst = assembly0.GetAttribute(aDoubleClass);
aDoubleInst.VerifyValue(0, TypedConstantKind.Primitive, 3.1415926);
var aInt16Inst = assembly0.GetAttribute(aInt16Class);
aInt16Inst.VerifyValue(0, TypedConstantKind.Primitive, (Int16)16);
var aInt32Inst = assembly0.GetAttribute(aInt32Class);
aInt32Inst.VerifyValue(0, TypedConstantKind.Primitive, 32);
var aInt64Inst = assembly0.GetAttribute(aInt64Class);
aInt64Inst.VerifyValue(0, TypedConstantKind.Primitive, 64L);
var aObjectInst = assembly0.GetAttribute(aObjectClass);
aObjectInst.VerifyValue(0, TypedConstantKind.Primitive, "object");
var aStringInst = assembly0.GetAttribute(aStringClass);
aStringInst.VerifyValue(0, TypedConstantKind.Primitive, "assembly");
var aTypeInst = assembly0.GetAttribute(aTypeClass);
aTypeInst.VerifyValue(0, TypedConstantKind.Type, typeof(string));
}
[Fact]
public void TestModuleAttributes()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.MDTestAttributeApplicationLib,
TestReferences.SymbolsTests.Metadata.MDTestAttributeDefLib,
Net40.References.mscorlib
});
var assembly1 = assemblies[1];
var module0 = assemblies[0].Modules[0];
//<Module:AString("module")>
//<Module:ABoolean(True)>
//<Module:AByte(1)>
//<Module:AChar("a"c)>
//<Module:ADouble(3.1415926)>
//<Module:AInt16(16)>
//<Module:AInt32(32)>
//<Module:AInt64(64)>
//<Module:AObject("object")>
//<Module:ASingle(3.14159)>
//<Module:AType(GetType(String))>
var aBoolClass = assembly1.Modules[0].GlobalNamespace.GetMember("ABooleanAttribute") as NamedTypeSymbol;
var aByteClass = assembly1.Modules[0].GlobalNamespace.GetMember("AByteAttribute") as NamedTypeSymbol;
var aCharClass = assembly1.Modules[0].GlobalNamespace.GetMember("ACharAttribute") as NamedTypeSymbol;
var aSingleClass = assembly1.Modules[0].GlobalNamespace.GetMember("ASingleAttribute") as NamedTypeSymbol;
var aDoubleClass = assembly1.Modules[0].GlobalNamespace.GetMember("ADoubleAttribute") as NamedTypeSymbol;
var aInt16Class = assembly1.Modules[0].GlobalNamespace.GetMember("AInt16Attribute") as NamedTypeSymbol;
var aInt32Class = assembly1.Modules[0].GlobalNamespace.GetMember("AInt32Attribute") as NamedTypeSymbol;
var aInt64Class = assembly1.Modules[0].GlobalNamespace.GetMember("AInt64Attribute") as NamedTypeSymbol;
var aObjectClass = assembly1.Modules[0].GlobalNamespace.GetMember("AObjectAttribute") as NamedTypeSymbol;
var aStringClass = assembly1.Modules[0].GlobalNamespace.GetMember("AStringAttribute") as NamedTypeSymbol;
var aTypeClass = assembly1.Modules[0].GlobalNamespace.GetMember("ATypeAttribute") as NamedTypeSymbol;
// Check attributes on module
var aBoolInst = module0.GetAttribute(aBoolClass);
aBoolInst.VerifyValue(0, TypedConstantKind.Primitive, true);
var aByteInst = module0.GetAttribute(aByteClass);
aByteInst.VerifyValue(0, TypedConstantKind.Primitive, Convert.ToByte(1));
var aCharInst = module0.GetAttribute(aCharClass);
aCharInst.VerifyValue(0, TypedConstantKind.Primitive, 'a');
var aSingleInst = module0.GetAttribute(aSingleClass);
aSingleInst.VerifyValue(0, TypedConstantKind.Primitive, 3.14159f);
var aDoubleInst = module0.GetAttribute(aDoubleClass);
aDoubleInst.VerifyValue(0, TypedConstantKind.Primitive, 3.1415926);
var aInt16Inst = module0.GetAttribute(aInt16Class);
aInt16Inst.VerifyValue(0, TypedConstantKind.Primitive, (Int16)16);
var aInt32Inst = module0.GetAttribute(aInt32Class);
aInt32Inst.VerifyValue(0, TypedConstantKind.Primitive, 32);
var aInt64Inst = module0.GetAttribute(aInt64Class);
aInt64Inst.VerifyValue(0, TypedConstantKind.Primitive, 64L);
var aObjectInst = module0.GetAttribute(aObjectClass);
aObjectInst.VerifyValue(0, TypedConstantKind.Primitive, "object");
var aStringInst = module0.GetAttribute(aStringClass);
aStringInst.VerifyValue(0, TypedConstantKind.Primitive, "module");
var aTypeInst = module0.GetAttribute(aTypeClass);
aTypeInst.VerifyValue(0, TypedConstantKind.Type, typeof(string));
}
[Fact]
public void TestAttributesOnClassAndMembers()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.MDTestAttributeApplicationLib,
TestReferences.SymbolsTests.Metadata.MDTestAttributeDefLib,
Net40.References.mscorlib
});
//<AString("C1")>
//Public Class C1
// <AString("InnerC1")>
// Public Class InnerC1(of t1)
// <AString("InnerC2")>
// Public class InnerC2(of s1, s2)
// End class
// End Class
// <AString("field1")>
// Public field1 As integer
// <AString("Property1")>
// Public Property Property1 As Integer
// <AString("Sub1")>
// Public Sub Sub1(<AString("p1")> p1 As Integer)
// End Sub
// <AString("Function1")>
// Public Function Function1(<AString("p1")> p1 As Integer) As <AString("Integer")> Integer
// Return 0
// End Function
//End Class
var c1 = (NamedTypeSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("C1");
var topLevel = (NamedTypeSymbol)assemblies[1].Modules[0].GlobalNamespace.GetMember("TopLevelClass");
var aNestedAttribute = (NamedTypeSymbol)topLevel.GetMember("ANestedAttribute");
c1.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, "C1");
var innerC1 = c1.GetTypeMembers("InnerC1").Single();
innerC1.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, "InnerC1");
//<TopLevelClass.ANested(True)>
//Public Class InnerC1(of t1)
Assert.Equal(aNestedAttribute, ((CSharpAttributeData)innerC1.GetAttributes(aNestedAttribute).Single()).AttributeClass);
var innerC2 = innerC1.GetTypeMembers("InnerC2").Single();
innerC2.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, "InnerC2");
var field1 = (FieldSymbol)c1.GetMember("field1");
field1.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, "field1");
var property1 = (PropertySymbol)c1.GetMember("Property1");
property1.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, "Property1");
var sub1 = (MethodSymbol)c1.GetMember("Sub1");
sub1.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, "Sub1");
var sub1P1 = sub1.Parameters.Single(p => p.Name == "p1");
sub1P1.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, "p1");
var function1 = (MethodSymbol)c1.GetMember("Function1");
function1.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, "Function1");
}
[Fact]
public void TestNamedAttributes()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.MDTestAttributeApplicationLib,
TestReferences.SymbolsTests.Metadata.MDTestAttributeDefLib,
Net40.References.mscorlib
});
var aBoolClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ABooleanAttribute") as NamedTypeSymbol;
var aByteClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("AByteAttribute") as NamedTypeSymbol;
var aCharClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ACharAttribute") as NamedTypeSymbol;
var aEnumClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("AEnumAttribute") as NamedTypeSymbol;
var aSingleClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ASingleAttribute") as NamedTypeSymbol;
var aDoubleClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ADoubleAttribute") as NamedTypeSymbol;
var aInt16Class = assemblies[1].Modules[0].GlobalNamespace.GetMember("AInt16Attribute") as NamedTypeSymbol;
var aInt32Class = assemblies[1].Modules[0].GlobalNamespace.GetMember("AInt32Attribute") as NamedTypeSymbol;
var aInt64Class = assemblies[1].Modules[0].GlobalNamespace.GetMember("AInt64Attribute") as NamedTypeSymbol;
var aObjectClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("AObjectAttribute") as NamedTypeSymbol;
var aStringClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("AStringAttribute") as NamedTypeSymbol;
var aTypeClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ATypeAttribute") as NamedTypeSymbol;
var c3 = (NamedTypeSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("C3");
//<ABoolean(False, B:=True)> <AByte(0, B:=1)>
//<AChar("a"c, C:="b"c)>
//<AEnum(TestAttributeEnum.No, e := TestAttributeEnum.Yes)
//<AInt16(16, I:=16)> <AInt32(32, I:=32)>
//<AInt64(64, I:=64)> <ASingle(3.1459, S:=3.14159)>
//<ADouble(3.1415926, D:=3.1415926)>
//<AString("hello", S:="world")>
//<AType(GetType(C1), T:=GetType(C3))>
// Check named value on attributes on c3
var a = c3.GetAttribute(aBoolClass);
a.VerifyNamedArgumentValue(0, "B", TypedConstantKind.Primitive, true);
a = c3.GetAttribute(aByteClass);
a.VerifyNamedArgumentValue(0, "B", TypedConstantKind.Primitive, Convert.ToByte(1));
a = c3.GetAttribute(aCharClass);
a.VerifyNamedArgumentValue(0, "C", TypedConstantKind.Primitive, 'b');
a = c3.GetAttribute(aEnumClass);
a.VerifyNamedArgumentValue(0, "E", TypedConstantKind.Enum, 0);
a = c3.GetAttribute(aSingleClass);
a.VerifyNamedArgumentValue(0, "S", TypedConstantKind.Primitive, 3.14159f);
a = c3.GetAttribute(aDoubleClass);
a.VerifyNamedArgumentValue(0, "D", TypedConstantKind.Primitive, 3.1415926);
a = c3.GetAttribute(aInt16Class);
a.VerifyNamedArgumentValue(0, "I", TypedConstantKind.Primitive, (Int16)16);
a = c3.GetAttribute(aInt32Class);
a.VerifyNamedArgumentValue(0, "I", TypedConstantKind.Primitive, 32);
a = c3.GetAttribute(aInt64Class);
a.VerifyNamedArgumentValue(0, "I", TypedConstantKind.Primitive, 64L);
a = c3.GetAttribute(aTypeClass);
a.VerifyNamedArgumentValue(0, "T", TypedConstantKind.Type, c3);
}
[Fact]
public void TestNamedAttributesWithArrays()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.MDTestAttributeApplicationLib,
TestReferences.SymbolsTests.Metadata.MDTestAttributeDefLib,
Net40.References.mscorlib
});
var aBoolClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ABooleanAttribute") as NamedTypeSymbol;
var aByteClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("AByteAttribute") as NamedTypeSymbol;
var aCharClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ACharAttribute") as NamedTypeSymbol;
var aEnumClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("AEnumAttribute") as NamedTypeSymbol;
var aSingleClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ASingleAttribute") as NamedTypeSymbol;
var aDoubleClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ADoubleAttribute") as NamedTypeSymbol;
var aInt16Class = assemblies[1].Modules[0].GlobalNamespace.GetMember("AInt16Attribute") as NamedTypeSymbol;
var aInt32Class = assemblies[1].Modules[0].GlobalNamespace.GetMember("AInt32Attribute") as NamedTypeSymbol;
var aInt64Class = assemblies[1].Modules[0].GlobalNamespace.GetMember("AInt64Attribute") as NamedTypeSymbol;
var aObjectClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("AObjectAttribute") as NamedTypeSymbol;
var aStringClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("AStringAttribute") as NamedTypeSymbol;
var aTypeClass = assemblies[1].Modules[0].GlobalNamespace.GetMember("ATypeAttribute") as NamedTypeSymbol;
var c4 = (NamedTypeSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("C4");
// Check named value on attributes on c4
//<AInt32(0, IA := {1,2})>
var a = c4.GetAttribute(aInt32Class);
a.VerifyNamedArgumentValue(0, "IA", TypedConstantKind.Array, new int[] { 1, 2 });
//<AEnum(TestAttributeEnum.No, ea:={TestAttributeEnum.Yes, TestAttributeEnum.No})>
a = c4.GetAttribute(aEnumClass);
a.VerifyNamedArgumentValue(0, "EA", TypedConstantKind.Array, new int[] { 0, 1 });
//<AString("No", sa:={"Yes", "No"})>
a = c4.GetAttribute(aStringClass);
a.VerifyNamedArgumentValue(0, "SA", TypedConstantKind.Array, new string[] { "Yes", "No" });
//<AObject("No", oa :={CType("Yes", Object), CType("No", Object)})>
a = c4.GetAttribute(aObjectClass);
a.VerifyNamedArgumentValue(0, "OA", TypedConstantKind.Array, new string[] { "Yes", "No" });
//<AType(GetType(C1), ta:={GetType(C1), GetType(C3)})>
var c1 = (TypeSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("C1");
var c3 = (TypeSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("C3");
a = c4.GetAttribute(aTypeClass);
a.VerifyNamedArgumentValue(0, "TA", TypedConstantKind.Array, new TypeSymbol[] { c1, c3 });
}
[Fact]
public void TestAttributesOnReturnTypes()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.MDTestAttributeApplicationLib,
TestReferences.SymbolsTests.Metadata.MDTestAttributeDefLib,
Net40.References.mscorlib
});
//<AString("C1")>
//Public Class C1
// <AString("InnerC1")>
// Public Class InnerC1(of t1)
// <AString("InnerC2")>
// Public class InnerC2(of s1, s2)
// End class
// End Class
// <AString("field1")>
// Public field1 As integer
// <AString("Property1")>
// Public Property Property1 As <AString("Integer")> Integer
// <AString("Sub1")>
// Public Sub Sub1(<AString("p1")> p1 As Integer)
// End Sub
// <AString("Function1")>
// Public Function Function1(<AString("p1")> p1 As Integer) As <AString("Integer")> Integer
// Return 0
// End Function
//End Class
var c1 = (NamedTypeSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMembers("C1").Single();
c1.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, "C1");
var property1 = (PropertySymbol)c1.GetMember("Property1");
var attr = property1.GetMethod.GetReturnTypeAttributes().First();
Assert.Equal("Integer", attr.CommonConstructorArguments.Single().Value);
Assert.Equal(0, property1.SetMethod.GetReturnTypeAttributes().Length);
var function1 = (MethodSymbol)c1.GetMember("Function1");
attr = function1.GetReturnTypeAttributes().First();
Assert.Equal("Integer", attr.CommonConstructorArguments.Single().Value);
var sub1 = (MethodSymbol)c1.GetMember("Sub1");
Assert.Equal(0, sub1.GetReturnTypeAttributes().Length);
}
[Fact]
public void TestAttributesWithTypesAndArrays()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.MDTestAttributeApplicationLib,
TestReferences.SymbolsTests.Metadata.MDTestAttributeDefLib,
Net40.References.mscorlib
});
//Public Class C2(Of T1)
// Custom attributes with generics
// <AType(GetType(List(Of )))>
// Public L1 As List(Of T1)
// <AType(GetType(List(Of C1)))>
// Public L2 As List(Of C1)
// <AType(GetType(List(Of String)))>
// Public L3 As List(Of String)
// <AType(GetType(List(Of KeyValuePair(Of C1, string))))>
// Public L4 As List(Of KeyValuePair(Of C1, string))
// <AType(GetType(List(Of KeyValuePair(Of String, C1.InnerC1(of integer).InnerC2(of string, string)))))>
// Public L5 As List(Of KeyValuePair(Of String, C1.InnerC1(of integer).InnerC2(of string, string)))
var c2 = (NamedTypeSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMembers("C2").Single();
var l = (FieldSymbol)c2.GetMember("L1");
l.GetAttributes().First().VerifyValue(0, TypedConstantKind.Type, "System.Collections.Generic.List<>");
l = (FieldSymbol)c2.GetMember("L2");
l.GetAttributes().First().VerifyValue(0, TypedConstantKind.Type, "System.Collections.Generic.List<C1>");
l = (FieldSymbol)c2.GetMember("L3");
l.GetAttributes().First().VerifyValue(0, TypedConstantKind.Type, "System.Collections.Generic.List<System.String>");
l = (FieldSymbol)c2.GetMember("L4");
l.GetAttributes().First().VerifyValue(0, TypedConstantKind.Type, "System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<C1, System.String>>");
l = (FieldSymbol)c2.GetMember("L5");
l.GetAttributes().First().VerifyValue(0, TypedConstantKind.Type, "System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<System.String, C1.InnerC1<System.Int32>.InnerC2<System.String, System.String>>>");
// Arrays
//<AInt32(New Integer() {1, 2})>
//Public A1 As Type()
//<AType(new Type(){GetType(string)})>
//Public A2 As Object()
//<AObject(new Type(){GetType(string)})>
//Public A3 As Object()
//<AObject(new Object(){GetType(string)})>
//Public A4 As Object()
//<AObject(new Object(){new Object() {GetType(string)}})>
//Public A5 As Object()
//<AObject({1, "two", GetType(string), 3.1415926})>
//Public A6 As Object()
//<AObject({1, new Object(){2,3,4}, 5})>
//Public A7 As Object()
//<AObject(new Integer(){1,2,3})>
//Public A8 As Object()
var stringType = typeof(string);
// DirectCast(assemblies(0).Modules(0), PEModuleSymbol).GetCorLibType(SpecialType.System_string)
var field = c2.GetMember<FieldSymbol>("A1");
var arg = field.GetAttributes().Single();
arg.VerifyValue(0, TypedConstantKind.Array, new int[] { 1, 2 });
field = c2.GetMember<FieldSymbol>("A2");
arg = field.GetAttributes().Single();
arg.VerifyValue(0, TypedConstantKind.Array, new object[] { stringType });
field = c2.GetMember<FieldSymbol>("A3");
arg = field.GetAttributes().Single();
arg.VerifyValue(0, TypedConstantKind.Array, new object[] { stringType });
field = c2.GetMember<FieldSymbol>("A4");
arg = field.GetAttributes().Single();
arg.VerifyValue(0, TypedConstantKind.Array, new object[] { stringType });
field = c2.GetMember<FieldSymbol>("A5");
arg = field.GetAttributes().Single();
arg.VerifyValue(0, TypedConstantKind.Array, new object[] { new object[] { stringType } });
field = c2.GetMember<FieldSymbol>("A6");
var t = field.GetAttributes().First().CommonConstructorArguments.Single().Type;
Assert.Equal("object[]", t.ToDisplayString());
arg = field.GetAttributes().Single();
arg.VerifyValue(0, TypedConstantKind.Array, new object[] { 1, "two", stringType, 3.1415926 });
field = c2.GetMember<FieldSymbol>("A7");
arg = field.GetAttributes().Single();
t = arg.CommonConstructorArguments.Single().Type;
Assert.Equal("object[]", t.ToDisplayString());
arg.VerifyValue(0, TypedConstantKind.Array, new object[] { 1, new object[] { 2, 3, 4 }, 5 });
field = c2.GetMember<FieldSymbol>("A8");
arg = field.GetAttributes().Single();
t = arg.CommonConstructorArguments.Single().Type;
Assert.Equal("int[]", t.ToDisplayString());
arg.VerifyValue(0, TypedConstantKind.Array, new int[] { 1, 2, 3 });
}
public struct AttributeArgs
{
public string[] Pos;
public KeyValuePair<string, string>[] Named;
public AttributeArgs(string[] p, KeyValuePair<string, string>[] n)
{
this.Pos = p;
this.Named = n;
}
}
[Fact]
public void TestDumpAllAttributesTesLib()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.MDTestAttributeDefLib ,
Net40.References.mscorlib
});
var assemblyArgs = new AttributeArgs[] {
new AttributeArgs(new string[]{ "8"} , null),
new AttributeArgs(null, new KeyValuePair<string, string>[]{ new KeyValuePair<string, string>("WrapNonExceptionThrows", "True")} )
};
CheckAttributes(assemblies[0], assemblyArgs);
}
private void CheckAttributes(Symbol s, AttributeArgs[] expected)
{
int i = 0;
foreach (var sa in s.GetAttributes())
{
int j = 0;
foreach (var pa in sa.CommonConstructorArguments)
{
CheckConstructorArg(expected[i].Pos[j], pa.Value.ToString());
j += 1;
}
j = 0;
foreach (var na in sa.CommonNamedArguments)
{
CheckNamedArg(expected[i].Named[j], na);
j += 1;
}
i += 1;
}
}
private static void CheckConstructorArg(string expected, object actual)
{
Assert.Equal(expected, actual.ToString());
}
private static void CheckNamedArg(KeyValuePair<string, string> expected, KeyValuePair<string, TypedConstant> actual)
{
Assert.Equal(expected.Key, actual.Key.ToString());
Assert.Equal(expected.Value, actual.Value.Value.ToString());
}
[Fact]
public void TestInteropAttributesAssembly()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.AttributeInterop01,
Net40.References.mscorlib
});
//[assembly: ImportedFromTypeLib("InteropAttributes")]
//[assembly: PrimaryInteropAssembly(1, 2)]
//[assembly: Guid("1234C65D-1234-447A-B786-64682CBEF136")]
//[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
//[assembly: AutomationProxy(false)]
//[assembly: ClassInterface(ClassInterfaceType.AutoDual)]
//[assembly: ComCompatibleVersion(1, 2, 3, 4)]
//[assembly: ComConversionLoss()]
//[assembly: ComVisible(true)]
//[assembly: TypeLibVersion(1, 0)]
var asm = (AssemblySymbol)assemblies[0];
var attrs = asm.GetAttributes();
// 10 + 2 compiler inserted
Assert.Equal(12, attrs.Length);
foreach (var a in attrs)
{
switch (a.AttributeClass.Name)
{
case "ImportedFromTypeLibAttribute":
a.VerifyValue(0, TypedConstantKind.Primitive, "InteropAttributes");
break;
case "PrimaryInteropAssemblyAttribute":
a.VerifyValue(1, TypedConstantKind.Primitive, 2);
break;
case "GuidAttribute":
a.VerifyValue(0, TypedConstantKind.Primitive, "1234C65D-1234-447A-B786-64682CBEF136");
break;
case "BestFitMappingAttribute":
a.VerifyValue(0, TypedConstantKind.Primitive, false);
a.VerifyNamedArgumentValue(0, "ThrowOnUnmappableChar", TypedConstantKind.Primitive, true);
break;
case "AutomationProxyAttribute":
a.VerifyValue(0, TypedConstantKind.Primitive, false);
break;
case "ClassInterfaceAttribute":
Assert.Equal(1, a.CommonConstructorArguments.Length);
Assert.Equal(0, a.CommonNamedArguments.Length);
// enum is stored as its underneath type
Assert.Equal("System.Runtime.InteropServices.ClassInterfaceType", a.CommonConstructorArguments[0].Type.ToDisplayString());
// ClassInterfaceType.AutoDual
Assert.Equal(2, a.CommonConstructorArguments[0].Value);
break;
case "ComCompatibleVersionAttribute":
a.VerifyValue(2, TypedConstantKind.Primitive, 3);
break;
case "ComConversionLossAttribute":
Assert.Equal(0, a.CommonConstructorArguments.Length);
Assert.Equal(0, a.CommonNamedArguments.Length);
break;
case "ComVisibleAttribute":
a.VerifyValue(0, TypedConstantKind.Primitive, true);
break;
case "TypeLibVersionAttribute":
Assert.Equal(0, a.CommonNamedArguments.Length);
Assert.Equal(2, a.CommonConstructorArguments.Length);
break;
case "CompilationRelaxationsAttribute":
a.VerifyValue(0, TypedConstantKind.Primitive, 8);
break;
case "RuntimeCompatibilityAttribute":
a.VerifyNamedArgumentValue(0, "WrapNonExceptionThrows", TypedConstantKind.Primitive, true);
break;
default:
Assert.Equal("Unexpected Attr", a.AttributeClass.Name);
break;
}
}
}
/// Did not Skip the test - will remove the explicit cast (from IMethodSymbol to MethodSymbol) once this bug is fixed
[Fact]
public void TestInteropAttributesInterface()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.AttributeInterop01,
Net40.References.mscorlib
});
//[ComImport, Guid("ABCDEF5D-2448-447A-B786-64682CBEF123")]
//[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
//[TypeLibImportClass(typeof(object)), TypeLibType(TypeLibTypeFlags.FAggregatable)]
//public interface IFoo
//{
// [AllowReversePInvokeCalls()]
// void DoSomething();
// [ComRegisterFunction()]
// void Register(object o);
// [ComUnregisterFunction()]
// void UnRegister();
// [TypeLibFunc(TypeLibFuncFlags.FDefaultBind)]
// void LibFunc();
//}
var sysNS = (NamespaceSymbol)assemblies[1].GlobalNamespace.GetMember("System");
var runtimeNS = (NamespaceSymbol)sysNS.GetMember("Runtime");
var interopNS = (NamespaceSymbol)runtimeNS.GetMember("InteropServices");
var appNS = (NamespaceSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("Interop");
var igoo = (NamedTypeSymbol)appNS.GetMember("IFoo");
// ComImport is Pseudo attr
Assert.Equal(4, igoo.GetAttributes().Length);
// get attr by NamedTypeSymbol
var attrObj = (NamedTypeSymbol)interopNS.GetTypeMembers("GuidAttribute").Single();
var attrSym = igoo.GetAttribute(attrObj);
//Assert.Null(attrSym.NamedArguments)
attrSym.VerifyValue(0, TypedConstantKind.Primitive, "ABCDEF5D-2448-447A-B786-64682CBEF123");
attrObj = (NamedTypeSymbol)interopNS.GetTypeMembers("InterfaceTypeAttribute").Single();
// use first ctor
var ctor = attrObj.InstanceConstructors.First();
attrSym = igoo.GetAttribute(ctor);
// param in ctor is Int16, but Int32 in MD
Assert.Equal(typeof(Int32), attrSym.CommonConstructorArguments[0].Value.GetType());
Assert.Equal(1, attrSym.CommonConstructorArguments[0].Value);
attrObj = (NamedTypeSymbol)interopNS.GetTypeMembers("TypeLibImportClassAttribute").Single();
var msym = attrObj.InstanceConstructors.First();
attrSym = igoo.GetAttribute(msym);
Assert.Equal("object", ((Symbol)attrSym.CommonConstructorArguments[0].ValueInternal).ToString());
// =============================
var mem = (MethodSymbol)igoo.GetMember("DoSomething");
Assert.Equal(1, mem.GetAttributes().Length);
mem = (MethodSymbol)igoo.GetMember("Register");
Assert.Equal(1, mem.GetAttributes().Length);
mem = (MethodSymbol)igoo.GetMember("UnRegister");
Assert.Equal(1, mem.GetAttributes().Length);
mem = (MethodSymbol)igoo.GetMember("LibFunc");
attrSym = mem.GetAttributes().First();
Assert.Equal(1, attrSym.CommonConstructorArguments.Length);
Assert.Equal(32, attrSym.CommonConstructorArguments[0].Value);
}
[Fact]
public void TestInteropAttributesDelegate()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.AttributeInterop01,
Net40.References.mscorlib
});
// [Serializable, ComVisible(false)]
// [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall, BestFitMapping = true, CharSet = CharSet.Ansi, SetLastError = true, ThrowOnUnmappableChar = true)]
// public delegate void DFoo(char p1, sbyte p2);
var sysNS = (NamespaceSymbol)assemblies[1].GlobalNamespace.GetMember("System");
var runtimeNS = (NamespaceSymbol)sysNS.GetMember("Runtime");
var interopNS = (NamespaceSymbol)runtimeNS.GetMember("InteropServices");
var appNS = (NamespaceSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("Interop");
var dfoo = (NamedTypeSymbol)appNS.GetMember("DFoo");
// Pseudo - Serializable
Assert.Equal(2, dfoo.GetAttributes().Length);
// get attr by NamedTypeSymbol
var attrObj = (NamedTypeSymbol)interopNS.GetTypeMembers("ComVisibleAttribute").Single();
var attrSym = dfoo.GetAttribute(attrObj);
attrSym.VerifyValue(0, TypedConstantKind.Primitive, false);
attrObj = (NamedTypeSymbol)interopNS.GetTypeMembers("UnmanagedFunctionPointerAttribute").Single();
attrSym = dfoo.GetAttribute(attrObj);
//Assert.Equal(1, attrSym.ConstructorArguments.Count)
Assert.Equal(3, attrSym.CommonConstructorArguments[0].Value);
Assert.Equal(4, attrSym.CommonNamedArguments.Length);
Assert.Equal("BestFitMapping", attrSym.CommonNamedArguments[0].Key);
Assert.Equal(true, attrSym.CommonNamedArguments[0].Value.Value);
attrSym.VerifyNamedArgumentValue(0, "BestFitMapping", TypedConstantKind.Primitive, true);
attrSym.VerifyNamedArgumentValue(1, "CharSet", TypedConstantKind.Enum, (int)CharSet.Ansi);
attrSym.VerifyNamedArgumentValue(2, "SetLastError", TypedConstantKind.Primitive, true);
attrSym.VerifyNamedArgumentValue(3, "ThrowOnUnmappableChar", TypedConstantKind.Primitive, true);
}
[Fact]
public void TestInteropAttributesEnum()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.AttributeInterop02,
Net40.References.mscorlib
});
// [Guid("31230DD5-2448-447A-B786-64682CBEFEEE"), Flags]
// public enum MyEnum : sbyte {
// [NonSerialized]zero = 0, one = 1, two = 2, [Obsolete("message", false)]three = 4
// }
var sysNS = (NamespaceSymbol)assemblies[1].GlobalNamespace.GetMember("System");
var runtimeNS = (NamespaceSymbol)sysNS.GetMember("Runtime");
var interopNS = (NamespaceSymbol)runtimeNS.GetMember("InteropServices");
var modattr = assemblies[0].Modules[0].GetAttributes().First();
Assert.Equal("UnverifiableCodeAttribute", modattr.AttributeClass.Name);
var appNS = (NamespaceSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("EventNS");
var myEnum = (NamedTypeSymbol)appNS.GetMember("MyEnum");
//
Assert.Equal(2, myEnum.GetAttributes().Length);
var field = (FieldSymbol)myEnum.GetMember("zero");
// Pseudo: NonSerialized
Assert.Equal(0, field.GetAttributes().Length);
field = (FieldSymbol)myEnum.GetMember("three");
Assert.Equal(1, field.GetAttributes().Length);
var attrSym = field.GetAttributes().First();
Assert.Equal("ObsoleteAttribute", attrSym.AttributeClass.Name);
attrSym.VerifyValue(0, TypedConstantKind.Primitive, "message");
attrSym.VerifyValue(1, TypedConstantKind.Primitive, false);
}
[Fact]
public void TestInteropAttributesMembers()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.AttributeInterop01,
Net40.References.mscorlib
});
//[ComImport, TypeLibType(TypeLibTypeFlags.FAggregatable)]
//[Guid("A88A175D-2448-447A-B786-CCC82CBEF156"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
//[CoClass(typeof(CBar))]
//public interface IBar '{
// [DispId(10)]
// long MarshalAsGetProperty { [return: MarshalAs(UnmanagedType.I8)] get; }
// [DispId(20), IndexerNameAttribute("MyIndex")]
// int this[int idx] { get; set; }
// [DispId(30), PreserveSig]
// int MixedAttrMethod1([In] [MarshalAs(UnmanagedType.U4)] uint v1, [In, Out][MarshalAs(UnmanagedType.I4)] ref int v2);
// [DispId(40), MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
// void IDispatchParameters([MarshalAs(UnmanagedType.IDispatch)] object v1, [Out] [MarshalAs(UnmanagedType.IUnknown)] out object v2);
// [DispId(50), TypeLibFunc(TypeLibFuncFlags.FBindable)]
// void SCodeParameter([MarshalAs(UnmanagedType.Error)] int v1);
// [DispId(60)]
// [return: MarshalAs(UnmanagedType.BStr)]
// string VariantParameters([MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = "YumYum", MarshalType = "IUnknown")] object v1, [In][Out] ref object v2);
// [LCIDConversion(1)]
// void DecimalStringParameter([In] decimal v1, [MarshalAs(UnmanagedType.LPStr)] string v2, [MarshalAs(UnmanagedType.LPWStr)] string v3);
// void CurrencyParameter([In, MarshalAs(UnmanagedType.Currency)] decimal v1);
// // int MixedAttrMethod([In] [ComAliasName(stdole.OLE_COLOR)]uint v1, [In][Out][MarshalAs(UnmanagedType.I4)] ref int v2);
//}
var sysNS = (NamespaceSymbol)assemblies[1].GlobalNamespace.GetMember("System");
var runtimeNS = (NamespaceSymbol)sysNS.GetMember("Runtime");
var interopNS = (NamespaceSymbol)runtimeNS.GetMember("InteropServices");
var reflectNS = (NamespaceSymbol)sysNS.GetMember("Reflection");
var appNS = (NamespaceSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("Interop");
//
var ibar = (NamedTypeSymbol)appNS.GetMember("IBar");
// Pseudo - ComImport ( 4 + 1 -> DefaultMember)
Assert.Equal(5, ibar.GetAttributes().Length);
var atts = ibar.GetAttributes();
// get attr by NamedTypeSymbol
var attrObj = (NamedTypeSymbol)interopNS.GetTypeMembers("CoClassAttribute").Single();
var attrSym = ibar.GetAttribute(attrObj);
var cbar = (NamedTypeSymbol)appNS.GetMember("CBar");
attrSym.VerifyValue(0, TypedConstantKind.Type, cbar);
attrObj = (NamedTypeSymbol)reflectNS.GetTypeMembers("DefaultMemberAttribute").Single();
attrSym = ibar.GetAttribute(attrObj);
attrSym.VerifyValue(0, TypedConstantKind.Primitive, "MyIndex");
//===================
// Members
var mem = (PropertySymbol)ibar.GetMember("MarshalAsGetProperty");
mem.GetAttributes().First().VerifyValue(0, TypedConstantKind.Primitive, 10);
// attribute nor work on return type
//attrSym = mem.Type.GetAttribute(attrObj)
// TODO: index
var mem2 = (MethodSymbol)ibar.GetMember("MixedAttrMethod1");
// Pseudo: PreserveSig
Assert.Equal(1, mem2.GetAttributes().Length);
mem2 = (MethodSymbol)ibar.GetMember("IDispatchParameters");
// Pseudo: MethodImpl
Assert.Equal(1, mem2.GetAttributes().Length);
// ? Pseudo: Out & MarshalAs
//Assert.Equal(2, mem2.Parameters.Count)
//Assert.Equal(2, mem2.Parameters(1).GetAttributes().Count)
//attrSym = mem2.Parameters(1).GetAttributes().First()
//Dim attrSym2 = mem2.Parameters(1).GetAttributes().Last()
//' swap
//If (attrSym2.AttributeClass.Name = "OutAttribute") Then
// Dim tmp = attrSym
// attrSym = attrSym2
// attrSym2 = tmp
//End If
//'attrObj = DirectCast(interopNS.GetTypeMembers("MarshalAsAttribute").Single(), NamedTypeSymbol)
//Assert.Equal("MarshalAsAttribute", attrSym2.AttributeClass.Name) Assert.Equal(1,
//attrSym2.ConstructorArguments(0).Value)
mem2 = (MethodSymbol)ibar.GetMember("DecimalStringParameter");
Assert.Equal(1, mem2.GetAttributes().Length);
attrSym = mem2.GetAttributes().First();
Assert.Equal("LCIDConversionAttribute", attrSym.AttributeClass.Name);
attrSym.VerifyValue(0, TypedConstantKind.Primitive, 1);
}
[Fact]
public void TestAttributesNames()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.AttributeTestLib01,
TestReferences.SymbolsTests.Metadata.AttributeTestDef01,
Net40.References.mscorlib
});
var caNS = (NamespaceSymbol)assemblies[1].GlobalNamespace.GetMember("CustomAttribute");
//
var attrObj1 = (NamedTypeSymbol)caNS.GetTypeMembers("AttrName").Single();
var attrObj2 = (NamedTypeSymbol)caNS.GetTypeMembers("AttrNameAttribute").Single();
//
//[assembly: @AttrName()]
//[assembly: @AttrName(UShortField = 321)]
//[module: AttrNameAttribute(TypeField = typeof(Dictionary<string, int>))]
// 2 + 2 compiler inserted
Assert.Equal(4, assemblies[0].GetAttributes().Length);
var attrSym = assemblies[0].GetAttribute(attrObj1);
Assert.Equal("AttrName", attrSym.AttributeClass.Name);
attrSym = assemblies[0].GetAttributes(attrObj1).Last();
Assert.Equal("AttrName", attrSym.AttributeClass.Name);
attrSym.VerifyNamedArgumentValue(0, "UShortField", TypedConstantKind.Primitive, Convert.ToUInt16(321));
attrSym = assemblies[0].Modules[0].GetAttributes().First();
Assert.Equal("AttrNameAttribute", attrSym.AttributeClass.Name);
attrSym.VerifyNamedArgumentValue(0, "TypeField", TypedConstantKind.Type, typeof(Dictionary<string, int>));
Assert.Equal(2, (attrSym.CommonNamedArguments[0].Value.ValueInternal as NamedTypeSymbol).Arity);
}
[Fact]
public void TestAttributesOnTypeParameters()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
TestReferences.SymbolsTests.Metadata.AttributeTestLib01 ,
TestReferences.SymbolsTests.Metadata.AttributeTestDef01 ,
Net40.References.mscorlib
});
var caNS = (NamespaceSymbol)assemblies[1].GlobalNamespace.GetMember("CustomAttribute");
var attrObj1 = (NamedTypeSymbol)caNS.GetTypeMembers("AllInheritMultipleAttribute").Single();
var attrObj2 = (NamedTypeSymbol)caNS.GetTypeMembers("DerivedAttribute").Single();
var appNS = (NamespaceSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("AttributeUse");
//public interface IFoo<[typevar: AllInheritMultiple(3.1415926)] T, [AllInheritMultiple('q', 2)] V>
//{
// // default: method
// [AllInheritMultiple(p3:1.234f, p2: 1056, p1: "555")]
// // attribute on return, param
// [return: AllInheritMultiple("obj", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static)]
// V Method([param: DerivedAttribute(new sbyte[] {-1, 0, 1}, ObjectField = typeof(IList<>))]T t);
//}
//
var igoo = (NamedTypeSymbol)appNS.GetMember("IFoo");
// attribute on type parameter of interface
var tp = igoo.TypeParameters[0];
var attrSym = tp.GetAttributes().First();
Assert.Equal("AllInheritMultipleAttribute", attrSym.AttributeClass.Name);
// p2 is optional
Assert.Equal(2, attrSym.CommonConstructorArguments.Length);
attrSym.VerifyValue(0, TypedConstantKind.Primitive, 3.1415926);
//object
// NYI: default optional
// Assert.Equal(CByte(1), attrSym.ConstructorArguments[1].Value) 'enum
tp = igoo.TypeParameters[1];
attrSym = tp.GetAttribute(attrObj1);
Assert.Equal(3, attrSym.CommonConstructorArguments.Length);
attrSym.VerifyValue(0, TypedConstantKind.Primitive, 'q');
attrSym.VerifyValue(1, TypedConstantKind.Primitive, Convert.ToByte(2));
// NYI: optional
//Assert.Equal(CSByte(-1), attrSym.ConstructorArguments(2).Value)
// attribute on method
// [AllInheritMultiple(p3:1.234f, p2: 1056, p1: "555")]
var mtd = (MethodSymbol)igoo.GetMember("Method");
Assert.Equal(1, mtd.GetAttributes().Length);
attrSym = mtd.GetAttributes().First();
Assert.Equal(4, attrSym.CommonConstructorArguments.Length);
// p4 is default optional
Assert.Equal("555", attrSym.CommonConstructorArguments[0].Value);
attrSym.VerifyValue(0, TypedConstantKind.Primitive, "555");
// object
// [return: AllInheritMultiple("obj", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static)]
attrSym = mtd.GetReturnTypeAttributes().First();
Assert.Equal(2, attrSym.CommonConstructorArguments.Length);
Assert.Equal("obj", attrSym.CommonConstructorArguments[0].Value);
Assert.Equal(12, attrSym.CommonConstructorArguments[1].Value);
// [param: DerivedAttribute(new sbyte[] {-1, 0, 1}, ObjectField = typeof(IList<>))]
attrSym = mtd.Parameters[0].GetAttribute(attrObj2);
Assert.Equal(1, attrSym.CommonConstructorArguments.Length);
Assert.Equal(1, attrSym.CommonNamedArguments.Length);
Assert.Equal("sbyte[]", attrSym.CommonConstructorArguments[0].Type.ToDisplayString());
attrSym.VerifyValue(0, TypedConstantKind.Array, new sbyte[] { -1, 0, 1 });
Assert.Equal("ObjectField", attrSym.CommonNamedArguments[0].Key);
Assert.Equal("System.Collections.Generic.IList<>", (attrSym.CommonNamedArguments[0].Value.Value as INamedTypeSymbol).ToString());
}
//[AllInheritMultiple(new char[] { '1', '2' }, UIntField = 112233)]
//[type: AllInheritMultiple(new char[] { 'a', '\0', '\t' }, AryField = new ulong[] { 0, 1, ulong.MaxValue })]
//[AllInheritMultiple(null, "", null, "1234", AryProp = new object[2] { new ushort[] { 1 }, new ushort[] { 2, 3, 4 } })]
//public class Foo<[typevar: AllInheritMultiple(null), AllInheritMultiple()] T> : IFoo<T, ushort>
//{
// // named parameters
// [field: AllInheritMultiple(p2: System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Public, p1: -123)]
// [AllInheritMultiple(p1: 111, p2: System.Reflection.BindingFlags.NonPublic)]
// public int ClassField;
// [property: BaseAttribute(-1)]
// public Foo<char> Prop
// {
// // return:
// [AllInheritMultiple(1, 2, 3), AllInheritMultiple(4, 5, 1.1f)]
// get;
// [param: DerivedAttribute(-3)]
// set;
// }
// [AllInheritMultiple(+007, 256)]
// [AllInheritMultiple(-008, 255)]
// [method: DerivedAttribute(typeof(IFoo<short, ushort>), ObjectField = 1)]
// public ushort Method(T t) { return 0; }
// // Explicit NotImpl
// // ushort IFoo<T, ushort>.Method(T t) { return 0; }
//}
[Fact]
public void TestAttributesMultiples()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(mrefs: new[]{
TestReferences.SymbolsTests.Metadata.AttributeTestLib01,
TestReferences.SymbolsTests.Metadata.AttributeTestDef01,
Net40.References.mscorlib
});
var caNS = (NamespaceSymbol)assemblies[1].GlobalNamespace.GetMember("CustomAttribute");
var attrObj1 = (NamedTypeSymbol)caNS.GetTypeMembers("AllInheritMultipleAttribute").Single();
var mctors = attrObj1.Constructors;
//.ToList()
Assert.Equal(5, mctors.Length);
var attrObj2 = (NamedTypeSymbol)caNS.GetTypeMembers("DerivedAttribute").Single();
var appNS = (NamespaceSymbol)assemblies[0].Modules[0].GlobalNamespace.GetMember("AttributeUse");
var foo = (NamedTypeSymbol)appNS.GetMember("Foo");
// Attribute on class Foo
var attrs = (from a in foo.GetAttributes()
where a.AttributeConstructor.Equals((MethodSymbol)mctors[4])
select a).ToList();
Assert.Equal(foo.GetAttributes().Length, attrs.Count());
var count = 0;
foreach (var a in attrs)
{
var pos0 = a.CommonConstructorArguments[0].Values;
Assert.Equal("char[]", a.CommonConstructorArguments[0].Type.ToDisplayString());
// [AllInheritMultiple(null, "", null, "1234", AryProp = new object[2] { new ushort[] { 1 }, new ushort[] { 2, 3, 4 } })]
if (pos0.IsDefaultOrEmpty)
{
count += 1;
Assert.Equal("string[]", a.CommonConstructorArguments[1].Type.ToDisplayString());
Assert.Equal(3, a.CommonConstructorArguments[1].Values.Length);
var na0 = a.CommonNamedArguments[0].Value.Values;
Assert.Equal(2, na0.Length);
// jagged array
Assert.Equal("ushort[]", na0[1].Type.ToDisplayString());
var elem = na0[1].Values;
Assert.Equal("ushort", elem[1].Type.ToDisplayString());
// [AllInheritMultiple(new char[] { '1', '2' }, UIntField = 112233)]
}
else if (pos0.Length == 2)
{
count += 2;
Assert.Equal(1, a.CommonNamedArguments.Length);
// [type: AllInheritMultiple(new char[] { 'a', '\0', '\t' }, AryField = new ulong[] { 0, 1, ulong.MaxValue })]
}
else if (pos0.Length == 3)
{
count += 4;
Assert.Equal("AryField", a.CommonNamedArguments[0].Key);
Assert.Equal("ulong[]", a.CommonNamedArguments[0].Value.Type.ToDisplayString());
var na1 = a.CommonNamedArguments[0].Value.Values;
Assert.Equal("AryField", a.CommonNamedArguments[0].Key);
}
else
{
count += 99;
// should not be here
}
}
// hit 3 attr once each
Assert.Equal(7, count);
// attribute on type parameter of class Foo
var tp = foo.TypeParameters[0];
Assert.Equal(2, tp.GetAttributes().Length);
// field
var fld = (FieldSymbol)foo.GetMember("ClassField");
Assert.Equal(2, fld.GetAttributes().Length);
Assert.Equal(0, fld.GetAttributes().First().CommonNamedArguments.Length);
// property
var prop = (PropertySymbol)foo.GetMember("Prop");
Assert.Equal(1, prop.GetAttributes().Length);
Assert.Equal(-1, prop.GetAttributes().First().CommonConstructorArguments[0].Value);
// get, set
Assert.Equal(3, prop.GetMethod.GetAttributes().Length);
Assert.Equal(1, prop.SetMethod.GetAttributes().Length);
var attrSym = tp.GetAttribute(attrObj1);
// method
var mtd = (MethodSymbol)foo.GetMember("Method");
Assert.Equal(3, mtd.GetAttributes().Length);
attrs = (from a in mtd.GetAttributes()
where a.AttributeConstructor.Equals((MethodSymbol)mctors[2])
select a).ToList(); ;
Assert.Equal(1, attrs.Count);
// [AllInheritMultiple(-008, 255)] ' p3 is optional
attrSym = attrs.First();
Assert.Equal(3, attrSym.CommonConstructorArguments.Length);
Assert.Equal(-8, attrSym.CommonConstructorArguments[0].Value);
// object
Assert.Equal(Convert.ToByte(255), attrSym.CommonConstructorArguments[1].Value);
attrs = (from a in mtd.GetAttributes()
where a.AttributeConstructor.Equals((MethodSymbol)mctors[3])
select a).ToList(); ;
Assert.Equal(1, attrs.Count);
// [AllInheritMultiple(+007, 256)] ' p3, p4 optional
attrSym = attrs.First();
Assert.Equal(4, attrSym.CommonConstructorArguments.Length);
// p4 is default optional
Assert.Equal(7, attrSym.CommonConstructorArguments[0].Value);
// object
Assert.Equal(256L, attrSym.CommonConstructorArguments[1].Value);
// default
Assert.Equal(0.123f, attrSym.CommonConstructorArguments[2].Value);
Assert.Equal(Convert.ToInt16(-2), attrSym.CommonConstructorArguments[3].Value);
// [method: DerivedAttribute(typeof(IFoo<short, ushort>), ObjectField = 1)]
attrs = mtd.GetAttributes(attrObj2).ToList();
Assert.Equal(1, attrs.Count);
attrSym = attrs.First();
Assert.Equal(1, attrSym.CommonConstructorArguments.Length);
Assert.Equal(1, attrSym.CommonNamedArguments.Length);
Assert.Equal("AttributeUse.IFoo<System.Int16, System.UInt16>", (attrSym.CommonConstructorArguments[0].Value as INamedTypeSymbol).ToDisplayString(SymbolDisplayFormat.TestFormat));
Assert.Equal(1, attrSym.CommonNamedArguments[0].Value.Value);
}
#region "Regression"
[Fact]
public void TestAttributesAssemblyVersionValue()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(mrefs: new[] {
NetFramework.SystemCore,
NetFramework.System,
Net40.References.mscorlib
});
var sysNS = (NamespaceSymbol)assemblies[2].GlobalNamespace.GetMember("System");
var refNS = (NamespaceSymbol)sysNS.GetMember("Reflection");
var rtNS = (NamespaceSymbol)sysNS.GetMember("Runtime");
var asmFileAttr = (NamedTypeSymbol)refNS.GetTypeMembers("AssemblyFileVersionAttribute").Single();
var attr1 = assemblies[0].GetAttribute(asmFileAttr);
attr1.VerifyValue(0, TypedConstantKind.Primitive, "4.6.1055.0");
var asmInfoAttr = (NamedTypeSymbol)refNS.GetTypeMembers("AssemblyInformationalVersionAttribute").Single();
attr1 = assemblies[0].GetAttribute(asmInfoAttr);
attr1.VerifyValue(0, TypedConstantKind.Primitive, "4.6.1055.0");
}
[Fact]
public void TestAttributesWithTypeOfInternalClass()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(mrefs: new[]{
NetFramework.SystemCore,
NetFramework.System,
Net40.References.mscorlib
});
var corsysNS = assemblies[2].GlobalNamespace.GetMembers("System").Single() as NamespaceSymbol;
var diagNS = corsysNS.GetMembers("Diagnostics").Single() as NamespaceSymbol;
var sysNS = (NamespaceSymbol)assemblies[0].GlobalNamespace.GetMember("System");
var linqNS = (NamespaceSymbol)sysNS.GetMember("Linq");
var exprNS = (NamespaceSymbol)linqNS.GetMember("Expressions");
var dbgProxyAttr = (NamedTypeSymbol)diagNS.GetTypeMembers("DebuggerTypeProxyAttribute").Single();
// [DebuggerTypeProxy(typeof(Expression.BinaryExpressionProxy))] - internal class as argument to typeof()
// public class BinaryExpression : Expression {... }
var attr1 = exprNS.GetTypeMembers("BinaryExpression").First().GetAttribute(dbgProxyAttr);
Assert.Equal("System.Linq.Expressions.Expression.BinaryExpressionProxy", ((ITypeSymbol)attr1.CommonConstructorArguments[0].Value).ToDisplayString(SymbolDisplayFormat.TestFormat));
// [DebuggerTypeProxy(typeof(Expression.TypeBinaryExpressionProxy))]
// public sealed class TypeBinaryExpression : Expression
attr1 = exprNS.GetTypeMembers("TypeBinaryExpression").First().GetAttribute(dbgProxyAttr);
Assert.Equal("System.Linq.Expressions.Expression.TypeBinaryExpressionProxy", ((ITypeSymbol)attr1.CommonConstructorArguments[0].Value).ToDisplayString(SymbolDisplayFormat.TestFormat));
}
[Fact]
public void TestAttributesStaticInstanceCtors()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
{
Net461.References.SystemConfiguration,
Net461.References.System,
Net461.References.mscorlib
});
var sysNS = (NamespaceSymbol)assemblies[1].GlobalNamespace.GetMember("System");
var secondNS = (NamespaceSymbol)sysNS.GetMember("Configuration");
var type01 = (NamedTypeSymbol)secondNS.GetTypeMembers("SchemeSettingElement").Single();
var mems = type01.GetMembers("GenericUriParserOptions");
var prop = mems.First() as PropertySymbol;
if (prop == null)
{
prop = mems.Last() as PropertySymbol;
}
// [ConfigurationProperty("genericUriParserOptions", DefaultValue=0, IsRequired=true)]
var attr = prop.GetAttributes().First();
Assert.Equal("ConfigurationPropertyAttribute", attr.AttributeClass.Name);
attr.VerifyValue(0, TypedConstantKind.Primitive, "genericUriParserOptions");
attr.VerifyNamedArgumentValue(1, "IsRequired", TypedConstantKind.Primitive, true);
Assert.Equal("DefaultValue", attr.CommonNamedArguments[0].Key);
Assert.Equal(0, attr.CommonNamedArguments[0].Value.Value);
}
[Fact]
public void TestAttributesOverloadedCtors()
{
var assemblies = MetadataTestHelpers.GetSymbolsForReferences(mrefs: new[]
{
NetFramework.SystemData,
NetFramework.SystemCore,
NetFramework.System,
Net40.References.mscorlib
});
var sysNS = (NamespaceSymbol)assemblies[0].GlobalNamespace.GetMember("System");
var secondNS = (NamespaceSymbol)sysNS.GetMember("Data");
var thirdNS = (NamespaceSymbol)secondNS.GetMember("Common");
var resCatAttr = (NamedTypeSymbol)secondNS.GetTypeMembers("ResCategoryAttribute").Single();
var resDesAttr = (NamedTypeSymbol)secondNS.GetTypeMembers("ResDescriptionAttribute").Single();
var level01NS = (NamespaceSymbol)assemblies[2].GlobalNamespace.GetMember("System");
var level02NS = (NamespaceSymbol)level01NS.GetMember("ComponentModel");
var defValAttr = (NamedTypeSymbol)level02NS.GetTypeMembers("DefaultValueAttribute").Single();
var type01 = (NamedTypeSymbol)thirdNS.GetTypeMembers("DataAdapter").Single();
var prop = type01.GetMember("MissingMappingAction") as PropertySymbol;
// [DefaultValue(1), ResCategory("DataCategory_Mapping"), ResDescription("DataAdapter_MissingMappingAction")]
// public MissingMappingAction MissingMappingAction { get; set; }
var attr = prop.GetAttributes(resCatAttr).Single();
attr.VerifyValue(0, TypedConstantKind.Primitive, "DataCategory_Mapping");
attr = prop.GetAttributes(resDesAttr).Single();
attr.VerifyValue(0, TypedConstantKind.Primitive, "DataAdapter_MissingMappingAction");
attr = prop.GetAttributes(defValAttr).Single();
Assert.Equal(1, attr.CommonConstructorArguments.Length);
Assert.Equal(1, attr.CommonConstructorArguments[0].Value);
}
#endregion
[Fact]
[WorkItem(530209, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530209")]
public void Bug530209_DecimalConstant()
{
var compilation = CreateCompilation(
@"
public class Class1
{
public const decimal d1 = -7;
public void M1(decimal d1 = -7)
{}
}");
CompileAndVerify(compilation, symbolValidator: module =>
{
var peModule = (PEModuleSymbol)module;
var class1 = module.GlobalNamespace.GetTypeMember("Class1");
var field = class1.GetMember<PEFieldSymbol>("d1");
var parameter = (PEParameterSymbol)class1.GetMethod("M1").GetParameters().Single();
Assert.Empty(field.GetAttributes());
Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", peModule.GetCustomAttributesForToken(field.Handle).Single().ToString());
Assert.Equal(field.ConstantValue, -7m);
Assert.Empty(parameter.GetAttributes());
Assert.Equal("System.Runtime.CompilerServices.DecimalConstantAttribute(0, 128, 0, 0, 7)", peModule.GetCustomAttributesForToken(parameter.Handle).Single().ToString());
Assert.Equal(parameter.ExplicitDefaultValue, -7m);
});
}
[ConditionalFact(typeof(ClrOnly))]
[WorkItem(530209, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530209")]
[WorkItem(23760, "https://github.com/dotnet/roslyn/issues/23760")] // reason for skipping Mono
public void Bug530209_DecimalConstant_FromIL()
{
var ilSource = @"
.class public auto ansi beforefieldinit Class1
extends[mscorlib] System.Object
{
.field public static initonly valuetype[mscorlib]System.Decimal d1
.custom instance void[mscorlib]
System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32)
= {uint8(0)
uint8(128)
uint32(0)
uint32(0)
uint32(7)}
.custom instance void[mscorlib]
System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
int32,
int32,
int32)
= {uint8(0)
uint8(128)
int32(0)
int32(0)
int32(8)}
.field public static initonly valuetype[mscorlib]System.DateTime d2
.custom instance void[mscorlib] System.Runtime.CompilerServices.DateTimeConstantAttribute::.ctor(int64)
= {int64(634925952000000000)}
.custom instance void[mscorlib]
System.Runtime.CompilerServices.DateTimeConstantAttribute::.ctor(int64)
= {int64(634925952000000001)}
.method private specialname rtspecialname static
void .cctor() cil managed
{
// Code size 33 (0x21)
.maxstack 8
IL_0000: ldc.i4.s -7
IL_0002: conv.i8
IL_0003: newobj instance void [mscorlib]System.Decimal::.ctor(int64)
IL_0008: stsfld valuetype[mscorlib]System.Decimal Class1::d1
IL_000d: ldc.i8 0x8cfb5ca13a30000
IL_0016: newobj instance void [mscorlib]System.DateTime::.ctor(int64)
IL_001b: stsfld valuetype[mscorlib]System.DateTime Class1::d2
IL_0020: ret
} // end of method Class1::.cctor
.method public specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Class1::.ctor
.method public instance void M1([opt] valuetype[mscorlib] System.Decimal d1,
[opt] valuetype[mscorlib] System.DateTime d2) cil managed
{
.param[1]
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32)
= {
uint8(0)
uint8(128)
uint32(0)
uint32(0)
uint32(7)}
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
int32,
int32,
int32)
= {
uint8(0)
uint8(128)
int32(0)
int32(0)
int32(8)}
.param[2]
.custom instance void [mscorlib]System.Runtime.CompilerServices.DateTimeConstantAttribute::.ctor(int64)
= { int64(634925952000000001)}
.custom instance void [mscorlib]System.Runtime.CompilerServices.DateTimeConstantAttribute::.ctor(int64)
= { int64(634925952000000000)}
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method Class1::M1
} // end of class Class1
";
var csSource = @"
class Class2 : Class1
{
}";
CompileAndVerify(CreateCompilationWithILAndMscorlib40(csSource, ilSource), symbolValidator: module =>
{
var class1 = module.GlobalNamespace.GetTypeMember("Class2").BaseType();
Assert.Equal("Class1", class1.ToTestDisplayString());
var field1 = class1.GetField("d1");
Assert.Empty(field1.GetAttributes());
Assert.Equal(field1.ConstantValue, -7m);
var field2 = class1.GetField("d2");
Assert.Equal(2, field2.GetAttributes().Length);
Assert.Null(field2.ConstantValue);
var parameters = class1.GetMethod("M1").GetParameters();
Assert.Equal(2, parameters.Count());
Assert.Empty(parameters.First().GetAttributes());
Assert.Equal(parameters.First().ExplicitDefaultValue, -7m);
Assert.Empty(parameters.Last().GetAttributes());
Assert.Equal(parameters.Last().ExplicitDefaultValue, new DateTime(2013, 1, 1));
});
// Switch order of API calls
CompileAndVerify(CreateCompilationWithILAndMscorlib40(csSource, ilSource), symbolValidator: module =>
{
var class1 = module.GlobalNamespace.GetTypeMember("Class2").BaseType();
Assert.Equal("Class1", class1.ToTestDisplayString());
var field1 = class1.GetField("d1");
Assert.Equal(field1.ConstantValue, -7m);
Assert.Empty(field1.GetAttributes());
var field2 = class1.GetField("d2");
Assert.Null(field2.ConstantValue);
Assert.Equal(2, field2.GetAttributes().Length);
var parameters = class1.GetMethod("M1").GetParameters();
Assert.Equal(2, parameters.Count());
Assert.Equal(parameters.First().ExplicitDefaultValue, -7m);
Assert.Empty(parameters.First().GetAttributes());
Assert.Equal(parameters.Last().ExplicitDefaultValue, new DateTime(2013, 1, 1));
Assert.Empty(parameters.Last().GetAttributes());
});
}
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
[WorkItem(18092, "https://github.com/dotnet/roslyn/issues/18092")]
public void ForwardedSystemType()
{
var ilSource = @"
.class extern forwarder System.Type
{
.assembly extern mscorlib
}
.class public auto ansi beforefieldinit MyAttribute
extends [mscorlib]System.Attribute
{
.method public hidebysig specialname rtspecialname
instance void .ctor(class [mscorlib]System.Type val) cil managed
{
// Code size 9 (0x9)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Attribute::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ret
} // end of method MyAttribute::.ctor
} // end of class MyAttribute
";
var c = CreateCompilationWithILAndMscorlib40(@"
[MyAttribute(typeof(MyAttribute))]
public class Test
{
}", ilSource);
const string expected = "MyAttribute(typeof(MyAttribute))";
Assert.Equal(expected, c.GetTypeByMetadataName("Test").GetAttributes().Single().ToString());
CompileAndVerify(c, symbolValidator: (m) =>
{
Assert.Equal(expected, m.GlobalNamespace.GetTypeMember("Test").GetAttributes().Single().ToString());
});
}
}
}
|