3 // Sebastien Pouliot <sebastien@xamarin.com>
5 // Copyright 2013-2014 Xamarin Inc. http://www.xamarin.com
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 using System.Collections.Generic;
31 using System.Xml.Linq;
33 namespace Xamarin.ApiDiff {
35 public abstract class MemberComparer : Comparer {
37 public abstract string GroupName { get; }
38 public abstract string ElementName { get; }
40 public void Compare (XElement source, XElement target)
42 var s = source.Element (GroupName);
43 var t = target.Element (GroupName);
44 if (XNode.DeepEquals (s, t))
48 Add (t.Elements (ElementName));
49 } else if (t == null) {
50 Remove (s.Elements (ElementName));
52 Compare (s.Elements (ElementName), t.Elements (ElementName));
56 public override void SetContext (XElement current)
60 public XElement Source { get; set; }
62 public virtual bool Find (XElement e)
64 return e.GetAttribute ("name") == Source.GetAttribute ("name");
67 XElement Find (IEnumerable<XElement> target)
69 return State.Lax ? target.FirstOrDefault (Find) : target.SingleOrDefault (Find);
72 public override void Compare (IEnumerable<XElement> source, IEnumerable<XElement> target)
77 foreach (var s in source) {
80 var t = Find (target);
82 // not in target, it was removed
87 if (IsNowObsoleted (s, t)) {
94 // still in target so will be part of Added
99 // delayed, that way we show "Modified", "Added" and then "Removed"
102 // remaining == newly added in target
105 // obsolete (considering as added, they were not obsolete before, wrt regex)
107 foreach (var item in obsoleted) {
109 if (State.IgnoreAdded.Any (re => re.IsMatch (GetDescription (item))))
112 BeforeObsoleting (obsoleted);
121 void Add (IEnumerable<XElement> elements)
124 foreach (var item in elements) {
126 if (State.IgnoreAdded.Any (re => re.IsMatch (GetDescription (item))))
129 BeforeAdding (elements);
138 void Remove (IEnumerable<XElement> elements)
141 foreach (var item in elements) {
142 if (State.IgnoreRemoved.Any (re => re.IsMatch (GetDescription (item))))
146 BeforeRemoving (elements);
155 public abstract string GetDescription (XElement e);
157 protected StringBuilder GetObsoleteMessage (XElement e)
159 var sb = new StringBuilder ();
160 string o = e.GetObsoleteMessage ();
162 sb.Append ("[Obsolete");
164 sb.Append (" (\"").Append (o).Append ("\")");
166 for (int i = 0; i < State.Indent + 1; i++)
172 public override bool Equals (XElement source, XElement target)
174 if (base.Equals (source, target))
177 return GetDescription (source) == GetDescription (target);
180 bool IsNowObsoleted (XElement source, XElement target)
182 var s = GetObsoleteMessage (source).ToString ();
183 var t = GetObsoleteMessage (target).ToString ();
184 // true if it was no [Obsolete] in the source but now is [Obsolete] in the target
185 return (s.Length == 0 && t.Length > 0);
188 public virtual void BeforeAdding (IEnumerable<XElement> list)
190 Output.WriteLine ("<p>Added {0}:</p><pre>", list.Count () > 1 ? GroupName : ElementName);
193 public override void Added (XElement target)
195 Indent ().WriteLine ("\t{0}", GetDescription (target));
198 public virtual void AfterAdding ()
200 Output.WriteLine ("</pre>");
203 public virtual void BeforeObsoleting (IEnumerable<XElement> list)
205 Output.WriteLine ("<p>Obsoleted {0}:</p><pre>", list.Count () > 1 ? GroupName : ElementName);
208 public void Obsoleted (XElement target)
210 Indent ().WriteLine ("\t{0}{1}{2}", GetObsoleteMessage (target), GetDescription (target), Environment.NewLine);
213 public virtual void AfterObsoleting ()
215 Output.WriteLine ("</pre>");
218 public override void Modified (XElement source, XElement target)
222 public virtual void BeforeRemoving (IEnumerable<XElement> list)
224 Output.WriteLine ("<p>Removed {0}:</p><pre>", list.Count () > 1 ? GroupName : ElementName);
227 public override void Removed (XElement source)
229 Indent ().WriteLine ("\t{0}", GetDescription (source));
232 public virtual void AfterRemoving ()
234 Output.WriteLine ("</pre>");