Browse Source

Merge branch 'master' into toggle-smooth-scrolling

pull/3394/head
Hertzole 4 months ago committed by GitHub
parent
commit
dcb37f7f8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      Directory.Packages.props
  2. 45
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  3. 3
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  4. 6
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  5. 18
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Comparisons.cs
  6. 24
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs
  7. 22
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs
  8. 28
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs
  9. 18
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Structs.cs
  10. 5
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  11. 4
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  12. 5
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs
  13. 18
      ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs
  14. 8
      ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs
  15. 2
      ILSpy/AssemblyTree/AssemblyTreeModel.cs
  16. 1
      ILSpy/ILSpy.csproj

4
Directory.Packages.props

@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageVersion Include="Microsoft.NETCore.ILAsm" Version="9.0.0" />
<PackageVersion Include="Microsoft.NETCore.ILDAsm" Version="9.0.0" />
<PackageVersion Include="Microsoft.Sbom.Targets" Version="3.0.1" />
<PackageVersion Include="Microsoft.Sbom.Targets" Version="3.0.1" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
<PackageVersion Include="Mono.Cecil" Version="0.11.6" />
@ -46,7 +46,7 @@ @@ -46,7 +46,7 @@
<PackageVersion Include="System.Resources.Extensions" Version="9.0.1" />
<PackageVersion Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.0" />
<PackageVersion Include="TomsToolbox.Composition.MicrosoftExtensions" Version="2.22.0" />
<PackageVersion Include="TomsToolbox.Wpf.Composition" Version="2.20.0" />
<PackageVersion Include="TomsToolbox.Wpf.Composition" Version="2.22.0" />
<PackageVersion Include="TomsToolbox.Wpf.Composition.AttributedModel" Version="2.22.0" />
<PackageVersion Include="TomsToolbox.Wpf.Styles" Version="2.22.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.3" />

45
ICSharpCode.Decompiler.Tests/Helpers/Tester.cs

@ -18,7 +18,6 @@ @@ -18,7 +18,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection.PortableExecutable;
@ -330,6 +329,45 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -330,6 +329,45 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return tempFile;
}
const string nonEmbeddedAttributesSnippet = @"
using System;
#if !NET60
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
internal sealed class CompilerFeatureRequiredAttribute : Attribute
{
public CompilerFeatureRequiredAttribute(string featureName)
{
}
}
internal class IsExternalInit
{
}
#endif
#if !NET70
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
internal sealed class RequiredMemberAttribute : Attribute
{
}
#endif
#if !NET60
}
#endif
";
static readonly Lazy<string> nonEmbeddedAttributesSnippetFile = new Lazy<string>(GetNonEmbeddedAttributesSnippetFile);
static string GetNonEmbeddedAttributesSnippetFile()
{
// Note: this leaks a temporary file, we're not attempting to delete it, because it is only one.
var tempFile = Path.GetTempFileName();
File.WriteAllText(tempFile, nonEmbeddedAttributesSnippet);
return tempFile;
}
public static List<string> GetPreprocessorSymbols(CompilerOptions flags)
{
var preprocessorSymbols = new List<string>();
@ -419,6 +457,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -419,6 +457,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
sourceFileNames.Add(targetFrameworkAttributeSnippetFile.Value);
}
if (targetNet40)
{
sourceFileNames.Add(nonEmbeddedAttributesSnippetFile.Value);
}
var preprocessorSymbols = GetPreprocessorSymbols(flags);
if ((flags & CompilerOptions.UseMcsMask) == 0)

3
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -130,6 +130,7 @@ @@ -130,6 +130,7 @@
<Compile Include="ProjectDecompiler\TargetFrameworkTests.cs" />
<Compile Include="TestAssemblyResolver.cs" />
<Compile Include="TestCases\ILPretty\MonoFixed.cs" />
<Compile Include="TestCases\Pretty\Comparisons.cs" />
<None Include="TestCases\VBPretty\VBAutomaticEvents.vb" />
<Compile Include="TestCases\VBPretty\VBAutomaticEvents.cs" />
<Compile Include="TestCases\VBPretty\VBNonGenericForEach.cs" />
@ -151,7 +152,7 @@ @@ -151,7 +152,7 @@
<None Include="TestCases\Pretty\CovariantReturns.cs" />
<Compile Include="TestCases\VBPretty\VBPropertiesTest.cs" />
<None Include="TestCases\ILPretty\Issue2260SwitchString.cs" />
<None Include="TestCases\Pretty\Records.cs" />
<Compile Include="TestCases\Pretty\Records.cs" />
<Compile Include="TestCases\VBPretty\Issue2192.cs" />
<Compile Include="Util\FileUtilityTests.cs" />
<Compile Include="TestCases\Pretty\FunctionPointers.cs" />

6
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -586,6 +586,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -586,6 +586,12 @@ namespace ICSharpCode.Decompiler.Tests
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task Comparisons([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task ConstantsTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{

18
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Comparisons.cs

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public class Comparisons
{
private class A
{
}
private class B
{
}
private bool CompareUnrelatedNeedsCast(A a, B b)
{
return (object)a == b;
}
}
}

24
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs

@ -235,6 +235,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests @@ -235,6 +235,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
{
int Property { get; set; }
}
#if CS90
public class Issue3392Type
{
public bool Flag { get; init; }
public List<int> List { get; } = new List<int>();
public Issue3392Type(object x)
{
}
}
#endif
#endregion
private S s1;
@ -1010,6 +1023,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests @@ -1010,6 +1023,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
otherItem.Data2.Nullable = 3m;
return otherItem;
}
#if CS90
public Issue3392Type Issue3392(Issue3392Type x)
{
x = new Issue3392Type(null) {
Flag = false
};
x.List.AddRange(Enumerable.Range(0, 10));
return x;
}
#endif
#if CS60
public OtherItem2 Issue1345c()
{

22
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs

@ -32,6 +32,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -32,6 +32,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
B
}
internal class OptionalArgumentTest
{
private static void Test()
{
Test2();
Test3();
Test4();
}
private static void Test2(int a = 0)
{
}
private static void Test3(int a = 0, int? b = null)
{
}
private static void Test4(int? b = null, int a = 0)
{
}
}
public OptionalArguments(string name, int a = 5)
{

28
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public record PairWithPrimaryCtor<A, B>(A First, B Second);
public record PrimaryCtor(int A, string B);
public record PrimaryCtorWithAttribute([RecordTest("param")] [property: RecordTest("property")][field: RecordTest("field")] int a);
public record PrimaryCtorWithAttribute([RecordTest("param")][property: RecordTest("property")][field: RecordTest("field")] int a);
public record PrimaryCtorWithField(int A, string B)
{
public double C = 1.0;
@ -169,7 +169,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -169,7 +169,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public record struct PairWithPrimaryCtor<A, B>(A First, B Second);
public record struct PrimaryCtor(int A, string B);
public record struct PrimaryCtorWithAttribute([RecordTest("param")] [property: RecordTest("property")][field: RecordTest("field")] int a);
public record struct PrimaryCtorWithAttribute([RecordTest("param")][property: RecordTest("property")][field: RecordTest("field")] int a);
public record struct PrimaryCtorWithField(int A, string B)
{
public double C = 1.0;
@ -242,27 +242,3 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -242,27 +242,3 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
#endif
}
#if !NET60
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
internal sealed class CompilerFeatureRequiredAttribute : Attribute
{
public CompilerFeatureRequiredAttribute(string featureName)
{
}
}
internal class IsExternalInit
{
}
#endif
#if !NET70
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
internal sealed class RequiredMemberAttribute : Attribute
{
}
#endif
#if !NET60
}
#endif

18
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Structs.cs

@ -59,20 +59,4 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -59,20 +59,4 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public required string LastName { get; set; }
}
#endif
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
internal sealed class CompilerFeatureRequiredAttribute : Attribute
{
public CompilerFeatureRequiredAttribute(string featureName)
{
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
internal sealed class RequiredMemberAttribute : Attribute
{
}
}
}

5
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -1043,7 +1043,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1043,7 +1043,10 @@ namespace ICSharpCode.Decompiler.CSharp
bool IsOptionalArgument(IParameter parameter, TranslatedExpression arg)
{
if (!parameter.IsOptional || !arg.ResolveResult.IsCompileTimeConstant)
if (!parameter.IsOptional)
return false;
if (!arg.ResolveResult.IsCompileTimeConstant && arg.ResolveResult is not ConversionResolveResult { Conversion.IsNullLiteralConversion: true })
return false;
if (parameter.GetAttributes().Any(a => a.AttributeType.IsKnownType(KnownAttribute.CallerMemberName)
|| a.AttributeType.IsKnownType(KnownAttribute.CallerFilePath)

4
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -1530,8 +1530,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1530,8 +1530,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteToken(Roles.RBracket);
switch (attributeSection.Parent)
{
case ParameterDeclaration _:
if (attributeSection.NextSibling is AttributeSection)
case ParameterDeclaration pd:
if (pd.Attributes.Last() != attributeSection)
Space(policy.SpaceBetweenParameterAttributeSections);
else
Space();

5
ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs

@ -805,7 +805,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -805,7 +805,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
if (op == BinaryOperatorType.Equality || op == BinaryOperatorType.InEquality)
{
if (lhsType.IsReferenceType == true && rhsType.IsReferenceType == true)
if (lhsType.IsReferenceType == true && rhsType.IsReferenceType == true
&& (conversions.IdentityConversion(lhsType, rhsType)
|| conversions.ExplicitConversion(lhsType, rhsType).IsReferenceConversion
|| conversions.ExplicitConversion(rhsType, lhsType).IsReferenceConversion))
{
// If it's a reference comparison
if (op == BinaryOperatorType.Equality)

18
ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs

@ -172,13 +172,27 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -172,13 +172,27 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
"Microsoft.CodeAnalysis.EmbeddedAttribute",
};
internal static readonly HashSet<string> nonEmbeddedAttributeNames = new HashSet<string>() {
// non-embedded attributes, but we still want to remove them
"System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute",
"System.Runtime.CompilerServices.RequiredMemberAttribute",
"System.Runtime.CompilerServices.IsExternalInit",
};
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
var typeDefinition = typeDeclaration.GetSymbol() as ITypeDefinition;
if (typeDefinition == null || !attributeNames.Contains(typeDefinition.FullName))
if (typeDefinition == null)
return;
if (!typeDefinition.HasAttribute(KnownAttribute.Embedded))
if (attributeNames.Contains(typeDefinition.FullName))
{
if (!typeDefinition.HasAttribute(KnownAttribute.Embedded))
return;
}
else if (!nonEmbeddedAttributeNames.Contains(typeDefinition.FullName))
return;
if (typeDeclaration.Parent is NamespaceDeclaration ns && ns.Members.Count == 1)
ns.Remove();
else

8
ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs

@ -103,6 +103,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -103,6 +103,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return;
}
int initializerItemsCount = 0;
bool initializerContainsInitOnlyItems = false;
possibleIndexVariables.Clear();
currentPath.Clear();
isCollection = false;
@ -113,13 +114,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -113,13 +114,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// if the method is a setter we're dealing with an object initializer
// if the method is named Add and has at least 2 arguments we're dealing with a collection/dictionary initializer
while (pos + initializerItemsCount + 1 < block.Instructions.Count
&& IsPartOfInitializer(block.Instructions, pos + initializerItemsCount + 1, v, instType, ref blockKind, context))
&& IsPartOfInitializer(block.Instructions, pos + initializerItemsCount + 1, v, instType, ref blockKind, ref initializerContainsInitOnlyItems, context))
{
initializerItemsCount++;
}
// Do not convert the statements into an initializer if there's an incompatible usage of the initializer variable
// directly after the possible initializer.
if (IsMethodCallOnVariable(block.Instructions[pos + initializerItemsCount + 1], v))
if (!initializerContainsInitOnlyItems && IsMethodCallOnVariable(block.Instructions[pos + initializerItemsCount + 1], v))
return;
// Calculate the correct number of statements inside the initializer:
// All index variables that were used in the initializer have Index set to -1.
@ -200,7 +201,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -200,7 +201,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
bool isCollection;
readonly Stack<HashSet<AccessPathElement>> pathStack = new Stack<HashSet<AccessPathElement>>();
bool IsPartOfInitializer(InstructionCollection<ILInstruction> instructions, int pos, ILVariable target, IType rootType, ref BlockKind blockKind, StatementTransformContext context)
bool IsPartOfInitializer(InstructionCollection<ILInstruction> instructions, int pos, ILVariable target, IType rootType, ref BlockKind blockKind, ref bool initializerContainsInitOnlyItems, StatementTransformContext context)
{
// Include any stores to local variables that are single-assigned and do not reference the initializer-variable
// in the list of possible index variables.
@ -255,6 +256,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -255,6 +256,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (blockKind != BlockKind.ObjectInitializer && blockKind != BlockKind.WithInitializer)
blockKind = BlockKind.ObjectInitializer;
initializerContainsInitOnlyItems |= lastElement.Member is IProperty { Setter.IsInitOnly: true };
return true;
default:
return false;

2
ILSpy/AssemblyTree/AssemblyTreeModel.cs

@ -767,6 +767,8 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -767,6 +767,8 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
else
{
// ensure that we are only connected once to the event, else we might get multiple notifications
ContextMenuProvider.ContextMenuClosed -= ContextMenuClosed;
ContextMenuProvider.ContextMenuClosed += ContextMenuClosed;
}
}

1
ILSpy/ILSpy.csproj

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<RollForward>major</RollForward>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>

Loading…
Cancel
Save