You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
254
mcs/tools/mono-api-html/PropertyComparer.cs
Normal file
254
mcs/tools/mono-api-html/PropertyComparer.cs
Normal file
@ -0,0 +1,254 @@
|
||||
//
|
||||
// Authors
|
||||
// Sebastien Pouliot <sebastien@xamarin.com>
|
||||
//
|
||||
// Copyright 2013 Xamarin Inc. http://www.xamarin.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public class PropertyComparer : MemberComparer {
|
||||
|
||||
public override string GroupName {
|
||||
get { return "properties"; }
|
||||
}
|
||||
|
||||
public override string ElementName {
|
||||
get { return "property"; }
|
||||
}
|
||||
|
||||
public override bool Find (XElement e)
|
||||
{
|
||||
if (!base.Find (e))
|
||||
return false;
|
||||
// the same Item (indexer) property can have different parameters
|
||||
return e.GetAttribute ("params") == Source.GetAttribute ("params");
|
||||
}
|
||||
|
||||
void GetAccessors (XElement element, out XElement getter, out XElement setter)
|
||||
{
|
||||
var methods = element.Element ("methods");
|
||||
|
||||
getter = null;
|
||||
setter = null;
|
||||
|
||||
if (methods == null)
|
||||
return;
|
||||
|
||||
foreach (var m in methods.Elements ("method")) {
|
||||
var n = m.GetAttribute ("name");
|
||||
if (n.StartsWith ("get_", StringComparison.Ordinal)) {
|
||||
getter = m;
|
||||
} else if (n.StartsWith ("set_", StringComparison.Ordinal)) {
|
||||
setter = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MethodAttributes GetMethodAttributes (XElement getter, XElement setter)
|
||||
{
|
||||
if (getter == null)
|
||||
return setter.GetMethodAttributes ();
|
||||
else if (setter == null)
|
||||
return getter.GetMethodAttributes ();
|
||||
|
||||
var gAttr = getter.GetMethodAttributes ();
|
||||
var sAttr = setter.GetMethodAttributes ();
|
||||
var g = gAttr & MethodAttributes.MemberAccessMask;
|
||||
var s = sAttr & MethodAttributes.MemberAccessMask;
|
||||
// Visibility is ordered numerically (higher value = more visible).
|
||||
// We want the most visible.
|
||||
var visibility = (MethodAttributes) Math.Max ((int) g, (int) s);
|
||||
// Do a bitwise or with the rest of the flags
|
||||
var g_no_visibility = gAttr & ~MethodAttributes.MemberAccessMask;
|
||||
var s_no_visibility = sAttr & ~MethodAttributes.MemberAccessMask;
|
||||
return g_no_visibility | s_no_visibility | visibility;
|
||||
}
|
||||
|
||||
void RenderPropertyType (XElement source, XElement target, ApiChange change)
|
||||
{
|
||||
var srcType = source.GetTypeName ("ptype");
|
||||
var tgtType = target.GetTypeName ("ptype");
|
||||
|
||||
if (srcType == tgtType) {
|
||||
change.Append (tgtType);
|
||||
} else {
|
||||
change.AppendModified (srcType, tgtType, true);
|
||||
}
|
||||
change.Append (" ");
|
||||
}
|
||||
|
||||
void RenderAccessors (XElement srcGetter, XElement tgtGetter, XElement srcSetter, XElement tgtSetter, ApiChange change)
|
||||
{
|
||||
// FIXME: this doesn't render changes in the accessor visibility (a protected setter can become public for instance).
|
||||
change.Append (" {");
|
||||
if (tgtGetter != null) {
|
||||
if (srcGetter != null) {
|
||||
change.Append (" ").Append ("get;");
|
||||
} else {
|
||||
change.Append (" ").AppendAdded ("get;");
|
||||
}
|
||||
} else if (srcGetter != null) {
|
||||
change.Append (" ").AppendRemoved ("get;");
|
||||
}
|
||||
|
||||
if (tgtSetter != null) {
|
||||
if (srcSetter != null) {
|
||||
change.Append (" ").Append ("set;");
|
||||
} else {
|
||||
change.Append (" ").AppendAdded ("set;");
|
||||
}
|
||||
} else if (srcSetter != null) {
|
||||
change.Append (" ").AppendRemoved ("set;");
|
||||
}
|
||||
|
||||
change.Append (" }");
|
||||
|
||||
// Ignore added property setters if asked to
|
||||
if (srcSetter == null && tgtSetter != null && State.IgnoreAddedPropertySetters && !change.Breaking) {
|
||||
change.AnyChange = false;
|
||||
change.HasIgnoredChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderIndexers (List<XElement> srcIndexers, List<XElement> tgtIndexers, ApiChange change)
|
||||
{
|
||||
change.Append ("this [");
|
||||
for (int i = 0; i < srcIndexers.Count; i++) {
|
||||
var source = srcIndexers [i];
|
||||
var target = tgtIndexers [i];
|
||||
|
||||
if (i > 0)
|
||||
change.Append (", ");
|
||||
|
||||
var srcType = source.GetTypeName ("type");
|
||||
var tgtType = target.GetTypeName ("type");
|
||||
if (srcType == tgtType) {
|
||||
change.Append (tgtType);
|
||||
} else {
|
||||
change.AppendModified (srcType, tgtType, true);
|
||||
}
|
||||
change.Append (" ");
|
||||
|
||||
var srcName = source.GetAttribute ("name");
|
||||
var tgtName = target.GetAttribute ("name");
|
||||
if (srcName == tgtName) {
|
||||
change.Append (tgtName);
|
||||
} else {
|
||||
change.AppendModified (srcName, tgtName, true);
|
||||
}
|
||||
}
|
||||
change.Append ("]");
|
||||
}
|
||||
|
||||
public override bool Equals (XElement source, XElement target, ApiChanges changes)
|
||||
{
|
||||
if (base.Equals (source, target, changes))
|
||||
return true;
|
||||
|
||||
XElement srcGetter, srcSetter;
|
||||
XElement tgtGetter, tgtSetter;
|
||||
GetAccessors (source, out srcGetter, out srcSetter);
|
||||
GetAccessors (target, out tgtGetter, out tgtSetter);
|
||||
|
||||
List<XElement> srcIndexers = null;
|
||||
List<XElement> tgtIndexers = null;
|
||||
bool isIndexer = false;
|
||||
if (srcGetter != null) {
|
||||
srcIndexers = srcGetter.DescendantList ("parameters", "parameter");
|
||||
tgtIndexers = tgtGetter.DescendantList ("parameters", "parameter");
|
||||
isIndexer = srcIndexers != null && srcIndexers.Count > 0;
|
||||
}
|
||||
|
||||
var change = new ApiChange ();
|
||||
change.Header = "Modified " + GroupName;
|
||||
RenderMethodAttributes (GetMethodAttributes (srcGetter, srcSetter), GetMethodAttributes (tgtGetter, tgtSetter), change);
|
||||
RenderPropertyType (source, target, change);
|
||||
if (isIndexer) {
|
||||
RenderIndexers (srcIndexers, tgtIndexers, change);
|
||||
} else {
|
||||
RenderName (source, target, change);
|
||||
}
|
||||
RenderGenericParameters (source, target, change);
|
||||
RenderAccessors (srcGetter, tgtGetter, srcSetter, tgtSetter, change);
|
||||
|
||||
changes.Add (source, target, change);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GetProperties (XElement e, out bool @virtual, out bool @override, out bool @static, out bool getter, out bool setter, out bool family)
|
||||
{
|
||||
@virtual = @override = @static = getter = setter = family = false;
|
||||
|
||||
var methods = e.Element ("methods");
|
||||
if (methods != null) {
|
||||
foreach (var m in methods.Elements ("method")) {
|
||||
@virtual |= m.IsTrue ("virtual");
|
||||
@static |= m.IsTrue ("static");
|
||||
var n = m.GetAttribute ("name");
|
||||
getter |= n.StartsWith ("get_", StringComparison.Ordinal);
|
||||
setter |= n.StartsWith ("set_", StringComparison.Ordinal);
|
||||
var attribs = (MethodAttributes) Int32.Parse (m.GetAttribute ("attrib"));
|
||||
family = ((attribs & MethodAttributes.Public) != MethodAttributes.Public);
|
||||
@override |= (attribs & MethodAttributes.NewSlot) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetDescription (XElement e)
|
||||
{
|
||||
string name = e.Attribute ("name").Value;
|
||||
string ptype = e.GetTypeName ("ptype");
|
||||
|
||||
bool virt = false;
|
||||
bool over = false;
|
||||
bool stat = false;
|
||||
bool getter = false;
|
||||
bool setter = false;
|
||||
bool family = false;
|
||||
GetProperties (e, out virt, out over, out stat, out getter, out setter, out family);
|
||||
|
||||
var sb = new StringBuilder ();
|
||||
|
||||
sb.Append (family ? "protected " : "public ");
|
||||
if (virt && !State.IgnoreVirtualChanges)
|
||||
sb.Append (over ? "override " : "virtual ");
|
||||
else if (stat)
|
||||
sb.Append ("static ");
|
||||
sb.Append (ptype).Append (' ').Append (name).Append (" { ");
|
||||
if (getter)
|
||||
sb.Append ("get; ");
|
||||
if (setter)
|
||||
sb.Append ("set; ");
|
||||
sb.Append ("}");
|
||||
|
||||
return sb.ToString ();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user