diff options
author | Rolf Bjarne Kvinge <rolf@xamarin.com> | 2016-01-28 17:14:13 +0300 |
---|---|---|
committer | Rolf Bjarne Kvinge <rolf@xamarin.com> | 2016-01-28 17:32:56 +0300 |
commit | a8c6b0d380ba283a3aad3aa61d27beee5ab7df29 (patch) | |
tree | 54a7499cd04a0286d4397151f5195cb2a22398ce | |
parent | 4279991d274796eb3ae6c5507c6194bd3cd69187 (diff) |
[mono-api-html] Make it possible to hide/show non-breaking changes in the html output.
We now add data-is-[non-]breaking attributes to the generated
html elements, and then use some javascript logic to show/hide
non-breaking elements (and the javascript also looks in the
container elements show/hide containers that have only
non-breaking descendants).
Also use css classes/styles to colorize.
8 files changed, 147 insertions, 34 deletions
diff --git a/mcs/tools/corcompare/mono-api-html/ApiChange.cs b/mcs/tools/corcompare/mono-api-html/ApiChange.cs index 72e905b8c58..1d902cacfad 100644 --- a/mcs/tools/corcompare/mono-api-html/ApiChange.cs +++ b/mcs/tools/corcompare/mono-api-html/ApiChange.cs @@ -21,15 +21,9 @@ namespace Xamarin.ApiDiff public ApiChange AppendAdded (string text, bool breaking = false) { - if (breaking) - Member.Append ("<span style='text-decoration: underline'>"); - if (State.Colorize) - Member.Append ("<span style='color:green'>"); + Member.Append ("<span class='added ").Append (breaking ? "added-breaking-inline" : string.Empty).Append ("'>"); Member.Append (text); - if (State.Colorize) - Member.Append ("</span>"); - if (breaking) - Member.Append ("</span>"); + Member.Append ("</span>"); Breaking |= breaking; AnyChange = true; return this; @@ -37,12 +31,8 @@ namespace Xamarin.ApiDiff public ApiChange AppendRemoved (string text, bool breaking = true) { - Member.Append ("<span style='text-decoration: line-through'>"); - if (State.Colorize && breaking) - Member.Append ("<span style='color:red'>"); + Member.Append ("<span class='removed removed-inline ").Append (breaking ? "removed-breaking-inline" : string.Empty).Append ("'>"); Member.Append (text); - if (State.Colorize && breaking) - Member.Append ("</span>"); Member.Append ("</span>"); Breaking |= breaking; AnyChange = true; diff --git a/mcs/tools/corcompare/mono-api-html/ApiDiff.cs b/mcs/tools/corcompare/mono-api-html/ApiDiff.cs index 69454e1184c..8fe27844852 100644 --- a/mcs/tools/corcompare/mono-api-html/ApiDiff.cs +++ b/mcs/tools/corcompare/mono-api-html/ApiDiff.cs @@ -168,12 +168,98 @@ namespace Xamarin.ApiDiff { } 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 { diff --git a/mcs/tools/corcompare/mono-api-html/ClassComparer.cs b/mcs/tools/corcompare/mono-api-html/ClassComparer.cs index 761f87a5552..1e19ab4b38e 100644 --- a/mcs/tools/corcompare/mono-api-html/ClassComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/ClassComparer.cs @@ -72,11 +72,13 @@ namespace Xamarin.ApiDiff { 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 (State.Colorize ? "<pre style='color: green'>" : "<pre>"); + 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) @@ -226,17 +228,17 @@ namespace Xamarin.ApiDiff { 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) { - var style = string.Empty; - if (State.Colorize) - style = "style='color: red'"; - Output.Write ("<h3>Removed Type <span {0}>{1}.{2}</span></h3>", style, State.Namespace, GetTypeName (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) diff --git a/mcs/tools/corcompare/mono-api-html/FieldComparer.cs b/mcs/tools/corcompare/mono-api-html/FieldComparer.cs index bb4f6c6b075..a2b0225b448 100644 --- a/mcs/tools/corcompare/mono-api-html/FieldComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/FieldComparer.cs @@ -189,8 +189,9 @@ namespace Xamarin.ApiDiff { { 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 (State.Colorize ? "<pre style='color: green'>" : "<pre>"); + Output.WriteLine ("<pre class='added' data-is-non-breaking>"); } else { base.BeforeAdding (list); } @@ -201,7 +202,7 @@ namespace Xamarin.ApiDiff { first = true; if (State.BaseType == "System.Enum") { Output.WriteLine ("<p>Removed value{0}:</p>", list.Count () > 1 ? "s" : String.Empty); - Output.WriteLine (State.Colorize ? "<pre style='color: red'>" : "<pre>"); + Output.WriteLine ("<pre class='removed' data-is-breaking>"); } else { base.BeforeRemoving (list); } diff --git a/mcs/tools/corcompare/mono-api-html/MemberComparer.cs b/mcs/tools/corcompare/mono-api-html/MemberComparer.cs index dee528ebc7a..92e36e8fd79 100644 --- a/mcs/tools/corcompare/mono-api-html/MemberComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/MemberComparer.cs @@ -41,6 +41,11 @@ namespace Xamarin.ApiDiff { public abstract string GroupName { get; } public abstract string ElementName { get; } + protected virtual bool IsBreakingRemoval (XElement e) + { + return true; + } + public void Compare (XElement source, XElement target) { var s = source.Element (GroupName); @@ -136,8 +141,10 @@ namespace Xamarin.ApiDiff { Output.WriteLine ("<p>{0}:</p>", changes.Key); Output.WriteLine ("<pre>"); foreach (var element in changes.Value) { + 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); + Output.Write ("</div>"); } Output.WriteLine ("</pre>"); @@ -192,10 +199,10 @@ namespace Xamarin.ApiDiff { public virtual void BeforeAdding (IEnumerable<XElement> list) { first = true; - Output.WriteLine ("<p>Added {0}:</p>", list.Count () > 1 ? GroupName : ElementName); - bool isInterface = list.Count () > 0 && IsInInterface (list.First ()); - Output.WriteLine (State.Colorize ? string.Format ("<pre style='color: {0}'>", isInterface ? "red" : "green") : "<pre>"); + Output.WriteLine ("<div>"); + Output.WriteLine ("<p>Added {0}:</p>", list.Count () > 1 ? GroupName : ElementName); + Output.WriteLine ("<pre>"); } public override void Added (XElement target) @@ -203,13 +210,18 @@ namespace Xamarin.ApiDiff { var o = GetObsoleteMessage (target); if (!first && (o.Length > 0)) Output.WriteLine (); - Indent ().WriteLine ("\t{0}{1}", o, GetDescription (target)); + Indent (); + bool isInterface = IsInInterface (target); + Output.Write ("\t<span class='added added-{0} {1}' {2}>", ElementName, isInterface ? "breaking" : string.Empty, isInterface ? "data-is-breaking" : "data-is-non-breaking"); + Output.Write ("{0}{1}", o, GetDescription (target)); + Output.WriteLine ("</span>"); first = false; } public virtual void AfterAdding () { - Output.WriteLine ("</pre>");; + Output.WriteLine ("</pre>"); + Output.WriteLine ("</div>"); } public override void Modified (XElement source, XElement target, ApiChanges change) @@ -220,7 +232,7 @@ namespace Xamarin.ApiDiff { { first = true; Output.WriteLine ("<p>Removed {0}:</p>\n", list.Count () > 1 ? GroupName : ElementName); - Output.WriteLine (State.Colorize ? "<pre style='color: red'>" : "<pre>"); + Output.WriteLine ("<pre>"); } public override void Removed (XElement source) @@ -228,7 +240,13 @@ namespace Xamarin.ApiDiff { var o = GetObsoleteMessage (source); if (!first && (o.Length > 0)) Output.WriteLine (); - Indent ().WriteLine ("\t{0}{1}", o, GetDescription (source)); + + bool is_breaking = IsBreakingRemoval (source); + + Indent (); + Output.Write ("\t<span class='removed removed-{0} {2}' {1}>", ElementName, is_breaking ? "data-is-breaking" : "data-is-non-breaking", is_breaking ? "breaking" : string.Empty); + Output.Write ("{0}{1}", o, GetDescription (source)); + Output.WriteLine ("</span>"); first = false; } @@ -558,15 +576,13 @@ namespace Xamarin.ApiDiff { return; // neither is obsolete var change = new ApiChange (); change.Header = "Obsoleted " + GroupName; - if (State.Colorize) - change.Append ("<span style='color:gray'>"); + change.Append (string.Format ("<span class='obsolete obsolete-{0}' data-is-non-breaking>", ElementName)); change.Append ("[Obsolete ("); if (tgtObsolete != string.Empty) change.Append ("\"").Append (tgtObsolete).Append ("\""); change.Append (")]\n"); change.Append (GetDescription (target)); - if (State.Colorize) - change.Append ("</span>"); + change.Append ("</span>"); change.AnyChange = true; changes.Add (source, target, change); } else if (tgtObsolete == null) { diff --git a/mcs/tools/corcompare/mono-api-html/MethodComparer.cs b/mcs/tools/corcompare/mono-api-html/MethodComparer.cs index 1dffa17dfcc..4c893e757ec 100644 --- a/mcs/tools/corcompare/mono-api-html/MethodComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/MethodComparer.cs @@ -26,6 +26,7 @@ using System; using System.Linq; +using System.Reflection; using System.Xml.Linq; namespace Xamarin.ApiDiff { @@ -62,5 +63,15 @@ namespace Xamarin.ApiDiff { 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 + } } }
\ No newline at end of file diff --git a/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs b/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs index 258374c6b9d..746166e0a64 100644 --- a/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs +++ b/mcs/tools/corcompare/mono-api-html/NamespaceComparer.cs @@ -61,11 +61,13 @@ namespace Xamarin.ApiDiff { 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); + Output.WriteLine ("</div> <!-- end namespace {0} -->", name); Output.WriteLine (); } @@ -78,18 +80,24 @@ namespace Xamarin.ApiDiff { var s = Output.ToString (); State.Output = output; if (s.Length > 0) { - Output.WriteLine ("<h2>Namespace {0}</h2>", target.Attribute ("name").Value); + 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) { - Output.WriteLine ("<h2>Removed Namespace {0}</h2>", source.Attribute ("name").Value); + 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 (); } } diff --git a/mcs/tools/corcompare/mono-api-html/mono-api-html.csproj b/mcs/tools/corcompare/mono-api-html/mono-api-html.csproj index 286a4d0192a..6ac0f241ade 100644 --- a/mcs/tools/corcompare/mono-api-html/mono-api-html.csproj +++ b/mcs/tools/corcompare/mono-api-html/mono-api-html.csproj @@ -19,7 +19,6 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <ConsolePause>false</ConsolePause> - <Commandlineparameters>/Developer/MonoTouch/Source/monotouch/tools/apidiff/references/compat/monotouch.xml /Developer/MonoTouch/Source/monotouch/tools/apidiff/temp/compat/monotouch.xml -i INSObjectProtocol /tmp/diff.html</Commandlineparameters> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>full</DebugType> |