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
81
mcs/tools/mono-api-html/ApiChange.cs
Normal file
81
mcs/tools/mono-api-html/ApiChange.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff
|
||||
{
|
||||
public class ApiChange
|
||||
{
|
||||
public string Header;
|
||||
public StringBuilder Member = new StringBuilder ();
|
||||
public bool Breaking;
|
||||
public bool AnyChange;
|
||||
public bool HasIgnoredChanges;
|
||||
|
||||
public ApiChange Append (string text)
|
||||
{
|
||||
Member.Append (text);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApiChange AppendAdded (string text, bool breaking = false)
|
||||
{
|
||||
Member.Append ("<span class='added ").Append (breaking ? "added-breaking-inline" : string.Empty).Append ("'>");
|
||||
Member.Append (text);
|
||||
Member.Append ("</span>");
|
||||
Breaking |= breaking;
|
||||
AnyChange = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApiChange AppendRemoved (string text, bool breaking = true)
|
||||
{
|
||||
Member.Append ("<span class='removed removed-inline ").Append (breaking ? "removed-breaking-inline" : string.Empty).Append ("'>");
|
||||
Member.Append (text);
|
||||
Member.Append ("</span>");
|
||||
Breaking |= breaking;
|
||||
AnyChange = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApiChange AppendModified (string old, string @new, bool breaking = true)
|
||||
{
|
||||
if (old.Length > 0)
|
||||
AppendRemoved (old, breaking);
|
||||
if (old.Length > 0 && @new.Length > 0)
|
||||
Append (" ");
|
||||
if (@new.Length > 0)
|
||||
AppendAdded (@new);
|
||||
Breaking |= breaking;
|
||||
AnyChange = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class ApiChanges : Dictionary<string, List<ApiChange>> {
|
||||
public void Add (XElement source, XElement target, ApiChange change)
|
||||
{
|
||||
if (!change.AnyChange) {
|
||||
// This is most likely because the rendering doesn't take into account something that's different (solution: fix rendering).
|
||||
if (!change.HasIgnoredChanges) {
|
||||
var isField = source.Name.LocalName == "field";
|
||||
if (isField) {
|
||||
Console.WriteLine ("Comparison resulting in no changes (src: {2} dst: {3}) :\n{0}\n{1}\n\n", source.ToString (), target.ToString (), source.GetFieldAttributes (), target.GetFieldAttributes ());
|
||||
} else {
|
||||
Console.WriteLine ("Comparison resulting in no changes (src: {2} dst: {3}) :\n{0}\n{1}\n\n", source.ToString (), target.ToString (), source.GetMethodAttributes (), target.GetMethodAttributes ());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
List<ApiChange> list;
|
||||
if (!TryGetValue (change.Header, out list)) {
|
||||
list = new List<ApiChange> ();
|
||||
base.Add (change.Header, list);
|
||||
}
|
||||
list.Add (change);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
277
mcs/tools/mono-api-html/ApiDiff.cs
Normal file
277
mcs/tools/mono-api-html/ApiDiff.cs
Normal file
@@ -0,0 +1,277 @@
|
||||
//
|
||||
// The main differences with mono-api-diff are:
|
||||
// * this tool directly produce HTML similar to gdiff.sh used for Xamarin.iOS
|
||||
// * this tool reports changes in an "evolutionary" way, not in a breaking way,
|
||||
// i.e. it does not assume the source assembly is right (but simply older)
|
||||
// * the diff .xml output was not easy to convert back into the HTML format
|
||||
// that gdiff.sh produced
|
||||
//
|
||||
// Authors
|
||||
// Sebastien Pouliot <sebastien@xamarin.com>
|
||||
//
|
||||
// Copyright 2013-2014 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.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Mono.Options;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public static class State {
|
||||
static TextWriter output;
|
||||
|
||||
public static TextWriter Output {
|
||||
get {
|
||||
if (output == null)
|
||||
output = Console.Out;
|
||||
return output;
|
||||
}
|
||||
set { output = value; }
|
||||
}
|
||||
|
||||
public static string Assembly { get; set; }
|
||||
public static string Namespace { get; set; }
|
||||
public static string Type { get; set; }
|
||||
public static string BaseType { get; set; }
|
||||
|
||||
public static int Indent { get; set; }
|
||||
|
||||
static List<Regex> ignoreAdded = new List<Regex> ();
|
||||
public static List<Regex> IgnoreAdded {
|
||||
get { return ignoreAdded; }
|
||||
}
|
||||
|
||||
static List<Regex> ignoreNew = new List<Regex> ();
|
||||
public static List<Regex> IgnoreNew {
|
||||
get { return ignoreNew; }
|
||||
}
|
||||
|
||||
static List<Regex> ignoreRemoved = new List<Regex> ();
|
||||
public static List<Regex> IgnoreRemoved {
|
||||
get { return ignoreRemoved; }
|
||||
}
|
||||
|
||||
public static bool IgnoreParameterNameChanges { get; set; }
|
||||
public static bool IgnoreVirtualChanges { get; set; }
|
||||
public static bool IgnoreAddedPropertySetters { get; set; }
|
||||
|
||||
public static bool Lax;
|
||||
public static bool Colorize = true;
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
public static int Main (string[] args)
|
||||
{
|
||||
var showHelp = false;
|
||||
string diff = null;
|
||||
List<string> extra = null;
|
||||
|
||||
var options = new OptionSet {
|
||||
{ "h|help", "Show this help", v => showHelp = true },
|
||||
{ "d|diff=", "HTML diff file out output (omit for stdout)", v => diff = v },
|
||||
{ "i|ignore=", "Ignore new, added, and removed members whose description matches a given C# regular expression (see below).",
|
||||
v => {
|
||||
var r = new Regex (v);
|
||||
State.IgnoreAdded.Add (r);
|
||||
State.IgnoreRemoved.Add (r);
|
||||
State.IgnoreNew.Add (r);
|
||||
}
|
||||
},
|
||||
{ "a|ignore-added=", "Ignore added members whose description matches a given C# regular expression (see below).",
|
||||
v => State.IgnoreAdded.Add (new Regex (v))
|
||||
},
|
||||
{ "r|ignore-removed=", "Ignore removed members whose description matches a given C# regular expression (see below).",
|
||||
v => State.IgnoreRemoved.Add (new Regex (v))
|
||||
},
|
||||
{ "n|ignore-new=", "Ignore new namespaces and types whose description matches a given C# regular expression (see below).",
|
||||
v => State.IgnoreNew.Add (new Regex (v))
|
||||
},
|
||||
{ "ignore-changes-parameter-names", "Ignore changes to parameter names for identically prototyped methods.",
|
||||
v => State.IgnoreParameterNameChanges = v != null
|
||||
},
|
||||
{ "ignore-changes-property-setters", "Ignore adding setters to properties.",
|
||||
v => State.IgnoreAddedPropertySetters = v != null
|
||||
},
|
||||
{ "ignore-changes-virtual", "Ignore changing non-`virtual` to `virtual` or adding `override`.",
|
||||
v => State.IgnoreVirtualChanges = v != null
|
||||
},
|
||||
{ "c|colorize:", "Colorize HTML output", v => State.Colorize = string.IsNullOrEmpty (v) ? true : bool.Parse (v) },
|
||||
{ "x|lax", "Ignore duplicate XML entries", v => State.Lax = true }
|
||||
};
|
||||
|
||||
try {
|
||||
extra = options.Parse (args);
|
||||
} catch (OptionException e) {
|
||||
Console.WriteLine ("Option error: {0}", e.Message);
|
||||
showHelp = true;
|
||||
}
|
||||
|
||||
if (showHelp || extra == null || extra.Count < 2 || extra.Count > 3) {
|
||||
Console.WriteLine (@"Usage: mono-api-html [options] <reference.xml> <assembly.xml> [diff.html]");
|
||||
Console.WriteLine ();
|
||||
Console.WriteLine ("Available options:");
|
||||
options.WriteOptionDescriptions (Console.Out);
|
||||
Console.WriteLine ();
|
||||
Console.WriteLine ("Ignoring Members:");
|
||||
Console.WriteLine ();
|
||||
Console.WriteLine (" Members that were added can be filtered out of the diff by using the");
|
||||
Console.WriteLine (" -i, --ignore-added option. The option takes a C# regular expression");
|
||||
Console.WriteLine (" to match against member descriptions. For example, to ignore the");
|
||||
Console.WriteLine (" introduction of the interfaces 'INSCopying' and 'INSCoding' on types");
|
||||
Console.WriteLine (" pass the following to mono-api-html:");
|
||||
Console.WriteLine ();
|
||||
Console.WriteLine (" mono-api-html ... -i 'INSCopying$' -i 'INSCoding$'");
|
||||
Console.WriteLine ();
|
||||
Console.WriteLine (" The regular expressions will match any member description ending with");
|
||||
Console.WriteLine (" 'INSCopying' or 'INSCoding'.");
|
||||
Console.WriteLine ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
var input = extra [0];
|
||||
var output = extra [1];
|
||||
if (extra.Count == 3 && diff == null)
|
||||
diff = extra [2];
|
||||
|
||||
try {
|
||||
var ac = new AssemblyComparer (input, output);
|
||||
if (diff != null) {
|
||||
string diffHtml = String.Empty;
|
||||
using (var writer = new StringWriter ()) {
|
||||
State.Output = writer;
|
||||
ac.Compare ();
|
||||
diffHtml = State.Output.ToString ();
|
||||
}
|
||||
if (diffHtml.Length > 0) {
|
||||
using (var file = new StreamWriter (diff)) {
|
||||
file.WriteLine ("<div>");
|
||||
if (State.Colorize) {
|
||||
file.WriteLine ("<style scoped>");
|
||||
file.WriteLine ("\t.obsolete { color: gray; }");
|
||||
file.WriteLine ("\t.added { color: green; }");
|
||||
file.WriteLine ("\t.removed-inline { text-decoration: line-through; }");
|
||||
file.WriteLine ("\t.removed-breaking-inline { color: red;}");
|
||||
file.WriteLine ("\t.added-breaking-inline { text-decoration: underline; }");
|
||||
file.WriteLine ("\t.nonbreaking { color: black; }");
|
||||
file.WriteLine ("\t.breaking { color: red; }");
|
||||
file.WriteLine ("</style>");
|
||||
}
|
||||
file.WriteLine (
|
||||
@"<script type=""text/javascript"">
|
||||
// Only some elements have 'data-is-[non-]breaking' attributes. Here we
|
||||
// iterate over all descendents elements, and set 'data-is-[non-]breaking'
|
||||
// depending on whether there are any descendents with that attribute.
|
||||
function propagateDataAttribute (element)
|
||||
{
|
||||
if (element.hasAttribute ('data-is-propagated'))
|
||||
return;
|
||||
|
||||
var i;
|
||||
var any_breaking = element.hasAttribute ('data-is-breaking');
|
||||
var any_non_breaking = element.hasAttribute ('data-is-non-breaking');
|
||||
for (i = 0; i < element.children.length; i++) {
|
||||
var el = element.children [i];
|
||||
propagateDataAttribute (el);
|
||||
any_breaking |= el.hasAttribute ('data-is-breaking');
|
||||
any_non_breaking |= el.hasAttribute ('data-is-non-breaking');
|
||||
}
|
||||
|
||||
if (any_breaking)
|
||||
element.setAttribute ('data-is-breaking', null);
|
||||
else if (any_non_breaking)
|
||||
element.setAttribute ('data-is-non-breaking', null);
|
||||
element.setAttribute ('data-is-propagated', null);
|
||||
}
|
||||
|
||||
function hideNonBreakingChanges ()
|
||||
{
|
||||
var topNodes = document.querySelectorAll ('[data-is-topmost]');
|
||||
var n;
|
||||
var i;
|
||||
for (n = 0; n < topNodes.length; n++) {
|
||||
propagateDataAttribute (topNodes [n]);
|
||||
var elements = topNodes [n].querySelectorAll ('[data-is-non-breaking]');
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
var el = elements [i];
|
||||
if (!el.hasAttribute ('data-original-display'))
|
||||
el.setAttribute ('data-original-display', el.style.display);
|
||||
el.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
var links = document.getElementsByClassName ('hide-nonbreaking');
|
||||
for (i = 0; i < links.length; i++)
|
||||
links [i].style.display = 'none';
|
||||
links = document.getElementsByClassName ('restore-nonbreaking');
|
||||
for (i = 0; i < links.length; i++)
|
||||
links [i].style.display = '';
|
||||
}
|
||||
|
||||
function showNonBreakingChanges ()
|
||||
{
|
||||
var elements = document.querySelectorAll ('[data-original-display]');
|
||||
var i;
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
var el = elements [i];
|
||||
el.style.display = el.getAttribute ('data-original-display');
|
||||
}
|
||||
|
||||
var links = document.getElementsByClassName ('hide-nonbreaking');
|
||||
for (i = 0; i < links.length; i++)
|
||||
links [i].style.display = '';
|
||||
links = document.getElementsByClassName ('restore-nonbreaking');
|
||||
for (i = 0; i < links.length; i++)
|
||||
links [i].style.display = 'none';
|
||||
}
|
||||
</script>");
|
||||
if (ac.SourceAssembly == ac.TargetAssembly) {
|
||||
file.WriteLine ("<h1>{0}.dll</h1>", ac.SourceAssembly);
|
||||
} else {
|
||||
file.WriteLine ("<h1>{0}.dll vs {1}.dll</h1>", ac.SourceAssembly, ac.TargetAssembly);
|
||||
}
|
||||
file.WriteLine ("<a href='javascript: hideNonBreakingChanges (); ' class='hide-nonbreaking'>Hide non-breaking changes</a>");
|
||||
file.WriteLine ("<a href='javascript: showNonBreakingChanges (); ' class='restore-nonbreaking' style='display: none;'>Show non-breaking changes</a>");
|
||||
file.WriteLine ("<br/>");
|
||||
file.WriteLine ("<div data-is-topmost>");
|
||||
file.Write (diffHtml);
|
||||
file.WriteLine ("</div> <!-- end topmost div -->");
|
||||
file.WriteLine ("</div>");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
State.Output = Console.Out;
|
||||
ac.Compare ();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
Console.WriteLine (e);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
79
mcs/tools/mono-api-html/AssemblyComparer.cs
Normal file
79
mcs/tools/mono-api-html/AssemblyComparer.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// 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.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public class AssemblyComparer : Comparer {
|
||||
|
||||
XDocument source;
|
||||
XDocument target;
|
||||
NamespaceComparer comparer;
|
||||
|
||||
public AssemblyComparer (string sourceFile, string targetFile)
|
||||
{
|
||||
source = XDocument.Load (sourceFile);
|
||||
target = XDocument.Load (targetFile);
|
||||
comparer = new NamespaceComparer ();
|
||||
}
|
||||
|
||||
public string SourceAssembly { get; private set; }
|
||||
public string TargetAssembly { get; private set; }
|
||||
|
||||
public void Compare ()
|
||||
{
|
||||
Compare (source.Element ("assemblies").Elements ("assembly"),
|
||||
target.Element ("assemblies").Elements ("assembly"));
|
||||
}
|
||||
|
||||
public override void SetContext (XElement current)
|
||||
{
|
||||
State.Assembly = current.GetAttribute ("name");
|
||||
}
|
||||
|
||||
public override void Added (XElement target, bool wasParentAdded)
|
||||
{
|
||||
// one assembly per xml file
|
||||
}
|
||||
|
||||
public override void Modified (XElement source, XElement target, ApiChanges diff)
|
||||
{
|
||||
SourceAssembly = source.GetAttribute ("name");
|
||||
TargetAssembly = target.GetAttribute ("name");
|
||||
// TODO: version
|
||||
// ? custom attributes ?
|
||||
comparer.Compare (source, target);
|
||||
}
|
||||
|
||||
public override void Removed (XElement source)
|
||||
{
|
||||
// one assembly per xml file
|
||||
}
|
||||
}
|
||||
}
|
261
mcs/tools/mono-api-html/ClassComparer.cs
Normal file
261
mcs/tools/mono-api-html/ClassComparer.cs
Normal file
@@ -0,0 +1,261 @@
|
||||
//
|
||||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public class ClassComparer : Comparer {
|
||||
|
||||
InterfaceComparer icomparer;
|
||||
ConstructorComparer ccomparer;
|
||||
FieldComparer fcomparer;
|
||||
PropertyComparer pcomparer;
|
||||
EventComparer ecomparer;
|
||||
MethodComparer mcomparer;
|
||||
ClassComparer kcomparer;
|
||||
|
||||
public ClassComparer ()
|
||||
{
|
||||
icomparer = new InterfaceComparer ();
|
||||
ccomparer = new ConstructorComparer ();
|
||||
fcomparer = new FieldComparer ();
|
||||
pcomparer = new PropertyComparer ();
|
||||
ecomparer = new EventComparer ();
|
||||
mcomparer = new MethodComparer ();
|
||||
}
|
||||
|
||||
public override void SetContext (XElement current)
|
||||
{
|
||||
State.Type = current.GetAttribute ("name");
|
||||
State.BaseType = current.GetAttribute ("base");
|
||||
}
|
||||
|
||||
public void Compare (XElement source, XElement target)
|
||||
{
|
||||
var s = source.Element ("classes");
|
||||
var t = target.Element ("classes");
|
||||
if (XNode.DeepEquals (s, t))
|
||||
return;
|
||||
Compare (s.Elements ("class"), t.Elements ("class"));
|
||||
}
|
||||
|
||||
public override void Added (XElement target, bool wasParentAdded)
|
||||
{
|
||||
string name = target.Attribute ("name").Value;
|
||||
if (State.IgnoreNew.Any (re => re.IsMatch (name)))
|
||||
return;
|
||||
Output.WriteLine ("<div> <!-- start type {0} -->", name);
|
||||
Output.WriteLine ("<h3>New Type {0}.{1}</h3>", State.Namespace, name);
|
||||
Output.WriteLine ("<pre class='added' data-is-non-breaking>");
|
||||
State.Indent = 0;
|
||||
AddedInner (target);
|
||||
Output.WriteLine ("</pre>");
|
||||
Output.WriteLine ("</div> <!-- end type {0} -->", name);
|
||||
}
|
||||
|
||||
public void AddedInner (XElement target)
|
||||
{
|
||||
SetContext (target);
|
||||
if (target.IsTrue ("serializable"))
|
||||
Indent ().WriteLine ("[Serializable]");
|
||||
|
||||
var type = target.Attribute ("type").Value;
|
||||
|
||||
if (type == "enum") {
|
||||
// check if [Flags] is present
|
||||
var cattrs = target.Element ("attributes");
|
||||
if (cattrs != null) {
|
||||
foreach (var ca in cattrs.Elements ("attribute")) {
|
||||
if (ca.GetAttribute ("name") == "System.FlagsAttribute") {
|
||||
Indent ().WriteLine ("[Flags]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Indent ().Write ("public");
|
||||
|
||||
if (type != "enum") {
|
||||
bool seal = target.IsTrue ("sealed");
|
||||
bool abst = target.IsTrue ("abstract");
|
||||
if (seal && abst)
|
||||
Output.Write (" static");
|
||||
else if (seal && type != "struct")
|
||||
Output.Write (" sealed");
|
||||
else if (abst && type != "interface")
|
||||
Output.Write (" abstract");
|
||||
}
|
||||
|
||||
Output.Write (' ');
|
||||
Output.Write (type);
|
||||
Output.Write (' ');
|
||||
Output.Write (target.GetAttribute ("name"));
|
||||
|
||||
var baseclass = target.GetAttribute ("base");
|
||||
if ((type != "enum") && (type != "struct")) {
|
||||
if (baseclass != null) {
|
||||
if (baseclass == "System.Object") {
|
||||
// while true we do not need to be reminded every time...
|
||||
baseclass = null;
|
||||
} else {
|
||||
Output.Write (" : ");
|
||||
Output.Write (baseclass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// interfaces on enums are "standard" not user provided - so we do not want to show them
|
||||
if (type != "enum") {
|
||||
var i = target.Element ("interfaces");
|
||||
if (i != null) {
|
||||
var interfaces = new List<string> ();
|
||||
foreach (var iface in i.Elements ("interface"))
|
||||
interfaces.Add (icomparer.GetDescription (iface));
|
||||
Output.Write ((baseclass == null) ? " : " : ", ");
|
||||
Output.Write (String.Join (", ", interfaces));
|
||||
}
|
||||
}
|
||||
|
||||
Output.WriteLine (" {");
|
||||
|
||||
var t = target.Element ("constructors");
|
||||
if (t != null) {
|
||||
Indent ().WriteLine ("\t// constructors");
|
||||
foreach (var ctor in t.Elements ("constructor"))
|
||||
ccomparer.Added (ctor, true);
|
||||
}
|
||||
|
||||
t = target.Element ("fields");
|
||||
if (t != null) {
|
||||
if (type != "enum")
|
||||
Indent ().WriteLine ("\t// fields");
|
||||
else
|
||||
SetContext (target);
|
||||
foreach (var field in t.Elements ("field"))
|
||||
fcomparer.Added (field, true);
|
||||
}
|
||||
|
||||
t = target.Element ("properties");
|
||||
if (t != null) {
|
||||
Indent ().WriteLine ("\t// properties");
|
||||
foreach (var property in t.Elements ("property"))
|
||||
pcomparer.Added (property, true);
|
||||
}
|
||||
|
||||
t = target.Element ("events");
|
||||
if (t != null) {
|
||||
Indent ().WriteLine ("\t// events");
|
||||
foreach (var evnt in t.Elements ("event"))
|
||||
ecomparer.Added (evnt, true);
|
||||
}
|
||||
|
||||
t = target.Element ("methods");
|
||||
if (t != null) {
|
||||
Indent ().WriteLine ("\t// methods");
|
||||
foreach (var method in t.Elements ("method"))
|
||||
mcomparer.Added (method, true);
|
||||
}
|
||||
|
||||
t = target.Element ("classes");
|
||||
if (t != null) {
|
||||
Output.WriteLine ();
|
||||
Indent ().WriteLine ("\t// inner types");
|
||||
kcomparer = new NestedClassComparer ();
|
||||
State.Indent++;
|
||||
foreach (var inner in t.Elements ("class"))
|
||||
kcomparer.AddedInner (inner);
|
||||
State.Indent--;
|
||||
}
|
||||
Indent ().WriteLine ("}");
|
||||
}
|
||||
|
||||
public override void Modified (XElement source, XElement target, ApiChanges diff)
|
||||
{
|
||||
// hack - there could be changes that we're not monitoring (e.g. attributes properties)
|
||||
var output = Output;
|
||||
State.Output = new StringWriter ();
|
||||
|
||||
var sb = source.GetAttribute ("base");
|
||||
var tb = target.GetAttribute ("base");
|
||||
if (sb != tb) {
|
||||
Output.Write ("Modified base type: ");
|
||||
Output.WriteLine (new ApiChange ().AppendModified (sb, tb, true).Member.ToString ());
|
||||
}
|
||||
|
||||
ccomparer.Compare (source, target);
|
||||
icomparer.Compare (source, target);
|
||||
fcomparer.Compare (source, target);
|
||||
pcomparer.Compare (source, target);
|
||||
ecomparer.Compare (source, target);
|
||||
mcomparer.Compare (source, target);
|
||||
|
||||
var si = source.Element ("classes");
|
||||
if (si != null) {
|
||||
var ti = target.Element ("classes");
|
||||
kcomparer = new NestedClassComparer ();
|
||||
kcomparer.Compare (si.Elements ("class"), ti == null ? null : ti.Elements ("class"));
|
||||
}
|
||||
|
||||
var s = (Output as StringWriter).ToString ();
|
||||
State.Output = output;
|
||||
if (s.Length > 0) {
|
||||
var tn = GetTypeName (target);
|
||||
Output.WriteLine ("<!-- start type {0} --> <div>", tn);
|
||||
Output.WriteLine ("<h3>Type Changed: {0}.{1}</h3>", State.Namespace, GetTypeName (target));
|
||||
Output.WriteLine (s);
|
||||
Output.WriteLine ("</div> <!-- end type {0} -->", tn);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Removed (XElement source)
|
||||
{
|
||||
Output.Write ("<h3>Removed Type <span class='breaking' data-is-breaking>{0}.{1}</span></h3>", State.Namespace, GetTypeName (source));
|
||||
}
|
||||
|
||||
public virtual string GetTypeName (XElement type)
|
||||
{
|
||||
return type.GetAttribute ("name");
|
||||
}
|
||||
}
|
||||
|
||||
public class NestedClassComparer : ClassComparer {
|
||||
|
||||
public override void SetContext (XElement current)
|
||||
{
|
||||
}
|
||||
|
||||
public override string GetTypeName (XElement type)
|
||||
{
|
||||
return State.Type + "." + base.GetTypeName (type);
|
||||
}
|
||||
}
|
||||
}
|
98
mcs/tools/mono-api-html/Comparer.cs
Normal file
98
mcs/tools/mono-api-html/Comparer.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public abstract class Comparer {
|
||||
|
||||
protected List<XElement> removed = new List<XElement> ();
|
||||
protected ApiChanges modified = new ApiChanges ();
|
||||
|
||||
public TextWriter Output {
|
||||
get { return State.Output; }
|
||||
}
|
||||
|
||||
protected TextWriter Indent ()
|
||||
{
|
||||
for (int i = 0; i < State.Indent; i++)
|
||||
State.Output.Write ("\t");
|
||||
return State.Output;
|
||||
}
|
||||
|
||||
public abstract void Added (XElement target, bool wasParentAdded);
|
||||
public abstract void Modified (XElement source, XElement target, ApiChanges changes);
|
||||
public abstract void Removed (XElement source);
|
||||
|
||||
public virtual bool Equals (XElement source, XElement target, ApiChanges changes)
|
||||
{
|
||||
return XNode.DeepEquals (source, target);
|
||||
}
|
||||
|
||||
public abstract void SetContext (XElement current);
|
||||
|
||||
public virtual void Compare (IEnumerable<XElement> source, IEnumerable<XElement> target)
|
||||
{
|
||||
removed.Clear ();
|
||||
modified.Clear ();
|
||||
|
||||
foreach (var s in source) {
|
||||
SetContext (s);
|
||||
string sn = s.GetAttribute ("name");
|
||||
var t = target == null ? null : target.SingleOrDefault (x => x.GetAttribute ("name") == sn);
|
||||
if (t == null) {
|
||||
// not in target, it was removed
|
||||
removed.Add (s);
|
||||
} else {
|
||||
t.Remove ();
|
||||
// possibly modified
|
||||
if (Equals (s, t, modified))
|
||||
continue;
|
||||
|
||||
// still in target so will be part of Added
|
||||
Modified (s, t, modified);
|
||||
}
|
||||
}
|
||||
// delayed, that way we show "Modified", "Added" and then "Removed"
|
||||
foreach (var item in removed) {
|
||||
SetContext (item);
|
||||
Removed (item);
|
||||
}
|
||||
// remaining == newly added in target
|
||||
if (target != null) {
|
||||
foreach (var item in target) {
|
||||
SetContext (item);
|
||||
Added (item, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
148
mcs/tools/mono-api-html/ConstructorComparer.cs
Normal file
148
mcs/tools/mono-api-html/ConstructorComparer.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// 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 {
|
||||
|
||||
// MethodComparer inherits from this one
|
||||
public class ConstructorComparer : MemberComparer {
|
||||
|
||||
public override string GroupName {
|
||||
get { return "constructors"; }
|
||||
}
|
||||
|
||||
public override string ElementName {
|
||||
get { return "constructor"; }
|
||||
}
|
||||
|
||||
public override bool Find (XElement e)
|
||||
{
|
||||
return (e.Attribute ("name").Value == Source.Attribute ("name").Value);
|
||||
}
|
||||
|
||||
void RenderReturnType (XElement source, XElement target, ApiChange change)
|
||||
{
|
||||
var srcType = source.GetTypeName ("returntype");
|
||||
var tgtType = target.GetTypeName ("returntype");
|
||||
|
||||
if (srcType != tgtType) {
|
||||
change.AppendModified (srcType, tgtType, true);
|
||||
change.Append (" ");
|
||||
} else if (srcType != null) {
|
||||
// ctor don't have a return type
|
||||
change.Append (srcType);
|
||||
change.Append (" ");
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals (XElement source, XElement target, ApiChanges changes)
|
||||
{
|
||||
if (base.Equals (source, target, changes))
|
||||
return true;
|
||||
|
||||
var change = new ApiChange ();
|
||||
change.Header = "Modified " + GroupName;
|
||||
RenderMethodAttributes (source, target, change);
|
||||
RenderReturnType (source, target, change);
|
||||
RenderName (source, target, change);
|
||||
RenderGenericParameters (source, target, change);
|
||||
RenderParameters (source, target, change);
|
||||
|
||||
changes.Add (source, target, change);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string GetDescription (XElement e)
|
||||
{
|
||||
var sb = new StringBuilder ();
|
||||
|
||||
var attribs = e.Attribute ("attrib");
|
||||
if (attribs != null) {
|
||||
var attr = (MethodAttributes) Int32.Parse (attribs.Value);
|
||||
if ((attr & MethodAttributes.Public) != MethodAttributes.Public) {
|
||||
sb.Append ("protected ");
|
||||
} else {
|
||||
sb.Append ("public ");
|
||||
}
|
||||
|
||||
if ((attr & MethodAttributes.Static) != 0) {
|
||||
sb.Append ("static ");
|
||||
} else if ((attr & MethodAttributes.Virtual) != 0) {
|
||||
if ((attr & MethodAttributes.VtableLayoutMask) == 0)
|
||||
sb.Append ("override ");
|
||||
else
|
||||
sb.Append ("virtual ");
|
||||
}
|
||||
}
|
||||
|
||||
string name = e.GetAttribute ("name");
|
||||
|
||||
var r = e.GetTypeName ("returntype");
|
||||
if (r != null) {
|
||||
// ctor dont' have a return type
|
||||
sb.Append (r).Append (' ');
|
||||
} else {
|
||||
// show the constructor as it would be defined in C#
|
||||
name = name.Replace (".ctor", State.Type);
|
||||
}
|
||||
|
||||
// the XML file `name` does not contain parameter names, so we must process them ourselves
|
||||
// which gives us the opportunity to simplify type names
|
||||
sb.Append (name.Substring (0, name.IndexOf ('(')));
|
||||
|
||||
var genericp = e.Element ("generic-parameters");
|
||||
if (genericp != null) {
|
||||
var list = new List<string> ();
|
||||
foreach (var p in genericp.Elements ("generic-parameter")) {
|
||||
list.Add (p.GetTypeName ("name"));
|
||||
}
|
||||
sb.Append ("<").Append (String.Join (", ", list)).Append (">");
|
||||
}
|
||||
|
||||
sb.Append (" (");
|
||||
var parameters = e.Element ("parameters");
|
||||
if (parameters != null) {
|
||||
var list = new List<string> ();
|
||||
foreach (var p in parameters.Elements ("parameter")) {
|
||||
var pTypeName = p.GetTypeName ("type");
|
||||
list.Add (State.IgnoreParameterNameChanges
|
||||
? pTypeName
|
||||
: pTypeName + " " + p.GetAttribute ("name"));
|
||||
}
|
||||
sb.Append (String.Join (", ", list));
|
||||
}
|
||||
sb.Append (");");
|
||||
|
||||
return sb.ToString ();
|
||||
}
|
||||
}
|
||||
}
|
75
mcs/tools/mono-api-html/EventComparer.cs
Normal file
75
mcs/tools/mono-api-html/EventComparer.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// 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.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public class EventComparer : MemberComparer {
|
||||
|
||||
public override string GroupName {
|
||||
get { return "events"; }
|
||||
}
|
||||
|
||||
public override string ElementName {
|
||||
get { return "event"; }
|
||||
}
|
||||
|
||||
public override bool Equals (XElement source, XElement target, ApiChanges changes)
|
||||
{
|
||||
if (base.Equals (source, target, changes))
|
||||
return true;
|
||||
|
||||
var change = new ApiChange ();
|
||||
change.Header = "Modified " + GroupName;
|
||||
change.Append ("public event ");
|
||||
|
||||
var srcEventType = source.GetTypeName ("eventtype");
|
||||
var tgtEventType = target.GetTypeName ("eventtype");
|
||||
|
||||
if (srcEventType != tgtEventType) {
|
||||
change.AppendModified (srcEventType, tgtEventType, true);
|
||||
} else {
|
||||
change.Append (srcEventType);
|
||||
}
|
||||
change.Append (" ");
|
||||
change.Append (source.GetAttribute ("name")).Append (";");
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string GetDescription (XElement e)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ();
|
||||
// TODO: attribs
|
||||
sb.Append ("public event ");
|
||||
sb.Append (e.GetTypeName ("eventtype")).Append (' ');
|
||||
sb.Append (e.GetAttribute ("name")).Append (';');
|
||||
return sb.ToString ();
|
||||
}
|
||||
}
|
||||
}
|
211
mcs/tools/mono-api-html/FieldComparer.cs
Normal file
211
mcs/tools/mono-api-html/FieldComparer.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
//
|
||||
// Authors
|
||||
// Sebastien Pouliot <sebastien@xamarin.com>
|
||||
//
|
||||
// Copyright 2013-2014 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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public class FieldComparer : MemberComparer {
|
||||
|
||||
public override string GroupName {
|
||||
get { return "fields"; }
|
||||
}
|
||||
|
||||
public override string ElementName {
|
||||
get { return "field"; }
|
||||
}
|
||||
|
||||
void RenderFieldAttributes (FieldAttributes source, FieldAttributes target, ApiChange change)
|
||||
{
|
||||
var srcNotSerialized = (source & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized;
|
||||
var tgtNotSerialized = (target & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized;
|
||||
if (srcNotSerialized != tgtNotSerialized) {
|
||||
// this is not a breaking change, so only render it if it changed.
|
||||
if (srcNotSerialized) {
|
||||
change.AppendRemoved ("[NonSerialized]\n");
|
||||
} else {
|
||||
change.AppendAdded ("[NonSerialized]\n");
|
||||
}
|
||||
}
|
||||
|
||||
// the visibility values are the same for MethodAttributes and FieldAttributes, so just use the same method.
|
||||
RenderVisibility ((MethodAttributes) source, (MethodAttributes) target, change);
|
||||
// same for the static flag
|
||||
RenderStatic ((MethodAttributes) source, (MethodAttributes) target, change);
|
||||
|
||||
var srcLiteral = (source & FieldAttributes.Literal) != 0;
|
||||
var tgtLiteral = (target & FieldAttributes.Literal) != 0;
|
||||
|
||||
if (srcLiteral) {
|
||||
if (tgtLiteral) {
|
||||
change.Append ("const ");
|
||||
} else {
|
||||
change.AppendRemoved ("const", true).Append (" ");
|
||||
}
|
||||
} else if (tgtLiteral) {
|
||||
change.AppendAdded ("const", true).Append (" ");
|
||||
}
|
||||
|
||||
var srcInitOnly = (source & FieldAttributes.InitOnly) != 0;
|
||||
var tgtInitOnly = (target & FieldAttributes.InitOnly) != 0;
|
||||
if (srcInitOnly) {
|
||||
if (tgtInitOnly) {
|
||||
change.Append ("readonly ");
|
||||
} else {
|
||||
change.AppendRemoved ("readonly", false).Append (" ");
|
||||
}
|
||||
} else if (tgtInitOnly) {
|
||||
change.AppendAdded ("readonly", true).Append (" ");
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals (XElement source, XElement target, ApiChanges changes)
|
||||
{
|
||||
if (base.Equals (source, target, changes))
|
||||
return true;
|
||||
|
||||
var name = source.GetAttribute ("name");
|
||||
var srcValue = source.GetAttribute ("value");
|
||||
var tgtValue = target.GetAttribute ("value");
|
||||
var change = new ApiChange ();
|
||||
change.Header = "Modified " + GroupName;
|
||||
|
||||
if (State.BaseType == "System.Enum") {
|
||||
change.Append (name).Append (" = ");
|
||||
if (srcValue != tgtValue) {
|
||||
change.AppendModified (srcValue, tgtValue, true);
|
||||
} else {
|
||||
change.Append (srcValue);
|
||||
}
|
||||
} else {
|
||||
RenderFieldAttributes (source.GetFieldAttributes (), target.GetFieldAttributes (), change);
|
||||
|
||||
var srcType = source.GetTypeName ("fieldtype");
|
||||
var tgtType = target.GetTypeName ("fieldtype");
|
||||
|
||||
if (srcType != tgtType) {
|
||||
change.AppendModified (srcType, tgtType, true);
|
||||
} else {
|
||||
change.Append (srcType);
|
||||
}
|
||||
change.Append (" ");
|
||||
change.Append (name);
|
||||
|
||||
if (srcType == "string" && srcValue != null)
|
||||
srcValue = "\"" + srcValue + "\"";
|
||||
|
||||
if (tgtType == "string" && tgtValue != null)
|
||||
tgtValue = "\"" + tgtValue + "\"";
|
||||
|
||||
if (srcValue != tgtValue) {
|
||||
change.Append (" = ");
|
||||
if (srcValue == null)
|
||||
srcValue = "null";
|
||||
if (tgtValue == null)
|
||||
tgtValue = "null";
|
||||
change.AppendModified (srcValue, tgtValue, true);
|
||||
} else if (srcValue != null) {
|
||||
change.Append (" = ");
|
||||
change.Append (srcValue);
|
||||
}
|
||||
change.Append (";");
|
||||
}
|
||||
|
||||
changes.Add (source, target, change);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string GetDescription (XElement e)
|
||||
{
|
||||
var sb = new StringBuilder ();
|
||||
|
||||
string name = e.GetAttribute ("name");
|
||||
string value = e.GetAttribute ("value");
|
||||
|
||||
if (State.BaseType == "System.Enum") {
|
||||
sb.Append (name).Append (" = ").Append (value).Append (',');
|
||||
} else {
|
||||
var attribs = e.Attribute ("attrib");
|
||||
if (attribs != null) {
|
||||
var attr = (FieldAttributes)Int32.Parse (attribs.Value);
|
||||
if ((attr & FieldAttributes.Public) != FieldAttributes.Public) {
|
||||
sb.Append ("protected ");
|
||||
} else {
|
||||
sb.Append ("public ");
|
||||
}
|
||||
|
||||
if ((attr & FieldAttributes.Static) != 0)
|
||||
sb.Append ("static ");
|
||||
|
||||
if ((attr & FieldAttributes.Literal) != 0)
|
||||
sb.Append ("const ");
|
||||
}
|
||||
|
||||
string ftype = e.GetTypeName ("fieldtype");
|
||||
sb.Append (ftype).Append (' ');
|
||||
sb.Append (name);
|
||||
if (ftype == "string" && e.Attribute ("value") != null) {
|
||||
if (value == null)
|
||||
sb.Append (" = null");
|
||||
else
|
||||
sb.Append (" = \"").Append (value).Append ('"');
|
||||
}
|
||||
sb.Append (';');
|
||||
}
|
||||
|
||||
return sb.ToString ();
|
||||
}
|
||||
|
||||
public override void BeforeAdding (IEnumerable<XElement> list)
|
||||
{
|
||||
first = true;
|
||||
if (State.BaseType == "System.Enum") {
|
||||
Output.WriteLine ("<div>");
|
||||
Output.WriteLine ("<p>Added value{0}:</p>", list.Count () > 1 ? "s" : String.Empty);
|
||||
Output.WriteLine ("<pre class='added' data-is-non-breaking>");
|
||||
} else {
|
||||
base.BeforeAdding (list);
|
||||
}
|
||||
}
|
||||
|
||||
public override void BeforeRemoving (IEnumerable<XElement> list)
|
||||
{
|
||||
first = true;
|
||||
if (State.BaseType == "System.Enum") {
|
||||
Output.WriteLine ("<p>Removed value{0}:</p>", list.Count () > 1 ? "s" : String.Empty);
|
||||
Output.WriteLine ("<pre class='removed' data-is-breaking>");
|
||||
} else {
|
||||
base.BeforeRemoving (list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
207
mcs/tools/mono-api-html/Helpers.cs
Normal file
207
mcs/tools/mono-api-html/Helpers.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
//
|
||||
// Authors
|
||||
// Sebastien Pouliot <sebastien@xamarin.com>
|
||||
//
|
||||
// Copyright 2013-2014 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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public static class Helper {
|
||||
public static bool IsTrue (this XElement self, string name)
|
||||
{
|
||||
return (self.GetAttribute (name) == "true");
|
||||
}
|
||||
|
||||
public static string GetAttribute (this XElement self, string name)
|
||||
{
|
||||
var n = self.Attribute (name);
|
||||
if (n == null)
|
||||
return null;
|
||||
return n.Value;
|
||||
}
|
||||
|
||||
// null == no obsolete, String.Empty == no description
|
||||
public static string GetObsoleteMessage (this XElement self)
|
||||
{
|
||||
var cattrs = self.Element ("attributes");
|
||||
if (cattrs == null)
|
||||
return null;
|
||||
|
||||
foreach (var ca in cattrs.Elements ("attribute")) {
|
||||
if (ca.GetAttribute ("name") != "System.ObsoleteAttribute")
|
||||
continue;
|
||||
var props = ca.Element ("properties");
|
||||
if (props == null)
|
||||
return String.Empty; // no description
|
||||
foreach (var p in props.Elements ("property")) {
|
||||
if (p.GetAttribute ("name") != "Message")
|
||||
continue;
|
||||
return p.GetAttribute ("value");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IEnumerable<XElement> Descendants (this XElement self, params string[] names)
|
||||
{
|
||||
XElement el = self;
|
||||
if (el == null)
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < names.Length - 1; i++) {
|
||||
el = el.Element (names [i]);
|
||||
if (el == null)
|
||||
return null;
|
||||
}
|
||||
return el.Elements (names [names.Length - 1]);
|
||||
}
|
||||
|
||||
public static List<XElement> DescendantList (this XElement self, params string[] names)
|
||||
{
|
||||
var descendants = self.Descendants (names);
|
||||
if (descendants == null)
|
||||
return null;
|
||||
return descendants.ToList ();
|
||||
}
|
||||
|
||||
// make it beautiful (.NET -> C#)
|
||||
public static string GetTypeName (this XElement self, string name)
|
||||
{
|
||||
string type = self.GetAttribute (name);
|
||||
if (type == null)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = null;
|
||||
bool is_nullable = false;
|
||||
if (type.StartsWith ("System.Nullable`1[", StringComparison.Ordinal)) {
|
||||
is_nullable = true;
|
||||
sb = new StringBuilder (type, 18, type.Length - 19, 1024);
|
||||
} else {
|
||||
sb = new StringBuilder (type);
|
||||
}
|
||||
|
||||
bool is_ref = (sb [sb.Length - 1] == '&');
|
||||
if (is_ref)
|
||||
sb.Remove (sb.Length - 1, 1);
|
||||
|
||||
int array = 0;
|
||||
while ((sb [sb.Length - 1] == ']') && (sb [sb.Length - 2] == '[')) {
|
||||
sb.Remove (sb.Length - 2, 2);
|
||||
array++;
|
||||
}
|
||||
|
||||
bool is_pointer = (sb [sb.Length - 1] == '*');
|
||||
if (is_pointer)
|
||||
sb.Remove (sb.Length - 1, 1);
|
||||
|
||||
type = GetTypeName (sb.Replace ('+', '.').ToString ());
|
||||
sb.Length = 0;
|
||||
if (is_ref)
|
||||
sb.Append (self.GetAttribute ("direction")).Append (' ');
|
||||
|
||||
sb.Append (type);
|
||||
|
||||
while (array-- > 0)
|
||||
sb.Append ("[]");
|
||||
if (is_nullable)
|
||||
sb.Append ('?');
|
||||
if (is_pointer)
|
||||
sb.Append ('*');
|
||||
return sb.ToString ();
|
||||
}
|
||||
|
||||
static string GetTypeName (string type)
|
||||
{
|
||||
int pos = type.IndexOf ('`');
|
||||
if (pos >= 0) {
|
||||
int end = type.LastIndexOf (']');
|
||||
string subtype = type.Substring (pos + 3, end - pos - 3);
|
||||
return type.Substring (0, pos) + "<" + GetTypeName (subtype) + ">";
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case "System.String":
|
||||
return "string";
|
||||
case "System.Int32":
|
||||
return "int";
|
||||
case "System.UInt32":
|
||||
return "uint";
|
||||
case "System.Int64":
|
||||
return "long";
|
||||
case "System.UInt64":
|
||||
return "ulong";
|
||||
case "System.Void":
|
||||
return "void";
|
||||
case "System.Boolean":
|
||||
return "bool";
|
||||
case "System.Object":
|
||||
return "object";
|
||||
case "System.Single":
|
||||
return "float";
|
||||
case "System.Double":
|
||||
return "double";
|
||||
case "System.Byte":
|
||||
return "byte";
|
||||
case "System.SByte":
|
||||
return "sbyte";
|
||||
case "System.Int16":
|
||||
return "short";
|
||||
case "System.UInt16":
|
||||
return "ushort";
|
||||
case "System.Char":
|
||||
return "char";
|
||||
case "System.nint":
|
||||
return "nint";
|
||||
case "System.nuint":
|
||||
return "uint";
|
||||
case "System.nfloat":
|
||||
return "nfloat";
|
||||
case "System.IntPtr":
|
||||
return "IntPtr";
|
||||
default:
|
||||
if (type.StartsWith (State.Namespace, StringComparison.Ordinal))
|
||||
type = type.Substring (State.Namespace.Length + 1);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
public static MethodAttributes GetMethodAttributes (this XElement element)
|
||||
{
|
||||
var srcAttribs = element.Attribute ("attrib");
|
||||
return (MethodAttributes) (srcAttribs != null ? Int32.Parse (srcAttribs.Value) : 0);
|
||||
}
|
||||
|
||||
public static FieldAttributes GetFieldAttributes (this XElement element)
|
||||
{
|
||||
var srcAttribs = element.Attribute ("attrib");
|
||||
return (FieldAttributes) (srcAttribs != null ? Int32.Parse (srcAttribs.Value) : 0);
|
||||
}
|
||||
}
|
||||
}
|
47
mcs/tools/mono-api-html/InterfaceComparer.cs
Normal file
47
mcs/tools/mono-api-html/InterfaceComparer.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// 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.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public class InterfaceComparer : MemberComparer {
|
||||
|
||||
public override string GroupName {
|
||||
get { return "interfaces"; }
|
||||
}
|
||||
|
||||
public override string ElementName {
|
||||
get { return "interface"; }
|
||||
}
|
||||
|
||||
public override string GetDescription (XElement e)
|
||||
{
|
||||
return e.GetTypeName ("name");
|
||||
}
|
||||
}
|
||||
}
|
10
mcs/tools/mono-api-html/Makefile
Normal file
10
mcs/tools/mono-api-html/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
thisdir = tools/mono-api-html
|
||||
SUBDIRS =
|
||||
include ../../build/rules.make
|
||||
|
||||
LIB_REFS = Mono.Cecil System.Xml System.Core System System.Xml.Linq
|
||||
LOCAL_MCS_FLAGS =
|
||||
|
||||
PROGRAM = mono-api-html.exe
|
||||
|
||||
include ../../build/executable.make
|
608
mcs/tools/mono-api-html/MemberComparer.cs
Normal file
608
mcs/tools/mono-api-html/MemberComparer.cs
Normal file
File diff suppressed because it is too large
Load Diff
77
mcs/tools/mono-api-html/MethodComparer.cs
Normal file
77
mcs/tools/mono-api-html/MethodComparer.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public class MethodComparer : ConstructorComparer {
|
||||
|
||||
public override string GroupName {
|
||||
get { return "methods"; }
|
||||
}
|
||||
|
||||
public override string ElementName {
|
||||
get { return "method"; }
|
||||
}
|
||||
|
||||
// operators have identical names but vary by return types
|
||||
public override bool Find (XElement e)
|
||||
{
|
||||
if (e.GetAttribute ("name") != Source.GetAttribute ("name"))
|
||||
return false;
|
||||
|
||||
if (e.GetAttribute ("returntype") != Source.GetAttribute ("returntype"))
|
||||
return false;
|
||||
|
||||
var eGP = e.Element ("generic-parameters");
|
||||
var sGP = Source.Element ("generic-parameters");
|
||||
|
||||
if (eGP == null && sGP == null)
|
||||
return true;
|
||||
else if (eGP == null ^ sGP == null)
|
||||
return false;
|
||||
else {
|
||||
var eGPs = eGP.Elements ("generic-parameter");
|
||||
var sGPs = sGP.Elements ("generic-parameter");
|
||||
return eGPs.Count () == sGPs.Count ();
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool IsBreakingRemoval (XElement e)
|
||||
{
|
||||
// Removing virtual methods that override another method is not a breaking change.
|
||||
var is_override = e.Attribute ("is-override");
|
||||
if (is_override != null)
|
||||
return is_override.Value != "true";
|
||||
|
||||
return true; // all other removals are breaking changes
|
||||
}
|
||||
}
|
||||
}
|
104
mcs/tools/mono-api-html/NamespaceComparer.cs
Normal file
104
mcs/tools/mono-api-html/NamespaceComparer.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Xamarin.ApiDiff {
|
||||
|
||||
public class NamespaceComparer : Comparer {
|
||||
|
||||
ClassComparer comparer;
|
||||
|
||||
public NamespaceComparer ()
|
||||
{
|
||||
comparer = new ClassComparer ();
|
||||
}
|
||||
|
||||
public void Compare (XElement source, XElement target)
|
||||
{
|
||||
var s = source.Element ("namespaces");
|
||||
var t = target.Element ("namespaces");
|
||||
if (XNode.DeepEquals (s, t))
|
||||
return;
|
||||
Compare (s.Elements ("namespace"), t.Elements ("namespace"));
|
||||
}
|
||||
|
||||
public override void SetContext (XElement current)
|
||||
{
|
||||
State.Namespace = current.Attribute ("name").Value;
|
||||
}
|
||||
|
||||
public override void Added (XElement target, bool wasParentAdded)
|
||||
{
|
||||
string name = target.Attribute ("name").Value;
|
||||
if (State.IgnoreNew.Any (re => re.IsMatch (name)))
|
||||
return;
|
||||
|
||||
Output.WriteLine ("<!-- start namespace {0} --> <div> ", name);
|
||||
Output.WriteLine ("<h2>New Namespace {0}</h2>", name);
|
||||
Output.WriteLine ();
|
||||
// list all new types
|
||||
foreach (var addedType in target.Element ("classes").Elements ("class"))
|
||||
comparer.Added (addedType, true);
|
||||
Output.WriteLine ("</div> <!-- end namespace {0} -->", name);
|
||||
Output.WriteLine ();
|
||||
}
|
||||
|
||||
public override void Modified (XElement source, XElement target, ApiChanges differences)
|
||||
{
|
||||
var output = Output;
|
||||
State.Output = new StringWriter ();
|
||||
comparer.Compare (source, target);
|
||||
|
||||
var s = Output.ToString ();
|
||||
State.Output = output;
|
||||
if (s.Length > 0) {
|
||||
var name = target.Attribute ("name").Value;
|
||||
Output.WriteLine ("<!-- start namespace {0} --> <div> ", name);
|
||||
Output.WriteLine ("<h2>Namespace {0}</h2>", name);
|
||||
Output.WriteLine (s);
|
||||
Output.WriteLine ("</div> <!-- end namespace {0} -->", name);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Removed (XElement source)
|
||||
{
|
||||
var name = source.Attribute ("name").Value;
|
||||
Output.WriteLine ("<!-- start namespace {0} --> <div>", name);
|
||||
Output.WriteLine ("<h2>Removed Namespace {0}</h2>", name);
|
||||
Output.WriteLine ();
|
||||
// list all removed types
|
||||
foreach (var removedType in source.Element ("classes").Elements ("class"))
|
||||
comparer.Removed (removedType);
|
||||
Output.WriteLine ("</div> <!-- end namespace {0} -->", name);
|
||||
Output.WriteLine ();
|
||||
}
|
||||
}
|
||||
}
|
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 ();
|
||||
}
|
||||
}
|
||||
}
|
15
mcs/tools/mono-api-html/mono-api-html.exe.sources
Normal file
15
mcs/tools/mono-api-html/mono-api-html.exe.sources
Normal file
@@ -0,0 +1,15 @@
|
||||
ApiChange.cs
|
||||
ApiDiff.cs
|
||||
AssemblyComparer.cs
|
||||
ClassComparer.cs
|
||||
Comparer.cs
|
||||
ConstructorComparer.cs
|
||||
EventComparer.cs
|
||||
FieldComparer.cs
|
||||
Helpers.cs
|
||||
InterfaceComparer.cs
|
||||
MemberComparer.cs
|
||||
MethodComparer.cs
|
||||
NamespaceComparer.cs
|
||||
PropertyComparer.cs
|
||||
../../class/Mono.Options/Mono.Options/Options.cs
|
Reference in New Issue
Block a user