Imported Upstream version 6.6.0.89

Former-commit-id: b39a328747c2f3414dc52e009fb6f0aa80ca2492
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-09-24 08:53:40 +00:00
parent cf815e07e0
commit 95fdb59ea6
2556 changed files with 138145 additions and 47453 deletions

View File

@@ -0,0 +1,8 @@
namespace Mono.Documentation.Util
{
public enum ApiStyle
{
Classic,
Unified
}
}

View File

@@ -0,0 +1,189 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
using Mono.Collections.Generic;
using Mono.Documentation.Updater;
namespace Mono.Documentation.Util
{
public static class AttachedEntitiesHelper
{
private const string PropertyConst = "Property";
private const string EventConst = "Event";
private static readonly int EventLength = EventConst.Length;
private static readonly int PropertyLength = PropertyConst.Length;
public static string GetEventName(string fieldDefinitionName)
{
return fieldDefinitionName.Substring(0, fieldDefinitionName.Length - EventLength);
}
public static string GetPropertyName(string fieldDefinitionName)
{
return fieldDefinitionName.Substring(0, fieldDefinitionName.Length - PropertyLength);
}
public static IEnumerable<MemberReference> GetAttachedEntities(TypeDefinition type)
{
var methodsLookUpTable = GetMethodsLookUpTable(type);
foreach (var attachedEventReference in GetAttachedEvents(type, methodsLookUpTable))
{
yield return attachedEventReference;
}
foreach (var attachedEventProperty in GetAttachedProperties(type, methodsLookUpTable))
{
yield return attachedEventProperty;
}
}
private static Dictionary<string, IEnumerable<MethodDefinition>> GetMethodsLookUpTable(TypeDefinition type)
{
return type.Methods.GroupBy(i => i.Name, i => i).ToDictionary(i => i.Key, i => i.AsEnumerable());
}
#region Attached Events
private static IEnumerable<AttachedEventReference> GetAttachedEvents(TypeDefinition type, Dictionary<string, IEnumerable<MethodDefinition>> methods)
{
foreach (var field in type.Fields)
{
if (IsAttachedEvent(field, methods))
yield return new AttachedEventReference(field);
}
}
private static bool IsAttachedEvent(FieldDefinition field, Dictionary<string, IEnumerable<MethodDefinition>> methods)
{
// https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/attached-events-overview
if (!field.Name.EndsWith(EventConst))
return false;
var addMethodName = $"Add{GetEventName(field.Name)}Handler";
var removeMethodName = $"Remove{GetEventName(field.Name)}Handler";
return
// WPF implements attached events as routed events; the identifier to use for an event (RoutedEvent) is already defined by the WPF event system
IsAssignableTo(field.FieldType, "System.Windows.RoutedEvent")
&& field.IsPublic
&& field.IsStatic
&& field.IsInitOnly
// Has a method Add*Handler with two parameters.
// Has a method Remove*Handler with two parameters.
&& methods.ContainsKey(addMethodName)
&& methods.ContainsKey(removeMethodName)
&& methods[addMethodName].Any(IsAttachedEventMethod)
&& methods[removeMethodName].Any(IsAttachedEventMethod);
}
private static bool IsAttachedEventMethod(MethodDefinition method)
{
// The method must be public and static, with no return value.
return method.IsPublic
&& method.IsStatic
&& method.ReturnType.FullName == Consts.VoidFullName
&& AreAttachedEventMethodParameters(method.Parameters);
}
private static bool AreAttachedEventMethodParameters(Collection<ParameterDefinition> parameters)
{
if (parameters.Count != 2)
return false;
return
// The first parameter is DependencyObject
IsAssignableTo(parameters[0].ParameterType, "System.Windows.DependencyObject")
// The second parameter is the handler to add/remove
&& IsAttachedEventHandler(parameters[1].ParameterType);
}
private static bool IsAttachedEventHandler(TypeReference typeReference)
{
var type = typeReference.Resolve();
if (!DocUtils.IsDelegate(type))
return false;
MethodDefinition invoke = type.GetMethod("Invoke");
return invoke.Parameters.Count == 2;
}
#endregion
#region Attached Properties
private static IEnumerable<AttachedPropertyReference> GetAttachedProperties(TypeDefinition type, Dictionary<string, IEnumerable<MethodDefinition>> methods)
{
foreach (var field in type.Fields)
{
if (IsAttachedProperty(field, methods))
yield return new AttachedPropertyReference(field);
}
}
private static bool IsAttachedProperty(FieldDefinition field, Dictionary<string, IEnumerable<MethodDefinition>> methods)
{
// https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/attached-properties-overview
// https://github.com/mono/api-doc-tools/issues/63#issuecomment-328995418
if (!field.Name.EndsWith(PropertyConst, StringComparison.Ordinal))
return false;
var propertyName = GetPropertyName(field.Name);
var getMethodName = $"Get{propertyName}";
var setMethodName = $"Set{propertyName}";
var hasExistingProperty = field?.DeclaringType?.Properties.Any (p => p.Name.Equals (propertyName, System.StringComparison.Ordinal));
var hasExistingField = field?.DeclaringType?.Fields.Any (f => f.Name.Equals (propertyName, System.StringComparison.Ordinal));
return !hasExistingProperty.IsTrue () && !hasExistingField.IsTrue () &&
// Class X has a static field of type DependencyProperty [Name]Property
(field.FieldType.FullName == Consts.DependencyPropertyFullName || field.FieldType.FullName == Consts.DependencyPropertyFullNameXaml)
&& field.IsPublic
&& field.IsStatic
&& field.IsInitOnly
// Class X also has static methods with the following names: Get[Name] and Set[Name]
&& ((methods.ContainsKey(getMethodName) && methods[getMethodName].Any(IsAttachedPropertyGetMethod))
|| (methods.ContainsKey(setMethodName) && methods[setMethodName].Any(IsAttachedPropertySetMethod)));
}
private static bool IsAttachedPropertyGetMethod(MethodDefinition method)
{
return method.Parameters.Count == 1
// returns a value of type dp.PropertyType (or IsAssignableTo…), where dp is the value of the static field.
// && IsAssignableTo(method.ReturnType, "");
// The Get method takes one argument of type DependencyObject(or something IsAssignableTo(DependencyObject),
&& (IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullName) || IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullNameXaml));
}
private static bool IsAttachedPropertySetMethod(MethodDefinition method)
{
return method.Parameters.Count == 2// The Set method takes two arguments.
// The first has type DependencyObject(or IsAssignableTo…),
&& (IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullName) || IsAssignableTo(method.Parameters[0].ParameterType, Consts.DependencyObjectFullNameXaml))
// the second has type dp.PropertyType (or IsAssignableTo…).
// && IsAssignableTo(method.Parameters[1].ParameterType, "")
// It returns void.
&& method.ReturnType.FullName == Consts.VoidFullName;
}
#endregion
private static bool IsAssignableTo(TypeReference type, string targetTypeName)
{
if (type == null)
return false;
var typeDefenition = type.Resolve();
if (typeDefenition == null || typeDefenition.IsSealed)
return type.FullName == targetTypeName;
return type.FullName == targetTypeName || IsAssignableTo(typeDefenition.BaseType, targetTypeName);
}
}
internal static class NBoolExtensions
{
public static bool IsTrue (this Nullable<bool> value) =>
value.HasValue && value.Value;
}
}

View File

@@ -0,0 +1,38 @@
using Mono.Cecil;
using Mono.Collections.Generic;
namespace Mono.Documentation.Util
{
public class AttachedEventDefinition : AttachedEventReference, IMemberDefinition
{
private readonly FieldDefinition fieldDefinition;
public AttachedEventDefinition(FieldDefinition fieldDefinition, MetadataToken metadataToken)
: base(fieldDefinition)
{
this.fieldDefinition = fieldDefinition;
MetadataToken = metadataToken;
}
public Collection<CustomAttribute> CustomAttributes => fieldDefinition.CustomAttributes;
public bool HasCustomAttributes => fieldDefinition.HasCustomAttributes;
public bool IsSpecialName
{
get { return fieldDefinition.IsSpecialName; }
set { fieldDefinition.IsSpecialName = value; }
}
public bool IsRuntimeSpecialName
{
get { return fieldDefinition.IsRuntimeSpecialName; }
set { fieldDefinition.IsRuntimeSpecialName = value; }
}
public new TypeDefinition DeclaringType
{
get { return fieldDefinition.DeclaringType; }
set { fieldDefinition.DeclaringType = value; }
}
}
}

View File

@@ -0,0 +1,21 @@
using Mono.Cecil;
namespace Mono.Documentation.Util
{
public class AttachedEventReference : FieldReference
{
private readonly FieldDefinition fieldDefinition;
private AttachedEventDefinition definition;
public AttachedEventReference(FieldDefinition fieldDefinition) : base(AttachedEntitiesHelper.GetEventName(fieldDefinition.Name), fieldDefinition.FieldType, fieldDefinition.DeclaringType)
{
this.fieldDefinition = fieldDefinition;
}
protected override IMemberDefinition ResolveDefinition()
{
return definition ??
(definition = new AttachedEventDefinition(fieldDefinition, MetadataToken));
}
}
}

View File

@@ -0,0 +1,50 @@
using Mono.Cecil;
using Mono.Collections.Generic;
namespace Mono.Documentation.Util
{
public class AttachedPropertyDefinition : AttachedPropertyReference, IMemberDefinition
{
private readonly FieldDefinition fieldDefinition;
public AttachedPropertyDefinition(FieldDefinition fieldDefinition, MetadataToken metadataToken) : base(fieldDefinition)
{
this.fieldDefinition = fieldDefinition;
MetadataToken = metadataToken;
}
public MemberReference GetMethod
{
get => this.DeclaringType.GetMember(
$"Get{AttachedEntitiesHelper.GetPropertyName(fieldDefinition.Name)}",
m => (m as MethodReference)?.Parameters.Count == 1);
}
public MemberReference SetMethod
{
get => this.DeclaringType.GetMember(
$"Set{AttachedEntitiesHelper.GetPropertyName(fieldDefinition.Name)}",
m => (m as MethodReference)?.Parameters.Count == 2);
}
public Collection<CustomAttribute> CustomAttributes => fieldDefinition.CustomAttributes;
public bool HasCustomAttributes => fieldDefinition.HasCustomAttributes;
public bool IsSpecialName
{
get { return fieldDefinition.IsSpecialName; }
set { fieldDefinition.IsSpecialName = value; }
}
public bool IsRuntimeSpecialName
{
get { return fieldDefinition.IsRuntimeSpecialName; }
set { fieldDefinition.IsRuntimeSpecialName = value; }
}
public new TypeDefinition DeclaringType
{
get { return fieldDefinition.DeclaringType; }
set { fieldDefinition.DeclaringType = value; }
}
}
}

View File

@@ -0,0 +1,21 @@
using Mono.Cecil;
namespace Mono.Documentation.Util
{
public class AttachedPropertyReference : FieldReference
{
private readonly FieldDefinition fieldDefinition;
private AttachedPropertyDefinition definition;
public AttachedPropertyReference(FieldDefinition fieldDefinition) : base(AttachedEntitiesHelper.GetPropertyName(fieldDefinition.Name), fieldDefinition.FieldType, fieldDefinition.DeclaringType)
{
this.fieldDefinition = fieldDefinition;
}
protected override IMemberDefinition ResolveDefinition()
{
return definition ??
(definition = new AttachedPropertyDefinition(fieldDefinition, MetadataToken));
}
}
}

View File

@@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
namespace Mono.Documentation.Util
{
static class CecilExtensions
{
public static string GetDeclaringType (this CustomAttribute attribute)
{
var type = attribute.Constructor.DeclaringType;
var typeName = type.FullName;
string translatedType = NativeTypeManager.GetTranslatedName (type);
return translatedType;
}
public static IEnumerable<MemberReference> GetMembers (this TypeDefinition type)
{
foreach (var c in type.Methods.Where (m => m.IsConstructor))
yield return (MemberReference)c;
foreach (var e in type.Events)
yield return (MemberReference)e;
foreach (var f in type.Fields)
yield return (MemberReference)f;
foreach (var m in type.Methods.Where (m => !m.IsConstructor))
yield return (MemberReference)m;
foreach (var t in type.NestedTypes)
yield return (MemberReference)t;
foreach (var p in type.Properties)
yield return (MemberReference)p;
foreach (var a in type.AttachedEntities())
yield return (MemberReference)a;
}
public static IEnumerable<MemberReference> GetMembers (this TypeDefinition type, string member)
{
return GetMembers (type).Where (m => m.Name == member);
}
public static MemberReference GetMember (this TypeDefinition type, string member)
{
return GetMembers (type, member).EnsureZeroOrOne ();
}
public static MemberReference GetMember(this TypeDefinition type, string member, Func<MemberReference, bool> overloadMatchCriteria)
{
return GetMembers(type, member)
.Where(overloadMatchCriteria)
.FirstOrDefault();
}
static T EnsureZeroOrOne<T> (this IEnumerable<T> source)
{
if (source.Count () > 1)
throw new InvalidOperationException ("too many matches");
return source.FirstOrDefault ();
}
public static MethodDefinition GetMethod (this TypeDefinition type, string method)
{
return type.Methods
.Where (m => m.Name == method)
.EnsureZeroOrOne ();
}
public static IEnumerable<MemberReference> GetDefaultMembers (this TypeReference type)
{
TypeDefinition def = type as TypeDefinition;
if (def == null)
return new MemberReference[0];
CustomAttribute defMemberAttr = def.CustomAttributes
.FirstOrDefault (c => c.AttributeType.FullName == "System.Reflection.DefaultMemberAttribute");
if (defMemberAttr == null)
return new MemberReference[0];
string name = (string)defMemberAttr.ConstructorArguments[0].Value;
return def.Properties
.Where (p => p.Name == name)
.Select (p => (MemberReference)p);
}
public static IEnumerable<TypeDefinition> GetTypes (this AssemblyDefinition assembly)
{
var exportedTypes = assembly.MainModule.ExportedTypes
.Select (et => et.Resolve ())
.Where(e => e != null);
var types = assembly.Modules.SelectMany (md => md.GetAllTypes ()).Union(exportedTypes);
return types;
}
public static TypeDefinition GetType (this AssemblyDefinition assembly, string type)
{
return GetTypes (assembly)
.Where (td => td.FullName == type)
.EnsureZeroOrOne ();
}
public static bool IsGenericType (this TypeReference type)
{
return type.GenericParameters.Count > 0;
}
public static bool IsGenericMethod (this MethodReference method)
{
return method.GenericParameters.Count > 0;
}
public static TypeReference GetUnderlyingType (this TypeDefinition type)
{
if (!type.IsEnum)
return type;
return type.Fields.First (f => f.Name == "value__").FieldType;
}
public static IEnumerable<TypeDefinition> GetAllTypes (this ModuleDefinition self)
{
return self.Types.SelectMany (t => t.GetAllTypes ());
}
static IEnumerable<TypeDefinition> GetAllTypes (this TypeDefinition self)
{
yield return self;
if (!self.HasNestedTypes)
yield break;
foreach (var type in self.NestedTypes.SelectMany (t => t.GetAllTypes ()))
yield return type;
}
public static IEnumerable<MemberReference> AttachedEntities(this TypeDefinition type)
{
return AttachedEntitiesHelper.GetAttachedEntities(type);
}
}
}

View File

@@ -0,0 +1,125 @@
using System.Collections.Generic;
using Mono.Cecil;
namespace Mono.Documentation.Util
{
static class NativeTypeManager
{
static Dictionary<string, string> toNativeType = new Dictionary<string, string> (){
{"int", "nint"},
{"Int32", "nint"},
{"System.Int32", "System.nint"},
{"uint", "nuint"},
{"UInt32", "nuint"},
{"System.UInt32", "System.nuint"},
{"float", "nfloat"},
{"Single", "nfloat"},
{"System.Single", "System.nfloat"},
{"SizeF", "CoreGraphics.CGSize"},
{"System.Drawing.SizeF", "CoreGraphics.CGSize"},
{"PointF", "CoreGraphics.CGPoint"},
{"System.Drawing.PointF", "CoreGraphics.CGPoint"},
{"RectangleF", "CoreGraphics.CGRect" },
{"System.Drawing.RectangleF", "CoreGraphics.CGRect"}
};
static Dictionary<string, string> fromNativeType = new Dictionary<string, string> (){
{"nint", "int"},
{"System.nint", "System.Int32"},
{"nuint", "uint"},
{"System.nuint", "System.UInt32"},
{"nfloat", "float"},
{"System.nfloat", "System.Single"},
{"CoreGraphics.CGSize", "System.Drawing.SizeF"},
{"CoreGraphics.CGPoint", "System.Drawing.PointF"},
{"CoreGraphics.CGRect", "System.Drawing.RectangleF"},
{"MonoTouch.CoreGraphics.CGSize", "System.Drawing.SizeF"},
{"MonoTouch.CoreGraphics.CGPoint", "System.Drawing.PointF"},
{"MonoTouch.CoreGraphics.CGRect", "System.Drawing.RectangleF"}
};
public static string ConvertToNativeType (string typename)
{
string nvalue;
bool isOut = false;
bool isArray = false;
string valueToCompare = StripToComparableType (typename, ref isOut, ref isArray);
if (toNativeType.TryGetValue (valueToCompare, out nvalue))
{
if (isArray)
{
nvalue += "[]";
}
if (isOut)
{
nvalue += "&";
}
return nvalue;
}
return typename;
}
public static string ConvertFromNativeType (string typename)
{
string nvalue;
bool isOut = false;
bool isArray = false;
string valueToCompare = StripToComparableType (typename, ref isOut, ref isArray);
if (fromNativeType.TryGetValue (valueToCompare, out nvalue))
{
if (isArray)
{
nvalue += "[]";
}
if (isOut)
{
nvalue += "&";
}
return nvalue;
}
// it wasn't one of the native types ... just return it
return typename;
}
static string StripToComparableType (string typename, ref bool isOut, ref bool isArray)
{
string valueToCompare = typename;
if (typename.EndsWith ("[]"))
{
valueToCompare = typename.Substring (0, typename.Length - 2);
isArray = true;
}
if (typename.EndsWith ("&"))
{
valueToCompare = typename.Substring (0, typename.Length - 1);
isOut = true;
}
if (typename.Contains ("<"))
{
// TODO: Need to recursively process generic parameters
}
return valueToCompare;
}
public static string GetTranslatedName (TypeReference t)
{
string typename = t.FullName;
bool isInAssembly = MDocUpdater.IsInAssemblies (t.Module.Name);
if (isInAssembly && !typename.StartsWith ("System") && MDocUpdater.HasDroppedNamespace (t))
{
string nameWithDropped = string.Format ("{0}.{1}", MDocUpdater.droppedNamespace, typename);
return nameWithDropped;
}
return typename;
}
}
}