Browse Source

Fix #2716: Add an option to allow sorting custom attributes

pull/3410/head
Siegfried Pammer 3 months ago
parent
commit
8b76879493
  1. 1
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 78
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  3. 18
      ICSharpCode.Decompiler/DecompilerSettings.cs
  4. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  5. 39
      ICSharpCode.Decompiler/Util/DelegateComparer.cs
  6. 9
      ILSpy/Properties/Resources.Designer.cs
  7. 3
      ILSpy/Properties/Resources.resx
  8. 3
      ILSpy/Properties/Resources.zh-Hans.resx

1
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -528,6 +528,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -528,6 +528,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
var typeSystemAstBuilder = new TypeSystemAstBuilder();
typeSystemAstBuilder.ShowAttributes = true;
typeSystemAstBuilder.SortAttributes = settings.SortCustomAttributes;
typeSystemAstBuilder.AlwaysUseShortTypeNames = true;
typeSystemAstBuilder.AddResolveResultAnnotations = true;
typeSystemAstBuilder.UseNullableSpecifierForValueTypes = settings.LiftNullables;

78
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -147,6 +147,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -147,6 +147,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// </summary>
public bool ShowAttributes { get; set; }
/// <summary>
/// Controls whether to sort attributes, if set to <see langword="false" /> attributes are shown in metadata order.
/// The default value is <see langword="false" />.
/// </summary>
public bool SortAttributes { get; set; }
/// <summary>
/// Controls whether to use fully-qualified type names or short type names.
/// The default value is <see langword="false" />.
@ -793,16 +799,72 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -793,16 +799,72 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return attr;
}
private IEnumerable<AttributeSection> ConvertAttributes(IEnumerable<IAttribute> attributes)
{
return attributes.Select(a => new AttributeSection(ConvertAttribute(a)));
}
private IEnumerable<AttributeSection> ConvertAttributes(IEnumerable<IAttribute> attributes, string target)
private IEnumerable<AttributeSection> ConvertAttributes(IEnumerable<IAttribute> attributes, string target = null)
{
return attributes.Select(a => new AttributeSection(ConvertAttribute(a)) {
AttributeTarget = target
if (SortAttributes)
attributes = attributes.OrderBy(a => a, new DelegateComparer<IAttribute>(CompareAttribute));
return attributes.Select(a => {
var section = new AttributeSection(ConvertAttribute(a));
if (target != null)
section.AttributeTarget = target;
return section;
});
static int CompareAttribute(IAttribute a, IAttribute b)
{
int result = CompareType(a.AttributeType, b.AttributeType);
if (result != 0)
return result;
if (a.HasDecodeErrors && b.HasDecodeErrors)
return 0;
if (a.HasDecodeErrors)
return -1;
if (b.HasDecodeErrors)
return 1;
result = a.FixedArguments.Length - b.FixedArguments.Length;
if (result != 0)
return result;
for (int i = 0; i < a.FixedArguments.Length; i++)
{
var argA = a.FixedArguments[i];
var argB = b.FixedArguments[i];
result = CompareType(argA.Type, argB.Type);
if (result != 0)
return result;
if (argA.Value is IComparable compA && argB.Value is IComparable compB)
result = compA.CompareTo(compB);
else
result = 0;
if (result != 0)
return result;
}
result = a.NamedArguments.Length - b.NamedArguments.Length;
if (result != 0)
return result;
for (int i = 0; i < a.FixedArguments.Length; i++)
{
var argA = a.NamedArguments[i];
var argB = b.NamedArguments[i];
result = argA.Name.CompareTo(argB.Name);
if (result != 0)
return result;
result = CompareType(argA.Type, argB.Type);
if (result != 0)
return result;
if (argA.Value is IComparable compA && argB.Value is IComparable compB)
result = compA.CompareTo(compB);
else
result = 0;
if (result != 0)
return result;
}
return 0;
}
static int CompareType(IType a, IType b)
{
return a.FullName.CompareTo(b.FullName);
}
}
#endregion

18
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -2148,6 +2148,24 @@ namespace ICSharpCode.Decompiler @@ -2148,6 +2148,24 @@ namespace ICSharpCode.Decompiler
}
}
bool sortCustomAttributes = false;
/// <summary>
/// Sort custom attributes.
/// </summary>
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.SortCustomAttributes")]
public bool SortCustomAttributes {
get { return sortCustomAttributes; }
set {
if (sortCustomAttributes != value)
{
sortCustomAttributes = value;
OnPropertyChanged();
}
}
}
CSharpFormattingOptions csharpFormattingOptions;
[Browsable(false)]

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -154,6 +154,7 @@ @@ -154,6 +154,7 @@
<Compile Include="Properties\DecompilerVersionInfo.cs" />
<Compile Include="TypeSystem\ITypeDefinitionOrUnknown.cs" />
<Compile Include="Util\BitOperations.cs" />
<Compile Include="Util\DelegateComparer.cs" />
<Compile Include="Util\Index.cs" />
<Compile Include="Metadata\WebCilFile.cs" />
<None Include="Properties\DecompilerVersionInfo.template.cs" />

39
ICSharpCode.Decompiler/Util/DelegateComparer.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
#nullable enable
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.Util
{
public class DelegateComparer<T> : IComparer<T>
{
private readonly Func<T?, T?, int> func;
public DelegateComparer(Func<T?, T?, int> func)
{
this.func = func ?? throw new ArgumentNullException(nameof(func));
}
public int Compare(T? x, T? y)
{
return func(x, y);
}
}
}

9
ILSpy/Properties/Resources.Designer.cs generated

@ -1325,6 +1325,15 @@ namespace ICSharpCode.ILSpy.Properties { @@ -1325,6 +1325,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Sort custom attributes.
/// </summary>
public static string DecompilerSettings_SortCustomAttributes {
get {
return ResourceManager.GetString("DecompilerSettings.SortCustomAttributes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Detect switch on integer even if IL code does not use a jump table.
/// </summary>

3
ILSpy/Properties/Resources.resx

@ -462,6 +462,9 @@ Are you sure you want to continue?</value> @@ -462,6 +462,9 @@ Are you sure you want to continue?</value>
<data name="DecompilerSettings.ShowInfoFromDebugSymbolsIfAvailable" xml:space="preserve">
<value>Show info from debug symbols, if available</value>
</data>
<data name="DecompilerSettings.SortCustomAttributes" xml:space="preserve">
<value>Sort custom attributes</value>
</data>
<data name="DecompilerSettings.SparseIntegerSwitch" xml:space="preserve">
<value>Detect switch on integer even if IL code does not use a jump table</value>
</data>

3
ILSpy/Properties/Resources.zh-Hans.resx

@ -435,6 +435,9 @@ @@ -435,6 +435,9 @@
<data name="DecompilerSettings.ShowInfoFromDebugSymbolsIfAvailable" xml:space="preserve">
<value>显示调试符号中的信息(如果可用)</value>
</data>
<data name="DecompilerSettings.SortCustomAttributes" xml:space="preserve">
<value />
</data>
<data name="DecompilerSettings.SparseIntegerSwitch" xml:space="preserve">
<value>检测整型 switch 即使 IL 代码不使用跳转表</value>
</data>

Loading…
Cancel
Save