2 // The main differences with mono-api-diff are:
3 // * this tool directly produce HTML similar to gdiff.sh used for Xamarin.iOS
4 // * this tool reports changes in an "evolutionary" way, not in a breaking way,
5 // i.e. it does not assume the source assembly is right (but simply older)
6 // * the diff .xml output was not easy to convert back into the HTML format
7 // that gdiff.sh produced
10 // Sebastien Pouliot <sebastien@xamarin.com>
12 // Copyright 2013-2014 Xamarin Inc. http://www.xamarin.com
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections.Generic;
37 using System.Text.RegularExpressions;
41 namespace Xamarin.ApiDiff {
43 public static class State {
44 static TextWriter output;
46 public static TextWriter Output {
52 set { output = value; }
55 public static string Assembly { get; set; }
56 public static string Namespace { get; set; }
57 public static string Type { get; set; }
58 public static string BaseType { get; set; }
60 public static int Indent { get; set; }
62 static List<Regex> ignoreAdded = new List<Regex> ();
63 public static List<Regex> IgnoreAdded {
64 get { return ignoreAdded; }
67 static List<Regex> ignoreRemoved = new List<Regex> ();
68 public static List<Regex> IgnoreRemoved {
69 get { return ignoreRemoved; }
72 public static bool Lax;
77 public static int Main (string[] args)
81 List<string> extra = null;
83 var options = new OptionSet {
84 { "h|help", "Show this help", v => showHelp = true },
85 { "d|diff=", "HTML diff file out output (omit for stdout)", v => diff = v },
86 { "i|ignore=", "Ignore both added and removed members whose description matches a given C# regular expression (see below).",
88 var r = new Regex (v);
89 State.IgnoreAdded.Add (r);
90 State.IgnoreRemoved.Add (r);
93 { "a|ignore-added=", "Ignore added members whose description matches a given C# regular expression (see below).",
94 v => State.IgnoreAdded.Add (new Regex (v))
96 { "r|ignore-removed=", "Ignore removed members whose description matches a given C# regular expression (see below).",
97 v => State.IgnoreRemoved.Add (new Regex (v))
99 { "x|lax", "Ignore duplicate XML entries", v => State.Lax = true }
103 extra = options.Parse (args);
104 } catch (OptionException e) {
105 Console.WriteLine ("Option error: {0}", e.Message);
109 if (showHelp || extra == null || extra.Count < 2 || extra.Count > 3) {
110 Console.WriteLine (@"Usage: mono-api-html [options] <reference.xml> <assembly.xml> [diff.html]");
111 Console.WriteLine ();
112 Console.WriteLine ("Available options:");
113 options.WriteOptionDescriptions (Console.Out);
114 Console.WriteLine ();
115 Console.WriteLine ("Ignoring Members:");
116 Console.WriteLine ();
117 Console.WriteLine (" Members that were added can be filtered out of the diff by using the");
118 Console.WriteLine (" -i, --ignore-added option. The option takes a C# regular expression");
119 Console.WriteLine (" to match against member descriptions. For example, to ignore the");
120 Console.WriteLine (" introduction of the interfaces 'INSCopying' and 'INSCoding' on types");
121 Console.WriteLine (" pass the following to mono-api-html:");
122 Console.WriteLine ();
123 Console.WriteLine (" mono-api-html ... -i 'INSCopying$' -i 'INSCoding$'");
124 Console.WriteLine ();
125 Console.WriteLine (" The regular expressions will match any member description ending with");
126 Console.WriteLine (" 'INSCopying' or 'INSCoding'.");
127 Console.WriteLine ();
131 var input = extra [0];
132 var output = extra [1];
133 if (extra.Count == 3 && diff == null)
137 var ac = new AssemblyComparer (input, output);
139 string diffHtml = String.Empty;
140 using (var writer = new StringWriter ()) {
141 State.Output = writer;
143 diffHtml = State.Output.ToString ();
145 if (diffHtml.Length > 0) {
146 using (var file = new StreamWriter (diff)) {
147 if (ac.SourceAssembly == ac.TargetAssembly) {
148 file.WriteLine ("<h1>{0}.dll</h1>", ac.SourceAssembly);
150 file.WriteLine ("<h1>{0}.dll vs {1}.dll</h1>", ac.SourceAssembly, ac.TargetAssembly);
152 file.Write (diffHtml);
156 State.Output = Console.Out;
160 catch (Exception e) {
161 Console.WriteLine (e);