diff --git a/src/DotNet/CustomAttribute.cs b/src/DotNet/CustomAttribute.cs index 030d27fb2..377fdf82e 100644 --- a/src/DotNet/CustomAttribute.cs +++ b/src/DotNet/CustomAttribute.cs @@ -43,8 +43,26 @@ public string TypeFullName { return string.Empty; } - } - + } + + /// + /// Gets the name of the attribute type + /// + internal string TypeName { + get { + if (ctor is MemberRef mrCtor) + return mrCtor.GetDeclaringTypeName() ?? string.Empty; + + if (ctor is MethodDef mdCtor) { + var declType = mdCtor.DeclaringType; + if (declType is not null) + return declType.Name; + } + + return string.Empty; + } + } + /// /// true if the raw custom attribute blob hasn't been parsed /// diff --git a/src/DotNet/CustomAttributeCollection.cs b/src/DotNet/CustomAttributeCollection.cs index c3b8a53af..07fba4659 100644 --- a/src/DotNet/CustomAttributeCollection.cs +++ b/src/DotNet/CustomAttributeCollection.cs @@ -37,8 +37,12 @@ public CustomAttributeCollection(int length, object context, Func /// Full name of custom attribute type that should be removed public void RemoveAll(string fullName) { + if (fullName == null) + return; + for (int i = Count - 1; i >= 0; i--) { - if (this[i].TypeFullName == fullName) + var ca = this[i]; + if (ca is not null && fullName.EndsWith(ca.TypeName, StringComparison.Ordinal) && ca.TypeFullName == fullName) RemoveAt(i); } } @@ -49,8 +53,11 @@ public void RemoveAll(string fullName) { /// Full name of custom attribute type /// A or null if it wasn't found public CustomAttribute Find(string fullName) { + if (fullName == null) + return null; + foreach (var ca in this) { - if (ca is not null && ca.TypeFullName == fullName) + if (ca is not null && fullName.EndsWith(ca.TypeName, StringComparison.Ordinal) && ca.TypeFullName == fullName) return ca; } @@ -63,8 +70,11 @@ public CustomAttribute Find(string fullName) { /// Full name of custom attribute type /// All s of the requested type public IEnumerable FindAll(string fullName) { + if (fullName == null) + yield break; + foreach (var ca in this) { - if (ca is not null && ca.TypeFullName == fullName) + if (ca is not null && fullName.EndsWith(ca.TypeName, StringComparison.Ordinal) && ca.TypeFullName == fullName) yield return ca; } } diff --git a/src/DotNet/MemberRef.cs b/src/DotNet/MemberRef.cs index ef1fe8325..fb0f587fd 100644 --- a/src/DotNet/MemberRef.cs +++ b/src/DotNet/MemberRef.cs @@ -285,8 +285,28 @@ string GetDeclaringTypeFullName(IMemberRefParent parent) { return declaringType?.FullName; } return null; // Should never be reached - } - + } + + /// + /// Get the declaring type's name + /// + /// Name or null if there's no declaring type + internal string GetDeclaringTypeName() => GetDeclaringTypeName(@class); + + string GetDeclaringTypeName(IMemberRefParent parent) { + if (parent is null) + return null; + if (parent is ITypeDefOrRef) + return ((ITypeDefOrRef)parent).Name; + if (parent is ModuleRef) + return $""; + if (parent is MethodDef) { + var declaringType = ((MethodDef)parent).DeclaringType; + return declaringType?.Name; + } + return null; // Should never be reached + } + /// /// Resolves the method/field ///