audit: Refresh utilities using code from Mono git master
Copy latest versions of mono-api-info.cs and mono-api-diff.cs from Mono git master, along with associated classes. As a consequence, mono-api-info.cs now depends on Mono.Cecil. Do the necessary adaptation for our use case: we do API comparison between version of our assemblies.
This commit is contained in:
parent
88bb31bfa7
commit
1eb786c735
7 changed files with 1379 additions and 494 deletions
53
audit/AssemblyResolver.cs
Normal file
53
audit/AssemblyResolver.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// AssemblyResolver.cs
|
||||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@novell.com)
|
||||
//
|
||||
// Copyright (C) 2007 Novell, Inc.
|
||||
//
|
||||
// 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;
|
||||
using System.IO;
|
||||
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace GuiCompare {
|
||||
|
||||
public class AssemblyResolver : DefaultAssemblyResolver {
|
||||
|
||||
public AssemblyDefinition ResolveFile (string file)
|
||||
{
|
||||
return ProcessFile (file);
|
||||
}
|
||||
|
||||
AssemblyDefinition ProcessFile (string file)
|
||||
{
|
||||
AddSearchDirectory (Path.GetDirectoryName (file));
|
||||
var assembly = AssemblyDefinition.ReadAssembly (file, new ReaderParameters { AssemblyResolver = this });
|
||||
RegisterAssembly (assembly);
|
||||
|
||||
return assembly;
|
||||
}
|
||||
}
|
||||
}
|
115
audit/Util.cs
Normal file
115
audit/Util.cs
Normal file
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// Util.cs
|
||||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@novell.com)
|
||||
//
|
||||
// Copyright (C) 2008 Novell, Inc.
|
||||
//
|
||||
// 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.Text;
|
||||
using Mono.Cecil;
|
||||
|
||||
using GuiCompare;
|
||||
|
||||
namespace Mono.AssemblyCompare {
|
||||
|
||||
static class TypeHelper {
|
||||
|
||||
public static AssemblyResolver Resolver = new AssemblyResolver ();
|
||||
|
||||
internal static bool IsPublic (TypeReference typeref)
|
||||
{
|
||||
if (typeref == null)
|
||||
throw new ArgumentNullException ("typeref");
|
||||
|
||||
TypeDefinition td = typeref.Resolve ();
|
||||
if (td == null)
|
||||
return false;
|
||||
|
||||
return td.IsPublic;
|
||||
}
|
||||
|
||||
internal static bool IsDelegate (TypeReference typeref)
|
||||
{
|
||||
return IsDerivedFrom (typeref, "System.MulticastDelegate");
|
||||
}
|
||||
|
||||
internal static bool IsDerivedFrom (TypeReference type, string derivedFrom)
|
||||
{
|
||||
bool first = true;
|
||||
foreach (var def in WalkHierarchy (type)) {
|
||||
if (first) {
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (def.FullName == derivedFrom)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static IEnumerable<TypeDefinition> WalkHierarchy (TypeReference type)
|
||||
{
|
||||
for (var def = type.Resolve (); def != null; def = GetBaseType (def))
|
||||
yield return def;
|
||||
}
|
||||
|
||||
internal static IEnumerable<TypeReference> GetInterfaces (TypeReference type)
|
||||
{
|
||||
var ifaces = new Dictionary<string, TypeReference> ();
|
||||
|
||||
foreach (var def in WalkHierarchy (type))
|
||||
foreach (TypeReference iface in def.Interfaces)
|
||||
ifaces [iface.FullName] = iface;
|
||||
|
||||
return ifaces.Values;
|
||||
}
|
||||
|
||||
internal static TypeDefinition GetBaseType (TypeDefinition child)
|
||||
{
|
||||
if (child.BaseType == null)
|
||||
return null;
|
||||
|
||||
return child.BaseType.Resolve ();
|
||||
}
|
||||
|
||||
internal static bool IsPublic (CustomAttribute att)
|
||||
{
|
||||
return IsPublic (att.AttributeType);
|
||||
}
|
||||
|
||||
internal static string GetFullName (CustomAttribute att)
|
||||
{
|
||||
return att.AttributeType.FullName;
|
||||
}
|
||||
|
||||
internal static TypeDefinition GetTypeDefinition (CustomAttribute att)
|
||||
{
|
||||
return att.AttributeType.Resolve ();
|
||||
}
|
||||
}
|
||||
}
|
294
audit/WellFormedXmlWriter.cs
Normal file
294
audit/WellFormedXmlWriter.cs
Normal file
|
@ -0,0 +1,294 @@
|
|||
//
|
||||
// WellFormedXmlWriter.cs
|
||||
//
|
||||
// Author:
|
||||
// Atsushi Enomoto <atsushi@ximian.com>
|
||||
//
|
||||
// Copyright (C) 2006 Novell, Inc. http://www.novell.com
|
||||
//
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Collections;
|
||||
using System.Xml;
|
||||
|
||||
namespace Mono.AssemblyCompare {
|
||||
|
||||
public class WellFormedXmlWriter : DefaultXmlWriter
|
||||
{
|
||||
public static bool IsValid (int ch)
|
||||
{
|
||||
return !IsInvalid (ch);
|
||||
}
|
||||
|
||||
public static bool IsInvalid (int ch)
|
||||
{
|
||||
switch (ch) {
|
||||
case 9:
|
||||
case 10:
|
||||
case 13:
|
||||
return false;
|
||||
}
|
||||
if (ch < 32)
|
||||
return true;
|
||||
if (ch < 0xD800)
|
||||
return false;
|
||||
if (ch < 0xE000)
|
||||
return true;
|
||||
if (ch < 0xFFFE)
|
||||
return false;
|
||||
if (ch < 0x10000)
|
||||
return true;
|
||||
if (ch < 0x110000)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int IndexOfInvalid (string s, bool allowSurrogate)
|
||||
{
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
if (IsInvalid (s [i])) {
|
||||
if (!allowSurrogate ||
|
||||
i + 1 == s.Length ||
|
||||
s [i] < '\uD800' ||
|
||||
s [i] >= '\uDC00' ||
|
||||
s [i + 1] < '\uDC00' ||
|
||||
s [i + 1] >= '\uE000')
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int IndexOfInvalid (char [] s, int start, int length, bool allowSurrogate)
|
||||
{
|
||||
int end = start + length;
|
||||
if (s.Length < end)
|
||||
throw new ArgumentOutOfRangeException ("length");
|
||||
for (int i = start; i < end; i++)
|
||||
if (IsInvalid (s [i])) {
|
||||
if (!allowSurrogate ||
|
||||
i + 1 == end ||
|
||||
s [i] < '\uD800' ||
|
||||
s [i] >= '\uDC00' ||
|
||||
s [i + 1] < '\uDC00' ||
|
||||
s [i + 1] >= '\uE000')
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public WellFormedXmlWriter (XmlWriter writer) : base (writer)
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteString (string text)
|
||||
{
|
||||
int i = IndexOfInvalid (text, true);
|
||||
if (i >= 0) {
|
||||
char [] arr = text.ToCharArray ();
|
||||
Writer.WriteChars (arr, 0, i);
|
||||
WriteChars (arr, i, arr.Length - i);
|
||||
} else {
|
||||
// no invalid character.
|
||||
Writer.WriteString (text);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteChars (char [] text, int idx, int length)
|
||||
{
|
||||
int start = idx;
|
||||
int end = idx + length;
|
||||
while ((idx = IndexOfInvalid (text, start, length, true)) >= 0) {
|
||||
if (start < idx)
|
||||
Writer.WriteChars (text, start, idx - start);
|
||||
Writer.WriteString (String.Format (CultureInfo.InvariantCulture,
|
||||
text [idx] < 0x80 ? "\\x{0:X02}" : "\\u{0:X04}",
|
||||
(int) text [idx]));
|
||||
length -= idx - start + 1;
|
||||
start = idx + 1;
|
||||
}
|
||||
if (start < end)
|
||||
Writer.WriteChars (text, start, end - start);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class DefaultXmlWriter : XmlWriter
|
||||
{
|
||||
XmlWriter writer;
|
||||
|
||||
public DefaultXmlWriter (XmlWriter writer)
|
||||
{
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
protected XmlWriter Writer {
|
||||
get { return writer; }
|
||||
}
|
||||
|
||||
public override void Close ()
|
||||
{
|
||||
writer.Close ();
|
||||
}
|
||||
|
||||
public override void Flush ()
|
||||
{
|
||||
writer.Flush ();
|
||||
}
|
||||
|
||||
public override string LookupPrefix (string ns)
|
||||
{
|
||||
return writer.LookupPrefix (ns);
|
||||
}
|
||||
|
||||
public override void WriteBase64 (byte [] buffer, int index, int count)
|
||||
{
|
||||
writer.WriteBase64 (buffer, index, count);
|
||||
}
|
||||
|
||||
public override void WriteBinHex (byte [] buffer, int index, int count)
|
||||
{
|
||||
writer.WriteBinHex (buffer, index, count);
|
||||
}
|
||||
|
||||
public override void WriteCData (string text)
|
||||
{
|
||||
writer.WriteCData (text);
|
||||
}
|
||||
|
||||
public override void WriteCharEntity (char ch)
|
||||
{
|
||||
writer.WriteCharEntity (ch);
|
||||
}
|
||||
|
||||
public override void WriteChars (char [] buffer, int index, int count)
|
||||
{
|
||||
writer.WriteChars (buffer, index, count);
|
||||
}
|
||||
|
||||
public override void WriteComment (string text)
|
||||
{
|
||||
writer.WriteComment (text);
|
||||
}
|
||||
|
||||
public override void WriteDocType (string name, string pubid, string sysid, string subset)
|
||||
{
|
||||
writer.WriteDocType (name, pubid, sysid, subset);
|
||||
}
|
||||
|
||||
public override void WriteEndAttribute ()
|
||||
{
|
||||
writer.WriteEndAttribute ();
|
||||
}
|
||||
|
||||
public override void WriteEndDocument ()
|
||||
{
|
||||
writer.WriteEndDocument ();
|
||||
}
|
||||
|
||||
public override void WriteEndElement ()
|
||||
{
|
||||
writer.WriteEndElement ();
|
||||
}
|
||||
|
||||
public override void WriteEntityRef (string name)
|
||||
{
|
||||
writer.WriteEntityRef (name);
|
||||
}
|
||||
|
||||
public override void WriteFullEndElement ()
|
||||
{
|
||||
writer.WriteFullEndElement ();
|
||||
}
|
||||
|
||||
public override void WriteName (string name)
|
||||
{
|
||||
writer.WriteName (name);
|
||||
}
|
||||
|
||||
public override void WriteNmToken (string name)
|
||||
{
|
||||
writer.WriteNmToken (name);
|
||||
}
|
||||
|
||||
public override void WriteNode (XmlReader reader, bool defattr)
|
||||
{
|
||||
writer.WriteNode (reader, defattr);
|
||||
}
|
||||
|
||||
public override void WriteProcessingInstruction (string name, string text)
|
||||
{
|
||||
writer.WriteProcessingInstruction (name, text);
|
||||
}
|
||||
|
||||
public override void WriteQualifiedName (string localName, string ns)
|
||||
{
|
||||
writer.WriteQualifiedName (localName, ns);
|
||||
}
|
||||
|
||||
public override void WriteRaw (string data)
|
||||
{
|
||||
writer.WriteRaw (data);
|
||||
}
|
||||
|
||||
public override void WriteRaw (char [] buffer, int index, int count)
|
||||
{
|
||||
writer.WriteRaw (buffer, index, count);
|
||||
}
|
||||
|
||||
public override void WriteStartAttribute (string prefix, string localName, string ns)
|
||||
{
|
||||
writer.WriteStartAttribute (prefix, localName, ns);
|
||||
}
|
||||
|
||||
public override void WriteStartDocument (bool standalone)
|
||||
{
|
||||
writer.WriteStartDocument (standalone);
|
||||
}
|
||||
|
||||
public override void WriteStartDocument ()
|
||||
{
|
||||
writer.WriteStartDocument ();
|
||||
}
|
||||
|
||||
public override void WriteStartElement (string prefix, string localName, string ns)
|
||||
{
|
||||
writer.WriteStartElement (prefix, localName, ns);
|
||||
}
|
||||
|
||||
public override void WriteString (string text)
|
||||
{
|
||||
writer.WriteString (text);
|
||||
}
|
||||
|
||||
public override void WriteSurrogateCharEntity (char lowChar, char highChar)
|
||||
{
|
||||
writer.WriteSurrogateCharEntity (lowChar, highChar);
|
||||
}
|
||||
|
||||
public override void WriteWhitespace (string ws)
|
||||
{
|
||||
writer.WriteWhitespace (ws);
|
||||
}
|
||||
|
||||
public override WriteState WriteState {
|
||||
get {
|
||||
return writer.WriteState;
|
||||
}
|
||||
}
|
||||
|
||||
public override string XmlLang {
|
||||
get {
|
||||
return writer.XmlLang;
|
||||
}
|
||||
}
|
||||
|
||||
public override XmlSpace XmlSpace {
|
||||
get {
|
||||
return writer.XmlSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,15 +25,18 @@ die "Usage: get-apiinfo.pl <root_dir> <outdir>" if (@ARGV != 2);
|
|||
$root = $ARGV[0];
|
||||
$outdir = $ARGV[1];
|
||||
|
||||
$cecildir = `pkg-config --variable=assemblies_dir mono-cecil`;
|
||||
chomp ($cecildir);
|
||||
|
||||
`mkdir -p $outdir`;
|
||||
`mkdir -p apitmp`;
|
||||
`cp $root/*/*.dll apitmp`;
|
||||
print "getting api info: ";
|
||||
print "Getting api info: ";
|
||||
foreach $assm (`ls apitmp/*.dll`) {
|
||||
chomp ($assm);
|
||||
$assm =~ /apitmp\/(.*)\.dll/;
|
||||
print "*";
|
||||
`mono mono-api-info.exe $assm > $outdir/$1.apiinfo`;
|
||||
`MONO_PATH=$cecildir mono mono-api-info.exe $assm > $outdir/$1.apiinfo`;
|
||||
}
|
||||
`rm -rf apitmp`;
|
||||
print " Completed\n\n";
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
MCS=mcs
|
||||
|
||||
COMMON_SOURCES = \
|
||||
AssemblyResolver.cs \
|
||||
Util.cs \
|
||||
WellFormedXmlWriter.cs
|
||||
|
||||
APIINFO_SOURCES = mono-api-info.cs $(COMMON_SOURCES)
|
||||
|
||||
all: extract-missing.exe mono-api-info.exe mono-api-diff.exe
|
||||
|
||||
check: all
|
||||
|
@ -11,8 +18,8 @@ check: all
|
|||
mono-api-diff.exe: mono-api-diff.cs
|
||||
$(MCS) mono-api-diff.cs
|
||||
|
||||
mono-api-info.exe: mono-api-info.cs
|
||||
$(MCS) mono-api-info.cs
|
||||
mono-api-info.exe: $(APIINFO_SOURCES)
|
||||
$(MCS) `pkg-config --libs mono-cecil` -out:$@ $^
|
||||
|
||||
extract-missing.exe: extract-missing.cs
|
||||
$(MCS) extract-missing.cs
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
//
|
||||
// Authors:
|
||||
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
||||
// Marek Safar (marek.safar@gmail.com)
|
||||
//
|
||||
// (C) 2003 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// (C) 2009,2010 Collier Technologies (http://www.colliertech.org)
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
@ -21,12 +22,14 @@ namespace Mono.AssemblyCompare
|
|||
{
|
||||
static int Main (string [] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
if (args.Length != 2) {
|
||||
Console.WriteLine ("Usage: mono mono-api-diff.exe <assembly 1 xml> <assembly 2 xml>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
XMLAssembly ms = CreateXMLAssembly (args [0]);
|
||||
XMLAssembly mono = CreateXMLAssembly (args [1]);
|
||||
XmlDocument doc = ms.CompareAndGetDocument (mono);
|
||||
XMLAssembly asm_base = CreateXMLAssembly (args [0]);
|
||||
XMLAssembly asm_curr = CreateXMLAssembly (args [1]);
|
||||
XmlDocument doc = asm_base.CompareAndGetDocument (asm_curr);
|
||||
|
||||
XmlTextWriter writer = new XmlTextWriter (Console.Out);
|
||||
writer.Formatting = Formatting.Indented;
|
||||
|
@ -177,6 +180,27 @@ namespace Mono.AssemblyCompare
|
|||
return (object []) list.ToArray (type);
|
||||
}
|
||||
|
||||
public static bool IsMeaninglessAttribute (string s)
|
||||
{
|
||||
if (s == null)
|
||||
return false;
|
||||
if (s == "System.Runtime.CompilerServices.CompilerGeneratedAttribute")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsTODOAttribute (string s)
|
||||
{
|
||||
if (s == null)
|
||||
return false;
|
||||
if (s.EndsWith ("MonoDocumentationNoteAttribute") ||
|
||||
s.EndsWith ("MonoExtensionAttribute") ||
|
||||
s.EndsWith ("MonoLimitationAttribute") ||
|
||||
s.EndsWith ("MonoNotSupportedAttribute"))
|
||||
return true;
|
||||
return s.EndsWith ("TODOAttribute");
|
||||
}
|
||||
|
||||
protected void AddAttribute (XmlNode node, string name, string value)
|
||||
{
|
||||
XmlAttribute attr = document.CreateAttribute (name);
|
||||
|
@ -266,14 +290,14 @@ namespace Mono.AssemblyCompare
|
|||
public bool HaveWarnings {
|
||||
get { return haveWarnings; }
|
||||
}
|
||||
|
||||
|
||||
public Counters Counters {
|
||||
get { return counters; }
|
||||
}
|
||||
|
||||
|
||||
public abstract void CompareTo (XmlDocument doc, XmlNode parent, object other);
|
||||
}
|
||||
|
||||
|
||||
abstract class XMLNameGroup : XMLData
|
||||
{
|
||||
protected XmlNode group;
|
||||
|
@ -448,19 +472,17 @@ namespace Mono.AssemblyCompare
|
|||
newNS.Add (node);
|
||||
AddAttribute (node, "name", xns.Name);
|
||||
|
||||
if (oh.ContainsKey (xns.Name)) {
|
||||
int idx = (int) oh [xns.Name];
|
||||
xns.CompareTo (document, node, other [idx]);
|
||||
int idx = -1;
|
||||
if (oh.ContainsKey (xns.Name))
|
||||
idx = (int) oh [xns.Name];
|
||||
XMLNamespace ons = idx >= 0 ? (XMLNamespace) other [idx] : null;
|
||||
xns.CompareTo (document, node, ons);
|
||||
if (idx >= 0)
|
||||
other [idx] = null;
|
||||
xns.AddCountersAttributes (node);
|
||||
counters.Present++;
|
||||
counters.PresentTotal++;
|
||||
counters.AddPartialToTotal (xns.Counters);
|
||||
} else {
|
||||
AddAttribute (node, "presence", "missing");
|
||||
counters.Missing++;
|
||||
counters.MissingTotal++;
|
||||
}
|
||||
xns.AddCountersAttributes (node);
|
||||
counters.Present++;
|
||||
counters.PresentTotal++;
|
||||
counters.AddPartialToTotal (xns.Counters);
|
||||
}
|
||||
|
||||
if (other != null) {
|
||||
|
@ -503,7 +525,7 @@ namespace Mono.AssemblyCompare
|
|||
this.document = doc;
|
||||
XmlNode parent = doc.CreateElement ("assemblies", null);
|
||||
doc.AppendChild (parent);
|
||||
|
||||
|
||||
CompareTo (doc, parent, other);
|
||||
|
||||
XmlNode decl = doc.CreateXmlDeclaration ("1.0", null, null);
|
||||
|
@ -547,7 +569,7 @@ namespace Mono.AssemblyCompare
|
|||
XmlNode childA = doc.CreateElement ("classes", null);
|
||||
parent.AppendChild (childA);
|
||||
|
||||
CompareTypes (childA, nspace.types);
|
||||
CompareTypes (childA, nspace != null ? nspace.types : new XMLClass [0]);
|
||||
}
|
||||
|
||||
void CompareTypes (XmlNode parent, XMLClass [] other)
|
||||
|
@ -564,23 +586,20 @@ namespace Mono.AssemblyCompare
|
|||
AddAttribute (node, "name", xclass.Name);
|
||||
AddAttribute (node, "type", xclass.Type);
|
||||
|
||||
if (oh.ContainsKey (xclass.Name)) {
|
||||
int idx = (int) oh [xclass.Name];
|
||||
xclass.CompareTo (document, node, other [idx]);
|
||||
int idx = -1;
|
||||
if (oh.ContainsKey (xclass.Name))
|
||||
idx = (int) oh [xclass.Name];
|
||||
xclass.CompareTo (document, node, idx >= 0 ? other [idx] : new XMLClass ());
|
||||
if (idx >= 0)
|
||||
other [idx] = null;
|
||||
counters.AddPartialToPartial (xclass.Counters);
|
||||
} else {
|
||||
AddAttribute (node, "presence", "missing");
|
||||
counters.Missing++;
|
||||
counters.MissingTotal++;
|
||||
}
|
||||
counters.AddPartialToPartial (xclass.Counters);
|
||||
}
|
||||
|
||||
if (other != null) {
|
||||
count = other.Length;
|
||||
for (int i = 0; i < count; i++) {
|
||||
XMLClass c = other [i];
|
||||
if (c == null || c.Name.EndsWith ("TODOAttribute"))
|
||||
if (c == null || IsTODOAttribute (c.Name))
|
||||
continue;
|
||||
|
||||
node = document.CreateElement ("class", null);
|
||||
|
@ -636,7 +655,7 @@ namespace Mono.AssemblyCompare
|
|||
XMLEvents events;
|
||||
XMLMethods methods;
|
||||
XMLClass [] nested;
|
||||
|
||||
|
||||
public override void LoadData (XmlNode node)
|
||||
{
|
||||
if (node == null)
|
||||
|
@ -670,7 +689,7 @@ namespace Mono.AssemblyCompare
|
|||
// Console.Error.WriteLine ("Empty class {0} {1}", name, type);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (child.Name == "attributes") {
|
||||
attributes = new XMLAttributes ();
|
||||
attributes.LoadData (child);
|
||||
|
@ -719,6 +738,12 @@ namespace Mono.AssemblyCompare
|
|||
child = child.NextSibling;
|
||||
}
|
||||
|
||||
if (child != null && child.Name == "generic-parameters") {
|
||||
// HACK: ignore this tag as it doesn't seem to
|
||||
// add any value when checking for differences
|
||||
return;
|
||||
}
|
||||
|
||||
if (child == null)
|
||||
return;
|
||||
|
||||
|
@ -752,28 +777,28 @@ namespace Mono.AssemblyCompare
|
|||
}
|
||||
|
||||
if (type != oclass.type)
|
||||
AddWarning (parent, "Class type is wrong: {0} != {1}", type, oclass.type);
|
||||
AddWarning (parent, "Class type is different: {0} != {1}", type, oclass.type);
|
||||
|
||||
if (baseName != oclass.baseName)
|
||||
AddWarning (parent, "Base class is wrong: {0} != {1}", baseName, oclass.baseName);
|
||||
AddWarning (parent, "Base class is different: {0} != {1}", baseName, oclass.baseName);
|
||||
|
||||
if (isAbstract != oclass.isAbstract || isSealed != oclass.isSealed) {
|
||||
if ((isAbstract && isSealed) || (oclass.isAbstract && oclass.isSealed))
|
||||
AddWarning (parent, "Should {0}be static", (isAbstract && isSealed) ? "" : "not ");
|
||||
AddWarning (parent, "Was {0}static", (isAbstract && isSealed) ? "" : "not ");
|
||||
else if (isAbstract != oclass.isAbstract)
|
||||
AddWarning (parent, "Should {0}be abstract", isAbstract ? "" : "not ");
|
||||
AddWarning (parent, "Was {0}abstract", isAbstract ? "" : "not ");
|
||||
else if (isSealed != oclass.isSealed)
|
||||
AddWarning (parent, "Should {0}be sealed", isSealed ? "" : "not ");
|
||||
AddWarning (parent, "Was {0}sealed", isSealed ? "" : "not ");
|
||||
}
|
||||
|
||||
if (isSerializable != oclass.isSerializable)
|
||||
AddWarning (parent, "Should {0}be serializable", isSerializable ? "" : "not ");
|
||||
AddWarning (parent, "Was {0}serializable", isSerializable ? "" : "not ");
|
||||
|
||||
if (charSet != oclass.charSet)
|
||||
AddWarning (parent, "CharSet is wrong: {0} != {1}", charSet, oclass.charSet);
|
||||
AddWarning (parent, "CharSet is different: {0} != {1}", charSet, oclass.charSet);
|
||||
|
||||
if (layout != oclass.layout)
|
||||
AddWarning (parent, "Layout is wrong: {0} != {1}", layout, oclass.layout);
|
||||
AddWarning (parent, "Layout is different: {0} != {1}", layout, oclass.layout);
|
||||
|
||||
if (interfaces != null || oclass.interfaces != null) {
|
||||
if (interfaces == null)
|
||||
|
@ -849,7 +874,7 @@ namespace Mono.AssemblyCompare
|
|||
for (int i = 0; i < count; i++) {
|
||||
XMLClass xclass = nested [i];
|
||||
|
||||
node = document.CreateElement ("nestedclass", null);
|
||||
node = document.CreateElement ("class", null);
|
||||
newNodes.Add (node);
|
||||
AddAttribute (node, "name", xclass.Name);
|
||||
AddAttribute (node, "type", xclass.Type);
|
||||
|
@ -871,12 +896,13 @@ namespace Mono.AssemblyCompare
|
|||
count = other.Length;
|
||||
for (int i = 0; i < count; i++) {
|
||||
XMLClass c = other [i];
|
||||
if (c == null || c.Name.EndsWith ("TODOAttribute"))
|
||||
if (c == null || IsTODOAttribute (c.Name))
|
||||
continue;
|
||||
|
||||
node = document.CreateElement ("nestedclass", null);
|
||||
node = document.CreateElement ("class", null);
|
||||
newNodes.Add (node);
|
||||
AddAttribute (node, "name", c.Name);
|
||||
AddAttribute (node, "type", c.Type);
|
||||
AddExtra (node);
|
||||
counters.Extra++;
|
||||
counters.ExtraTotal++;
|
||||
|
@ -920,6 +946,7 @@ namespace Mono.AssemblyCompare
|
|||
bool isUnsafe;
|
||||
bool isOptional;
|
||||
string defaultValue;
|
||||
XMLAttributes attributes;
|
||||
|
||||
public override void LoadData (XmlNode node)
|
||||
{
|
||||
|
@ -940,6 +967,16 @@ namespace Mono.AssemblyCompare
|
|||
isOptional = bool.Parse (node.Attributes["optional"].Value);
|
||||
if (node.Attributes["defaultValue"] != null)
|
||||
defaultValue = node.Attributes["defaultValue"].Value;
|
||||
|
||||
XmlNode child = node.FirstChild;
|
||||
if (child == null)
|
||||
return;
|
||||
|
||||
if (child.Name == "attributes") {
|
||||
attributes = new XMLAttributes ();
|
||||
attributes.LoadData (child);
|
||||
child = child.NextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompareTo (XmlDocument doc, XmlNode parent, object other)
|
||||
|
@ -948,23 +985,42 @@ namespace Mono.AssemblyCompare
|
|||
|
||||
XMLParameter oparm = (XMLParameter) other;
|
||||
|
||||
if (name != oparm.name)
|
||||
AddWarning (parent, "Parameter name is different: {0} != {1}", name, oparm.name);
|
||||
|
||||
if (type != oparm.type)
|
||||
AddWarning (parent, "Parameter type is wrong: {0} != {1}", type, oparm.type);
|
||||
|
||||
AddWarning (parent, "Parameter type is different: {0} != {1}", type, oparm.type);
|
||||
|
||||
if (attrib != oparm.attrib)
|
||||
AddWarning (parent, "Parameter attributes wrong: {0} != {1}", attrib, oparm.attrib);
|
||||
AddWarning (parent, "Parameter attributes different: {0} != {1}", attrib, oparm.attrib);
|
||||
|
||||
if (direction != oparm.direction)
|
||||
AddWarning (parent, "Parameter direction wrong: {0} != {1}", direction, oparm.direction);
|
||||
AddWarning (parent, "Parameter direction different: {0} != {1}", direction, oparm.direction);
|
||||
|
||||
if (isUnsafe != oparm.isUnsafe)
|
||||
AddWarning (parent, "Parameter unsafe wrong: {0} != {1}", isUnsafe, oparm.isUnsafe);
|
||||
AddWarning (parent, "Parameter unsafe different: {0} != {1}", isUnsafe, oparm.isUnsafe);
|
||||
|
||||
if (isOptional != oparm.isOptional)
|
||||
AddWarning (parent, "Parameter optional wrong: {0} != {1}", isOptional, oparm.isOptional);
|
||||
AddWarning (parent, "Parameter optional different: {0} != {1}", isOptional, oparm.isOptional);
|
||||
|
||||
if (defaultValue != oparm.defaultValue)
|
||||
AddWarning (parent, "Parameter default value wrong: {0} != {1}", (defaultValue == null) ? "(no default value)" : defaultValue, (oparm.defaultValue == null) ? "(no default value)" : oparm.defaultValue);
|
||||
AddWarning (parent, "Parameter default value different: {0} != {1}", (defaultValue == null) ? "(no default value)" : defaultValue, (oparm.defaultValue == null) ? "(no default value)" : oparm.defaultValue);
|
||||
|
||||
if (attributes != null || oparm.attributes != null) {
|
||||
if (attributes == null)
|
||||
attributes = new XMLAttributes ();
|
||||
|
||||
attributes.CompareTo (doc, parent, oparm.attributes);
|
||||
counters.AddPartialToPartial (attributes.Counters);
|
||||
if (oparm.attributes != null && oparm.attributes.IsTodo) {
|
||||
counters.Todo++;
|
||||
counters.TodoTotal++;
|
||||
counters.ErrorTotal++;
|
||||
AddAttribute (parent, "error", "todo");
|
||||
if (oparm.attributes.Comment != null)
|
||||
AddAttribute (parent, "comment", oparm.attributes.Comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Name {
|
||||
|
@ -1033,14 +1089,14 @@ namespace Mono.AssemblyCompare
|
|||
|
||||
if (de.Value == null) {
|
||||
if (other_value != null)
|
||||
AddWarning (parent, "Property '{0}' is 'null' and should be '{1}'", de.Key, other_value);
|
||||
AddWarning (parent, "Property '{0}' is 'null' and was '{1}'", de.Key, other_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (de.Value.Equals (other_value))
|
||||
continue;
|
||||
|
||||
AddWarning (parent, "Property '{0}' is '{1}' and should be '{2}'",
|
||||
AddWarning (parent, "Property '{0}' is '{1}' and was '{2}'",
|
||||
de.Key, de.Value, other_value == null ? "null" : other_value);
|
||||
}
|
||||
}
|
||||
|
@ -1067,17 +1123,17 @@ namespace Mono.AssemblyCompare
|
|||
|
||||
protected override bool CheckIfAdd (string value, XmlNode node)
|
||||
{
|
||||
if (value.EndsWith ("TODOAttribute")) {
|
||||
if (IsTODOAttribute (value)) {
|
||||
isTodo = true;
|
||||
|
||||
XmlNode pNode = node.SelectSingleNode ("properties");
|
||||
if (pNode.ChildNodes [0].Attributes ["value"] != null) {
|
||||
if (pNode != null && pNode.ChildNodes.Count > 0 && pNode.ChildNodes [0].Attributes ["value"] != null) {
|
||||
comment = pNode.ChildNodes [0].Attributes ["value"].Value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !IsMeaninglessAttribute (value);
|
||||
}
|
||||
|
||||
protected override void CompareToInner (string name, XmlNode node, XMLNameGroup other)
|
||||
|
@ -1095,7 +1151,7 @@ namespace Mono.AssemblyCompare
|
|||
{
|
||||
string key = null;
|
||||
|
||||
// if multiple attributes with the same name (type) exist, then we
|
||||
// if multiple attributes with the same name (type) exist, then we
|
||||
// cannot be sure which attributes correspond, so we must use the
|
||||
// name of the attribute (type) and the name/value of its properties
|
||||
// as key
|
||||
|
@ -1114,7 +1170,7 @@ namespace Mono.AssemblyCompare
|
|||
}
|
||||
}
|
||||
|
||||
// sort properties by name, as order of properties in XML is
|
||||
// sort properties by name, as order of properties in XML is
|
||||
// undefined
|
||||
keyParts.Sort ();
|
||||
|
||||
|
@ -1138,7 +1194,7 @@ namespace Mono.AssemblyCompare
|
|||
{
|
||||
XmlNode pNode = node.SelectSingleNode ("properties");
|
||||
|
||||
if (name.EndsWith ("TODOAttribute")) {
|
||||
if (IsTODOAttribute (name)) {
|
||||
isTodo = true;
|
||||
if (pNode.ChildNodes [0].Attributes ["value"] != null) {
|
||||
comment = pNode.ChildNodes [0].Attributes ["value"].Value;
|
||||
|
@ -1197,7 +1253,7 @@ namespace Mono.AssemblyCompare
|
|||
|
||||
XMLGenericGroup g = (XMLGenericGroup) other;
|
||||
if (attributes != g.attributes)
|
||||
AddWarning (parent, "Incorrect generic attributes: '{0}' != '{1}'", attributes, g.attributes);
|
||||
AddWarning (parent, "Different generic attributes: '{0}' != '{1}'", attributes, g.attributes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1233,7 +1289,7 @@ namespace Mono.AssemblyCompare
|
|||
XmlAttribute xatt = node.Attributes ["attrib"];
|
||||
if (xatt != null)
|
||||
access [name] = xatt.Value;
|
||||
|
||||
|
||||
XmlNode orig = node;
|
||||
|
||||
node = node.FirstChild;
|
||||
|
@ -1295,7 +1351,7 @@ namespace Mono.AssemblyCompare
|
|||
oaccName = ConvertToString (Int32.Parse (oacc));
|
||||
|
||||
if (accName != oaccName)
|
||||
AddWarning (parent, "Incorrect attributes: '{0}' != '{1}'", accName, oaccName);
|
||||
AddWarning (parent, "Different attributes: '{0}' != '{1}'", accName, oaccName);
|
||||
}
|
||||
|
||||
protected virtual string ConvertToString (int att)
|
||||
|
@ -1303,7 +1359,7 @@ namespace Mono.AssemblyCompare
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class XMLFields : XMLMember
|
||||
{
|
||||
Hashtable fieldTypes;
|
||||
|
@ -1341,7 +1397,7 @@ namespace Mono.AssemblyCompare
|
|||
oftype = fields.fieldTypes [name] as string;
|
||||
|
||||
if (ftype != oftype)
|
||||
AddWarning (parent, "Field type is {0} and should be {1}", oftype, ftype);
|
||||
AddWarning (parent, "Field type is {0} and was {1}", oftype, ftype);
|
||||
}
|
||||
if (fieldValues != null) {
|
||||
string fvalue = fieldValues [name] as string;
|
||||
|
@ -1350,7 +1406,7 @@ namespace Mono.AssemblyCompare
|
|||
ofvalue = fields.fieldValues [name] as string;
|
||||
|
||||
if (fvalue != ofvalue)
|
||||
AddWarning (parent, "Field value is {0} and should be {1}", ofvalue, fvalue);
|
||||
AddWarning (parent, "Field value is {0} and was {1}", ofvalue, fvalue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1506,9 +1562,11 @@ namespace Mono.AssemblyCompare
|
|||
public override string GetNodeKey (string name, XmlNode node)
|
||||
{
|
||||
XmlAttributeCollection atts = node.Attributes;
|
||||
return String.Format ("{0}:{1}:{2}", atts ["name"].Value,
|
||||
atts ["ptype"].Value,
|
||||
atts ["params"].Value);
|
||||
return String.Format ("{0}:{1}:{2}",
|
||||
(atts["name"] != null ? atts["name"].Value : ""),
|
||||
(atts["ptype"] != null ? atts["ptype"].Value : ""),
|
||||
(atts["params"] != null ? atts["params"].Value : "")
|
||||
);
|
||||
}
|
||||
|
||||
public override string GroupName {
|
||||
|
@ -1523,6 +1581,7 @@ namespace Mono.AssemblyCompare
|
|||
class XMLEvents : XMLMember
|
||||
{
|
||||
Hashtable eventTypes;
|
||||
Hashtable nameToMethod = new Hashtable ();
|
||||
|
||||
protected override void LoadExtraData (string name, XmlNode node)
|
||||
{
|
||||
|
@ -1534,6 +1593,19 @@ namespace Mono.AssemblyCompare
|
|||
eventTypes [name] = xatt.Value;
|
||||
}
|
||||
|
||||
XmlNode child = node.FirstChild;
|
||||
while (child != null) {
|
||||
if (child != null && child.Name == "methods") {
|
||||
XMLMethods m = new XMLMethods ();
|
||||
XmlNode parent = child.ParentNode;
|
||||
string key = GetNodeKey (name, parent);
|
||||
m.LoadData (child);
|
||||
nameToMethod [key] = m;
|
||||
break;
|
||||
}
|
||||
child = child.NextSibling;
|
||||
}
|
||||
|
||||
base.LoadExtraData (name, node);
|
||||
}
|
||||
|
||||
|
@ -1555,7 +1627,17 @@ namespace Mono.AssemblyCompare
|
|||
oetype = evt.eventTypes [name] as string;
|
||||
|
||||
if (etype != oetype)
|
||||
AddWarning (parent, "Event type is {0} and should be {1}", oetype, etype);
|
||||
AddWarning (parent, "Event type is {0} and was {1}", oetype, etype);
|
||||
|
||||
XMLMethods m = nameToMethod [name] as XMLMethods;
|
||||
XMLMethods om = evt.nameToMethod [name] as XMLMethods;
|
||||
if (m != null || om != null) {
|
||||
if (m == null)
|
||||
m = new XMLMethods ();
|
||||
|
||||
m.CompareTo (document, parent, om);
|
||||
counters.AddPartialToPartial (m.Counters);
|
||||
}
|
||||
} finally {
|
||||
AddCountersAttributes (parent);
|
||||
copy.AddPartialToPartial (counters);
|
||||
|
@ -1591,7 +1673,8 @@ namespace Mono.AssemblyCompare
|
|||
None = 0,
|
||||
Abstract = 1,
|
||||
Virtual = 2,
|
||||
Static = 4
|
||||
Static = 4,
|
||||
Final = 8,
|
||||
}
|
||||
|
||||
protected override void LoadExtraData (string name, XmlNode node)
|
||||
|
@ -1611,6 +1694,8 @@ namespace Mono.AssemblyCompare
|
|||
flags |= SignatureFlags.Static;
|
||||
if (((XmlElement) node).GetAttribute ("virtual") == "true")
|
||||
flags |= SignatureFlags.Virtual;
|
||||
if (((XmlElement) node).GetAttribute ("final") == "true")
|
||||
flags |= SignatureFlags.Final;
|
||||
if (flags != SignatureFlags.None) {
|
||||
if (signatureFlags == null)
|
||||
signatureFlags = new Hashtable ();
|
||||
|
@ -1640,6 +1725,23 @@ namespace Mono.AssemblyCompare
|
|||
base.LoadExtraData (name, node);
|
||||
}
|
||||
|
||||
public override string GetNodeKey (string name, XmlNode node)
|
||||
{
|
||||
// for explicit/implicit operators we need to include the return
|
||||
// type in the key to allow matching; as a side-effect, differences
|
||||
// in return types will be reported as extra/missing methods
|
||||
//
|
||||
// for regular methods we do not need to take into account the
|
||||
// return type for matching methods; differences in return types
|
||||
// will be reported as a warning on the method
|
||||
if (name.StartsWith ("op_")) {
|
||||
XmlAttribute xatt = node.Attributes ["returntype"];
|
||||
string returnType = xatt != null ? xatt.Value + " " : string.Empty;
|
||||
return returnType + name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
protected override void CompareToInner (string name, XmlNode parent, XMLNameGroup other)
|
||||
{
|
||||
// create backup of actual counters
|
||||
|
@ -1662,11 +1764,11 @@ namespace Mono.AssemblyCompare
|
|||
|
||||
if (flags!= oflags) {
|
||||
if (flags == SignatureFlags.None)
|
||||
AddWarning (parent, String.Format ("should not be {0}", oflags));
|
||||
AddWarning (parent, String.Format ("was not {0}", oflags));
|
||||
else if (oflags == SignatureFlags.None)
|
||||
AddWarning (parent, String.Format ("should be {0}", flags));
|
||||
AddWarning (parent, String.Format ("was {0}", flags));
|
||||
else
|
||||
AddWarning (parent, String.Format ("{0} and should be {1}", oflags, flags));
|
||||
AddWarning (parent, String.Format ("{0} and was {1}", oflags, flags));
|
||||
}
|
||||
|
||||
if (returnTypes != null) {
|
||||
|
@ -1676,7 +1778,7 @@ namespace Mono.AssemblyCompare
|
|||
ortype = methods.returnTypes[name] as string;
|
||||
|
||||
if (rtype != ortype)
|
||||
AddWarning (parent, "Return type is {0} and should be {1}", ortype, rtype);
|
||||
AddWarning (parent, "Return type is {0} and was {1}", ortype, rtype);
|
||||
}
|
||||
|
||||
if (parameters != null) {
|
||||
|
@ -1712,7 +1814,7 @@ namespace Mono.AssemblyCompare
|
|||
if ((ma & MethodAttributes.RequireSecObject) != 0)
|
||||
ma = (MethodAttributes) (att - (int) MethodAttributes.RequireSecObject);
|
||||
|
||||
// we don't care if the implementation is forwarded through PInvoke
|
||||
// we don't care if the implementation is forwarded through PInvoke
|
||||
if ((ma & MethodAttributes.PinvokeImpl) != 0)
|
||||
ma = (MethodAttributes) (att - (int) MethodAttributes.PinvokeImpl);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue