diff --git a/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs b/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs index efdd021d3..2ce551e79 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs @@ -20,7 +20,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers if (section.Attributes.Count == 0) section.Remove(); } - if (section.AttributeTarget == "module" && type.Identifier == "UnverifiableCode") + if (section.AttributeTarget == "module" && type.Identifier is "UnverifiableCode" or "RefSafetyRules") { attribute.Remove(); if (section.Attributes.Count == 0) @@ -34,35 +34,6 @@ namespace ICSharpCode.Decompiler.Tests.Helpers } } - public class RemoveEmbeddedAttributes : DepthFirstAstVisitor, IAstTransform - { - HashSet attributeNames = new HashSet() { - "System.Runtime.CompilerServices.IsReadOnlyAttribute", - "System.Runtime.CompilerServices.IsByRefLikeAttribute", - "System.Runtime.CompilerServices.IsUnmanagedAttribute", - "System.Runtime.CompilerServices.NullableAttribute", - "System.Runtime.CompilerServices.NullableContextAttribute", - "System.Runtime.CompilerServices.NativeIntegerAttribute", - "Microsoft.CodeAnalysis.EmbeddedAttribute", - }; - - public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration) - { - var typeDefinition = typeDeclaration.GetSymbol() as ITypeDefinition; - if (typeDefinition == null || !attributeNames.Contains(typeDefinition.FullName)) - return; - if (typeDeclaration.Parent is NamespaceDeclaration ns && ns.Members.Count == 1) - ns.Remove(); - else - typeDeclaration.Remove(); - } - - public void Run(AstNode rootNode, TransformContext context) - { - rootNode.AcceptVisitor(this); - } - } - public class RemoveNamespaceMy : DepthFirstAstVisitor, IAstTransform { public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs index d871bed94..967f564e6 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs @@ -72,7 +72,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" }); } - string otherOptions = $"-noconfig " + + string otherOptions = $"-nologo -noconfig " + "-optioninfer+ -optionexplicit+ " + $"-langversion:{languageVersion} " + $"/optimize{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}"; @@ -122,8 +122,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers var result = await command.ExecuteBufferedAsync().ConfigureAwait(false); - Console.WriteLine("output: " + result.StandardOutput); - Console.WriteLine("errors: " + result.StandardError); + if (!string.IsNullOrWhiteSpace(result.StandardOutput)) + { + Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput); + } + if (!string.IsNullOrWhiteSpace(result.StandardError)) + { + Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); + } Assert.AreEqual(0, result.ExitCode, "vbc failed"); return results; diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index 3b880ca57..1c6e5ac09 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -176,13 +176,19 @@ namespace ICSharpCode.Decompiler.Tests.Helpers } var command = Cli.Wrap(ilasmPath) - .WithArguments($"/nologo {otherOptions}/output=\"{outputFile}\" \"{sourceFileName}\"") + .WithArguments($"/quiet {otherOptions}/output=\"{outputFile}\" \"{sourceFileName}\"") .WithValidation(CommandResultValidation.None); var result = await command.ExecuteBufferedAsync().ConfigureAwait(false); - Console.WriteLine("output: " + result.StandardOutput); - Console.WriteLine("errors: " + result.StandardError); + if (!string.IsNullOrWhiteSpace(result.StandardOutput)) + { + Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput); + } + if (!string.IsNullOrWhiteSpace(result.StandardError)) + { + Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); + } Assert.AreEqual(0, result.ExitCode, "ilasm failed"); return outputFile; @@ -224,8 +230,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers var result = await command.ExecuteBufferedAsync().ConfigureAwait(false); - Console.WriteLine("output: " + result.StandardOutput); - Console.WriteLine("errors: " + result.StandardError); + if (!string.IsNullOrWhiteSpace(result.StandardOutput)) + { + Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput); + } + if (!string.IsNullOrWhiteSpace(result.StandardError)) + { + Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); + } Assert.AreEqual(0, result.ExitCode, "ildasm failed"); // Unlike the .imagebase directive (which is a fixed value when compiling with /deterministic), @@ -353,10 +365,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { preprocessorSymbols.Add("ROSLYN4"); preprocessorSymbols.Add("CS100"); - if (flags.HasFlag(CompilerOptions.Preview)) - { - preprocessorSymbols.Add("CS110"); - } + preprocessorSymbols.Add("CS110"); } } else if ((flags & CompilerOptions.UseMcsMask) != 0) @@ -430,7 +439,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { references = references.Concat(new[] { "-r:\"System.Runtime.CompilerServices.Unsafe.dll\"" }); } - string otherOptions = $"-noconfig " + + string otherOptions = $"-nologo -noconfig " + $"-langversion:{languageVersion} " + $"-unsafe -o{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}"; @@ -482,12 +491,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers var command = Cli.Wrap(cscPath) .WithArguments($"{otherOptions} -lib:{libPath} {string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}") .WithValidation(CommandResultValidation.None); - Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}"); + //Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}"); var result = await command.ExecuteBufferedAsync().ConfigureAwait(false); + if (!string.IsNullOrWhiteSpace(result.StandardOutput)) + { + Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput); + } + if (!string.IsNullOrWhiteSpace(result.StandardError)) + { + Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); + } - Console.WriteLine("output: " + result.StandardOutput); - Console.WriteLine("errors: " + result.StandardError); Assert.AreEqual(0, result.ExitCode, "csc failed"); return results; @@ -538,12 +553,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers var command = Cli.Wrap(mcsPath) .WithArguments($"{otherOptions}-out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}") .WithValidation(CommandResultValidation.None); - Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}"); + //Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}"); var result = await command.ExecuteBufferedAsync().ConfigureAwait(false); - Console.WriteLine("output: " + result.StandardOutput); - Console.WriteLine("errors: " + result.StandardError); + if (!string.IsNullOrWhiteSpace(result.StandardOutput)) + { + Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput); + } + if (!string.IsNullOrWhiteSpace(result.StandardError)) + { + Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); + } Assert.AreEqual(0, result.ExitCode, "mcs failed"); return results; @@ -558,7 +579,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers CompilerOptions.UseRoslyn1_3_2 => CSharp.LanguageVersion.CSharp6, CompilerOptions.UseRoslyn2_10_0 => CSharp.LanguageVersion.CSharp7_3, CompilerOptions.UseRoslyn3_11_0 => CSharp.LanguageVersion.CSharp9_0, - _ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp10_0, + _ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp11_0, }; DecompilerSettings settings = new(langVersion) { // Never use file-scoped namespaces @@ -815,8 +836,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers var result = await command.ExecuteBufferedAsync().ConfigureAwait(false); Assert.AreEqual(0, result.ExitCode, "sn failed"); - Console.WriteLine("output: " + result.StandardOutput); - Console.WriteLine("errors: " + result.StandardError); + if (!string.IsNullOrWhiteSpace(result.StandardOutput)) + { + Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput); + } + if (!string.IsNullOrWhiteSpace(result.StandardError)) + { + Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); + } } public static async Task FindMSBuild() diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 5134bd3e6..074902fe0 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -57,7 +57,7 @@ - + diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index 549273f56..3d77b3fb5 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -135,15 +135,7 @@ namespace ICSharpCode.Decompiler.Tests CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest, }; - static readonly CompilerOptions[] roslynLatestOnlyWithNet40Options = - { - CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40, - CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40, - CompilerOptions.UseRoslynLatest, - CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest, - }; - - static readonly CompilerOptions[] roslynLatestOnlyOptions = + static readonly CompilerOptions[] roslyn4OrNewerOptions = { CompilerOptions.UseRoslynLatest, CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest, @@ -261,7 +253,7 @@ namespace ICSharpCode.Decompiler.Tests } [Test] - public async Task SwitchExpressions([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions) + public async Task SwitchExpressions([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions) { await RunForLibrary(cscOptions: cscOptions); } @@ -275,7 +267,7 @@ namespace ICSharpCode.Decompiler.Tests [Test] public async Task DelegateConstruction([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions) { - await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); + await RunForLibrary(cscOptions: cscOptions); } [Test] @@ -340,7 +332,7 @@ namespace ICSharpCode.Decompiler.Tests [Test] public async Task LocalFunctions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions) { - await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); + await RunForLibrary(cscOptions: cscOptions); } [Test] @@ -494,13 +486,13 @@ namespace ICSharpCode.Decompiler.Tests } [Test] - public async Task NativeInts([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions) + public async Task NativeInts([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions) { - await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); + await RunForLibrary(cscOptions: cscOptions); } [Test] - public async Task FileScopedNamespaces([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions) + public async Task FileScopedNamespaces([ValueSource(nameof(roslyn4OrNewerOptions))] CompilerOptions cscOptions) { await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings()); } @@ -512,13 +504,13 @@ namespace ICSharpCode.Decompiler.Tests } [Test] - public async Task FunctionPointers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions) + public async Task FunctionPointers([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions) { - await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); + await RunForLibrary(cscOptions: cscOptions); } [Test] - public async Task Records([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions) + public async Task Records([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions) { await RunForLibrary(cscOptions: cscOptions | CompilerOptions.NullableEnable); } @@ -586,7 +578,7 @@ namespace ICSharpCode.Decompiler.Tests [Test] public async Task OptionalArguments([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) { - await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); + await RunForLibrary(cscOptions: cscOptions); } [Test] @@ -610,11 +602,6 @@ namespace ICSharpCode.Decompiler.Tests [Test] public async Task CustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) { - if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest)) - { - // Test C# 11 generic attributes - cscOptions |= CompilerOptions.Preview; - } await RunForLibrary(cscOptions: cscOptions); } @@ -669,7 +656,7 @@ namespace ICSharpCode.Decompiler.Tests [Test] public async Task YieldReturn([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions) { - await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); + await RunForLibrary(cscOptions: cscOptions); } [Test] @@ -703,9 +690,9 @@ namespace ICSharpCode.Decompiler.Tests } [Test] - public async Task StaticAbstractInterfaceMembers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions) + public async Task StaticAbstractInterfaceMembers([ValueSource(nameof(roslyn4OrNewerOptions))] CompilerOptions cscOptions) { - await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); + await RunForLibrary(cscOptions: cscOptions); } [Test] diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs index c853317bc..4ba4af434 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs @@ -2,16 +2,16 @@ using System; using System.Reflection; using System.Runtime.CompilerServices; +[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")] +[assembly: CLSCompliant(false)] [assembly: AssemblyFileVersion("4.0.0.0")] [assembly: AssemblyInformationalVersion("4.0.0.0")] [assembly: AssemblyTitle("System.Runtime.CompilerServices.Unsafe")] [assembly: AssemblyDescription("System.Runtime.CompilerServices.Unsafe")] -[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyProduct("Microsoft® .NET Framework")] -[assembly: CLSCompliant(false)] internal sealed class ExtraUnsafeTests { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il index 58552a14f..f0fe8207e 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il @@ -493,9 +493,35 @@ #ifdef netcoreapp #else +.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute + extends [CORE_ASSEMBLY]System.Attribute +{ + .custom instance void [CORE_ASSEMBLY]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( + 01 00 00 00 + ) + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [CORE_ASSEMBLY]System.Attribute::.ctor() + IL_0006: ret + } // end of method EmbeddedAttribute::.ctor + +} // end of class Microsoft.CodeAnalysis.EmbeddedAttribute + .class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.IsReadOnlyAttribute extends [CORE_ASSEMBLY]System.Attribute { + .custom instance void [CORE_ASSEMBLY]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( + 01 00 00 00 + ) .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs index 30c0402da..934d4a6fe 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs @@ -1,5 +1,7 @@ using System; +#if ROSLYN4 using System.Runtime.InteropServices; +#endif namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { @@ -127,6 +129,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } +#if ROSLYN4 internal class RecordStructs { public record struct Base(string A); @@ -227,6 +230,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } } +#endif } namespace System.Runtime.CompilerServices { diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs index 32063eb7a..8d880f4f0 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs @@ -170,9 +170,13 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler { var metadata = module.Metadata; var typeDef = metadata.GetTypeDefinition(type); - if (metadata.GetString(typeDef.Name) == "" || CSharpDecompiler.MemberIsHidden(module, type, Settings)) + string name = metadata.GetString(typeDef.Name); + string ns = metadata.GetString(typeDef.Namespace); + if (name == "" || CSharpDecompiler.MemberIsHidden(module, type, Settings)) return false; - if (metadata.GetString(typeDef.Namespace) == "XamlGeneratedNamespace" && metadata.GetString(typeDef.Name) == "GeneratedInternalTypeHelper") + if (ns == "XamlGeneratedNamespace" && name == "GeneratedInternalTypeHelper") + return false; + if (!typeDef.IsNested && RemoveEmbeddedAttributes.attributeNames.Contains(ns + "." + name)) return false; return true; } diff --git a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs index 455c8b21b..2d832dfd7 100644 --- a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs @@ -445,11 +445,23 @@ namespace ICSharpCode.Decompiler.CSharp var getter = property.Getter; if (!(getter != null && !property.CanSet)) return false; - if (property.GetAttributes().Any()) - return false; + var attrs = property.GetAttributes().ToList(); + switch (attrs.Count) + { + case 0: + // Roslyn 3.x does not emit a CompilerGeneratedAttribute on the property itself. + break; + case 1: + // Roslyn 4.4 started doing so. + if (!attrs[0].AttributeType.IsKnownType(KnownAttribute.CompilerGenerated)) + return false; + break; + default: + return false; + } if (getter.GetReturnTypeAttributes().Any()) return false; - var attrs = getter.GetAttributes().ToList(); + attrs = getter.GetAttributes().ToList(); if (attrs.Count != 1) return false; if (!attrs[0].AttributeType.IsKnownType(KnownAttribute.CompilerGenerated)) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs b/ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs index 6ba6b2e8e..1b57569ef 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs @@ -16,10 +16,12 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System.Collections.Generic; using System.Linq; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Semantics; +using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.CSharp.Transforms { @@ -151,4 +153,40 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } } + + /// + /// This transform is used to remove attributes that are embedded + /// + public class RemoveEmbeddedAttributes : DepthFirstAstVisitor, IAstTransform + { + internal static readonly HashSet attributeNames = new HashSet() { + "System.Runtime.CompilerServices.IsReadOnlyAttribute", + "System.Runtime.CompilerServices.IsByRefLikeAttribute", + "System.Runtime.CompilerServices.IsUnmanagedAttribute", + "System.Runtime.CompilerServices.NullableAttribute", + "System.Runtime.CompilerServices.NullableContextAttribute", + "System.Runtime.CompilerServices.NativeIntegerAttribute", + "System.Runtime.CompilerServices.RefSafetyRulesAttribute", + "Microsoft.CodeAnalysis.EmbeddedAttribute", + }; + + public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration) + { + var typeDefinition = typeDeclaration.GetSymbol() as ITypeDefinition; + if (typeDefinition == null || !attributeNames.Contains(typeDefinition.FullName)) + return; + if (!typeDefinition.HasAttribute(KnownAttribute.Embedded)) + return; + if (typeDeclaration.Parent is NamespaceDeclaration ns && ns.Members.Count == 1) + ns.Remove(); + else + typeDeclaration.Remove(); + } + + public void Run(AstNode rootNode, TransformContext context) + { + rootNode.AcceptVisitor(this); + } + } + } diff --git a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs index b0b419aab..0e0026ea8 100644 --- a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs +++ b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs @@ -26,6 +26,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; +using System.Runtime; using System.Security.Cryptography; using System.Text; using System.Threading; @@ -34,6 +35,7 @@ using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.CSharp.Syntax; +using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -50,6 +52,21 @@ namespace ICSharpCode.Decompiler.DebugInfo return file.Reader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.CodeView); } + private static bool IncludeTypeWhenGeneratingPdb(PEFile module, TypeDefinitionHandle type, DecompilerSettings settings) + { + var metadata = module.Metadata; + var typeDef = metadata.GetTypeDefinition(type); + string name = metadata.GetString(typeDef.Name); + string ns = metadata.GetString(typeDef.Namespace); + if (name == "" || CSharpDecompiler.MemberIsHidden(module, type, settings)) + return false; + if (ns == "XamlGeneratedNamespace" && name == "GeneratedInternalTypeHelper") + return false; + if (!typeDef.IsNested && RemoveEmbeddedAttributes.attributeNames.Contains(ns + "." + name)) + return false; + return true; + } + public static void WritePdb( PEFile file, CSharpDecompiler decompiler, @@ -80,7 +97,7 @@ namespace ICSharpCode.Decompiler.DebugInfo return Path.Combine(ns, WholeProjectDecompiler.CleanUpFileName(typeName.Name) + ".cs"); } - var sourceFiles = reader.GetTopLevelTypeDefinitions().GroupBy(BuildFileNameFromTypeName).ToList(); + var sourceFiles = reader.GetTopLevelTypeDefinitions().Where(t => IncludeTypeWhenGeneratingPdb(file, t, settings)).GroupBy(BuildFileNameFromTypeName).ToList(); DecompilationProgress currentProgress = new() { TotalUnits = sourceFiles.Count, UnitsCompleted = 0, diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index f9fa9a7b8..59d0b5706 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -813,7 +813,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms case BinaryNumericOperator.ShiftLeft: case BinaryNumericOperator.ShiftRight: if (inst.Right.MatchBinaryNumericInstruction(BinaryNumericOperator.BitAnd, out var lhs, out var rhs) - && rhs.MatchLdcI4(inst.ResultType == StackType.I8 ? 63 : 31)) + && MatchExpectedShiftSize(rhs)) { // a << (b & 31) => a << b context.Step("Combine bit.and into shift", inst); @@ -831,6 +831,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms } break; } + + bool MatchExpectedShiftSize(ILInstruction rhs) + { + switch (inst.ResultType) + { + case StackType.I4: + return rhs.MatchLdcI4(31); + case StackType.I8: + return rhs.MatchLdcI4(63); + case StackType.I: + // sizeof(IntPtr) * 8 - 1 + return rhs.MatchBinaryNumericInstruction(BinaryNumericOperator.Sub, out var mult, out var one) + && mult.MatchBinaryNumericInstruction(BinaryNumericOperator.Mul, out var size, out var eight) + && size.MatchSizeOf(out var sizeofType) && sizeofType.GetStackType() == StackType.I + && eight.MatchLdcI4(8) && one.MatchLdcI4(1); + default: + return false; + } + } } protected internal override void VisitTryCatchHandler(TryCatchHandler inst) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs index 6f6dcacaf..f0263c370 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs @@ -44,6 +44,7 @@ namespace ICSharpCode.Decompiler.TypeSystem NullablePublicOnly, Conditional, Obsolete, + Embedded, IsReadOnly, SpecialName, DebuggerHidden, @@ -122,6 +123,7 @@ namespace ICSharpCode.Decompiler.TypeSystem new TopLevelTypeName("System.Runtime.CompilerServices", "NullablePublicOnlyAttribute"), new TopLevelTypeName("System.Diagnostics", nameof(ConditionalAttribute)), new TopLevelTypeName("System", nameof(ObsoleteAttribute)), + new TopLevelTypeName("Microsoft.CodeAnalysis", "EmbeddedAttribute"), new TopLevelTypeName("System.Runtime.CompilerServices", "IsReadOnlyAttribute"), new TopLevelTypeName("System.Runtime.CompilerServices", nameof(SpecialNameAttribute)), new TopLevelTypeName("System.Diagnostics", nameof(DebuggerHiddenAttribute)), diff --git a/packages.props b/packages.props index 5d9cf5dd8..6699a3856 100644 --- a/packages.props +++ b/packages.props @@ -14,7 +14,7 @@ 6.0.0 - 4.3.0-2.final + 4.4.0-4.final 0.11.4 6.1.3.50 2.8.4