public static bool IgnoreVirtualChanges { get; set; }
public static bool IgnoreAddedPropertySetters { get; set; }
+ public static bool IgnoreNonbreaking { get; set; }
+
public static bool Lax;
public static bool Colorize = true;
}
-
class Program {
public static int Main (string[] args)
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 }
+ { "x|lax", "Ignore duplicate XML entries", v => State.Lax = true },
+ { "ignore-nonbreaking", "Ignore all nonbreaking changes", v => State.IgnoreNonbreaking = true }
};
try {
showHelp = true;
}
+ if (State.IgnoreNonbreaking) {
+ State.IgnoreAddedPropertySetters = true;
+ State.IgnoreVirtualChanges = true;
+ State.IgnoreNew.Add (new Regex (".*"));
+ State.IgnoreAdded.Add (new Regex (".*"));
+ }
+
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 ();
} 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/>");
+ if (!State.IgnoreNonbreaking) {
+ 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 -->");
Indent ().WriteLine ("}");
}
+ //HACK: we don't have hierarchy information here so just check some basic heuristics for now
+ bool IsBaseChangeCompatible (string source, string target)
+ {
+ if (source == "System.Object")
+ return true;
+ if (source == "System.Exception" && target.EndsWith ("Exception", StringComparison.Ordinal))
+ return true;
+ if (source == "System.EventArgs" && target.EndsWith ("EventArgs", StringComparison.Ordinal))
+ return true;
+ if (source == "System.Runtime.InteropServices.SafeHandle" && target.StartsWith ("Microsoft.Win32.SafeHandles.SafeHandle", StringComparison.Ordinal))
+ return true;
+ return false;
+ }
+
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 sb = source.GetAttribute ("base");
var tb = target.GetAttribute ("base");
- if (sb != tb) {
+ if (sb != tb && !(State.IgnoreNonbreaking && IsBaseChangeCompatible (sb, tb))) {
Output.Write ("Modified base type: ");
Output.WriteLine (new ApiChange ().AppendModified (sb, tb, true).Member.ToString ());
}
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");
+ if (!State.IgnoreNonbreaking) {
+ 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");
+ }
}
}
void Modify (ApiChanges modified)
{
foreach (var changes in modified) {
+ if (State.IgnoreNonbreaking && changes.Value.All (c => !c.Breaking))
+ continue;
Output.WriteLine ("<p>{0}:</p>", changes.Key);
Output.WriteLine ("<pre>");
foreach (var element in changes.Value) {
+ if (State.IgnoreNonbreaking && !element.Breaking)
+ continue;
Output.Write ("<div {0}>", element.Breaking ? "data-is-breaking" : "data-is-non-breaking");
foreach (var line in element.Member.ToString ().Split ('\n'))
Output.WriteLine ("\t{0}", line);
if (State.IgnoreRemoved.Any (re => re.IsMatch (GetDescription (item))))
continue;
SetContext (item);
+ if (State.IgnoreNonbreaking && !IsBreakingRemoval (item))
+ continue;
if (!r) {
BeforeRemoving (elements);
r = true;