private static Dictionary <string, List <ITypeDefinition> > GetShortNamesToTypeDefinitions(DecompilerTypeSystem winmd) { Dictionary <string, List <ITypeDefinition> > ret = new Dictionary <string, List <ITypeDefinition> >(); foreach (var type1 in winmd.GetTopLevelTypeDefinitions()) { if (type1.FullName == "<Module>") { continue; } if (type1.ParentModule != winmd.MainModule) { continue; } string name = type1.Name; if (!ret.TryGetValue(name, out var list)) { list = new List <ITypeDefinition>(); ret[name] = list; } list.Add(type1); } return(ret); }
private static Dictionary <string, List <IMember> > GetApiMemberNamesToMethodDefinitions(DecompilerTypeSystem winmd) { Dictionary <string, List <IMember> > ret = new Dictionary <string, List <IMember> >(); foreach (var type1 in winmd.GetTopLevelTypeDefinitions()) { if (type1.FullName == "<Module>") { continue; } if (type1.ParentModule != winmd.MainModule) { continue; } if (type1.Kind != TypeKind.Class || type1.Name != "Apis") { continue; } foreach (var m in type1.Members) { string name = m.Name; string archInfo = GetArchInfo(m.GetAttributes()); if (!string.IsNullOrEmpty(archInfo)) { name += $"({archInfo})"; } if (!ret.TryGetValue(name, out var list)) { list = new List <IMember>(); ret[name] = list; } list.Add(m); } } return(ret); }
private static Dictionary <string, ITypeDefinition> GetNamesToTypeDefinitions(DecompilerTypeSystem winmd) { Dictionary <string, ITypeDefinition> ret = new Dictionary <string, ITypeDefinition>(); foreach (var type1 in winmd.GetTopLevelTypeDefinitions()) { if (type1.FullName == "<Module>") { continue; } if (type1.ParentModule != winmd.MainModule) { continue; } string name = GetFullTypeName(type1); ret[name] = type1; } return(ret); }
public static int CompareWinmds(FileInfo first, FileInfo second, string exclusions, IConsole console) { bool same = true; DecompilerSettings settings = new DecompilerSettings() { ThrowOnAssemblyResolveErrors = false }; DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(first.FullName, settings); DecompilerTypeSystem winmd2 = CreateTypeSystemFromFile(second.FullName, settings); Dictionary <string, ITypeDefinition> winmd2NamesToTypes = GetNamesToTypeDefinitions(winmd2); Dictionary <string, List <ITypeDefinition> > winmd2ShortNamesToTypes = GetShortNamesToTypeDefinitions(winmd2); HashSet <string> visitedNames = new HashSet <string>(); foreach (var type1 in winmd1.GetTopLevelTypeDefinitions()) { if (type1.FullName == "<Module>") { continue; } if (type1.ParentModule != winmd1.MainModule) { continue; } var type1Name = GetFullTypeName(type1); visitedNames.Add(type1Name); winmd2NamesToTypes.TryGetValue(type1Name, out var type2); if (type2 == null) { if (winmd2ShortNamesToTypes.TryGetValue(type1.Name, out var list)) { foreach (var t2 in list) { if (CompareTypes(type1, t2, null)) { var type2Name = GetFullTypeName(t2); console?.Out.Write($"{type1Name} => {type2Name}\r\n"); visitedNames.Add(type2Name); same = false; type2 = t2; break; } } } if (type2 == null) { console?.Out.Write($"{type1Name} not found in 2nd winmd\r\n"); same = false; } continue; } same &= CompareTypes(type1, type2, console); } Dictionary <string, ITypeDefinition> winmd1NamesToTypes = GetNamesToTypeDefinitions(winmd1); foreach (var type2 in winmd2.GetTopLevelTypeDefinitions()) { if (type2.FullName == "<Module>") { continue; } var type2FullName = GetFullTypeName(type2); if (type2.ParentModule != winmd2.MainModule) { continue; } if (visitedNames.Contains(type2FullName)) { continue; } winmd1NamesToTypes.TryGetValue(type2FullName, out var type1); if (type1 == null) { console?.Out.Write($"{type2FullName} not found in 1st winmd\r\n"); same = false; } } if (same) { console.Out.Write($"No differences in winmd contents.\r\n"); } return(same ? 0 : -1); }
public static int ShowDuplicateImports(FileInfo winmd, IConsole console) { DecompilerSettings settings = new DecompilerSettings() { ThrowOnAssemblyResolveErrors = false }; DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(winmd.FullName, settings); Dictionary <string, List <string> > dllImportsToClassNames = new Dictionary <string, List <string> >(); foreach (var type1 in winmd1.GetTopLevelTypeDefinitions()) { if (type1.FullName == "<Module>") { continue; } if (type1.ParentModule != winmd1.MainModule) { continue; } if (type1.Kind != TypeKind.Class) { continue; } foreach (var method in type1.GetMethods()) { if (!method.IsStatic) { continue; } var dllImportAttr = method.GetAttribute(KnownAttribute.DllImport); if (dllImportAttr != null) { string entryPoint = method.Name; var dllName = (string)(dllImportAttr.FixedArguments[0].Value); var entryPointVar = dllImportAttr.NamedArguments.FirstOrDefault(a => a.Name == "EntryPoint"); if (entryPointVar.Name != null) { entryPoint = (string)entryPointVar.Value; } string fullImport = $"{dllName}:{entryPoint}"; string archInfo = GetArchInfo(method.GetAttributes()); if (!string.IsNullOrEmpty(archInfo)) { fullImport += $"({archInfo})"; } if (!dllImportsToClassNames.TryGetValue(fullImport, out var classNames)) { classNames = new List <string>(); dllImportsToClassNames[fullImport] = classNames; } classNames.Add(type1.FullName); } } } bool dupsFound = false; foreach (var pair in dllImportsToClassNames) { if (pair.Value.Count > 1) { if (dupsFound == false) { dupsFound = true; console.Out.Write("Duplicated imports detected:\r\n"); } pair.Value.Sort(); console?.Out.Write($"{pair.Key}\r\n"); foreach (var imp in pair.Value) { console?.Out.Write($" {imp}\r\n"); } } } if (!dupsFound) { console.Out.Write("No duplicate imports found.\r\n"); } return(dupsFound ? -1 : 0); }
public static int ShowDuplicateTypes(FileInfo winmd, IConsole console) { DecompilerSettings settings = new DecompilerSettings() { ThrowOnAssemblyResolveErrors = false }; DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(winmd.FullName, settings); Dictionary <string, List <string> > nameToNamespaces = new Dictionary <string, List <string> >(); foreach (var type1 in winmd1.GetTopLevelTypeDefinitions()) { if (type1.FullName == "<Module>") { continue; } if (type1.ParentModule != winmd1.MainModule) { continue; } var typeName = type1.Name; if (type1.Kind == TypeKind.Class && typeName == "Apis") { continue; } StringBuilder members = new StringBuilder(); foreach (var m in type1.Members) { if (type1.Kind == TypeKind.Enum && m.Name == "value__") { continue; } if (m.Name == ".ctor") { continue; } if (members.Length != 0) { members.Append(','); } members.Append(m.Name); } if (members.Length != 0) { typeName += $"({members})"; } string archInfo = GetArchInfo(type1.GetAttributes()); if (!string.IsNullOrEmpty(archInfo)) { typeName += $"({archInfo})"; } if (!nameToNamespaces.TryGetValue(typeName, out var namespaces)) { namespaces = new List <string>(); nameToNamespaces[typeName] = namespaces; } namespaces.Add(type1.Namespace); } bool dupsFound = false; foreach (var pair in nameToNamespaces) { if (pair.Value.Count > 1) { if (dupsFound == false) { dupsFound = true; console.Out.Write("Duplicate types detected:\r\n"); } pair.Value.Sort(); console?.Out.Write($"{pair.Key}\r\n"); foreach (var ns in pair.Value) { console?.Out.Write($" {ns}\r\n"); } } } if (!dupsFound) { console.Out.Write("No duplicate types found.\r\n"); } return(dupsFound ? -1 : 0); }
public static int ShowDuplicateConstants(FileInfo winmd, IConsole console) { DecompilerSettings settings = new DecompilerSettings() { ThrowOnAssemblyResolveErrors = false }; DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(winmd.FullName, settings); Dictionary <string, List <string> > nameToOwner = new Dictionary <string, List <string> >(); foreach (var type in winmd1.GetTopLevelTypeDefinitions()) { if (type.FullName == "<Module>") { continue; } if (type.ParentModule != winmd1.MainModule) { continue; } // Skip enums marked as a scoped enum (like a C++ class enum). // We don't count these in the duplicated constants if (type.Kind == TypeKind.Enum) { if (type.GetAttributes().Any(a => a.AttributeType.Name == "ScopedEnumAttribute")) { continue; } } if (type.Kind == TypeKind.Enum || (type.Kind == TypeKind.Class && type.Name == "Apis")) { foreach (var field in type.GetFields()) { if (field.Name == "value__") { continue; } if (!nameToOwner.TryGetValue(field.Name, out var owners)) { owners = new List <string>(); nameToOwner[field.Name] = owners; } owners.Add(type.FullName); } } } bool dupsFound = false; foreach (var pair in nameToOwner) { if (pair.Value.Count > 1) { if (dupsFound == false) { dupsFound = true; console.Out.Write("Duplicate constants/enum names detected:\r\n"); } pair.Value.Sort(); console?.Out.Write($"{pair.Key}\r\n"); foreach (var owner in pair.Value) { console?.Out.Write($" {owner}\r\n"); } } } if (!dupsFound) { console.Out.Write("No duplicate constants/enum names found.\r\n"); } return(dupsFound ? -1 : 0); }
public static int CompareWinmds(FileInfo first, FileInfo second, string exclusions, IConsole console) { bool same = true; DecompilerSettings settings = new DecompilerSettings() { ThrowOnAssemblyResolveErrors = false }; DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(first.FullName, settings); DecompilerTypeSystem winmd2 = CreateTypeSystemFromFile(second.FullName, settings); Dictionary <string, ITypeDefinition> winmd2NamesToTypes = GetNamesToTypeDefinitions(winmd2); Dictionary <string, List <ITypeDefinition> > winmd2ShortNamesToTypes = GetShortNamesToTypeDefinitions(winmd2); HashSet <string> visitedNames = new HashSet <string>(); foreach (var type1 in winmd1.GetTopLevelTypeDefinitions()) { if (type1.FullName == "<Module>") { continue; } if (type1.ParentModule != winmd1.MainModule) { continue; } // We'll compare the members of Apis in their own way if (type1.Name == "Apis") { continue; } var type1Name = GetFullTypeName(type1); visitedNames.Add(type1Name); winmd2NamesToTypes.TryGetValue(type1Name, out var type2); if (type2 == null) { if (winmd2ShortNamesToTypes.TryGetValue(type1.Name, out var list)) { foreach (var t2 in list) { if (CompareTypes(type1, t2, null)) { var type2Name = GetFullTypeName(t2); console?.Out.Write($"{type1Name} => {type2Name}\r\n"); visitedNames.Add(type2Name); same = false; type2 = t2; break; } } } if (type2 == null) { console?.Out.Write($"{type1Name} not found in 2nd winmd\r\n"); same = false; } continue; } same &= CompareTypes(type1, type2, console); } Dictionary <string, ITypeDefinition> winmd1NamesToTypes = GetNamesToTypeDefinitions(winmd1); foreach (var type2 in winmd2.GetTopLevelTypeDefinitions()) { if (type2.FullName == "<Module>") { continue; } if (type2.ParentModule != winmd2.MainModule) { continue; } // We'll compare the members of Apis in their own way if (type2.Name == "Apis") { continue; } var type2FullName = GetFullTypeName(type2); if (visitedNames.Contains(type2FullName)) { continue; } winmd1NamesToTypes.TryGetValue(type2FullName, out var type1); if (type1 == null) { console?.Out.Write($"{type2FullName} not found in 1st winmd\r\n"); same = false; } } var apiNameToMembers1 = GetApiMemberNamesToMethodDefinitions(winmd1); var apiNameToMembers2 = GetApiMemberNamesToMethodDefinitions(winmd2); HashSet <string> visitedM2Names = new HashSet <string>(); foreach (var api1MemberInfo in apiNameToMembers1) { if (apiNameToMembers2.TryGetValue(api1MemberInfo.Key, out var api2Members)) { foreach (var m1 in api1MemberInfo.Value) { string m1FullName = GetFullMemberName(m1); bool found = false; foreach (var m2 in api2Members) { if (m1.GetType() == m2.GetType()) { string m2FullName = GetFullMemberName(m2); bool membersSame; if (m1 is IField) { membersSame = CompareFields((IField)m1, (IField)m2, console); } else { membersSame = CompareMethods((IMethod)m1, (IMethod)m2, null); // If the members aren't the same on the methods and the namespaces also aren't // the same, then assume these aren't the same methods and keep going if (!membersSame && (m1.Namespace != m2.Namespace)) { continue; } if (!membersSame && console != null) { CompareMethods((IMethod)m1, (IMethod)m2, console); } } if (membersSame) { if (m1.Namespace != m2.Namespace) { console?.Out.Write($"{m1FullName} => {m2FullName}\r\n"); membersSame = false; } } same &= membersSame; visitedM2Names.Add(m2FullName); found = true; break; } } if (!found) { console?.Out.Write($"{m1FullName} not found in 2nd winmd\r\n"); } } } else { foreach (var m1 in api1MemberInfo.Value) { string m1FullName = GetFullMemberName(m1); console?.Out.Write($"{m1FullName} not found in 2nd winmd\r\n"); same = false; } } } foreach (var api2MemberInfo in apiNameToMembers2) { foreach (var api2Member in api2MemberInfo.Value) { string m2FullName = GetFullMemberName(api2Member); if (!visitedM2Names.Contains(m2FullName)) { console?.Out.Write($"{m2FullName} not found in 1st winmd\r\n"); same = false; } } } if (same) { console.Out.Write($"No differences in winmd contents.\r\n"); } return(same ? 0 : -1); }
public IEnumerable <DependenciesInNamespace> GetNamespaceDependencies(string winmdFileName) { DecompilerTypeSystem winmd1 = DecompilerTypeSystemUtils.CreateTypeSystemFromFile(winmdFileName); foreach (var type1 in winmd1.GetTopLevelTypeDefinitions()) { if (type1.FullName == "<Module>") { continue; } if (type1.ParentModule != winmd1.MainModule) { continue; } var typeNamespace = type1.Namespace; if (!this.namespacesToDepends.TryGetValue(typeNamespace, out var depends)) { depends = new(typeNamespace); this.namespacesToDepends[typeNamespace] = depends; } if (type1.Kind == TypeKind.Struct) { foreach (var field in type1.GetFields()) { string broughtInBy = $"{type1.Name}.{field.Name}"; this.AddTypeDependency(type1, depends, broughtInBy, field.Type); } } else if (type1.Kind == TypeKind.Class && type1.Name == "Apis") { foreach (var method in type1.GetMethods().Where(m => m.IsStatic && m.DeclaringType == type1)) { string returnBroughtInBy = $"{method.Name}::return"; this.AddTypeDependency(type1, depends, returnBroughtInBy, method.ReturnType); foreach (var p in method.Parameters) { string paramBroughtInBy = $"{method.Name}(...{p.Name}...)"; this.AddTypeDependency(type1, depends, paramBroughtInBy, p.Type); } } } else if (type1.Kind == TypeKind.Interface) { foreach (var directBaseType in type1.DirectBaseTypes) { if (directBaseType.FullName == "System.Object") { continue; } string inheritBroughtInBy = $"{type1.Name} inherits"; this.AddTypeDependency(type1, depends, inheritBroughtInBy, directBaseType); } foreach (var method in type1.GetMethods().Where(m => m.DeclaringType == type1)) { string returnBroughtInBy = $"{type1.Name}::{method.Name}::return"; this.AddTypeDependency(type1, depends, returnBroughtInBy, method.ReturnType); foreach (var p in method.Parameters) { string paramBroughtInBy = $"{type1.Name}::{method.Name}(...{p.Name}...)"; this.AddTypeDependency(type1, depends, paramBroughtInBy, p.Type); } } } } var finalDepends = this.namespacesToDepends.Values.OrderBy(d => d.Namespace); Dictionary <string, IEnumerable <string> > namespaceToDepends = new(); foreach (var dependsInNamespace in finalDepends) { namespaceToDepends.Add(dependsInNamespace.Namespace, dependsInNamespace.GetDependenciesByNamespace().Select(p => p.Key)); } foreach (var dependsInNamespace in finalDepends) { dependsInNamespace.LoadAllDependendencyNamespaces(namespaceToDepends); } return(finalDepends); }
private static IEnumerable <ITypeDefinition> GetSelfDefinedWinmdToplevelTypes(DecompilerTypeSystem winmd) { return(winmd.GetTopLevelTypeDefinitions().Where( type => type.ParentModule == winmd.MainModule && type.FullName != "<Module>")); }