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];
|
$root = $ARGV[0];
|
||||||
$outdir = $ARGV[1];
|
$outdir = $ARGV[1];
|
||||||
|
|
||||||
|
$cecildir = `pkg-config --variable=assemblies_dir mono-cecil`;
|
||||||
|
chomp ($cecildir);
|
||||||
|
|
||||||
`mkdir -p $outdir`;
|
`mkdir -p $outdir`;
|
||||||
`mkdir -p apitmp`;
|
`mkdir -p apitmp`;
|
||||||
`cp $root/*/*.dll apitmp`;
|
`cp $root/*/*.dll apitmp`;
|
||||||
print "getting api info: ";
|
print "Getting api info: ";
|
||||||
foreach $assm (`ls apitmp/*.dll`) {
|
foreach $assm (`ls apitmp/*.dll`) {
|
||||||
chomp ($assm);
|
chomp ($assm);
|
||||||
$assm =~ /apitmp\/(.*)\.dll/;
|
$assm =~ /apitmp\/(.*)\.dll/;
|
||||||
print "*";
|
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`;
|
`rm -rf apitmp`;
|
||||||
print " Completed\n\n";
|
print " Completed\n\n";
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
MCS=mcs
|
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
|
all: extract-missing.exe mono-api-info.exe mono-api-diff.exe
|
||||||
|
|
||||||
check: all
|
check: all
|
||||||
|
@ -11,8 +18,8 @@ check: all
|
||||||
mono-api-diff.exe: mono-api-diff.cs
|
mono-api-diff.exe: mono-api-diff.cs
|
||||||
$(MCS) mono-api-diff.cs
|
$(MCS) mono-api-diff.cs
|
||||||
|
|
||||||
mono-api-info.exe: mono-api-info.cs
|
mono-api-info.exe: $(APIINFO_SOURCES)
|
||||||
$(MCS) mono-api-info.cs
|
$(MCS) `pkg-config --libs mono-cecil` -out:$@ $^
|
||||||
|
|
||||||
extract-missing.exe: extract-missing.cs
|
extract-missing.exe: extract-missing.cs
|
||||||
$(MCS) extract-missing.cs
|
$(MCS) extract-missing.cs
|
||||||
|
|
|
@ -4,9 +4,10 @@
|
||||||
//
|
//
|
||||||
// Authors:
|
// Authors:
|
||||||
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
||||||
|
// Marek Safar (marek.safar@gmail.com)
|
||||||
//
|
//
|
||||||
// (C) 2003 Novell, Inc (http://www.novell.com)
|
// (C) 2003 Novell, Inc (http://www.novell.com)
|
||||||
//
|
// (C) 2009,2010 Collier Technologies (http://www.colliertech.org)
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
@ -21,12 +22,14 @@ namespace Mono.AssemblyCompare
|
||||||
{
|
{
|
||||||
static int Main (string [] args)
|
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;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
XMLAssembly ms = CreateXMLAssembly (args [0]);
|
XMLAssembly asm_base = CreateXMLAssembly (args [0]);
|
||||||
XMLAssembly mono = CreateXMLAssembly (args [1]);
|
XMLAssembly asm_curr = CreateXMLAssembly (args [1]);
|
||||||
XmlDocument doc = ms.CompareAndGetDocument (mono);
|
XmlDocument doc = asm_base.CompareAndGetDocument (asm_curr);
|
||||||
|
|
||||||
XmlTextWriter writer = new XmlTextWriter (Console.Out);
|
XmlTextWriter writer = new XmlTextWriter (Console.Out);
|
||||||
writer.Formatting = Formatting.Indented;
|
writer.Formatting = Formatting.Indented;
|
||||||
|
@ -177,6 +180,27 @@ namespace Mono.AssemblyCompare
|
||||||
return (object []) list.ToArray (type);
|
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)
|
protected void AddAttribute (XmlNode node, string name, string value)
|
||||||
{
|
{
|
||||||
XmlAttribute attr = document.CreateAttribute (name);
|
XmlAttribute attr = document.CreateAttribute (name);
|
||||||
|
@ -266,14 +290,14 @@ namespace Mono.AssemblyCompare
|
||||||
public bool HaveWarnings {
|
public bool HaveWarnings {
|
||||||
get { return haveWarnings; }
|
get { return haveWarnings; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Counters Counters {
|
public Counters Counters {
|
||||||
get { return counters; }
|
get { return counters; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void CompareTo (XmlDocument doc, XmlNode parent, object other);
|
public abstract void CompareTo (XmlDocument doc, XmlNode parent, object other);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class XMLNameGroup : XMLData
|
abstract class XMLNameGroup : XMLData
|
||||||
{
|
{
|
||||||
protected XmlNode group;
|
protected XmlNode group;
|
||||||
|
@ -448,19 +472,17 @@ namespace Mono.AssemblyCompare
|
||||||
newNS.Add (node);
|
newNS.Add (node);
|
||||||
AddAttribute (node, "name", xns.Name);
|
AddAttribute (node, "name", xns.Name);
|
||||||
|
|
||||||
if (oh.ContainsKey (xns.Name)) {
|
int idx = -1;
|
||||||
int idx = (int) oh [xns.Name];
|
if (oh.ContainsKey (xns.Name))
|
||||||
xns.CompareTo (document, node, other [idx]);
|
idx = (int) oh [xns.Name];
|
||||||
|
XMLNamespace ons = idx >= 0 ? (XMLNamespace) other [idx] : null;
|
||||||
|
xns.CompareTo (document, node, ons);
|
||||||
|
if (idx >= 0)
|
||||||
other [idx] = null;
|
other [idx] = null;
|
||||||
xns.AddCountersAttributes (node);
|
xns.AddCountersAttributes (node);
|
||||||
counters.Present++;
|
counters.Present++;
|
||||||
counters.PresentTotal++;
|
counters.PresentTotal++;
|
||||||
counters.AddPartialToTotal (xns.Counters);
|
counters.AddPartialToTotal (xns.Counters);
|
||||||
} else {
|
|
||||||
AddAttribute (node, "presence", "missing");
|
|
||||||
counters.Missing++;
|
|
||||||
counters.MissingTotal++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other != null) {
|
if (other != null) {
|
||||||
|
@ -503,7 +525,7 @@ namespace Mono.AssemblyCompare
|
||||||
this.document = doc;
|
this.document = doc;
|
||||||
XmlNode parent = doc.CreateElement ("assemblies", null);
|
XmlNode parent = doc.CreateElement ("assemblies", null);
|
||||||
doc.AppendChild (parent);
|
doc.AppendChild (parent);
|
||||||
|
|
||||||
CompareTo (doc, parent, other);
|
CompareTo (doc, parent, other);
|
||||||
|
|
||||||
XmlNode decl = doc.CreateXmlDeclaration ("1.0", null, null);
|
XmlNode decl = doc.CreateXmlDeclaration ("1.0", null, null);
|
||||||
|
@ -547,7 +569,7 @@ namespace Mono.AssemblyCompare
|
||||||
XmlNode childA = doc.CreateElement ("classes", null);
|
XmlNode childA = doc.CreateElement ("classes", null);
|
||||||
parent.AppendChild (childA);
|
parent.AppendChild (childA);
|
||||||
|
|
||||||
CompareTypes (childA, nspace.types);
|
CompareTypes (childA, nspace != null ? nspace.types : new XMLClass [0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompareTypes (XmlNode parent, XMLClass [] other)
|
void CompareTypes (XmlNode parent, XMLClass [] other)
|
||||||
|
@ -564,23 +586,20 @@ namespace Mono.AssemblyCompare
|
||||||
AddAttribute (node, "name", xclass.Name);
|
AddAttribute (node, "name", xclass.Name);
|
||||||
AddAttribute (node, "type", xclass.Type);
|
AddAttribute (node, "type", xclass.Type);
|
||||||
|
|
||||||
if (oh.ContainsKey (xclass.Name)) {
|
int idx = -1;
|
||||||
int idx = (int) oh [xclass.Name];
|
if (oh.ContainsKey (xclass.Name))
|
||||||
xclass.CompareTo (document, node, other [idx]);
|
idx = (int) oh [xclass.Name];
|
||||||
|
xclass.CompareTo (document, node, idx >= 0 ? other [idx] : new XMLClass ());
|
||||||
|
if (idx >= 0)
|
||||||
other [idx] = null;
|
other [idx] = null;
|
||||||
counters.AddPartialToPartial (xclass.Counters);
|
counters.AddPartialToPartial (xclass.Counters);
|
||||||
} else {
|
|
||||||
AddAttribute (node, "presence", "missing");
|
|
||||||
counters.Missing++;
|
|
||||||
counters.MissingTotal++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other != null) {
|
if (other != null) {
|
||||||
count = other.Length;
|
count = other.Length;
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
XMLClass c = other [i];
|
XMLClass c = other [i];
|
||||||
if (c == null || c.Name.EndsWith ("TODOAttribute"))
|
if (c == null || IsTODOAttribute (c.Name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
node = document.CreateElement ("class", null);
|
node = document.CreateElement ("class", null);
|
||||||
|
@ -636,7 +655,7 @@ namespace Mono.AssemblyCompare
|
||||||
XMLEvents events;
|
XMLEvents events;
|
||||||
XMLMethods methods;
|
XMLMethods methods;
|
||||||
XMLClass [] nested;
|
XMLClass [] nested;
|
||||||
|
|
||||||
public override void LoadData (XmlNode node)
|
public override void LoadData (XmlNode node)
|
||||||
{
|
{
|
||||||
if (node == null)
|
if (node == null)
|
||||||
|
@ -670,7 +689,7 @@ namespace Mono.AssemblyCompare
|
||||||
// Console.Error.WriteLine ("Empty class {0} {1}", name, type);
|
// Console.Error.WriteLine ("Empty class {0} {1}", name, type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child.Name == "attributes") {
|
if (child.Name == "attributes") {
|
||||||
attributes = new XMLAttributes ();
|
attributes = new XMLAttributes ();
|
||||||
attributes.LoadData (child);
|
attributes.LoadData (child);
|
||||||
|
@ -719,6 +738,12 @@ namespace Mono.AssemblyCompare
|
||||||
child = child.NextSibling;
|
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)
|
if (child == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -752,28 +777,28 @@ namespace Mono.AssemblyCompare
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != oclass.type)
|
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)
|
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 != oclass.isAbstract || isSealed != oclass.isSealed) {
|
||||||
if ((isAbstract && isSealed) || (oclass.isAbstract && 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)
|
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)
|
else if (isSealed != oclass.isSealed)
|
||||||
AddWarning (parent, "Should {0}be sealed", isSealed ? "" : "not ");
|
AddWarning (parent, "Was {0}sealed", isSealed ? "" : "not ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSerializable != oclass.isSerializable)
|
if (isSerializable != oclass.isSerializable)
|
||||||
AddWarning (parent, "Should {0}be serializable", isSerializable ? "" : "not ");
|
AddWarning (parent, "Was {0}serializable", isSerializable ? "" : "not ");
|
||||||
|
|
||||||
if (charSet != oclass.charSet)
|
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)
|
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 || oclass.interfaces != null) {
|
||||||
if (interfaces == null)
|
if (interfaces == null)
|
||||||
|
@ -849,7 +874,7 @@ namespace Mono.AssemblyCompare
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
XMLClass xclass = nested [i];
|
XMLClass xclass = nested [i];
|
||||||
|
|
||||||
node = document.CreateElement ("nestedclass", null);
|
node = document.CreateElement ("class", null);
|
||||||
newNodes.Add (node);
|
newNodes.Add (node);
|
||||||
AddAttribute (node, "name", xclass.Name);
|
AddAttribute (node, "name", xclass.Name);
|
||||||
AddAttribute (node, "type", xclass.Type);
|
AddAttribute (node, "type", xclass.Type);
|
||||||
|
@ -871,12 +896,13 @@ namespace Mono.AssemblyCompare
|
||||||
count = other.Length;
|
count = other.Length;
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
XMLClass c = other [i];
|
XMLClass c = other [i];
|
||||||
if (c == null || c.Name.EndsWith ("TODOAttribute"))
|
if (c == null || IsTODOAttribute (c.Name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
node = document.CreateElement ("nestedclass", null);
|
node = document.CreateElement ("class", null);
|
||||||
newNodes.Add (node);
|
newNodes.Add (node);
|
||||||
AddAttribute (node, "name", c.Name);
|
AddAttribute (node, "name", c.Name);
|
||||||
|
AddAttribute (node, "type", c.Type);
|
||||||
AddExtra (node);
|
AddExtra (node);
|
||||||
counters.Extra++;
|
counters.Extra++;
|
||||||
counters.ExtraTotal++;
|
counters.ExtraTotal++;
|
||||||
|
@ -920,6 +946,7 @@ namespace Mono.AssemblyCompare
|
||||||
bool isUnsafe;
|
bool isUnsafe;
|
||||||
bool isOptional;
|
bool isOptional;
|
||||||
string defaultValue;
|
string defaultValue;
|
||||||
|
XMLAttributes attributes;
|
||||||
|
|
||||||
public override void LoadData (XmlNode node)
|
public override void LoadData (XmlNode node)
|
||||||
{
|
{
|
||||||
|
@ -940,6 +967,16 @@ namespace Mono.AssemblyCompare
|
||||||
isOptional = bool.Parse (node.Attributes["optional"].Value);
|
isOptional = bool.Parse (node.Attributes["optional"].Value);
|
||||||
if (node.Attributes["defaultValue"] != null)
|
if (node.Attributes["defaultValue"] != null)
|
||||||
defaultValue = node.Attributes["defaultValue"].Value;
|
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)
|
public override void CompareTo (XmlDocument doc, XmlNode parent, object other)
|
||||||
|
@ -948,23 +985,42 @@ namespace Mono.AssemblyCompare
|
||||||
|
|
||||||
XMLParameter oparm = (XMLParameter) other;
|
XMLParameter oparm = (XMLParameter) other;
|
||||||
|
|
||||||
|
if (name != oparm.name)
|
||||||
|
AddWarning (parent, "Parameter name is different: {0} != {1}", name, oparm.name);
|
||||||
|
|
||||||
if (type != oparm.type)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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 {
|
public string Name {
|
||||||
|
@ -1033,14 +1089,14 @@ namespace Mono.AssemblyCompare
|
||||||
|
|
||||||
if (de.Value == null) {
|
if (de.Value == null) {
|
||||||
if (other_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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (de.Value.Equals (other_value))
|
if (de.Value.Equals (other_value))
|
||||||
continue;
|
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);
|
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)
|
protected override bool CheckIfAdd (string value, XmlNode node)
|
||||||
{
|
{
|
||||||
if (value.EndsWith ("TODOAttribute")) {
|
if (IsTODOAttribute (value)) {
|
||||||
isTodo = true;
|
isTodo = true;
|
||||||
|
|
||||||
XmlNode pNode = node.SelectSingleNode ("properties");
|
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;
|
comment = pNode.ChildNodes [0].Attributes ["value"].Value;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return !IsMeaninglessAttribute (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void CompareToInner (string name, XmlNode node, XMLNameGroup other)
|
protected override void CompareToInner (string name, XmlNode node, XMLNameGroup other)
|
||||||
|
@ -1095,7 +1151,7 @@ namespace Mono.AssemblyCompare
|
||||||
{
|
{
|
||||||
string key = null;
|
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
|
// cannot be sure which attributes correspond, so we must use the
|
||||||
// name of the attribute (type) and the name/value of its properties
|
// name of the attribute (type) and the name/value of its properties
|
||||||
// as key
|
// 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
|
// undefined
|
||||||
keyParts.Sort ();
|
keyParts.Sort ();
|
||||||
|
|
||||||
|
@ -1138,7 +1194,7 @@ namespace Mono.AssemblyCompare
|
||||||
{
|
{
|
||||||
XmlNode pNode = node.SelectSingleNode ("properties");
|
XmlNode pNode = node.SelectSingleNode ("properties");
|
||||||
|
|
||||||
if (name.EndsWith ("TODOAttribute")) {
|
if (IsTODOAttribute (name)) {
|
||||||
isTodo = true;
|
isTodo = true;
|
||||||
if (pNode.ChildNodes [0].Attributes ["value"] != null) {
|
if (pNode.ChildNodes [0].Attributes ["value"] != null) {
|
||||||
comment = pNode.ChildNodes [0].Attributes ["value"].Value;
|
comment = pNode.ChildNodes [0].Attributes ["value"].Value;
|
||||||
|
@ -1197,7 +1253,7 @@ namespace Mono.AssemblyCompare
|
||||||
|
|
||||||
XMLGenericGroup g = (XMLGenericGroup) other;
|
XMLGenericGroup g = (XMLGenericGroup) other;
|
||||||
if (attributes != g.attributes)
|
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"];
|
XmlAttribute xatt = node.Attributes ["attrib"];
|
||||||
if (xatt != null)
|
if (xatt != null)
|
||||||
access [name] = xatt.Value;
|
access [name] = xatt.Value;
|
||||||
|
|
||||||
XmlNode orig = node;
|
XmlNode orig = node;
|
||||||
|
|
||||||
node = node.FirstChild;
|
node = node.FirstChild;
|
||||||
|
@ -1295,7 +1351,7 @@ namespace Mono.AssemblyCompare
|
||||||
oaccName = ConvertToString (Int32.Parse (oacc));
|
oaccName = ConvertToString (Int32.Parse (oacc));
|
||||||
|
|
||||||
if (accName != oaccName)
|
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)
|
protected virtual string ConvertToString (int att)
|
||||||
|
@ -1303,7 +1359,7 @@ namespace Mono.AssemblyCompare
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class XMLFields : XMLMember
|
class XMLFields : XMLMember
|
||||||
{
|
{
|
||||||
Hashtable fieldTypes;
|
Hashtable fieldTypes;
|
||||||
|
@ -1341,7 +1397,7 @@ namespace Mono.AssemblyCompare
|
||||||
oftype = fields.fieldTypes [name] as string;
|
oftype = fields.fieldTypes [name] as string;
|
||||||
|
|
||||||
if (ftype != oftype)
|
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) {
|
if (fieldValues != null) {
|
||||||
string fvalue = fieldValues [name] as string;
|
string fvalue = fieldValues [name] as string;
|
||||||
|
@ -1350,7 +1406,7 @@ namespace Mono.AssemblyCompare
|
||||||
ofvalue = fields.fieldValues [name] as string;
|
ofvalue = fields.fieldValues [name] as string;
|
||||||
|
|
||||||
if (fvalue != ofvalue)
|
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)
|
public override string GetNodeKey (string name, XmlNode node)
|
||||||
{
|
{
|
||||||
XmlAttributeCollection atts = node.Attributes;
|
XmlAttributeCollection atts = node.Attributes;
|
||||||
return String.Format ("{0}:{1}:{2}", atts ["name"].Value,
|
return String.Format ("{0}:{1}:{2}",
|
||||||
atts ["ptype"].Value,
|
(atts["name"] != null ? atts["name"].Value : ""),
|
||||||
atts ["params"].Value);
|
(atts["ptype"] != null ? atts["ptype"].Value : ""),
|
||||||
|
(atts["params"] != null ? atts["params"].Value : "")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GroupName {
|
public override string GroupName {
|
||||||
|
@ -1523,6 +1581,7 @@ namespace Mono.AssemblyCompare
|
||||||
class XMLEvents : XMLMember
|
class XMLEvents : XMLMember
|
||||||
{
|
{
|
||||||
Hashtable eventTypes;
|
Hashtable eventTypes;
|
||||||
|
Hashtable nameToMethod = new Hashtable ();
|
||||||
|
|
||||||
protected override void LoadExtraData (string name, XmlNode node)
|
protected override void LoadExtraData (string name, XmlNode node)
|
||||||
{
|
{
|
||||||
|
@ -1534,6 +1593,19 @@ namespace Mono.AssemblyCompare
|
||||||
eventTypes [name] = xatt.Value;
|
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);
|
base.LoadExtraData (name, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1555,7 +1627,17 @@ namespace Mono.AssemblyCompare
|
||||||
oetype = evt.eventTypes [name] as string;
|
oetype = evt.eventTypes [name] as string;
|
||||||
|
|
||||||
if (etype != oetype)
|
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 {
|
} finally {
|
||||||
AddCountersAttributes (parent);
|
AddCountersAttributes (parent);
|
||||||
copy.AddPartialToPartial (counters);
|
copy.AddPartialToPartial (counters);
|
||||||
|
@ -1591,7 +1673,8 @@ namespace Mono.AssemblyCompare
|
||||||
None = 0,
|
None = 0,
|
||||||
Abstract = 1,
|
Abstract = 1,
|
||||||
Virtual = 2,
|
Virtual = 2,
|
||||||
Static = 4
|
Static = 4,
|
||||||
|
Final = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadExtraData (string name, XmlNode node)
|
protected override void LoadExtraData (string name, XmlNode node)
|
||||||
|
@ -1611,6 +1694,8 @@ namespace Mono.AssemblyCompare
|
||||||
flags |= SignatureFlags.Static;
|
flags |= SignatureFlags.Static;
|
||||||
if (((XmlElement) node).GetAttribute ("virtual") == "true")
|
if (((XmlElement) node).GetAttribute ("virtual") == "true")
|
||||||
flags |= SignatureFlags.Virtual;
|
flags |= SignatureFlags.Virtual;
|
||||||
|
if (((XmlElement) node).GetAttribute ("final") == "true")
|
||||||
|
flags |= SignatureFlags.Final;
|
||||||
if (flags != SignatureFlags.None) {
|
if (flags != SignatureFlags.None) {
|
||||||
if (signatureFlags == null)
|
if (signatureFlags == null)
|
||||||
signatureFlags = new Hashtable ();
|
signatureFlags = new Hashtable ();
|
||||||
|
@ -1640,6 +1725,23 @@ namespace Mono.AssemblyCompare
|
||||||
base.LoadExtraData (name, node);
|
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)
|
protected override void CompareToInner (string name, XmlNode parent, XMLNameGroup other)
|
||||||
{
|
{
|
||||||
// create backup of actual counters
|
// create backup of actual counters
|
||||||
|
@ -1662,11 +1764,11 @@ namespace Mono.AssemblyCompare
|
||||||
|
|
||||||
if (flags!= oflags) {
|
if (flags!= oflags) {
|
||||||
if (flags == SignatureFlags.None)
|
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)
|
else if (oflags == SignatureFlags.None)
|
||||||
AddWarning (parent, String.Format ("should be {0}", flags));
|
AddWarning (parent, String.Format ("was {0}", flags));
|
||||||
else
|
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) {
|
if (returnTypes != null) {
|
||||||
|
@ -1676,7 +1778,7 @@ namespace Mono.AssemblyCompare
|
||||||
ortype = methods.returnTypes[name] as string;
|
ortype = methods.returnTypes[name] as string;
|
||||||
|
|
||||||
if (rtype != ortype)
|
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) {
|
if (parameters != null) {
|
||||||
|
@ -1712,7 +1814,7 @@ namespace Mono.AssemblyCompare
|
||||||
if ((ma & MethodAttributes.RequireSecObject) != 0)
|
if ((ma & MethodAttributes.RequireSecObject) != 0)
|
||||||
ma = (MethodAttributes) (att - (int) MethodAttributes.RequireSecObject);
|
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)
|
if ((ma & MethodAttributes.PinvokeImpl) != 0)
|
||||||
ma = (MethodAttributes) (att - (int) MethodAttributes.PinvokeImpl);
|
ma = (MethodAttributes) (att - (int) MethodAttributes.PinvokeImpl);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue