Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent .NET members with names differing only by case from crashing the compatibility profiler #1195

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class AssemblyData : ICloneable
/// and then type name.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public JsonCaseInsensitiveStringDictionary<JsonCaseInsensitiveStringDictionary<TypeData>> Types { get; set; }
public JsonDictionary<string, JsonDictionary<string, TypeData>> Types { get; set; }

/// <summary>
/// Create a deep clone of the assembly data object.
Expand All @@ -34,7 +34,7 @@ public object Clone()
return new AssemblyData()
{
AssemblyName = (AssemblyNameData)AssemblyName.Clone(),
Types = (JsonCaseInsensitiveStringDictionary<JsonCaseInsensitiveStringDictionary<TypeData>>)Types?.Clone()
Types = (JsonDictionary<string, JsonDictionary<string, TypeData>>)Types?.Clone()
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class AvailableTypeData : ICloneable
/// keyed by simple assembly name.
/// </summary>
[DataMember]
public JsonCaseInsensitiveStringDictionary<AssemblyData> Assemblies { get; set; }
public JsonDictionary<string, AssemblyData> Assemblies { get; set; }

/// <summary>
/// Create a deep clone of the available type data object.
Expand All @@ -36,7 +36,7 @@ public object Clone()
return new AvailableTypeData()
{
TypeAccelerators = (JsonCaseInsensitiveStringDictionary<TypeAcceleratorData>)TypeAccelerators.Clone(),
Assemblies = (JsonCaseInsensitiveStringDictionary<AssemblyData>)Assemblies.Clone()
Assemblies = (JsonDictionary<string, AssemblyData>)Assemblies.Clone()
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ public class MemberData : ICloneable
/// Fields on the type, keyed by field name.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public JsonCaseInsensitiveStringDictionary<FieldData> Fields { get; set; }
public JsonDictionary<string, FieldData> Fields { get; set; }

/// <summary>
/// Properties on this type, keyed by property name.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public JsonCaseInsensitiveStringDictionary<PropertyData> Properties { get; set; }
public JsonDictionary<string, PropertyData> Properties { get; set; }

/// <summary>
/// Indexers on the type.
Expand All @@ -44,19 +44,19 @@ public class MemberData : ICloneable
/// Methods on the type, keyed by method name.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public JsonCaseInsensitiveStringDictionary<MethodData> Methods { get; set; }
public JsonDictionary<string, MethodData> Methods { get; set; }

/// <summary>
/// Events on the type, keyed by event name.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public JsonCaseInsensitiveStringDictionary<EventData> Events { get; set; }
public JsonDictionary<string, EventData> Events { get; set; }

/// <summary>
/// Types nested within the type, keyed by type name.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public JsonCaseInsensitiveStringDictionary<TypeData> NestedTypes { get; set; }
public JsonDictionary<string, TypeData> NestedTypes { get; set; }

/// <summary>
/// Create a deep clone of the member data object.
Expand All @@ -66,12 +66,12 @@ public object Clone()
return new MemberData()
{
Constructors = Constructors?.Select(c => (string[])c.Clone()).ToArray(),
Events = (JsonCaseInsensitiveStringDictionary<EventData>)Events?.Clone(),
Fields = (JsonCaseInsensitiveStringDictionary<FieldData>)Fields?.Clone(),
Events = (JsonDictionary<string, EventData>)Events?.Clone(),
Fields = (JsonDictionary<string, FieldData>)Fields?.Clone(),
Indexers = Indexers?.Select(i => (IndexerData)i.Clone()).ToArray(),
Methods = (JsonCaseInsensitiveStringDictionary<MethodData>)Methods?.Clone(),
NestedTypes = (JsonCaseInsensitiveStringDictionary<TypeData>)NestedTypes?.Clone(),
Properties = (JsonCaseInsensitiveStringDictionary<PropertyData>)Properties?.Clone(),
Methods = (JsonDictionary<string, MethodData>)Methods?.Clone(),
NestedTypes = (JsonDictionary<string, TypeData>)NestedTypes?.Clone(),
Properties = (JsonDictionary<string, PropertyData>)Properties?.Clone(),
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ public AssemblyData(Data.Types.AssemblyData assemblyData)
/// </summary>
public IReadOnlyDictionary<string, IReadOnlyDictionary<string, TypeData>> Types => _types?.Value;

private static IReadOnlyDictionary<string, IReadOnlyDictionary<string, TypeData>> CreateTypeDictionary(IReadOnlyDictionary<string, JsonCaseInsensitiveStringDictionary<Data.Types.TypeData>> typeData)
private static IReadOnlyDictionary<string, IReadOnlyDictionary<string, TypeData>> CreateTypeDictionary(IReadOnlyDictionary<string, JsonDictionary<string, Data.Types.TypeData>> typeData)
{
var namespaceDict = new Dictionary<string, IReadOnlyDictionary<string, TypeData>>(typeData.Count, StringComparer.OrdinalIgnoreCase);
foreach (KeyValuePair<string, JsonCaseInsensitiveStringDictionary<Data.Types.TypeData>> nspace in typeData)
foreach (KeyValuePair<string, JsonDictionary<string, Data.Types.TypeData>> nspace in typeData)
{
var typeDict = new Dictionary<string, TypeData>(nspace.Value.Count, StringComparer.OrdinalIgnoreCase);
foreach (KeyValuePair<string, Data.Types.TypeData> type in nspace.Value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ private static object Union(ParameterSetData thisParameterSet, ParameterSetData

private static object Union(AvailableTypeData thisTypes, AvailableTypeData thatTypes)
{
thisTypes.Assemblies = StringDictionaryUnion(thisTypes.Assemblies, thatTypes.Assemblies, Union);
thisTypes.Assemblies = DictionaryUnion(thisTypes.Assemblies, thatTypes.Assemblies, Union);
thisTypes.TypeAccelerators = StringDictionaryUnion(thisTypes.TypeAccelerators, thatTypes.TypeAccelerators);

return thisTypes;
Expand All @@ -136,18 +136,18 @@ private static object Union(AssemblyData thisAssembly, AssemblyData thatAssembly
{
if (thisAssembly.Types == null)
{
thisAssembly.Types = new JsonCaseInsensitiveStringDictionary<JsonCaseInsensitiveStringDictionary<TypeData>>();
thisAssembly.Types = new JsonDictionary<string, JsonDictionary<string, TypeData>>();
}

foreach (KeyValuePair<string, JsonCaseInsensitiveStringDictionary<TypeData>> nspace in thatAssembly.Types)
foreach (KeyValuePair<string, JsonDictionary<string, TypeData>> nspace in thatAssembly.Types)
{
if (!thisAssembly.Types.ContainsKey(nspace.Key))
{
thisAssembly.Types.Add(nspace.Key, nspace.Value);
continue;
}

thisAssembly.Types[nspace.Key] = StringDictionaryUnion(thisAssembly.Types[nspace.Key], nspace.Value, Union);
thisAssembly.Types[nspace.Key] = DictionaryUnion(thisAssembly.Types[nspace.Key], nspace.Value, Union);
}
}

Expand Down Expand Up @@ -192,11 +192,11 @@ private static object Union(MemberData thisMembers, MemberData thatMembers)

thisMembers.Constructors = ParameterUnion(thisMembers.Constructors, thatMembers.Constructors);

thisMembers.Events = StringDictionaryUnion(thisMembers.Events, thatMembers.Events);
thisMembers.Fields = StringDictionaryUnion(thisMembers.Fields, thatMembers.Fields);
thisMembers.Methods = StringDictionaryUnion(thisMembers.Methods, thatMembers.Methods, Union);
thisMembers.NestedTypes = StringDictionaryUnion(thisMembers.NestedTypes, thatMembers.NestedTypes, Union);
thisMembers.Properties = StringDictionaryUnion(thisMembers.Properties, thatMembers.Properties, Union);
thisMembers.Events = DictionaryUnion(thisMembers.Events, thatMembers.Events);
thisMembers.Fields = DictionaryUnion(thisMembers.Fields, thatMembers.Fields);
thisMembers.Methods = DictionaryUnion(thisMembers.Methods, thatMembers.Methods, Union);
thisMembers.NestedTypes = DictionaryUnion(thisMembers.NestedTypes, thatMembers.NestedTypes, Union);
thisMembers.Properties = DictionaryUnion(thisMembers.Properties, thatMembers.Properties, Union);

return thisMembers;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static AvailableTypeData AssembleAvailableTypes(
typeAcceleratorDict.Add(typeAccelerator.Key, ta);
}

var asms = new JsonCaseInsensitiveStringDictionary<AssemblyData>();
var asms = new JsonDictionary<string, AssemblyData>();
foreach (Assembly asm in assemblies)
{
// Don't want to include this module or assembly in the output
Expand All @@ -61,8 +61,17 @@ public static AvailableTypeData AssembleAvailableTypes(

try
{
// First check whether an assembly with this name already exists
// Only replace it if the current one is newer
AssemblyName asmName = asm.GetName();
if (asms.TryGetValue(asmName.Name, out AssemblyData currentAssemblyData)
&& asmName.Version < currentAssemblyData.AssemblyName.Version)
{
continue;
}

KeyValuePair<string, AssemblyData> asmData = AssembleAssembly(asm);
asms.Add(asmData.Key, asmData.Value);
asms[asmData.Key] = asmData.Value;
}
catch (ReflectionTypeLoadException e)
{
Expand Down Expand Up @@ -96,10 +105,10 @@ public static KeyValuePair<string, AssemblyData> AssembleAssembly(Assembly asm)
};

Type[] types = asm.GetTypes();
JsonCaseInsensitiveStringDictionary<JsonCaseInsensitiveStringDictionary<TypeData>> namespacedTypes = null;
JsonDictionary<string, JsonDictionary<string, TypeData>> namespacedTypes = null;
if (types.Any())
{
namespacedTypes = new JsonCaseInsensitiveStringDictionary<JsonCaseInsensitiveStringDictionary<TypeData>>();
namespacedTypes = new JsonDictionary<string, JsonDictionary<string, TypeData>>();
foreach (Type type in asm.GetTypes())
{
if (!type.IsPublic)
Expand All @@ -110,14 +119,14 @@ public static KeyValuePair<string, AssemblyData> AssembleAssembly(Assembly asm)
// Some types don't have a namespace, but we still want to file them
string typeNamespace = type.Namespace ?? "";

if (!namespacedTypes.ContainsKey(typeNamespace))
if (!namespacedTypes.TryGetValue(typeNamespace, out JsonDictionary<string, TypeData> typeDictionary))
{
namespacedTypes.Add(typeNamespace, new JsonCaseInsensitiveStringDictionary<TypeData>());
typeDictionary = new JsonDictionary<string, TypeData>();
}

TypeData typeData = AssembleType(type);

namespacedTypes[typeNamespace][type.Name] = typeData;
typeDictionary[type.Name] = typeData;
}
}

Expand Down Expand Up @@ -271,12 +280,12 @@ private static MemberData AssembleMembers(Type type, BindingFlags memberBinding)
return new MemberData()
{
Constructors = constructors.Any() ? constructors.Select(c => AssembleConstructor(c)).ToArray() : null,
Events = events.Any() ? new JsonCaseInsensitiveStringDictionary<EventData>(events.ToDictionary(e => e.Name, e => AssembleEvent(e), StringComparer.OrdinalIgnoreCase)) : null,
Fields = fields.Any() ? new JsonCaseInsensitiveStringDictionary<FieldData>(fields.ToDictionary(f => f.Name, f => AssembleField(f), StringComparer.OrdinalIgnoreCase)) : null,
Events = events.Any() ? new JsonDictionary<string, EventData>(events.ToDictionary(e => e.Name, e => AssembleEvent(e))) : null,
Fields = fields.Any() ? new JsonDictionary<string, FieldData>(fields.ToDictionary(f => f.Name, f => AssembleField(f))) : null,
Indexers = indexers.Any() ? indexers.Select(i => AssembleIndexer(i)).ToArray() : null,
Methods = methods.Any() ? new JsonCaseInsensitiveStringDictionary<MethodData>(methods.ToDictionary(m => m.Key, m => AssembleMethod(m.Value), StringComparer.OrdinalIgnoreCase)) : null,
NestedTypes = nestedTypes.Any() ? new JsonCaseInsensitiveStringDictionary<TypeData>(nestedTypes.ToDictionary(t => t.Name, t => AssembleType(t), StringComparer.OrdinalIgnoreCase)) : null,
Properties = properties.Any() ? new JsonCaseInsensitiveStringDictionary<PropertyData>(properties.ToDictionary(p => p.Name, p => AssembleProperty(p), StringComparer.OrdinalIgnoreCase)) : null
Methods = methods.Any() ? new JsonDictionary<string, MethodData>(methods.ToDictionary(m => m.Key, m => AssembleMethod(m.Value))) : null,
NestedTypes = nestedTypes.Any() ? new JsonDictionary<string, TypeData>(nestedTypes.ToDictionary(t => t.Name, t => AssembleType(t))) : null,
Properties = properties.Any() ? new JsonDictionary<string, PropertyData>(properties.ToDictionary(p => p.Name, p => AssembleProperty(p))) : null
};
}

Expand Down