Browse Source

Fix #3457: NRE when creating Mermaid diagram of assembly with (possibly) missing references.

net10upgrade
Siegfried Pammer 2 months ago
parent
commit
e5a85422d3
  1. 42
      ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs
  2. 34
      ICSharpCode.ILSpyX/MermaidDiagrammer/Factory.FlatMembers.cs

42
ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs

@ -20,6 +20,8 @@ using System; @@ -20,6 +20,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
#nullable enable
namespace ICSharpCode.Decompiler.TypeSystem
{
/// <summary>
@ -34,7 +36,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -34,7 +36,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary>
/// Gets the base member that has the same signature.
/// </summary>
public static IMember GetBaseMember(IMember member)
public static IMember? GetBaseMember(IMember member)
{
return GetBaseMembers(member, false).FirstOrDefault();
}
@ -109,7 +111,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -109,7 +111,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary>
/// Finds the member declared in 'derivedType' that has the same signature (could override) 'baseMember'.
/// </summary>
public static IMember GetDerivedMember(IMember baseMember, ITypeDefinition derivedType)
public static IMember? GetDerivedMember(IMember baseMember, ITypeDefinition derivedType)
{
if (baseMember == null)
throw new ArgumentNullException(nameof(baseMember));
@ -120,9 +122,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -120,9 +122,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
throw new ArgumentException("baseMember and derivedType must be from the same compilation");
baseMember = baseMember.MemberDefinition;
bool includeInterfaces = baseMember.DeclaringTypeDefinition.Kind == TypeKind.Interface;
IMethod method = baseMember as IMethod;
if (method != null)
bool includeInterfaces = baseMember.DeclaringTypeDefinition?.Kind == TypeKind.Interface;
if (baseMember is IMethod method)
{
foreach (IMethod derivedMethod in derivedType.Methods)
{
@ -137,8 +138,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -137,8 +138,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
}
}
IProperty property = baseMember as IProperty;
if (property != null)
if (baseMember is IProperty property)
{
foreach (IProperty derivedProperty in derivedType.Properties)
{
@ -175,7 +175,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -175,7 +175,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
foreach (var baseType in typeDef.GetNonInterfaceBaseTypes().Reverse())
{
ITypeDefinition baseTypeDef = baseType.GetDefinition();
ITypeDefinition? baseTypeDef = baseType.GetDefinition();
if (baseTypeDef == null)
continue;
foreach (var attr in baseTypeDef.GetAttributes())
@ -185,11 +185,11 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -185,11 +185,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
}
internal static IAttribute GetAttribute(ITypeDefinition typeDef, KnownAttribute attributeType)
internal static IAttribute? GetAttribute(ITypeDefinition typeDef, KnownAttribute attributeType)
{
foreach (var baseType in typeDef.GetNonInterfaceBaseTypes().Reverse())
{
ITypeDefinition baseTypeDef = baseType.GetDefinition();
ITypeDefinition? baseTypeDef = baseType.GetDefinition();
if (baseTypeDef == null)
continue;
var attr = baseTypeDef.GetAttribute(attributeType);
@ -202,7 +202,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -202,7 +202,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
internal static IEnumerable<IAttribute> GetAttributes(IMember member)
{
HashSet<IMember> visitedMembers = new HashSet<IMember>();
do
while (true)
{
member = member.MemberDefinition; // it's sufficient to look at the definitions
if (!visitedMembers.Add(member))
@ -214,13 +214,19 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -214,13 +214,19 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
yield return attr;
}
} while (member.IsOverride && (member = InheritanceHelper.GetBaseMember(member)) != null);
if (!member.IsOverride)
break;
var baseMember = GetBaseMember(member);
if (baseMember == null)
break;
member = baseMember;
}
}
internal static IAttribute GetAttribute(IMember member, KnownAttribute attributeType)
internal static IAttribute? GetAttribute(IMember member, KnownAttribute attributeType)
{
HashSet<IMember> visitedMembers = new HashSet<IMember>();
do
while (true)
{
member = member.MemberDefinition; // it's sufficient to look at the definitions
if (!visitedMembers.Add(member))
@ -231,7 +237,13 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -231,7 +237,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
var attr = member.GetAttribute(attributeType);
if (attr != null)
return attr;
} while (member.IsOverride && (member = InheritanceHelper.GetBaseMember(member)) != null);
if (!member.IsOverride)
break;
var baseMember = GetBaseMember(member);
if (baseMember == null)
break;
member = baseMember;
}
return null;
}
#endregion

34
ICSharpCode.ILSpyX/MermaidDiagrammer/Factory.FlatMembers.cs

@ -40,12 +40,34 @@ namespace ICSharpCode.ILSpyX.MermaidDiagrammer @@ -40,12 +40,34 @@ namespace ICSharpCode.ILSpyX.MermaidDiagrammer
&& !properties.Any(p => f.ReturnType.Equals(p.ReturnType)
&& Regex.IsMatch(f.Name, "_?" + p.Name, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.NonBacktracking))).ToArray();
private static IEnumerable<IMethod> GetMethods(ITypeDefinition type) => type.GetMethods(m =>
!m.IsOperator && !m.IsCompilerGenerated()
&& (m.DeclaringType == type // include methods if self-declared
/* but exclude methods declared by object and their overrides, if inherited */
|| (!m.DeclaringType.IsObject()
&& (!m.IsOverride || !InheritanceHelper.GetBaseMember(m).DeclaringType.IsObject()))));
private static IEnumerable<IMethod> GetMethods(ITypeDefinition type)
{
return type.GetMethods(IsDeclaredMethod);
bool IsDeclaredMethod(IMethod m)
{
if (m.IsOperator || m.IsCompilerGenerated())
return false;
if (m.DeclaringTypeDefinition == type)
{
// include methods if self-declared
return true;
}
else
{
// but exclude methods declared by object and their overrides, if inherited
if (m.DeclaringType.IsObject())
return false;
IMember? baseMember;
if (m.IsOverride && (baseMember = InheritanceHelper.GetBaseMember(m)) != null)
{
if (baseMember.DeclaringType.IsObject())
return false;
}
}
return true;
}
}
private string FormatMethod(IMethod method)
{

Loading…
Cancel
Save