Imported Upstream version 5.18.0.142

Former-commit-id: 7467d4b717762eeaf652d77f1486dd11ffb1ff1f
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-09 08:20:59 +00:00
parent e52655b4dc
commit 0abdbe5a7d
1547 changed files with 93792 additions and 47893 deletions

View File

@@ -295,13 +295,219 @@ namespace System
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern CustomAttributeData [] GetCustomAttributesDataInternal (ICustomAttributeProvider obj);
internal static IList<CustomAttributeData> GetCustomAttributesData (ICustomAttributeProvider obj)
internal static IList<CustomAttributeData> GetCustomAttributesData (ICustomAttributeProvider obj, bool inherit = false)
{
if (obj == null)
throw new ArgumentNullException ("obj");
throw new ArgumentNullException (nameof (obj));
CustomAttributeData [] attrs = GetCustomAttributesDataInternal (obj);
return Array.AsReadOnly<CustomAttributeData> (attrs);
if (!inherit)
return GetCustomAttributesDataBase (obj, null, false);
return GetCustomAttributesData (obj, typeof (MonoCustomAttrs), inherit);
}
internal static IList<CustomAttributeData> GetCustomAttributesData (ICustomAttributeProvider obj, Type attributeType, bool inherit)
{
if (obj == null)
throw new ArgumentNullException (nameof (obj));
if (attributeType == null)
throw new ArgumentNullException (nameof (attributeType));
if (attributeType == typeof (MonoCustomAttrs))
attributeType = null;
const string Message = "Invalid custom attribute data format";
IList<CustomAttributeData> r;
IList<CustomAttributeData> res = GetCustomAttributesDataBase (obj, attributeType, false);
// shortcut
if (!inherit && res.Count == 1) {
if (res [0] == null)
throw new CustomAttributeFormatException (Message);
if (attributeType != null) {
if (attributeType.IsAssignableFrom (res [0].AttributeType))
r = new CustomAttributeData[] { res [0] };
else
r = Array.Empty<CustomAttributeData> ();
} else {
r = new CustomAttributeData[] { res [0] };
}
return r;
}
if (inherit && GetBase (obj) == null)
inherit = false;
// if AttributeType is sealed, and Inherited is set to false, then
// there's no use in scanning base types
if ((attributeType != null && attributeType.IsSealed) && inherit) {
var usageAttribute = RetrieveAttributeUsage (attributeType);
if (!usageAttribute.Inherited)
inherit = false;
}
var initialSize = Math.Max (res.Count, 16);
List<CustomAttributeData> a = null;
ICustomAttributeProvider btype = obj;
/* Non-inherit case */
if (!inherit) {
if (attributeType == null) {
foreach (CustomAttributeData attrData in res) {
if (attrData == null)
throw new CustomAttributeFormatException (Message);
}
var result = new CustomAttributeData [res.Count];
res.CopyTo (result, 0);
return result;
} else {
a = new List<CustomAttributeData> (initialSize);
foreach (CustomAttributeData attrData in res) {
if (attrData == null)
throw new CustomAttributeFormatException (Message);
if (!attributeType.IsAssignableFrom (attrData.AttributeType))
continue;
a.Add (attrData);
}
return a.ToArray ();
}
}
/* Inherit case */
var attributeInfos = new Dictionary<Type, AttributeInfo> (initialSize);
int inheritanceLevel = 0;
a = new List<CustomAttributeData> (initialSize);
do {
foreach (CustomAttributeData attrData in res) {
AttributeUsageAttribute usage;
if (attrData == null)
throw new CustomAttributeFormatException (Message);
Type attrType = attrData.AttributeType;
if (attributeType != null) {
if (!attributeType.IsAssignableFrom (attrType))
continue;
}
AttributeInfo firstAttribute;
if (attributeInfos.TryGetValue (attrType, out firstAttribute))
usage = firstAttribute.Usage;
else
usage = RetrieveAttributeUsage (attrType);
// The same as for CustomAttributes.
//
// Only add attribute to the list of attributes if
// - we are on the first inheritance level, or the attribute can be inherited anyway
// and (
// - multiple attributes of the type are allowed
// or (
// - this is the first attribute we've discovered
// or
// - the attribute is on same inheritance level than the first
// attribute that was discovered for this attribute type ))
if ((inheritanceLevel == 0 || usage.Inherited) && (usage.AllowMultiple ||
(firstAttribute == null || (firstAttribute != null
&& firstAttribute.InheritanceLevel == inheritanceLevel))))
a.Add(attrData);
if (firstAttribute == null)
attributeInfos.Add (attrType, new AttributeInfo (usage, inheritanceLevel));
}
if ((btype = GetBase (btype)) != null) {
inheritanceLevel++;
res = GetCustomAttributesDataBase (btype, attributeType, true);
}
} while (inherit && btype != null);
return a.ToArray ();
}
internal static IList<CustomAttributeData> GetCustomAttributesDataBase (ICustomAttributeProvider obj, Type attributeType, bool inheritedOnly)
{
CustomAttributeData[] attrsData;
if (IsUserCattrProvider (obj)) {
//FIXME resolve this case if it makes sense. Assign empty array for now.
//attrsData = obj.GetCustomAttributesData(attributeType, true);
attrsData = Array.Empty<CustomAttributeData> ();
} else
attrsData = GetCustomAttributesDataInternal (obj);
//
// All pseudo custom attributes are Inherited = false hence we can avoid
// building attributes data array which would be discarded by inherited checks
//
if (!inheritedOnly) {
CustomAttributeData[] pseudoAttrsData = GetPseudoCustomAttributesData (obj, attributeType);
if (pseudoAttrsData != null) {
if (attrsData.Length == 0)
return Array.AsReadOnly (pseudoAttrsData);
CustomAttributeData[] res = new CustomAttributeData [attrsData.Length + pseudoAttrsData.Length];
Array.Copy (attrsData, res, attrsData.Length);
Array.Copy (pseudoAttrsData, 0, res, attrsData.Length, pseudoAttrsData.Length);
return Array.AsReadOnly (res);
}
}
return Array.AsReadOnly (attrsData);
}
internal static CustomAttributeData[] GetPseudoCustomAttributesData (ICustomAttributeProvider obj, Type attributeType)
{
CustomAttributeData[] pseudoAttrsData = null;
/* FIXME: Add other types */
if (obj is MonoMethod)
pseudoAttrsData = ((MonoMethod)obj).GetPseudoCustomAttributesData ();
else if (obj is FieldInfo)
pseudoAttrsData = ((FieldInfo)obj).GetPseudoCustomAttributesData ();
else if (obj is ParameterInfo)
pseudoAttrsData = ((ParameterInfo)obj).GetPseudoCustomAttributesData ();
else if (obj is Type)
pseudoAttrsData = GetPseudoCustomAttributesData (((Type)obj));
if ((attributeType != null) && (pseudoAttrsData != null)) {
for (int i = 0; i < pseudoAttrsData.Length; ++i) {
if (attributeType.IsAssignableFrom (pseudoAttrsData [i].AttributeType)) {
if (pseudoAttrsData.Length == 1)
return pseudoAttrsData;
else
return new CustomAttributeData[] { pseudoAttrsData[i] };
}
}
return Array.Empty<CustomAttributeData> ();
}
return pseudoAttrsData;
}
static CustomAttributeData[] GetPseudoCustomAttributesData (Type type)
{
int count = 0;
var Attributes = type.Attributes;
/* IsSerializable returns true for delegates/enums as well */
if ((Attributes & TypeAttributes.Serializable) != 0)
count++;
if ((Attributes & TypeAttributes.Import) != 0)
count++;
if (count == 0)
return null;
CustomAttributeData[] attrsData = new CustomAttributeData [count];
count = 0;
if ((Attributes & TypeAttributes.Serializable) != 0)
attrsData [count++] = new CustomAttributeData ((typeof (SerializableAttribute)).GetConstructor (Type.EmptyTypes));
if ((Attributes & TypeAttributes.Import) != 0)
attrsData [count++] = new CustomAttributeData ((typeof (ComImportAttribute)).GetConstructor (Type.EmptyTypes));
return attrsData;
}
internal static bool IsDefined (ICustomAttributeProvider obj, Type attributeType, bool inherit)