From e0f0a2aa2e156792bb1e898b4ca9687e509e9adb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Tue, 22 Feb 2011 21:14:33 +0100 Subject: [PATCH 01/21] Modifications of solution and project files made by VS2010. --- .gitignore | 3 +- ILSpy.sln | 92 ++++++++++--------- .../ICSharpCode.NRefactory.Demo.csproj | 16 +++- .../ICSharpCode.NRefactory.csproj | 6 -- 4 files changed, 61 insertions(+), 56 deletions(-) diff --git a/.gitignore b/.gitignore index b96f1bdfd..a81b8dbf5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ bin/ obj/ /ICSharpCode.Decompiler/Properties/AssemblyInfo.cs -/ILSpy/Properties/AssemblyInfo.cs \ No newline at end of file +/ILSpy/Properties/AssemblyInfo.cs +*.suo \ No newline at end of file diff --git a/ILSpy.sln b/ILSpy.sln index 409cbd730..14784f3b7 100644 --- a/ILSpy.sln +++ b/ILSpy.sln @@ -1,7 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -# SharpDevelop 4.0.1.7096 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy", "ILSpy\ILSpy.csproj", "{1E85EFF9-E370-4683-83E4-8A3D063FF791}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TreeView", "SharpTreeView\ICSharpCode.TreeView.csproj", "{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}" @@ -18,67 +17,70 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Decompiler.Test EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x86 = Debug|x86 - Release|x86 = Release|x86 Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|x86.Build.0 = Debug|x86 - {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|x86.ActiveCfg = Debug|x86 - {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|x86.Build.0 = Release|x86 - {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|x86.ActiveCfg = Release|x86 - {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|Any CPU.Build.0 = Debug|Any CPU {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|Any CPU.Build.0 = Release|Any CPU + {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|x86.ActiveCfg = Debug|x86 + {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|x86.Build.0 = Debug|x86 {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|x86.Build.0 = Debug|Any CPU - {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|x86.ActiveCfg = Debug|Any CPU - {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|x86.Build.0 = Release|Any CPU - {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|x86.ActiveCfg = Release|Any CPU - {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|Any CPU.Build.0 = Release|Any CPU + {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|x86.ActiveCfg = Release|x86 + {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|x86.Build.0 = Release|x86 {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|Any CPU.Build.0 = Release|Any CPU + {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|x86.ActiveCfg = Debug|Any CPU + {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|x86.Build.0 = Debug|Any CPU {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = net_2_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|Any CPU.Build.0 = Release|Any CPU + {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|x86.ActiveCfg = Release|Any CPU + {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|x86.Build.0 = Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_2_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_4_0_Release|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = net_2_0_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|x86.Build.0 = Debug|Any CPU - {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|x86.ActiveCfg = Debug|Any CPU - {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_2_0_Debug|Any CPU {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|x86.Build.0 = Release|Any CPU - {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|x86.ActiveCfg = Release|Any CPU - {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|Any CPU.Build.0 = Release|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|x86.ActiveCfg = Debug|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|x86.Build.0 = Debug|Any CPU {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x86.Build.0 = Debug|Any CPU - {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x86.ActiveCfg = Debug|Any CPU - {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|Any CPU.Build.0 = Release|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|x86.ActiveCfg = Release|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|x86.Build.0 = Release|Any CPU {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.Build.0 = Release|Any CPU - {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.ActiveCfg = Release|Any CPU - {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.Build.0 = Release|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x86.ActiveCfg = Debug|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x86.Build.0 = Debug|Any CPU {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|x86.Build.0 = Debug|Any CPU - {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|x86.ActiveCfg = Debug|Any CPU - {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|Any CPU.Build.0 = Debug|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.Build.0 = Release|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.ActiveCfg = Release|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.Build.0 = Release|Any CPU {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|x86.Build.0 = Release|Any CPU - {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|x86.ActiveCfg = Release|Any CPU - {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|Any CPU.Build.0 = Release|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|x86.ActiveCfg = Debug|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|x86.Build.0 = Debug|Any CPU {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|x86.Build.0 = Debug|x86 - {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|x86.ActiveCfg = Debug|x86 - {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|Any CPU.Build.0 = Debug|x86 + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|Any CPU.Build.0 = Release|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|x86.ActiveCfg = Release|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|x86.Build.0 = Release|Any CPU {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|Any CPU.ActiveCfg = Debug|x86 - {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.Build.0 = Release|x86 - {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.ActiveCfg = Release|x86 - {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|Any CPU.Build.0 = Release|x86 + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|Any CPU.Build.0 = Debug|x86 + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|x86.ActiveCfg = Debug|x86 + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|x86.Build.0 = Debug|x86 {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|Any CPU.ActiveCfg = Release|x86 + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|Any CPU.Build.0 = Release|x86 + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.ActiveCfg = Release|x86 + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection EndGlobal diff --git a/NRefactory/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj b/NRefactory/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj index 36ea620c6..906a94773 100644 --- a/NRefactory/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj +++ b/NRefactory/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj @@ -40,21 +40,29 @@ - + + Form + VBEditDialog.cs - + + UserControl + VBDomView.cs - + + Form + MainForm.cs - + + UserControl + VBDemo.cs diff --git a/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 6fdcd0c9f..68821f953 100644 --- a/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -350,11 +350,5 @@ Mono.Cecil - - - {D68133BD-1E63-496E-9EDE-4FBDBF77B486} - Mono.Cecil - - \ No newline at end of file From d13d7bd48fcf933d229c9b85fbfc1f022353873a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Tue, 22 Feb 2011 23:56:47 +0100 Subject: [PATCH 02/21] Basic output of custom attributes attached to types and methods. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 23 +++- .../Tests/CustomAttributes.cs | 15 +++ .../Tests/ICSharpCode.Decompiler.Tests.csproj | 9 ++ ICSharpCode.Decompiler/Tests/TestRunner.cs | 104 ++++++++++++++---- .../CSharp/OutputVisitor/OutputVisitor.cs | 11 +- 5 files changed, 139 insertions(+), 23 deletions(-) create mode 100644 ICSharpCode.Decompiler/Tests/CustomAttributes.cs diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 1d91f59b6..e2363ddb8 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -180,7 +180,8 @@ namespace Decompiler AddTypeMembers(astType, typeDef); } - + + ConvertCustomAtributes(astType, typeDef); return astType; } @@ -461,6 +462,7 @@ namespace Decompiler astMethod.Modifiers = ConvertModifiers(methodDef); astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context); } + ConvertCustomAtributes(astMethod, methodDef); return astMethod; } @@ -565,5 +567,24 @@ namespace Decompiler yield return astParam; } } + + static void ConvertCustomAtributes(AttributedNode attributedNode, ICustomAttributeProvider customAttributeProvider) + { + if (customAttributeProvider.HasCustomAttributes) + { + var section = new AttributeSection(); + //section.AttributeTarget = target; + foreach (var customAttribute in customAttributeProvider.CustomAttributes) + { + ICSharpCode.NRefactory.CSharp.Attribute attribute = new ICSharpCode.NRefactory.CSharp.Attribute(); + //customAttribute. + attribute.Type = ConvertType(customAttribute.AttributeType); + section.Attributes.Add(attribute); + + } + + attributedNode.Attributes.Add(section); + } + } } } diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes.cs new file mode 100644 index 000000000..fa12ffa9b --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes.cs @@ -0,0 +1,15 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + + +public static class CustomAtributes +{ + [Flags] + public enum EnumWithFlag + { + Item1, + Item2 + } +} diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 8d0896ef5..b6ce307f5 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -38,6 +38,14 @@ TRACE + + False + ..\..\libs\Gallio.dll + + + False + ..\..\libs\MbUnit.dll + 3.5 @@ -49,6 +57,7 @@ + diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs index d4fa06fdd..da07307da 100644 --- a/ICSharpCode.Decompiler/Tests/TestRunner.cs +++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs @@ -9,6 +9,7 @@ using System.Text; using Decompiler; using Microsoft.CSharp; using Mono.Cecil; +using MbUnit.Framework; namespace ICSharpCode.Decompiler.Tests { @@ -16,14 +17,31 @@ namespace ICSharpCode.Decompiler.Tests { public static void Main() { - Test(@"..\..\Tests\DelegateConstruction.cs"); - + TestFile(@"..\..\Tests\DelegateConstruction.cs"); + Console.ReadKey(); } - - - - static void Test(string fileName) + + [Test] + //[Row(@"..\..\Tests\DelegateConstruction.cs")] + //[Row(@"..\..\Tests\Loops.cs")] + [Row(@"..\..\Tests\CustomAttributes.cs")] + public void RoundtripFile(string fileName) + { + string code = File.ReadAllText(fileName); + AssemblyDefinition assembly = Compile(code); + AstBuilder decompiler = new AstBuilder(new DecompilerContext()); + decompiler.AddAssembly(assembly); + StringWriter output = new StringWriter(); + decompiler.GenerateCode(new PlainTextOutput(output)); + + var decompiledCode = output.ToString(); + var onlyCode = "using System;" + Environment.NewLine + StripCodeFileHeader(code); + + Assert.AreEqual(onlyCode, decompiledCode); + } + + static void TestFile(string fileName) { string code = File.ReadAllText(fileName); AssemblyDefinition assembly = Compile(code); @@ -32,11 +50,45 @@ namespace ICSharpCode.Decompiler.Tests StringWriter output = new StringWriter(); decompiler.GenerateCode(new PlainTextOutput(output)); StringWriter diff = new StringWriter(); - if (!Compare(code, output.ToString(), diff)) { + if (!Compare(code, output.ToString(), diff)) + { throw new Exception("Test failure." + Environment.NewLine + diff.ToString()); } } - + + static string StripCodeFileHeader(string code) + { + var reader = new StringReader(code); + + var buffer = new StringWriter(); + + string line; + var skipBlankLine = false; + while ((line = reader.ReadLine()) != null) + { + if (line.Trim().StartsWith("//")) + { + skipBlankLine = true; + continue; + } + else if (line.StartsWith("using ")) + { + skipBlankLine = true; + continue; + } + else if (skipBlankLine && String.IsNullOrWhiteSpace(line)) + { + continue; + } + + skipBlankLine = false; + + buffer.WriteLine(line); + } + + return buffer.ToString(); + } + static bool Compare(string input1, string input2, StringWriter diff) { bool ok = true; @@ -44,55 +96,67 @@ namespace ICSharpCode.Decompiler.Tests StringReader r1 = new StringReader(input1); StringReader r2 = new StringReader(input2); string line1, line2; - while ((line1 = r1.ReadLine()) != null) { + while ((line1 = r1.ReadLine()) != null) + { string trimmed = line1.Trim(); - if (trimmed.Length == 0 || trimmed.StartsWith("//", StringComparison.Ordinal) || line1.StartsWith("using ", StringComparison.Ordinal)) { + if (trimmed.Length == 0 || trimmed.StartsWith("//", StringComparison.Ordinal) || line1.StartsWith("using ", StringComparison.Ordinal)) + { diff.WriteLine(" " + line1); continue; } line2 = r2.ReadLine(); while (line2 != null && (line2.StartsWith("using ", StringComparison.Ordinal) || line2.Trim().Length == 0)) line2 = r2.ReadLine(); - if (line2 == null) { + if (line2 == null) + { ok = false; diff.WriteLine("-" + line1); continue; } - if (line1 != line2) { + if (line1 != line2) + { ok = false; if (numberOfContinuousMistakes++ > 5) return false; diff.WriteLine("-" + line1); diff.WriteLine("+" + line2); - } else { + } + else + { if (numberOfContinuousMistakes > 0) numberOfContinuousMistakes--; diff.WriteLine(" " + line1); } } - while ((line2 = r2.ReadLine()) != null) { + while ((line2 = r2.ReadLine()) != null) + { ok = false; diff.WriteLine("+" + line2); } return ok; } - + static AssemblyDefinition Compile(string code) { - CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary {{ "CompilerVersion", "v4.0" }}); + CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary { { "CompilerVersion", "v4.0" } }); CompilerParameters options = new CompilerParameters(); options.ReferencedAssemblies.Add("System.Core.dll"); CompilerResults results = provider.CompileAssemblyFromSource(options, code); - try { - if (results.Errors.Count > 0) { + try + { + if (results.Errors.Count > 0) + { StringBuilder b = new StringBuilder("Compiler error:"); - foreach (var error in results.Errors) { + foreach (var error in results.Errors) + { b.AppendLine(error.ToString()); } throw new Exception(b.ToString()); } return AssemblyDefinition.ReadAssembly(results.PathToAssembly); - } finally { + } + finally + { File.Delete(results.PathToAssembly); results.TempFiles.Delete(); } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index cf880653e..933a7f9a1 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -1083,7 +1083,8 @@ namespace ICSharpCode.NRefactory.CSharp StartNode(attribute); attribute.Type.AcceptVisitor(this, data); Space(policy.BeforeMethodCallParentheses); - WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.WithinMethodCallParentheses); + if (attribute.Arguments.Count != 0) + WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.WithinMethodCallParentheses); return EndNode(attribute); } @@ -1879,8 +1880,14 @@ namespace ICSharpCode.NRefactory.CSharp public object VisitSimpleType(SimpleType simpleType, object data) { + bool inAttribute = currentContainerNode is Attribute; StartNode(simpleType); - WriteIdentifier(simpleType.Identifier); + + var identifier = simpleType.Identifier; + if (inAttribute && identifier.EndsWith("Attribute")) + identifier = identifier.Substring(0, identifier.Length - 9); + WriteIdentifier(identifier); + WriteTypeArguments(simpleType.TypeArguments); return EndNode(simpleType); } From b4c55dc7050e338a188671c9da3bfb786adb3826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Wed, 23 Feb 2011 09:40:26 +0100 Subject: [PATCH 03/21] Removed redundant int base type of enum. --- .../CSharp/OutputVisitor/OutputVisitor.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index 933a7f9a1..8c5911e70 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -1161,7 +1161,7 @@ namespace ICSharpCode.NRefactory.CSharp } WriteIdentifier(typeDeclaration.Name); WriteTypeParameters(typeDeclaration.TypeParameters); - if (typeDeclaration.BaseTypes.Any()) { + if (typeDeclaration.BaseTypes.Any() && !IsStandardEnum(typeDeclaration)) { Space(); WriteToken(":", TypeDeclaration.ColonRole); Space(); @@ -1192,6 +1192,22 @@ namespace ICSharpCode.NRefactory.CSharp NewLine(); return EndNode(typeDeclaration); } + + private static bool IsStandardEnum(TypeDeclaration typeDeclaration) + { + if (typeDeclaration.ClassType != ClassType.Enum) + { + return false; + } + + if (typeDeclaration.BaseTypes.Count != 1) // is is possible? + { + return false; + } + + var baseType = typeDeclaration.BaseTypes.First() as PrimitiveType; + return baseType != null && baseType.Keyword == "int"; + } public object VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration, object data) { From 7e5e94534ce24e0d3fd27d2d28337af18c1f84e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Wed, 23 Feb 2011 17:42:36 +0100 Subject: [PATCH 04/21] Print a custom attribute's positional arguments. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 6 +++++- ICSharpCode.Decompiler/Tests/CustomAttributes.cs | 6 +++++- .../CSharp/Ast/GeneralScope/Attribute.cs | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index b4ed67ac3..3a30aae48 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -578,10 +578,14 @@ namespace Decompiler foreach (var customAttribute in customAttributeProvider.CustomAttributes) { ICSharpCode.NRefactory.CSharp.Attribute attribute = new ICSharpCode.NRefactory.CSharp.Attribute(); - //customAttribute. attribute.Type = ConvertType(customAttribute.AttributeType); section.Attributes.Add(attribute); + foreach (var parameter in customAttribute.ConstructorArguments) + { + attribute.Arguments.Add(new PrimitiveExpression(parameter.Value)); + } + } attributedNode.Attributes.Add(section); diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes.cs index fa12ffa9b..17f1a55ed 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes.cs @@ -9,7 +9,11 @@ public static class CustomAtributes [Flags] public enum EnumWithFlag { - Item1, +// Item1, Item2 } + [Obsolete("some message")] + public static void ObsoletedMethod() + { + } } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs index 877771736..b5a44275b 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs @@ -25,12 +25,14 @@ // THE SOFTWARE. using System.Collections.Generic; +using System.Diagnostics; namespace ICSharpCode.NRefactory.CSharp { /// /// Attribute(Arguments) /// + [DebuggerDisplay("Attribute {Type}")] public class Attribute : AstNode { public override NodeType NodeType { From 679d525806d8ca7c0820255679aadde728f75881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Thu, 24 Feb 2011 00:59:51 +0100 Subject: [PATCH 05/21] Fixed enum boxing decompilation bug. Enum in attributes better printing. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 71 ++++++++++++++++++- .../Ast/AstMethodBodyBuilder.cs | 38 +++------- ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs | 9 +++ .../Tests/CustomAttributes.cs | 8 +++ 4 files changed, 97 insertions(+), 29 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 3a30aae48..5bdefecc4 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -6,8 +6,10 @@ using System.Threading; using Decompiler.Transforms; using ICSharpCode.Decompiler; using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.NRefactory.Utils; using Mono.Cecil; using Mono.Cecil.Cil; +using Ast = ICSharpCode.NRefactory.CSharp; using ClassType = ICSharpCode.NRefactory.TypeSystem.ClassType; using VarianceModifier = ICSharpCode.NRefactory.TypeSystem.VarianceModifier; @@ -583,7 +585,17 @@ namespace Decompiler foreach (var parameter in customAttribute.ConstructorArguments) { - attribute.Arguments.Add(new PrimitiveExpression(parameter.Value)); + var isEnum = parameter.Type.IsValueType && !parameter.Type.IsPrimitive; + Expression parameterValue; + if (isEnum) + { + parameterValue = MakePrimitive(Convert.ToInt64(parameter.Value), parameter.Type); + } + else + { + parameterValue = new PrimitiveExpression(parameter.Value); + } + attribute.Arguments.Add(parameterValue); } } @@ -591,5 +603,62 @@ namespace Decompiler attributedNode.Attributes.Add(section); } } + + + internal static Expression MakePrimitive(long val, TypeReference type) + { + if (TypeAnalysis.IsBoolean(type) && val == 0) + return new Ast.PrimitiveExpression(false); + else if (TypeAnalysis.IsBoolean(type) && val == 1) + return new Ast.PrimitiveExpression(true); + if (type != null) + { // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs) + TypeDefinition enumDefinition = type.Resolve(); + if (enumDefinition != null && enumDefinition.IsEnum) + { + foreach (FieldDefinition field in enumDefinition.Fields) + { + if (field.IsStatic && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val)) + return AstBuilder.ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); + else if (!field.IsStatic && field.IsRuntimeSpecialName) + type = field.FieldType; // use primitive type of the enum + } + if (IsFlagsEnum(enumDefinition)) + { + Expression expr = null; + foreach (FieldDefinition field in enumDefinition.Fields.Where(fld => fld.IsStatic)) + { + long fieldValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false); + if (fieldValue == 0) + continue; // skip None enum value + + if ((fieldValue & val) == fieldValue) + { + var fieldExpression = AstBuilder.ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); + if (expr == null) + expr = fieldExpression; + else + expr = new BinaryOperatorExpression(expr, BinaryOperatorType.BitwiseOr, fieldExpression); + } + } + if (expr != null) + return expr; + } + } + } + TypeCode code = TypeAnalysis.GetTypeCode(type); + if (code == TypeCode.Object) + return new Ast.PrimitiveExpression((int)val); + else + return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(code, val, false)); + } + + static bool IsFlagsEnum(TypeDefinition type) + { + if (!type.HasCustomAttributes) + return false; + + return type.CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute"); + } } } diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index eabbc2203..853cac5a8 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -514,7 +514,7 @@ namespace Decompiler return MakeRef(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand)); } case Code.Ldc_I4: - return MakePrimitive((int)operand, byteCode.InferredType); + return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType); case Code.Ldc_I8: case Code.Ldc_R4: case Code.Ldc_R8: @@ -763,7 +763,7 @@ namespace Decompiler if (TypeAnalysis.IsBoolean(actualType)) return expr; if (actualIsIntegerOrEnum) { - return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, MakePrimitive(0, actualType)); + return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, AstBuilder.MakePrimitive(0, actualType)); } else { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression()); } @@ -771,39 +771,21 @@ namespace Decompiler if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) { return new ConditionalExpression { Condition = expr, - TrueExpression = MakePrimitive(1, reqType), - FalseExpression = MakePrimitive(0, reqType) + TrueExpression = AstBuilder.MakePrimitive(1, reqType), + FalseExpression = AstBuilder.MakePrimitive(0, reqType) }; } + + if (expr is PrimitiveExpression && !requiredIsIntegerOrEnum && TypeAnalysis.IsEnum(actualType)) + { + return expr.CastTo(AstBuilder.ConvertType(actualType)); + } + if (actualIsIntegerOrEnum && requiredIsIntegerOrEnum) { return expr.CastTo(AstBuilder.ConvertType(reqType)); } return expr; } } - - Expression MakePrimitive(long val, TypeReference type) - { - if (TypeAnalysis.IsBoolean(type) && val == 0) - return new Ast.PrimitiveExpression(false); - else if (TypeAnalysis.IsBoolean(type) && val == 1) - return new Ast.PrimitiveExpression(true); - if (type != null) { // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs) - TypeDefinition enumDefinition = type.Resolve(); - if (enumDefinition != null && enumDefinition.IsEnum) { - foreach (FieldDefinition field in enumDefinition.Fields) { - if (field.IsStatic && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val)) - return AstBuilder.ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); - else if (!field.IsStatic && field.IsRuntimeSpecialName) - type = field.FieldType; // use primitive type of the enum - } - } - } - TypeCode code = TypeAnalysis.GetTypeCode(type); - if (code == TypeCode.Object) - return new Ast.PrimitiveExpression((int)val); - else - return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(code, val, false)); - } } } diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs index 6c79b565e..bcf83ba50 100644 --- a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs +++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs @@ -627,6 +627,15 @@ namespace Decompiler { return IsSigned(type) != null; } + + public static bool IsEnum(TypeReference type) + { + if (type == null) + return false; + // unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec) + TypeDefinition typeDef = type.Resolve() as TypeDefinition; + return typeDef != null && typeDef.IsEnum; + } static bool? IsSigned(TypeReference type) { diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes.cs index 17f1a55ed..11258a42e 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes.cs @@ -12,8 +12,16 @@ public static class CustomAtributes // Item1, Item2 } + [AttributeUsage(AttributeTargets.All)] + public class MyAttribute : Attribute + { + } [Obsolete("some message")] public static void ObsoletedMethod() { + //Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, (AttributeTargets)(AttributeTargets.Property | AttributeTargets.Field)); + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field); + AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field; + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets); } } From d1fff3fdb12291189c2f438887e7c47d9e039fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Thu, 24 Feb 2011 19:04:29 +0100 Subject: [PATCH 06/21] testing code that helps running independent decompilation tests. --- .../Tests/CodeSampleFileParser.cs | 114 ++++++++++++++++++ .../Tests/CustomAttributes.code.cs | 41 +++++++ .../Tests/CustomAttributes.cs | 27 ----- .../CustomAttributeSamples.cs | 81 +++++++++++++ .../CustomAttributes/CustomAttributeTests.cs | 23 ++++ .../CustomAttributes/CustomAttributes.cs | 47 ++++++++ .../Tests/DecompilerTestBase.cs | 89 ++++++++++++++ .../Tests/ICSharpCode.Decompiler.Tests.csproj | 16 ++- ICSharpCode.Decompiler/Tests/TestRunner.cs | 7 +- .../Tests/{ => Types}/DelegateConstruction.cs | 0 .../Tests/{ => Types}/PropertiesAndEvents.cs | 0 .../Tests/Types/TypeTests.cs | 29 +++++ .../Tests/{ => Types}/ValueTypes.cs | 0 13 files changed, 438 insertions(+), 36 deletions(-) create mode 100644 ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs create mode 100644 ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs delete mode 100644 ICSharpCode.Decompiler/Tests/CustomAttributes.cs create mode 100644 ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs create mode 100644 ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs create mode 100644 ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs create mode 100644 ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs rename ICSharpCode.Decompiler/Tests/{ => Types}/DelegateConstruction.cs (100%) rename ICSharpCode.Decompiler/Tests/{ => Types}/PropertiesAndEvents.cs (100%) create mode 100644 ICSharpCode.Decompiler/Tests/Types/TypeTests.cs rename ICSharpCode.Decompiler/Tests/{ => Types}/ValueTypes.cs (100%) diff --git a/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs b/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs new file mode 100644 index 000000000..c481c25e8 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +namespace ICSharpCode.Decompiler.Tests +{ + static class CodeSampleFileParser + { + public static IEnumerable ListSections(string s) + { + var query = from line in ToLines(s) + let sectionName = ReadSectionName(line) + where sectionName != null + select sectionName; + return query; + } + + public static string GetSection(string sectionName, string s) + { + var lines = ToLines(s); + + bool sectionFound = false; + var sectionText = new StringBuilder(); + + Action parser = null; + + Action commonSectionReader = line => + { + if (IsCommonSectionEnd(line)) + parser = null; + else + sectionText.AppendLine(line); + }; + + Action namedSectionReader = line => + { + string name = ReadSectionName(line); + if (name == null) + sectionText.AppendLine(line); + else if (name != sectionName) + parser = null; + }; + + Action defaultReader = line => + { + if (IsCommonSectionStart(line)) + parser = commonSectionReader; + else if (ReadSectionName(line) == sectionName) + { + parser = namedSectionReader; + sectionFound = true; + } + }; + + foreach(var line in lines) + { + (parser ?? defaultReader)(line); + } + + if (sectionFound) + return sectionText.ToString(); + else + return ""; + } + + public static bool IsCommentOrBlank(string s) + { + if(String.IsNullOrWhiteSpace(s)) + return true; + return s.Trim().StartsWith("//"); + } + + public static string ConcatLines(IEnumerable lines) + { + var buffer = new StringBuilder(); + foreach (var line in lines) + { + buffer.AppendLine(line); + } + return buffer.ToString(); + } + + static string ReadSectionName(string line) + { + line = line.TrimStart(); + if (line.StartsWith("//$$")) + return line.Substring(4).Trim(); + else + return null; + } + + static bool IsCommonSectionStart(string line) + { + return line.Trim() == "//$CS"; + } + + static bool IsCommonSectionEnd(string line) + { + return line.Trim() == "//$CE"; + } + + static IEnumerable ToLines(string s) + { + var reader = new StringReader(s); + string line; + while ((line = reader.ReadLine()) != null) + { + yield return line; + } + } + } +} diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs new file mode 100644 index 000000000..4130b0b0f --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs @@ -0,0 +1,41 @@ +using System; +namespace aa +{ + public static class CustomAtributes + { + [Flags] + public enum EnumWithFlag + { + All = 15, + None = 0, + Item1 = 1, + Item2 = 2, + Item3 = 4, + Item4 = 8 + } + [AttributeUsage(AttributeTargets.All)] + public class MyAttribute : Attribute + { + public MyAttribute(CustomAtributes.EnumWithFlag en) + { + } + } + [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.Item1 | CustomAtributes.EnumWithFlag.Item2)] + private static int field; + [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.All)] + public static string Property + { + get + { + return "aa"; + } + } + [Obsolete("some message")] + public static void ObsoletedMethod() + { + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field); + AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field; + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets); + } + } +} diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes.cs deleted file mode 100644 index 11258a42e..000000000 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; - - -public static class CustomAtributes -{ - [Flags] - public enum EnumWithFlag - { -// Item1, - Item2 - } - [AttributeUsage(AttributeTargets.All)] - public class MyAttribute : Attribute - { - } - [Obsolete("some message")] - public static void ObsoletedMethod() - { - //Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, (AttributeTargets)(AttributeTargets.Property | AttributeTargets.Field)); - Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field); - AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field; - Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets); - } -} diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs new file mode 100644 index 000000000..e92a50f59 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs @@ -0,0 +1,81 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +//$CS +using System; +//$CE + +//$$ ParameterlessAttributeUsage +namespace ParameterLessAttributeUsage +{ + [Flags] + public enum EnumWithFlagsAttribute + { + None + } +} +//$$ AttributeWithEnumArgument +namespace AttributeWithEnumArgument +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } +} +//$$ AttributeWithEnumExpressionArgument +namespace AttributeWithEnumExpressionArgument +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Interface)] + public class MyAttributeAttribute : Attribute + { + } +} +//$$ AttributeWithStringExpressionArgument +namespace AttributeWithStringExpressionArgument +{ + [Obsolete("message")] + public class ObsoletedClass + { + } +} +//$$ AttributeAppliedToEvent (ignored) +namespace AttributeAppliedToEvent +{ + [AttributeUsage(AttributeTargets.Event)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + [MyAttribute] + public event EventHandler MyEvent; + } +} +//$$ AttributeAppliedToField +namespace AttributeAppliedToField +{ + [AttributeUsage(AttributeTargets.Field)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + [MyAttribute] + public int Field; + } +} +//$$ AttributeAppliedToMethod +namespace AttributeAppliedToMethod +{ + [AttributeUsage(AttributeTargets.Method)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + [MyAttribute] + public void Method() + { + } + } +} diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs new file mode 100644 index 000000000..70ff0f799 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MbUnit.Framework; + +namespace ICSharpCode.Decompiler.Tests.CustomAttributes +{ + public class CustomAttributeTests : DecompilerTestBase + { + [StaticTestFactory] + public static IEnumerable CustomAttributeSamples() + { + return GenerateSectionTests(@"CustomAttributes\CustomAttributeSamples.cs"); + } + + [Test] + public void CustomAttributesMultiTest() + { + ValidateFileRoundtrip(@"CustomAttributes\CustomAttributes.cs"); + } + } +} diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs new file mode 100644 index 000000000..7baaf2982 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs @@ -0,0 +1,47 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + + +namespace aa +{ + public static class CustomAtributes + { + [Flags] + public enum EnumWithFlag + { + All = 15, + None = 0, + Item1 = 1, + Item2 = 2, + Item3 = 4, + Item4 = 8 + } + [AttributeUsage(AttributeTargets.All)] + public class MyAttribute : Attribute + { + public MyAttribute(CustomAtributes.EnumWithFlag en) + { + } + } + [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.Item1 | CustomAtributes.EnumWithFlag.Item2)] + private static int field; + [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.All)] + public static string Property + { + get + { + return "aa"; + } + } + [Obsolete("some message")] + public static void ObsoletedMethod() + { + //Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, (AttributeTargets)(AttributeTargets.Property | AttributeTargets.Field)); + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field); + AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field; + Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets); + } + } +} \ No newline at end of file diff --git a/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs new file mode 100644 index 000000000..b27cccf46 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Mono.Cecil; +using System.IO; +using Decompiler; +using Microsoft.CSharp; +using System.CodeDom.Compiler; +using MbUnit.Framework; + +namespace ICSharpCode.Decompiler.Tests +{ + public abstract class DecompilerTestBase + { + protected static IEnumerable GenerateSectionTests(string samplesFileName) + { + string code = File.ReadAllText(Path.Combine(@"..\..\Tests", samplesFileName)); + foreach (var sectionName in CodeSampleFileParser.ListSections(code)) + { + if (sectionName.EndsWith("(ignored)", StringComparison.OrdinalIgnoreCase)) + continue; + + var testedSectionName = sectionName; + yield return new TestCase(testedSectionName, () => + { + var testCode = CodeSampleFileParser.GetSection(testedSectionName, code); + System.Diagnostics.Debug.WriteLine(testCode); + var decompiledTestCode = RoundtripCode(testCode); + Assert.AreEqual(testCode, decompiledTestCode); + }); + } + } + + protected static void ValidateFileRoundtrip(string samplesFileName) + { + var lines = File.ReadAllLines(Path.Combine(@"..\..\Tests", samplesFileName)); + var testCode = RemoveIgnorableLines(lines); + var decompiledTestCode = RoundtripCode(testCode); + Assert.AreEqual(testCode, decompiledTestCode); + } + + static string RemoveIgnorableLines(IEnumerable lines) + { + return CodeSampleFileParser.ConcatLines(lines.Where(l => !CodeSampleFileParser.IsCommentOrBlank(l))); + } + + /// + /// Compiles and decompiles a source code. + /// + /// The source code to copile. + /// The decompilation result of compiled source code. + static string RoundtripCode(string code) + { + AssemblyDefinition assembly = Compile(code); + AstBuilder decompiler = new AstBuilder(new DecompilerContext()); + decompiler.AddAssembly(assembly); + StringWriter output = new StringWriter(); + decompiler.GenerateCode(new PlainTextOutput(output)); + return output.ToString(); + } + + static AssemblyDefinition Compile(string code) + { + CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary { { "CompilerVersion", "v4.0" } }); + CompilerParameters options = new CompilerParameters(); + options.ReferencedAssemblies.Add("System.Core.dll"); + CompilerResults results = provider.CompileAssemblyFromSource(options, code); + try + { + if (results.Errors.Count > 0) + { + StringBuilder b = new StringBuilder("Compiler error:"); + foreach (var error in results.Errors) + { + b.AppendLine(error.ToString()); + } + throw new Exception(b.ToString()); + } + return AssemblyDefinition.ReadAssembly(results.PathToAssembly); + } + finally + { + File.Delete(results.PathToAssembly); + results.TempFiles.Delete(); + } + } + } +} diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index be4061104..1e82a0137 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -56,12 +56,17 @@ - - - - + + + + + + + + + - + @@ -73,5 +78,6 @@ ICSharpCode.Decompiler + \ No newline at end of file diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs index da07307da..d726f91a4 100644 --- a/ICSharpCode.Decompiler/Tests/TestRunner.cs +++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs @@ -22,10 +22,6 @@ namespace ICSharpCode.Decompiler.Tests Console.ReadKey(); } - [Test] - //[Row(@"..\..\Tests\DelegateConstruction.cs")] - //[Row(@"..\..\Tests\Loops.cs")] - [Row(@"..\..\Tests\CustomAttributes.cs")] public void RoundtripFile(string fileName) { string code = File.ReadAllText(fileName); @@ -38,6 +34,9 @@ namespace ICSharpCode.Decompiler.Tests var decompiledCode = output.ToString(); var onlyCode = "using System;" + Environment.NewLine + StripCodeFileHeader(code); + File.WriteAllText(Path.ChangeExtension(fileName, ".decomp.cs"), decompiledCode); + File.WriteAllText(Path.ChangeExtension(fileName, ".code.cs"), onlyCode); + Assert.AreEqual(onlyCode, decompiledCode); } diff --git a/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs b/ICSharpCode.Decompiler/Tests/Types/DelegateConstruction.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/DelegateConstruction.cs rename to ICSharpCode.Decompiler/Tests/Types/DelegateConstruction.cs diff --git a/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs b/ICSharpCode.Decompiler/Tests/Types/PropertiesAndEvents.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs rename to ICSharpCode.Decompiler/Tests/Types/PropertiesAndEvents.cs diff --git a/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs new file mode 100644 index 000000000..fca3ace99 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MbUnit.Framework; + +namespace ICSharpCode.Decompiler.Tests.Types +{ + public class TypeTests : DecompilerTestBase + { + [Test] + public void ValueTypes() + { + ValidateFileRoundtrip(@"Types\ValueTypes.cs"); + } + + [Test] + public void PropertiesAndEvents() + { + ValidateFileRoundtrip(@"Types\PropertiesAndEvents.cs"); + } + + [Test] + public void DelegateConstruction() + { + ValidateFileRoundtrip(@"Types\DelegateConstruction.cs"); + } + } +} diff --git a/ICSharpCode.Decompiler/Tests/ValueTypes.cs b/ICSharpCode.Decompiler/Tests/Types/ValueTypes.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/ValueTypes.cs rename to ICSharpCode.Decompiler/Tests/Types/ValueTypes.cs From 464acf02eaf1f7fc57f89300e07af9a53eecf87a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Thu, 24 Feb 2011 20:35:28 +0100 Subject: [PATCH 07/21] fixed printing of enum values that cannot be mapped to enum named constants. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 17 ++++++-- .../Tests/ICSharpCode.Decompiler.Tests.csproj | 2 + .../Tests/Types/EnumSamples.cs | 39 +++++++++++++++++++ .../Tests/Types/EnumTests.cs | 17 ++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs create mode 100644 ICSharpCode.Decompiler/Tests/Types/EnumTests.cs diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 5bdefecc4..4ba5042bb 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -515,6 +515,7 @@ namespace Decompiler Body = AstMethodBodyBuilder.CreateMethodBody(propDef.SetMethod, context) }.WithAnnotation(propDef.SetMethod); } + ConvertCustomAtributes(astProp, propDef); return astProp; } @@ -552,6 +553,7 @@ namespace Decompiler else initializer.Initializer = new PrimitiveExpression(fieldDef.Constant); } + ConvertCustomAtributes(astField, fieldDef); return astField; } @@ -619,12 +621,13 @@ namespace Decompiler foreach (FieldDefinition field in enumDefinition.Fields) { if (field.IsStatic && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val)) - return AstBuilder.ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); + return ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); else if (!field.IsStatic && field.IsRuntimeSpecialName) type = field.FieldType; // use primitive type of the enum } if (IsFlagsEnum(enumDefinition)) { + long enumValue = val; Expression expr = null; foreach (FieldDefinition field in enumDefinition.Fields.Where(fld => fld.IsStatic)) { @@ -632,18 +635,24 @@ namespace Decompiler if (fieldValue == 0) continue; // skip None enum value - if ((fieldValue & val) == fieldValue) + if ((fieldValue & enumValue) == fieldValue) { - var fieldExpression = AstBuilder.ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); + var fieldExpression = ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field); if (expr == null) expr = fieldExpression; else expr = new BinaryOperatorExpression(expr, BinaryOperatorType.BitwiseOr, fieldExpression); + + enumValue &= ~fieldValue; + if (enumValue == 0) + break; } } - if (expr != null) + if(enumValue == 0 && expr != null) return expr; } + TypeCode enumBaseTypeCode = TypeAnalysis.GetTypeCode(type); + return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(enumDefinition)); } } TypeCode code = TypeAnalysis.GetTypeCode(type); diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 1e82a0137..bae7fefe6 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -56,6 +56,8 @@ + + diff --git a/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs b/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs new file mode 100644 index 000000000..b1cc54128 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +//$CS +using System; +//$CE + +//$$ SingleValue +public class TS_SingleValue +{ + public AttributeTargets Method() + { + return AttributeTargets.Class; + } +} +//$$ TwoValuesOr +public class TS_TwoValuesOr +{ + public AttributeTargets Method() + { + return AttributeTargets.Class | AttributeTargets.Method; + } +} +//$$ ThreeValuesOr +public class TS_ThreeValuesOr +{ + public AttributeTargets Method() + { + return AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter; + } +} +//$$ UnknownNumericValue +public class TS_UnknownNumericValue +{ + public AttributeTargets Method() + { + return (AttributeTargets)1000000; + } +} diff --git a/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs new file mode 100644 index 000000000..b4234f623 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MbUnit.Framework; + +namespace ICSharpCode.Decompiler.Tests.Types +{ + public class EnumTests : DecompilerTestBase + { + [StaticTestFactory] + public static IEnumerable EnumSamples() + { + return GenerateSectionTests(@"Types\EnumSamples.cs"); + } + } +} From fde3c114ec13e318fcef8cd69f531c1a816d730a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Thu, 24 Feb 2011 22:28:37 +0100 Subject: [PATCH 08/21] Printing initializers of enum members. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 6 ++ .../Tests/Types/EnumSamples.cs | 65 +++++++++++++++++++ .../CSharp/OutputVisitor/OutputVisitor.cs | 7 +- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index e87322481..66508ddff 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -161,6 +161,7 @@ namespace Decompiler if (typeDef.IsEnum) { + long expectedEnumMemberValue = 0; foreach (FieldDefinition field in typeDef.Fields) { if (field.IsRuntimeSpecialName) { // the value__ field @@ -168,6 +169,11 @@ namespace Decompiler } else { EnumMemberDeclaration enumMember = new EnumMemberDeclaration(); enumMember.Name = CleanName(field.Name); + long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false); + if (memberValue != expectedEnumMemberValue) { + enumMember.AddChild(new PrimitiveExpression(field.Constant), EnumMemberDeclaration.InitializerRole); + } + expectedEnumMemberValue = memberValue + 1; astType.AddChild(enumMember, TypeDeclaration.MemberRole); } } diff --git a/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs b/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs index b1cc54128..4d08d8a98 100644 --- a/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs +++ b/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs @@ -37,3 +37,68 @@ public class TS_UnknownNumericValue return (AttributeTargets)1000000; } } +//$$ AllValue +public class TS_AllValue +{ + public AttributeTargets Method() + { + return AttributeTargets.All; + } +} +//$$ ZeroValue +public class TS_ZeroValue +{ + public AttributeTargets Method() + { + return (AttributeTargets)0; + } +} +//$$ PreservingTypeWhenBoxed +public class TS_PreservingTypeWhenBoxed +{ + public object Method() + { + return AttributeTargets.Delegate; + } +} +//$$ PreservingTypeWhenBoxedTwoEnum +public class TS_PreservingTypeWhenBoxedTwoEnum +{ + public object Method() + { + return AttributeTargets.Class | AttributeTargets.Delegate; + } +} +//$$ DeclarationSimpleEnum +public enum TS_DeclarationSimpleEnum +{ + Item1, + Item2 +} +//$$ DeclarationLongBasedEnum +public enum TS_DeclarationLongBasedEnum : long +{ + Item1, + Item2 +} +//$$ DeclarationLongWithInitializers +public enum TS_DeclarationLongWithInitializers : long +{ + Item1, + Item2 = 20L, + Item3 +} +//$$ DeclarationShortWithInitializers +public enum TS_DeclarationShortWithInitializers : short +{ + Item1, + Item2 = 20, + Item3 +} +//$$ DeclarationByteWithInitializers +public enum TS_DeclarationByteWithInitializers : byte +{ + Item1, + Item2 = 20, + Item3 +} diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index 4e3111458..ec0ad4b92 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -146,13 +146,14 @@ namespace ICSharpCode.NRefactory.CSharp /// Writes a comma. /// /// The next node after the comma. - void Comma(AstNode nextNode) + /// When set prevents printing a space after comma. + void Comma(AstNode nextNode, bool noSpacesAfterComma = false) { WriteSpecialsUpToRole(AstNode.Roles.Comma, nextNode); Space(policy.SpacesBeforeComma); formatter.WriteToken(","); lastWritten = LastWritten.Other; - Space(policy.SpacesAfterComma); + Space(!noSpacesAfterComma && policy.SpacesAfterComma); } void WriteCommaSeparatedList(IEnumerable list) @@ -1187,7 +1188,7 @@ namespace ICSharpCode.NRefactory.CSharp if (first) { first = false; } else { - Comma(member); + Comma(member, noSpacesAfterComma: true); NewLine(); } member.AcceptVisitor(this, data); From d8588bde2a9c271dfe7a12681095a1799b3a18fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Thu, 24 Feb 2011 22:35:10 +0100 Subject: [PATCH 09/21] forcing printing all initializers of members of Flags enums. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 3 ++- ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 66508ddff..341d2974a 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -162,6 +162,7 @@ namespace Decompiler if (typeDef.IsEnum) { long expectedEnumMemberValue = 0; + bool forcePrintingInitializers = IsFlagsEnum(typeDef); foreach (FieldDefinition field in typeDef.Fields) { if (field.IsRuntimeSpecialName) { // the value__ field @@ -170,7 +171,7 @@ namespace Decompiler EnumMemberDeclaration enumMember = new EnumMemberDeclaration(); enumMember.Name = CleanName(field.Name); long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false); - if (memberValue != expectedEnumMemberValue) { + if (forcePrintingInitializers || memberValue != expectedEnumMemberValue) { enumMember.AddChild(new PrimitiveExpression(field.Constant), EnumMemberDeclaration.InitializerRole); } expectedEnumMemberValue = memberValue + 1; diff --git a/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs b/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs index 4d08d8a98..67d81fa30 100644 --- a/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs +++ b/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs @@ -102,3 +102,13 @@ public enum TS_DeclarationByteWithInitializers : byte Item2 = 20, Item3 } +//$$ DeclarationFlags +[Flags] +public enum TS_DeclarationFlags +{ + None = 0, + Item1 = 1, + Item2 = 2, + Item3 = 4, + All = 7 +} From 09177affc162fa74369dcb70081879f63cc4846c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Fri, 25 Feb 2011 23:50:10 +0100 Subject: [PATCH 10/21] partial support for named arguments in attributes. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 31 ++++++++++++------- .../CustomAttributeSamples.cs | 10 +++++- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 341d2974a..c1fbc41cf 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -600,21 +600,30 @@ namespace Decompiler attribute.Type = ConvertType(customAttribute.AttributeType); section.Attributes.Add(attribute); - foreach (var parameter in customAttribute.ConstructorArguments) - { - var isEnum = parameter.Type.IsValueType && !parameter.Type.IsPrimitive; - Expression parameterValue; - if (isEnum) + if(customAttribute.HasConstructorArguments) + foreach (var parameter in customAttribute.ConstructorArguments) { - parameterValue = MakePrimitive(Convert.ToInt64(parameter.Value), parameter.Type); + var isEnum = parameter.Type.IsValueType && !parameter.Type.IsPrimitive; + Expression parameterValue; + if (isEnum) + { + parameterValue = MakePrimitive(Convert.ToInt64(parameter.Value), parameter.Type); + } + else + { + parameterValue = new PrimitiveExpression(parameter.Value); + } + attribute.Arguments.Add(parameterValue); } - else + + if (customAttribute.HasProperties) + foreach (var property in customAttribute.Properties) { - parameterValue = new PrimitiveExpression(parameter.Value); + var propertyReference = customAttribute.AttributeType.Resolve().Properties.First(pr => pr.Name == property.Name); + var propertyName = new IdentifierExpression(property.Name).WithAnnotation(propertyReference); + var propertyArgument = new PrimitiveExpression(property.Argument.Value); + attribute.Arguments.Add(new AssignmentExpression(propertyName, propertyArgument)); } - attribute.Arguments.Add(parameterValue); - } - } attributedNode.Attributes.Add(section); diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs index e92a50f59..ef3a8af3f 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs @@ -11,7 +11,7 @@ namespace ParameterLessAttributeUsage [Flags] public enum EnumWithFlagsAttribute { - None + None = 0 } } //$$ AttributeWithEnumArgument @@ -79,3 +79,11 @@ namespace AttributeAppliedToMethod } } } +//$$ NamedParameter +namespace NamedParameter +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public class MyAttributeAttribute : Attribute + { + } +} From 9f1eb2b4cdb20bf3406778b5226ac1cebdce344f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sat, 26 Feb 2011 00:21:46 +0100 Subject: [PATCH 11/21] support for type arguments of custom attributes. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 7 +++ .../CustomAttributeSamples.cs | 45 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index c1fbc41cf..2b3a363dd 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -609,6 +609,13 @@ namespace Decompiler { parameterValue = MakePrimitive(Convert.ToInt64(parameter.Value), parameter.Type); } + else if (parameter.Value is TypeReference) + { + parameterValue = new TypeOfExpression() + { + Type = ConvertType((TypeReference)parameter.Value), + }; + } else { parameterValue = new PrimitiveExpression(parameter.Value); diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs index ef3a8af3f..453328001 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs @@ -38,6 +38,22 @@ namespace AttributeWithStringExpressionArgument { } } +//$$ AttributeWithTypeArgument +namespace AttributeWithTypeArgument +{ + [AttributeUsage(AttributeTargets.All)] + public class MyTypeAttribute : Attribute + { + public MyTypeAttribute(Type t) + { + } + } + + [MyType(typeof(Attribute))] + public class SomeClass + { + } +} //$$ AttributeAppliedToEvent (ignored) namespace AttributeAppliedToEvent { @@ -64,6 +80,24 @@ namespace AttributeAppliedToField public int Field; } } +//$$ AttributeAppliedToProperty +namespace AttributeAppliedToProperty +{ + public class TestClass + { + [Obsolete("reason")] + public int Property + { + get + { + return 0; + } + } + } +} +//$$ AttributeAppliedToDelegate +[Obsolete("reason")] +public delegate int AttributeAppliedToDelegate(); //$$ AttributeAppliedToMethod namespace AttributeAppliedToMethod { @@ -79,6 +113,17 @@ namespace AttributeAppliedToMethod } } } +//$$ AttributeAppliedToInterface +[Obsolete("reason")] +public interface AttributeAppliedToInterface +{ +} +//$$ AttributeAppliedToStruct +[Obsolete("reason")] +public struct AttributeAppliedToStruct +{ + public int Field; +} //$$ NamedParameter namespace NamedParameter { From 1df7e5f7775aef22f4c326172c8fdcc1fecd0554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sat, 26 Feb 2011 00:57:10 +0100 Subject: [PATCH 12/21] corrected printing values of named parameters of attributes. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 44 ++++++----- .../CustomAttributeSamples.cs | 73 ++++++++++++++++++- 2 files changed, 96 insertions(+), 21 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 2b3a363dd..94473dba2 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -603,23 +603,7 @@ namespace Decompiler if(customAttribute.HasConstructorArguments) foreach (var parameter in customAttribute.ConstructorArguments) { - var isEnum = parameter.Type.IsValueType && !parameter.Type.IsPrimitive; - Expression parameterValue; - if (isEnum) - { - parameterValue = MakePrimitive(Convert.ToInt64(parameter.Value), parameter.Type); - } - else if (parameter.Value is TypeReference) - { - parameterValue = new TypeOfExpression() - { - Type = ConvertType((TypeReference)parameter.Value), - }; - } - else - { - parameterValue = new PrimitiveExpression(parameter.Value); - } + Expression parameterValue = ConvertArgumentValue(parameter); attribute.Arguments.Add(parameterValue); } @@ -628,8 +612,8 @@ namespace Decompiler { var propertyReference = customAttribute.AttributeType.Resolve().Properties.First(pr => pr.Name == property.Name); var propertyName = new IdentifierExpression(property.Name).WithAnnotation(propertyReference); - var propertyArgument = new PrimitiveExpression(property.Argument.Value); - attribute.Arguments.Add(new AssignmentExpression(propertyName, propertyArgument)); + var argumentValue = ConvertArgumentValue(property.Argument); + attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue)); } } @@ -637,6 +621,28 @@ namespace Decompiler } } + private static Expression ConvertArgumentValue(CustomAttributeArgument parameter) + { + var type = parameter.Type.Resolve(); + Expression parameterValue; + if (type.IsEnum) + { + parameterValue = MakePrimitive(Convert.ToInt64(parameter.Value), type); + } + else if (parameter.Value is TypeReference) + { + parameterValue = new TypeOfExpression() + { + Type = ConvertType((TypeReference)parameter.Value), + }; + } + else + { + parameterValue = new PrimitiveExpression(parameter.Value); + } + return parameterValue; + } + internal static Expression MakePrimitive(long val, TypeReference type) { diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs index 453328001..af74a2a6a 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs @@ -124,11 +124,80 @@ public struct AttributeAppliedToStruct { public int Field; } -//$$ NamedParameter -namespace NamedParameter +//$$ NamedPropertyParameter +namespace NamedPropertyParameter { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public class MyAttributeAttribute : Attribute { } } +//$$ NamedStringPropertyParameter +namespace NamedStringPropertyParameter +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public string Prop + { + get + { + return ""; + } + set + { + return; + } + } + } + [MyAttribute(Prop = "value")] + public class MyClass + { + } +} +//$$ NamedTypePropertyParameter +namespace NamedTypePropertyParameter +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public Type Prop + { + get + { + return null; + } + set + { + return; + } + } + } + [MyAttribute(Prop = typeof(Enum))] + public class MyClass + { + } +} +//$$ NamedEnumPropertyParameter +namespace NamedEnumPropertyParameter +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public AttributeTargets Prop + { + get + { + return AttributeTargets.All; + } + set + { + return; + } + } + } + [MyAttribute(Prop = (AttributeTargets.Class | AttributeTargets.Method))] + public class MyClass + { + } +} From 3609dd641aad78f64aad4eea5367a6ebd5ee0b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sat, 26 Feb 2011 08:07:16 +0100 Subject: [PATCH 13/21] printing of field named arguments in attributes. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 17 +++++++++++++---- .../CustomAttributes/CustomAttributeSamples.cs | 13 +++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 94473dba2..8be1173f0 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -608,13 +608,22 @@ namespace Decompiler } if (customAttribute.HasProperties) - foreach (var property in customAttribute.Properties) + foreach (var propertyNamedArg in customAttribute.Properties) { - var propertyReference = customAttribute.AttributeType.Resolve().Properties.First(pr => pr.Name == property.Name); - var propertyName = new IdentifierExpression(property.Name).WithAnnotation(propertyReference); - var argumentValue = ConvertArgumentValue(property.Argument); + var propertyReference = customAttribute.AttributeType.Resolve().Properties.First(pr => pr.Name == propertyNamedArg.Name); + var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference); + var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument); attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue)); } + + if (customAttribute.HasFields) + foreach (var fieldNamedArg in customAttribute.Fields) + { + var fieldReference = customAttribute.AttributeType.Resolve().Fields.First(f => f.Name == fieldNamedArg.Name); + var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference); + var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument); + attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue)); + } } attributedNode.Attributes.Add(section); diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs index af74a2a6a..1d91f1fe0 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs @@ -201,3 +201,16 @@ namespace NamedEnumPropertyParameter { } } +//$$ NamedEnumFieldParameter +namespace NamedEnumFieldParameter +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public AttributeTargets Field; + } + [MyAttribute(Field = (AttributeTargets.Class | AttributeTargets.Method))] + public class MyClass + { + } +} From 75661da50ed003b453a1d74759f8f1fdfe5311cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sat, 26 Feb 2011 08:50:05 +0100 Subject: [PATCH 14/21] attributed parameter declaration. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 1 + .../CustomAttributeSamples.cs | 62 ++++++++++++------- .../Ast/TypeMembers/ParameterDeclaration.cs | 2 +- .../CSharp/OutputVisitor/OutputVisitor.cs | 3 +- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 8be1173f0..d5560eb1a 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -584,6 +584,7 @@ namespace Decompiler } // TODO: params, this + ConvertCustomAtributes(astParam, paramDef); yield return astParam; } } diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs index 1d91f1fe0..85c5b2679 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs @@ -54,8 +54,8 @@ namespace AttributeWithTypeArgument { } } -//$$ AttributeAppliedToEvent (ignored) -namespace AttributeAppliedToEvent +//$$ AppliedToEvent +namespace AppliedToEvent { [AttributeUsage(AttributeTargets.Event)] public class MyAttributeAttribute : Attribute @@ -67,8 +67,8 @@ namespace AttributeAppliedToEvent public event EventHandler MyEvent; } } -//$$ AttributeAppliedToField -namespace AttributeAppliedToField +//$$ AppliedToField +namespace AppliedToField { [AttributeUsage(AttributeTargets.Field)] public class MyAttributeAttribute : Attribute @@ -80,8 +80,8 @@ namespace AttributeAppliedToField public int Field; } } -//$$ AttributeAppliedToProperty -namespace AttributeAppliedToProperty +//$$ AppliedToProperty +namespace AppliedToProperty { public class TestClass { @@ -95,11 +95,11 @@ namespace AttributeAppliedToProperty } } } -//$$ AttributeAppliedToDelegate +//$$ AppliedToDelegate [Obsolete("reason")] -public delegate int AttributeAppliedToDelegate(); -//$$ AttributeAppliedToMethod -namespace AttributeAppliedToMethod +public delegate int AppliedToDelegate(); +//$$ AppliedToMethod +namespace AppliedToMethod { [AttributeUsage(AttributeTargets.Method)] public class MyAttributeAttribute : Attribute @@ -113,27 +113,41 @@ namespace AttributeAppliedToMethod } } } -//$$ AttributeAppliedToInterface +//$$ AppliedToInterface [Obsolete("reason")] -public interface AttributeAppliedToInterface +public interface AppliedToInterface { } -//$$ AttributeAppliedToStruct +//$$ AppliedToStruct [Obsolete("reason")] -public struct AttributeAppliedToStruct +public struct AppliedToStruct { public int Field; } -//$$ NamedPropertyParameter -namespace NamedPropertyParameter +//$$ AppliedToParameter +namespace AppliedToParameter +{ + [AttributeUsage(AttributeTargets.Parameter)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public void Method([MyAttribute]int val) + { + } + } +} +//$$ NamedInitializerProperty +namespace NamedInitializerProperty { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public class MyAttributeAttribute : Attribute { } } -//$$ NamedStringPropertyParameter -namespace NamedStringPropertyParameter +//$$ NamedInitializerPropertyString +namespace NamedInitializerPropertyString { [AttributeUsage(AttributeTargets.All)] public class MyAttributeAttribute : Attribute @@ -155,8 +169,8 @@ namespace NamedStringPropertyParameter { } } -//$$ NamedTypePropertyParameter -namespace NamedTypePropertyParameter +//$$ NamedInitializerPropertyType +namespace NamedInitializerPropertyType { [AttributeUsage(AttributeTargets.All)] public class MyAttributeAttribute : Attribute @@ -178,8 +192,8 @@ namespace NamedTypePropertyParameter { } } -//$$ NamedEnumPropertyParameter -namespace NamedEnumPropertyParameter +//$$ NamedInitializerPropertyEnum +namespace NamedInitializerPropertyEnum { [AttributeUsage(AttributeTargets.All)] public class MyAttributeAttribute : Attribute @@ -201,8 +215,8 @@ namespace NamedEnumPropertyParameter { } } -//$$ NamedEnumFieldParameter -namespace NamedEnumFieldParameter +//$$ NamedInitializerFieldEnum +namespace NamedInitializerFieldEnum { [AttributeUsage(AttributeTargets.All)] public class MyAttributeAttribute : Attribute diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs index 0334d2a3f..05bd3140e 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp This } - public class ParameterDeclaration : AstNode + public class ParameterDeclaration : AttributedNode { public static readonly Role AttributeRole = AttributedNode.AttributeRole; public static readonly Role ModifierRole = new Role("Modifier", CSharpTokenNode.Null); diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index ec0ad4b92..1a7f0e498 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -1110,7 +1110,8 @@ namespace ICSharpCode.NRefactory.CSharp } WriteCommaSeparatedList(attributeSection.Attributes); WriteToken("]", AstNode.Roles.RBracket); - NewLine(); + if (!(attributeSection.Parent is ParameterDeclaration)) + NewLine(); return EndNode(attributeSection); } From 6b9c2b7462ef1dd10c27859d4c3dd829c1e8d1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sat, 26 Feb 2011 09:29:07 +0100 Subject: [PATCH 15/21] attribute target: method return --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 5 +++-- .../CustomAttributes/CustomAttributeSamples.cs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index d5560eb1a..b072254be 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -480,6 +480,7 @@ namespace Decompiler astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context); } ConvertCustomAtributes(astMethod, methodDef); + ConvertCustomAtributes(astMethod, methodDef.MethodReturnType, AttributeTarget.Return); return astMethod; } @@ -589,12 +590,12 @@ namespace Decompiler } } - static void ConvertCustomAtributes(AttributedNode attributedNode, ICustomAttributeProvider customAttributeProvider) + static void ConvertCustomAtributes(AttributedNode attributedNode, ICustomAttributeProvider customAttributeProvider, AttributeTarget target = AttributeTarget.None) { if (customAttributeProvider.HasCustomAttributes) { var section = new AttributeSection(); - //section.AttributeTarget = target; + section.AttributeTarget = target; foreach (var customAttribute in customAttributeProvider.CustomAttributes) { ICSharpCode.NRefactory.CSharp.Attribute attribute = new ICSharpCode.NRefactory.CSharp.Attribute(); diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs index 85c5b2679..685c87c79 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs @@ -228,3 +228,19 @@ namespace NamedInitializerFieldEnum { } } +//$$ TargetReturn +namespace TargetReturn +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + [return: MyAttribute] + public int MyMethod() + { + return 5; + } + } +} From 19993ff43bc716452eaf0cb0d8f6ee1470d6b210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sat, 26 Feb 2011 13:12:19 +0100 Subject: [PATCH 16/21] more attribute targets implemented. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 32 ++-- .../AssemblyCustomAttribute.cs | 6 + .../CustomAttributeSamples.cs | 152 ++++++++++++++++++ .../CustomAttributes/CustomAttributeTests.cs | 6 + .../CustomAttributes/CustomAttributes.cs | 1 - .../Tests/DecompilerTestBase.cs | 1 + .../Tests/Helpers/RemoveCompilerAttribute.cs | 31 ++++ .../Tests/ICSharpCode.Decompiler.Tests.csproj | 11 +- ILSpy/CSharpLanguage.cs | 5 +- .../CSharp/Ast/CompilationUnit.cs | 2 +- 10 files changed, 231 insertions(+), 16 deletions(-) create mode 100644 ICSharpCode.Decompiler/Tests/CustomAttributes/AssemblyCustomAttribute.cs create mode 100644 ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index b072254be..a3a579fab 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -64,21 +64,25 @@ namespace Decompiler astCompileUnit.AcceptVisitor(new OutputVisitor(outputFormatter, formattingPolicy), null); } - public void AddAssembly(AssemblyDefinition assemblyDefinition) + public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false) { astCompileUnit.AddChild( new UsingDeclaration { Import = new SimpleType("System") }, CompilationUnit.MemberRole); - foreach(TypeDefinition typeDef in assemblyDefinition.MainModule.Types) { - // Skip nested types - they will be added by the parent type - if (typeDef.DeclaringType != null) continue; - // Skip the class - if (typeDef.Name == "") continue; - - AddType(typeDef); - } + ConvertCustomAtributes(astCompileUnit, assemblyDefinition, AttributeTarget.Assembly); + + if(!onlyAssemblyLevel) + foreach (TypeDefinition typeDef in assemblyDefinition.MainModule.Types) + { + // Skip nested types - they will be added by the parent type + if (typeDef.DeclaringType != null) continue; + // Skip the class + if (typeDef.Name == "") continue; + + AddType(typeDef); + } } NamespaceDeclaration GetCodeNamespace(string name) @@ -193,6 +197,11 @@ namespace Decompiler ConvertCustomAtributes(astType, typeDef); return astType; } + + public void Transform(IAstTransform transform) + { + transform.Run(astCompileUnit); + } string CleanName(string name) { @@ -525,11 +534,16 @@ namespace Decompiler astProp.Getter = new Accessor { Body = AstMethodBodyBuilder.CreateMethodBody(propDef.GetMethod, context) }.WithAnnotation(propDef.GetMethod); + ConvertCustomAtributes(astProp.Getter, propDef.GetMethod); + ConvertCustomAtributes(astProp.Getter, propDef.GetMethod.MethodReturnType, AttributeTarget.Return); } if (propDef.SetMethod != null) { astProp.Setter = new Accessor { Body = AstMethodBodyBuilder.CreateMethodBody(propDef.SetMethod, context) }.WithAnnotation(propDef.SetMethod); + ConvertCustomAtributes(astProp.Setter, propDef.SetMethod); + ConvertCustomAtributes(astProp.Setter, propDef.SetMethod.MethodReturnType, AttributeTarget.Return); + ConvertCustomAtributes(astProp.Setter, propDef.SetMethod.Parameters.Last(), AttributeTarget.Param); } ConvertCustomAtributes(astProp, propDef); return astProp; diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/AssemblyCustomAttribute.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/AssemblyCustomAttribute.cs new file mode 100644 index 000000000..9d95a4861 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/AssemblyCustomAttribute.cs @@ -0,0 +1,6 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +[assembly: CLSCompliant(false)] diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs index 685c87c79..98b4a403b 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs @@ -5,6 +5,8 @@ using System; //$CE +//$$ TargetModule (ignored) +//[module: CLSCompliantAttribute(false)] //$$ ParameterlessAttributeUsage namespace ParameterLessAttributeUsage { @@ -95,6 +97,48 @@ namespace AppliedToProperty } } } +//$$ AppliedToPropertyGet +namespace AppliedToPropertyGet +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + public int Property + { + [MyAttribute] + get + { + return 0; + } + } + } +} +//$$ AppliedToPropertySet +namespace AppliedToPropertySet +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class TestClass + { + public int Property + { + get + { + return 3; + } + [MyAttribute] + set + { + return; + } + } + } +} //$$ AppliedToDelegate [Obsolete("reason")] public delegate int AppliedToDelegate(); @@ -244,3 +288,111 @@ namespace TargetReturn } } } +//$$ TargetPropertyGetReturn +namespace TargetPropertyGetReturn +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public int Prop + { + [return: MyAttribute] + get + { + return 3; + } + } + } +} +//$$ TargetPropertySetParam +namespace TargetPropertySetParam +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public int Prop + { + [param: MyAttribute] + set + { + return; + } + } + } +} +//$$ TargetPropertySetReturn +namespace TargetPropertySetReturn +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public int Prop + { + get + { + return 3; + } + [return: MyAttribute] + set + { + return; + } + } + } +} +//$$ TargetPropertyIndexSetParam +namespace TargetPropertyIndexSetParam +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + } + public class MyClass + { + public string this[int index] + { + get + { + return ""; + } + [param: MyAttribute] + set + { + return; + } + } + } +} +//$$ TargetPropertyIndexSetMultiParam +namespace TargetPropertyIndexSetMultiParam +{ + [AttributeUsage(AttributeTargets.All)] + public class MyAttributeAttribute : Attribute + { + public int Field; + } + public class MyClass + { + public string this[[MyAttribute(Field = 2)]int index1, [MyAttribute(Field = 3)]int index2] + { + get + { + return ""; + } + [param: MyAttribute] + set + { + return; + } + } + } +} diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs index 70ff0f799..d453e484f 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs @@ -19,5 +19,11 @@ namespace ICSharpCode.Decompiler.Tests.CustomAttributes { ValidateFileRoundtrip(@"CustomAttributes\CustomAttributes.cs"); } + + [Test] + public void AssemblyCustomAttributesMultiTest() + { + ValidateFileRoundtrip(@"CustomAttributes\AssemblyCustomAttribute.cs"); + } } } diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs index 7baaf2982..bfaf57c8a 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs @@ -3,7 +3,6 @@ using System; - namespace aa { public static class CustomAtributes diff --git a/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs index b27cccf46..db4368cb7 100644 --- a/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs +++ b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs @@ -55,6 +55,7 @@ namespace ICSharpCode.Decompiler.Tests AssemblyDefinition assembly = Compile(code); AstBuilder decompiler = new AstBuilder(new DecompilerContext()); decompiler.AddAssembly(assembly); + decompiler.Transform(new Helpers.RemoveCompilerAttribute()); StringWriter output = new StringWriter(); decompiler.GenerateCode(new PlainTextOutput(output)); return output.ToString(); diff --git a/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs b/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs new file mode 100644 index 000000000..8b364268e --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.NRefactory.CSharp; +using Decompiler.Transforms; + +namespace ICSharpCode.Decompiler.Tests.Helpers +{ + class RemoveCompilerAttribute : DepthFirstAstVisitor, IAstTransform + { + public override object VisitAttribute(NRefactory.CSharp.Attribute attribute, object data) + { + var section = (AttributeSection)attribute.Parent; + SimpleType type = attribute.Type as SimpleType; + if (section.AttributeTarget == AttributeTarget.Assembly && + (type.Identifier == "CompilationRelaxationsAttribute" || type.Identifier == "RuntimeCompatibilityAttribute")) + { + attribute.Remove(); + if (section.Attributes.Count == 0) + section.Remove(); + } + return null; + } + + public void Run(AstNode node) + { + node.AcceptVisitor(this, null); + } + } +} diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 70e05f043..af8673d30 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -57,6 +57,8 @@ + + @@ -70,7 +72,6 @@ - @@ -79,14 +80,16 @@ {D68133BD-1E63-496E-9EDE-4FBDBF77B486} Mono.Cecil + + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} + ICSharpCode.NRefactory + {984CC812-9470-4A13-AFF9-CC44068D666C} ICSharpCode.Decompiler - - - + diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs index 7ff152475..6ca6f267f 100644 --- a/ILSpy/CSharpLanguage.cs +++ b/ILSpy/CSharpLanguage.cs @@ -132,6 +132,9 @@ namespace ICSharpCode.ILSpy } } else { base.DecompileAssembly(assembly, fileName, output, options); + AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: null); + codeDomBuilder.AddAssembly(assembly, onlyAssemblyLevel: true); + codeDomBuilder.GenerateCode(output, transformAbortCondition); } } @@ -375,7 +378,7 @@ namespace ICSharpCode.ILSpy CurrentType = currentType }); } - + public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes) { AstType astType = AstBuilder.ConvertType(type, typeAttributes); diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs index 9a5047719..1b97a4cd0 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs @@ -28,7 +28,7 @@ using System.Collections.Generic; namespace ICSharpCode.NRefactory.CSharp { - public class CompilationUnit : AstNode + public class CompilationUnit : AttributedNode { public static readonly Role MemberRole = new Role("Member", AstNode.Null); From 8b1be87732281a02eb668c62b3f68bcad86d4085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sat, 26 Feb 2011 14:52:00 +0100 Subject: [PATCH 17/21] changed version of referenced gallio and mbunit libraries. --- .../Tests/ICSharpCode.Decompiler.Tests.csproj | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 78c202773..51344082d 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -38,13 +38,11 @@ TRACE - + False - ..\..\libs\Gallio.dll - + False - ..\..\libs\MbUnit.dll From 33290c2a7f653443f1891bc1a3cc8b8c3d9d25d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sat, 26 Feb 2011 17:38:39 +0100 Subject: [PATCH 18/21] renamed files with sample code --- .../Tests/CustomAttributes/CustomAttributeTests.cs | 6 +++--- ...omAttribute.cs => S_AssemblyCustomAttribute.cs} | 0 ...ibuteSamples.cs => S_CustomAttributeSamples.cs} | 0 .../{CustomAttributes.cs => S_CustomAttributes.cs} | 0 .../Tests/ICSharpCode.Decompiler.Tests.csproj | 14 +++++++------- ICSharpCode.Decompiler/Tests/Types/EnumTests.cs | 2 +- ...teConstruction.cs => S_DelegateConstruction.cs} | 0 .../Types/{EnumSamples.cs => S_EnumSamples.cs} | 0 ...ertiesAndEvents.cs => S_PropertiesAndEvents.cs} | 0 .../Tests/Types/{ValueTypes.cs => S_ValueTypes.cs} | 0 ICSharpCode.Decompiler/Tests/Types/TypeTests.cs | 6 +++--- 11 files changed, 14 insertions(+), 14 deletions(-) rename ICSharpCode.Decompiler/Tests/CustomAttributes/{AssemblyCustomAttribute.cs => S_AssemblyCustomAttribute.cs} (100%) rename ICSharpCode.Decompiler/Tests/CustomAttributes/{CustomAttributeSamples.cs => S_CustomAttributeSamples.cs} (100%) rename ICSharpCode.Decompiler/Tests/CustomAttributes/{CustomAttributes.cs => S_CustomAttributes.cs} (100%) rename ICSharpCode.Decompiler/Tests/Types/{DelegateConstruction.cs => S_DelegateConstruction.cs} (100%) rename ICSharpCode.Decompiler/Tests/Types/{EnumSamples.cs => S_EnumSamples.cs} (100%) rename ICSharpCode.Decompiler/Tests/Types/{PropertiesAndEvents.cs => S_PropertiesAndEvents.cs} (100%) rename ICSharpCode.Decompiler/Tests/Types/{ValueTypes.cs => S_ValueTypes.cs} (100%) diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs index d453e484f..76608c595 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs @@ -11,19 +11,19 @@ namespace ICSharpCode.Decompiler.Tests.CustomAttributes [StaticTestFactory] public static IEnumerable CustomAttributeSamples() { - return GenerateSectionTests(@"CustomAttributes\CustomAttributeSamples.cs"); + return GenerateSectionTests(@"CustomAttributes\S_CustomAttributeSamples.cs"); } [Test] public void CustomAttributesMultiTest() { - ValidateFileRoundtrip(@"CustomAttributes\CustomAttributes.cs"); + ValidateFileRoundtrip(@"CustomAttributes\S_CustomAttributes.cs"); } [Test] public void AssemblyCustomAttributesMultiTest() { - ValidateFileRoundtrip(@"CustomAttributes\AssemblyCustomAttribute.cs"); + ValidateFileRoundtrip(@"CustomAttributes\S_AssemblyCustomAttribute.cs"); } } } diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/AssemblyCustomAttribute.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/CustomAttributes/AssemblyCustomAttribute.cs rename to ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeSamples.cs rename to ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributes.cs rename to ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 51344082d..146aca67d 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -54,16 +54,16 @@ - - + + - - + + - - + + @@ -72,7 +72,7 @@ - + diff --git a/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs index b4234f623..07af8968b 100644 --- a/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs +++ b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs @@ -11,7 +11,7 @@ namespace ICSharpCode.Decompiler.Tests.Types [StaticTestFactory] public static IEnumerable EnumSamples() { - return GenerateSectionTests(@"Types\EnumSamples.cs"); + return GenerateSectionTests(@"Types\S_EnumSamples.cs"); } } } diff --git a/ICSharpCode.Decompiler/Tests/Types/DelegateConstruction.cs b/ICSharpCode.Decompiler/Tests/Types/S_DelegateConstruction.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/Types/DelegateConstruction.cs rename to ICSharpCode.Decompiler/Tests/Types/S_DelegateConstruction.cs diff --git a/ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs b/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/Types/EnumSamples.cs rename to ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs diff --git a/ICSharpCode.Decompiler/Tests/Types/PropertiesAndEvents.cs b/ICSharpCode.Decompiler/Tests/Types/S_PropertiesAndEvents.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/Types/PropertiesAndEvents.cs rename to ICSharpCode.Decompiler/Tests/Types/S_PropertiesAndEvents.cs diff --git a/ICSharpCode.Decompiler/Tests/Types/ValueTypes.cs b/ICSharpCode.Decompiler/Tests/Types/S_ValueTypes.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/Types/ValueTypes.cs rename to ICSharpCode.Decompiler/Tests/Types/S_ValueTypes.cs diff --git a/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs index fca3ace99..3875edd1c 100644 --- a/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs +++ b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs @@ -11,19 +11,19 @@ namespace ICSharpCode.Decompiler.Tests.Types [Test] public void ValueTypes() { - ValidateFileRoundtrip(@"Types\ValueTypes.cs"); + ValidateFileRoundtrip(@"Types\S_ValueTypes.cs"); } [Test] public void PropertiesAndEvents() { - ValidateFileRoundtrip(@"Types\PropertiesAndEvents.cs"); + ValidateFileRoundtrip(@"Types\S_PropertiesAndEvents.cs"); } [Test] public void DelegateConstruction() { - ValidateFileRoundtrip(@"Types\DelegateConstruction.cs"); + ValidateFileRoundtrip(@"Types\S_DelegateConstruction.cs"); } } } From e8c25366067c0181dd124638a0e1c096291e2288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sat, 26 Feb 2011 18:32:42 +0100 Subject: [PATCH 19/21] BugFix: incorrectly removed empty constructors with parameters --- .../Ast/Transforms/ConvertConstructorCallIntoInitializer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs b/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs index 4ffa69c9c..ee2225073 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs @@ -48,6 +48,7 @@ namespace Decompiler.Transforms if (ctors.Length == 1 && ctors[0].Body.Children.Count() == 0 && ctors[0].Initializer.ConstructorInitializerType == ConstructorInitializerType.Base && ctors[0].Initializer.Arguments.Count() == 0 + && ctors[0].Parameters.Count == 0 && ctors[0].Modifiers == ((typeDeclaration.Modifiers & Modifiers.Abstract) == Modifiers.Abstract ? Modifiers.Protected : Modifiers.Public)) { ctors[0].Remove(); From cd200fa5046255ed0794eae360f2db6da6c4e424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Tue, 1 Mar 2011 18:36:22 +0100 Subject: [PATCH 20/21] Replaced MBUnit with NUnit. --- .../CustomAttributes/CustomAttributeTests.cs | 10 ++-- .../S_CustomAttributeSamples.cs | 2 +- .../Tests/DecompilerTestBase.cs | 21 +------- ...onstruction.cs => DelegateConstruction.cs} | 0 .../Tests/ICSharpCode.Decompiler.Tests.csproj | 13 ++--- ...iesAndEvents.cs => PropertiesAndEvents.cs} | 0 ICSharpCode.Decompiler/Tests/TestRunner.cs | 52 ------------------- .../Tests/Types/EnumTests.cs | 8 +-- .../Tests/Types/TypeTests.cs | 19 +------ .../{Types/S_ValueTypes.cs => ValueTypes.cs} | 0 10 files changed, 17 insertions(+), 108 deletions(-) rename ICSharpCode.Decompiler/Tests/{Types/S_DelegateConstruction.cs => DelegateConstruction.cs} (100%) rename ICSharpCode.Decompiler/Tests/{Types/S_PropertiesAndEvents.cs => PropertiesAndEvents.cs} (100%) rename ICSharpCode.Decompiler/Tests/{Types/S_ValueTypes.cs => ValueTypes.cs} (100%) diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs index 76608c595..4f040b293 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs @@ -2,16 +2,16 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using MbUnit.Framework; +using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.CustomAttributes { public class CustomAttributeTests : DecompilerTestBase { - [StaticTestFactory] - public static IEnumerable CustomAttributeSamples() - { - return GenerateSectionTests(@"CustomAttributes\S_CustomAttributeSamples.cs"); + [Test] + public void CustomAttributeSamples() + { + ValidateFileRoundtrip(@"CustomAttributes\S_CustomAttributeSamples.cs"); } [Test] diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs index 98b4a403b..aa6d4660a 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs @@ -46,7 +46,7 @@ namespace AttributeWithTypeArgument [AttributeUsage(AttributeTargets.All)] public class MyTypeAttribute : Attribute { - public MyTypeAttribute(Type t) + public MyTypeAttribute(Type t) : base() { } } diff --git a/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs index db4368cb7..c1a13b925 100644 --- a/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs +++ b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs @@ -7,31 +7,12 @@ using System.IO; using Decompiler; using Microsoft.CSharp; using System.CodeDom.Compiler; -using MbUnit.Framework; +using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests { public abstract class DecompilerTestBase { - protected static IEnumerable GenerateSectionTests(string samplesFileName) - { - string code = File.ReadAllText(Path.Combine(@"..\..\Tests", samplesFileName)); - foreach (var sectionName in CodeSampleFileParser.ListSections(code)) - { - if (sectionName.EndsWith("(ignored)", StringComparison.OrdinalIgnoreCase)) - continue; - - var testedSectionName = sectionName; - yield return new TestCase(testedSectionName, () => - { - var testCode = CodeSampleFileParser.GetSection(testedSectionName, code); - System.Diagnostics.Debug.WriteLine(testCode); - var decompiledTestCode = RoundtripCode(testCode); - Assert.AreEqual(testCode, decompiledTestCode); - }); - } - } - protected static void ValidateFileRoundtrip(string samplesFileName) { var lines = File.ReadAllLines(Path.Combine(@"..\..\Tests", samplesFileName)); diff --git a/ICSharpCode.Decompiler/Tests/Types/S_DelegateConstruction.cs b/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/Types/S_DelegateConstruction.cs rename to ICSharpCode.Decompiler/Tests/DelegateConstruction.cs diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 146aca67d..d7b6f327a 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -38,10 +38,7 @@ TRACE - - False - - + False @@ -59,10 +56,10 @@ - + - - + + @@ -72,7 +69,7 @@ - + diff --git a/ICSharpCode.Decompiler/Tests/Types/S_PropertiesAndEvents.cs b/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/Types/S_PropertiesAndEvents.cs rename to ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs index d726f91a4..543200603 100644 --- a/ICSharpCode.Decompiler/Tests/TestRunner.cs +++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs @@ -9,7 +9,6 @@ using System.Text; using Decompiler; using Microsoft.CSharp; using Mono.Cecil; -using MbUnit.Framework; namespace ICSharpCode.Decompiler.Tests { @@ -22,24 +21,6 @@ namespace ICSharpCode.Decompiler.Tests Console.ReadKey(); } - public void RoundtripFile(string fileName) - { - string code = File.ReadAllText(fileName); - AssemblyDefinition assembly = Compile(code); - AstBuilder decompiler = new AstBuilder(new DecompilerContext()); - decompiler.AddAssembly(assembly); - StringWriter output = new StringWriter(); - decompiler.GenerateCode(new PlainTextOutput(output)); - - var decompiledCode = output.ToString(); - var onlyCode = "using System;" + Environment.NewLine + StripCodeFileHeader(code); - - File.WriteAllText(Path.ChangeExtension(fileName, ".decomp.cs"), decompiledCode); - File.WriteAllText(Path.ChangeExtension(fileName, ".code.cs"), onlyCode); - - Assert.AreEqual(onlyCode, decompiledCode); - } - static void TestFile(string fileName) { string code = File.ReadAllText(fileName); @@ -55,39 +36,6 @@ namespace ICSharpCode.Decompiler.Tests } } - static string StripCodeFileHeader(string code) - { - var reader = new StringReader(code); - - var buffer = new StringWriter(); - - string line; - var skipBlankLine = false; - while ((line = reader.ReadLine()) != null) - { - if (line.Trim().StartsWith("//")) - { - skipBlankLine = true; - continue; - } - else if (line.StartsWith("using ")) - { - skipBlankLine = true; - continue; - } - else if (skipBlankLine && String.IsNullOrWhiteSpace(line)) - { - continue; - } - - skipBlankLine = false; - - buffer.WriteLine(line); - } - - return buffer.ToString(); - } - static bool Compare(string input1, string input2, StringWriter diff) { bool ok = true; diff --git a/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs index 07af8968b..b84147082 100644 --- a/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs +++ b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs @@ -2,16 +2,16 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using MbUnit.Framework; +using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Types { public class EnumTests : DecompilerTestBase { - [StaticTestFactory] - public static IEnumerable EnumSamples() + [Test] + public void EnumSamples() { - return GenerateSectionTests(@"Types\S_EnumSamples.cs"); + ValidateFileRoundtrip(@"Types\S_EnumSamples.cs"); } } } diff --git a/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs index 3875edd1c..56d7db39f 100644 --- a/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs +++ b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs @@ -2,28 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using MbUnit.Framework; +using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Types { public class TypeTests : DecompilerTestBase { - [Test] - public void ValueTypes() - { - ValidateFileRoundtrip(@"Types\S_ValueTypes.cs"); - } - - [Test] - public void PropertiesAndEvents() - { - ValidateFileRoundtrip(@"Types\S_PropertiesAndEvents.cs"); - } - - [Test] - public void DelegateConstruction() - { - ValidateFileRoundtrip(@"Types\S_DelegateConstruction.cs"); - } } } diff --git a/ICSharpCode.Decompiler/Tests/Types/S_ValueTypes.cs b/ICSharpCode.Decompiler/Tests/ValueTypes.cs similarity index 100% rename from ICSharpCode.Decompiler/Tests/Types/S_ValueTypes.cs rename to ICSharpCode.Decompiler/Tests/ValueTypes.cs From f25904a47432767797efae10ffa8e1ad285b0ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Tue, 1 Mar 2011 20:38:53 +0100 Subject: [PATCH 21/21] changed TextRunner to accept test file name. --- .../Tests/CustomAttributes/S_CustomAttributes.cs | 2 +- ICSharpCode.Decompiler/Tests/TestRunner.cs | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs index bfaf57c8a..dbd064eb4 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs @@ -20,7 +20,7 @@ namespace aa [AttributeUsage(AttributeTargets.All)] public class MyAttribute : Attribute { - public MyAttribute(CustomAtributes.EnumWithFlag en) + public MyAttribute(CustomAtributes.EnumWithFlag en) : base() { } } diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs index 543200603..71815fffa 100644 --- a/ICSharpCode.Decompiler/Tests/TestRunner.cs +++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs @@ -14,9 +14,12 @@ namespace ICSharpCode.Decompiler.Tests { public class TestRunner { - public static void Main() + public static void Main(string[] args) { - TestFile(@"..\..\Tests\DelegateConstruction.cs"); + if (args.Length == 1) + TestFile(args[0]); + else + TestFile(@"..\..\Tests\DelegateConstruction.cs"); Console.ReadKey(); } @@ -27,6 +30,7 @@ namespace ICSharpCode.Decompiler.Tests AssemblyDefinition assembly = Compile(code); AstBuilder decompiler = new AstBuilder(new DecompilerContext()); decompiler.AddAssembly(assembly); + decompiler.Transform(new Helpers.RemoveCompilerAttribute()); StringWriter output = new StringWriter(); decompiler.GenerateCode(new PlainTextOutput(output)); StringWriter diff = new StringWriter();