Skip to content

Commit

Permalink
[nnyeah] Move to generating map on the fly (#14868)
Browse files Browse the repository at this point in the history
Remove the XML serialization and now make the map into a form that will work much better for actually modifying the assemblies
  • Loading branch information
stephen-hawley authored May 3, 2022
1 parent b72e7be commit 1c7d63f
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 154 deletions.
6 changes: 3 additions & 3 deletions tools/nnyeah/nnyeah/AssemblyComparator/ComparingVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void VisitTypes (TypeReworker reworker, ModuleElements earlier, ModuleElements l
continue;
}

TypeEvents.InvokeFound (this, typeNameAndValue.Key, laterElems.DeclaringType.ToString ());
TypeEvents.InvokeFound (this, typeNameAndValue.Key, laterElems.DeclaringType);

VisitAllMembers (reworker, typeNameAndValue.Value, laterElems);
}
Expand All @@ -63,7 +63,7 @@ void VisitMember<T> (TypeReworker reworker, TypeElement<T> elem,
{
foreach (var late in later) {
if (elem.Signature == late.Signature) {
events.InvokeFound (this, elem.Signature, late.Signature);
events.InvokeFound (this, elem.Signature, late.Element);
return;
}
}
Expand All @@ -74,7 +74,7 @@ void VisitMember<T> (TypeReworker reworker, TypeElement<T> elem,
}
foreach (var late in later) {
if (remappedSig == late.Signature) {
events.InvokeFound (this, elem.Signature, late.Signature);
events.InvokeFound (this, elem.Signature, late.Element);
return;
}
}
Expand Down
9 changes: 5 additions & 4 deletions tools/nnyeah/nnyeah/AssemblyComparator/ItemFoundEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Mono.Cecil;

#nullable enable

Expand All @@ -12,20 +13,20 @@ public ItemNotFoundEventArgs (string original)
}

public class ItemFoundEventArgs<T> : EventArgs {
public ItemFoundEventArgs (string original, string mapped)
public ItemFoundEventArgs (string original, T mapped)
{
Original = original;
Mapped = mapped;
}
public string Original { get; init; }
public string Mapped { get; init; }
public T Mapped { get; init; }
}

public class ItemEvents<T> {
public class ItemEvents<T> where T: IMemberDefinition {
public EventHandler<ItemNotFoundEventArgs<T>> NotFound = (s, e) => { };
public EventHandler<ItemFoundEventArgs<T>> Found = (s, e) => { };

internal void InvokeFound (object sender, string original, string mapped) =>
internal void InvokeFound (object sender, string original, T mapped) =>
Found.Invoke (sender, new (original, mapped));

internal void InvokeNotFound (object sender, string original) =>
Expand Down
35 changes: 6 additions & 29 deletions tools/nnyeah/nnyeah/AssemblyComparator/TypeAndMemberMap.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.IO;
using System.Collections.Generic;
using Mono.Cecil;
using System.Xml.Serialization;

#nullable enable
Expand All @@ -8,46 +9,22 @@ namespace Microsoft.MaciOS.Nnyeah.AssemblyComparator {
[XmlRoot]
public class TypeAndMemberMap {
public List<string> TypesNotPresent { get; init; } = new List<string> ();
public UniquingStringDictionary TypeMap { get; init; } = new UniquingStringDictionary ();
public Dictionary<string, TypeDefinition> TypeMap { get; init; } = new Dictionary<string, TypeDefinition> ();

public List<string> MethodsNotPresent { get; init; } = new List<string> ();
public UniquingStringDictionary MethodMap { get; init; } = new UniquingStringDictionary ();
public Dictionary<string, MethodDefinition> MethodMap { get; init; } = new Dictionary<string, MethodDefinition> ();

public List<string> FieldsNotPresent { get; init; } = new List<string> ();
public UniquingStringDictionary FieldMap { get; init; } = new UniquingStringDictionary ();
public Dictionary<string, FieldDefinition> FieldMap { get; init; } = new Dictionary<string, FieldDefinition> ();

public List<string> EventsNotPresent { get; init; } = new List<string> ();
public UniquingStringDictionary EventMap { get; init; } = new UniquingStringDictionary ();
public Dictionary<string, EventDefinition> EventMap { get; init; } = new Dictionary<string, EventDefinition> ();

public List<string> PropertiesNotPresent { get; init; } = new List<string> ();
public UniquingStringDictionary PropertyMap { get; init; } = new UniquingStringDictionary ();
public Dictionary<string, PropertyDefinition> PropertyMap { get; init; } = new Dictionary<string, PropertyDefinition> ();

public TypeAndMemberMap ()
{
}

public void ToXml (string path)
{
using var stm = new FileStream (path, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
ToXml (stm);
}

public void ToXml (Stream stm)
{
var serializer = new XmlSerializer (typeof (TypeAndMemberMap));
serializer.Serialize (stm, this);
}

public static TypeAndMemberMap? FromXml (string path)
{
using var stm = new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read);
return FromXml (stm);
}

public static TypeAndMemberMap? FromXml (Stream stm)
{
var serializer = new XmlSerializer (typeof (TypeAndMemberMap));
return (TypeAndMemberMap?)serializer.Deserialize (stm);
}
}
}
74 changes: 0 additions & 74 deletions tools/nnyeah/nnyeah/AssemblyComparator/UniquingStringDictionary.cs

This file was deleted.

83 changes: 39 additions & 44 deletions tools/nnyeah/nnyeah/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using Microsoft.MaciOS.Nnyeah.AssemblyComparator;
using Mono.Cecil;
using System.Diagnostics.CodeAnalysis;

namespace Microsoft.MaciOS.Nnyeah {
class Program {
Expand All @@ -14,8 +15,7 @@ static void Main (string [] args)
var verbose = false;
var forceOverwrite = false;
var suppressWarnings = false;
var compareAssemblies = false;
string? earlierAssembly = null, laterAssembly = null;
string? xamarinAssembly = null, microsoftAssembly = null;

var options = new OptionSet () {
{ "h|?|help", o => doHelp = true },
Expand All @@ -24,9 +24,8 @@ static void Main (string [] args)
{ "v|verbose", o => verbose = true },
{ "f|force-overwrite", o => forceOverwrite = true },
{ "s|suppress-warnings", o => suppressWarnings = true },
{ "c|compare-assemblies", o => compareAssemblies = true },
{ "e|earlier-assembly=", f => earlierAssembly = f },
{ "l|later-assembly=", f => laterAssembly = f },
{ "x|xamarin-assembly=", f => xamarinAssembly = f },
{ "m|microsoft-assembly=", f => microsoftAssembly = f },
};

try {
Expand All @@ -35,63 +34,59 @@ static void Main (string [] args)
doHelp = true;
}

var badForMungingAssembly = !compareAssemblies && (infile is null || outfile is null);
var badForComparingAssemblies = compareAssemblies && (earlierAssembly is null || laterAssembly is null || outfile is null);
var badForMungingAssembly = infile is null || outfile is null;
var badForComparingAssemblies = xamarinAssembly is null || microsoftAssembly is null;

if (doHelp || badForComparingAssemblies || badForMungingAssembly) {
PrintOptions (options, Console.Out);
Environment.Exit (0);
}

if (compareAssemblies) {
try {
CompareAssemblies (earlierAssembly!, laterAssembly!, outfile!, publicOnly: true,
forceOverwrite: forceOverwrite);
} catch (Exception e) {
Console.Error.WriteLine (Errors.E0011, e.Message);
}
} else {
ReworkFile (infile!, outfile!, verbose, forceOverwrite, suppressWarnings);
if (!TryLoadTypeAndModuleMap (xamarinAssembly!, microsoftAssembly!, publicOnly: true,
out var typeAndModuleMap, out var failureReason)) {
Console.Error.WriteLine (Errors.E0011, failureReason);
}
ReworkFile (infile!, outfile!, verbose, forceOverwrite, suppressWarnings);
}

static void CompareAssemblies (string earlier, string later,
string outfile, bool publicOnly, bool forceOverwrite)
static bool TryLoadTypeAndModuleMap (string earlier, string later, bool publicOnly,
[NotNullWhen (returnValue: true)] out TypeAndMemberMap? result,
[NotNullWhen (returnValue: false)] out string? reason)
{
if (File.Exists (outfile) && !forceOverwrite) {
Console.Error.WriteLine (Errors.E0002, outfile);
Environment.Exit (1);
}

using var ealierFile = TryOpenRead (earlier);
using var laterFile = TryOpenRead (later);

var earlierModule = ModuleDefinition.ReadModule (ealierFile);
var laterModule = ModuleDefinition.ReadModule (laterFile);
try {
using var ealierFile = TryOpenRead (earlier);
using var laterFile = TryOpenRead (later);

var comparingVisitor = new ComparingVisitor (earlierModule, laterModule, publicOnly);
var map = new TypeAndMemberMap ();
var earlierModule = ModuleDefinition.ReadModule (ealierFile);
var laterModule = ModuleDefinition.ReadModule (laterFile);

comparingVisitor.TypeEvents.NotFound += (s, e) => { map.TypesNotPresent.Add (e.Original); };
comparingVisitor.TypeEvents.Found += (s, e) => { map.TypeMap.Add (e.Original, e.Mapped); };
var comparingVisitor = new ComparingVisitor (earlierModule, laterModule, publicOnly);
var map = new TypeAndMemberMap ();

comparingVisitor.MethodEvents.NotFound += (s, e) => { map.MethodsNotPresent.Add (e.Original); };
comparingVisitor.MethodEvents.Found += (s, e) => { map.MethodMap.Add (e.Original, e.Mapped); };
comparingVisitor.TypeEvents.NotFound += (s, e) => { map.TypesNotPresent.Add (e.Original); };
comparingVisitor.TypeEvents.Found += (s, e) => { map.TypeMap.Add (e.Original, e.Mapped); };

comparingVisitor.FieldEvents.NotFound += (s, e) => { map.FieldsNotPresent.Add (e.Original); };
comparingVisitor.FieldEvents.Found += (s, e) => { map.FieldMap.Add (e.Original, e.Mapped); };
comparingVisitor.MethodEvents.NotFound += (s, e) => { map.MethodsNotPresent.Add (e.Original); };
comparingVisitor.MethodEvents.Found += (s, e) => { map.MethodMap.Add (e.Original, e.Mapped); };

comparingVisitor.EventEvents.NotFound += (s, e) => { map.EventsNotPresent.Add (e.Original); };
comparingVisitor.EventEvents.Found += (s, e) => { map.EventMap.Add (e.Original, e.Mapped); };
comparingVisitor.FieldEvents.NotFound += (s, e) => { map.FieldsNotPresent.Add (e.Original); };
comparingVisitor.FieldEvents.Found += (s, e) => { map.FieldMap.Add (e.Original, e.Mapped); };

comparingVisitor.PropertyEvents.NotFound += (s, e) => { map.PropertiesNotPresent.Add (e.Original); };
comparingVisitor.PropertyEvents.Found += (s, e) => { map.PropertyMap.Add (e.Original, e.Mapped); };
comparingVisitor.EventEvents.NotFound += (s, e) => { map.EventsNotPresent.Add (e.Original); };
comparingVisitor.EventEvents.Found += (s, e) => { map.EventMap.Add (e.Original, e.Mapped); };

comparingVisitor.Visit ();
comparingVisitor.PropertyEvents.NotFound += (s, e) => { map.PropertiesNotPresent.Add (e.Original); };
comparingVisitor.PropertyEvents.Found += (s, e) => { map.PropertyMap.Add (e.Original, e.Mapped); };

using var ostm = new FileStream (outfile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
map.ToXml (ostm);
ostm.Close ();
comparingVisitor.Visit ();
result = map;
reason = null;
return true;
} catch (Exception e) {
result = null;
reason = e.Message;
return false;
}
}


Expand Down

5 comments on commit 1c7d63f

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 [CI Build] API Diff 📋

API Current PR diff

✅ API Diff (from PR only) (no change)

View API diff
View dotnet API diff
View dotnet legacy API diff
View dotnet iOS-MacCatalayst API diff

API diff

✅ API Diff from stable

View API diff
View dotnet API diff
View dotnet legacy API diff
View dotnet iOS-MacCatalayst API diff

Generator diff

Generator Diff (no change)

Pipeline on Agent XAMMINI-051.Monterey
Hash: 1c7d63f393b01df4ceb9d51382d8f0f5150ca5f5

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💻 [CI Build] Tests on macOS M1 - Mac Big Sur (11.5) passed 💻

All tests on macOS M1 - Mac Big Sur (11.5) passed.

Pipeline on Agent
Hash: 1c7d63f393b01df4ceb9d51382d8f0f5150ca5f5

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ [CI Build] Tests on macOS Mac Catalina (10.15) failed ❌

Failed tests are:

  • introspection

Pipeline on Agent
Hash: 1c7d63f393b01df4ceb9d51382d8f0f5150ca5f5

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📚 [CI Build] Artifacts 📚

Packages generated

View packages

Pipeline on Agent XAMMINI-052.Monterey
Hash: 1c7d63f393b01df4ceb9d51382d8f0f5150ca5f5

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ [CI Build] Tests failed on VSTS: simulator tests iOS ❌

Tests failed on VSTS: simulator tests iOS.

Test results

2 tests failed, 232 tests passed.

Failed tests

  • introspection/iOS Unified 64-bits - simulator/Debug (iOS 12.4) [dotnet]: Failed
  • introspection/tvOS - simulator/Debug (tvOS 12.4) [dotnet]: Failed

Pipeline on Agent XAMBOT-1035.Monterey'
[nnyeah] Move to generating map on the fly (#14868)

Please sign in to comment.