From 25c757b7cd37c09b8b32daf8f25b90a8e65b3ca2 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 16 Feb 2019 08:27:14 +0100 Subject: [PATCH] Add first attempt at PdbGenerationTestRunner. --- .../DebugInfo/SequencePointTests.cs | 55 ------------------ .../Helpers/Tester.cs | 51 +++++++++++----- .../ICSharpCode.Decompiler.Tests.csproj | 11 +++- .../IL/SequenceOfNestedIfs.dll | Bin 2560 -> 0 bytes .../IL/StackTests.exe | Bin 2048 -> 0 bytes .../PdbGenerationTestRunner.cs | 54 +++++++++++++++++ .../TestCases/PdbGen/.gitignore | 2 + .../TestCases/PdbGen/HelloWorld.xml | 33 +++++++++++ .../DebugInfo/PortablePdbWriter.cs | 2 +- NuGet.config | 1 + 10 files changed, 136 insertions(+), 73 deletions(-) delete mode 100644 ICSharpCode.Decompiler.Tests/DebugInfo/SequencePointTests.cs delete mode 100644 ICSharpCode.Decompiler.Tests/IL/SequenceOfNestedIfs.dll delete mode 100644 ICSharpCode.Decompiler.Tests/IL/StackTests.exe create mode 100644 ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/PdbGen/.gitignore create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml diff --git a/ICSharpCode.Decompiler.Tests/DebugInfo/SequencePointTests.cs b/ICSharpCode.Decompiler.Tests/DebugInfo/SequencePointTests.cs deleted file mode 100644 index 1212469b9..000000000 --- a/ICSharpCode.Decompiler.Tests/DebugInfo/SequencePointTests.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using ICSharpCode.Decompiler.CSharp.OutputVisitor; -using ICSharpCode.Decompiler.Tests.Helpers; -using ICSharpCode.Decompiler.TypeSystem; -using NUnit.Framework; - -namespace ICSharpCode.Decompiler.Tests.Util -{ - [TestFixture] - public class SequencePointTests - { - [Test] - public void BasicSequencePoints() - { - TestCreateSequencePoints(@"class C { void M() { int i = 0; int j = 1; } }", - "int num = 0;", - "int num2 = 1;"); - } - - private void TestCreateSequencePoints(string code, params string[] expectedSequencePoints) - { - var decompiler = Tester.GetDecompilerForSnippet(code); - - var tree = decompiler.DecompileType(new FullTypeName("C")); - - var output = new StringWriter(); - tree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }); - TokenWriter tokenWriter = new TextWriterTokenWriter(output); - tokenWriter = new InsertMissingTokensDecorator(tokenWriter, (ILocatable)tokenWriter); - var formattingOptions = FormattingOptionsFactory.CreateSharpDevelop(); - tree.AcceptVisitor(new CSharpOutputVisitor(tokenWriter, formattingOptions)); - - var functionsWithSequencePoints = decompiler.CreateSequencePoints(tree); - var finalText = output.ToString(); - - var lines = finalText.Split(new[] { output.NewLine }, StringSplitOptions.None); - - var actualSequencePoints = new List(); - foreach (var sequencePoint in functionsWithSequencePoints.Values.First()) { - if (sequencePoint.IsHidden) { - continue; - } - - var line = lines[sequencePoint.StartLine - 1]; - var text = line.Substring(sequencePoint.StartColumn - 1, sequencePoint.EndColumn - sequencePoint.StartColumn); - actualSequencePoints.Add(text); - } - - Assert.True(Enumerable.SequenceEqual(expectedSequencePoints, actualSequencePoints)); - } - } -} diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index ace9d1ef9..4e2bf424c 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -36,7 +36,10 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Emit; +using Microsoft.CodeAnalysis.Text; using Microsoft.CSharp; +using Microsoft.DiaSymReader.Tools; using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Helpers @@ -345,23 +348,39 @@ namespace ICSharpCode.Decompiler.Tests.Helpers } } - public static CSharpDecompiler GetDecompilerForSnippet(string csharpText) + public static void CompileCSharpWithPdb(string assemblyName, Dictionary sourceFiles, PdbToXmlOptions options) { - var syntaxTree = SyntaxFactory.ParseSyntaxTree(csharpText); - var compilation = CSharpCompilation.Create( - "TestAssembly", - new[] { syntaxTree }, - defaultReferences.Value, - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); - var peStream = new MemoryStream(); - var emitResult = compilation.Emit(peStream); - peStream.Position = 0; - - var moduleDefinition = new PEFile("TestAssembly.dll", peStream, PEStreamOptions.PrefetchEntireImage); - var resolver = new UniversalAssemblyResolver("TestAssembly.dll", false, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchEntireImage); - var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings()); - - return decompiler; + var parseOptions = new CSharpParseOptions(languageVersion: Microsoft.CodeAnalysis.CSharp.LanguageVersion.Latest); + + List embeddedTexts = new List(); + List syntaxTrees = new List(); + + foreach (KeyValuePair file in sourceFiles) { + var sourceText = SourceText.From(file.Value, Encoding.UTF8); + syntaxTrees.Add(SyntaxFactory.ParseSyntaxTree(sourceText, parseOptions, file.Key)); + embeddedTexts.Add(EmbeddedText.FromSource(file.Key, sourceText)); + } + + var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(assemblyName), + syntaxTrees, defaultReferences.Value, + new CSharpCompilationOptions( + OutputKind.DynamicallyLinkedLibrary, + platform: Platform.AnyCpu, + optimizationLevel: OptimizationLevel.Debug, + allowUnsafe: true, + deterministic: true + )); + using (FileStream peStream = File.Open(assemblyName + ".dll", FileMode.OpenOrCreate, FileAccess.ReadWrite)) + using (FileStream pdbStream = File.Open(assemblyName + ".pdb", FileMode.OpenOrCreate, FileAccess.ReadWrite)) { + var emitResult = compilation.Emit(peStream, pdbStream, options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb), embeddedTexts: embeddedTexts); + if (!emitResult.Success) { + StringBuilder b = new StringBuilder("Compiler error:"); + foreach (var diag in emitResult.Diagnostics) { + b.AppendLine(diag.ToString()); + } + throw new Exception(b.ToString()); + } + } } internal static string GetSuffix(CompilerOptions cscOptions) diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 76c263b9b..679c27753 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -39,6 +39,7 @@ + @@ -125,7 +126,7 @@ - + @@ -201,6 +202,10 @@ + + + + @@ -217,4 +222,8 @@ + + + + \ No newline at end of file diff --git a/ICSharpCode.Decompiler.Tests/IL/SequenceOfNestedIfs.dll b/ICSharpCode.Decompiler.Tests/IL/SequenceOfNestedIfs.dll deleted file mode 100644 index f517d4546d31c69b00e806950d055a6af4afebda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2560 zcmeHI%}Z2K6#u<9I*giPVP*w+WfEc*4?~NJh{;jX@{2~ZLb5k+uKMbIOn2T`CPnl` zL4>Q?v}qH8v??f~MXPrG4=(xxS_fI@ym?b&LRi~6ynD|1opbKF=iCq8@YyBA0MyX< z_6>MLk|`bX-?JO!ZfbwqgjaPRJKktRA3Mh9?4l?re^!~UuuRYM1Cf(Ll{{g4qHi=S zTt6?3#>V>HQR=aNU`W%keCyt5WwjOP9SvFo5GRXXwl?tuK_g9rnIJ(vuA8YMah^al zCx-MLpgH`0$_Vl#qIXH)$HHaPTAl_rt+i|n2_R7wnIJq+g^fU72?)1v;pD6Cl~70m zIBzKF_*PUyn#|l=bz*{K?j`Y8^qKl+;@Wi7LUaI6Xbmm2{yE#F@1fcCsaCyZRZCS+ zeQSzR#kv~tJW8oA(h4<)b`sQm+JpF^T2c=@U|b|u{2HaH(HEI>#`wBWbK{}=Hy%p2 zuDXC!Z}xbv7VQS#gZUn#%joXv-g}S$?UzHmjp|Ka2X2#mPdJ$klB$>#hO>PD17<}pMMr-*j$R55^mb_E66vu{=bsm&4 zl5wO^PgiOJBcZ+Qqvi&FA+CbsD^!a@MFkEI`}vY1k085H z45VwEEO~+LN+aXD1>2D-E7iPh$s!^L+s(kv*^V7791Z9+a-~4RumWF2IWU^LAgusd zd8s5lOODQrNXnfboGHRBTE24Z9EQz6D%*767p4c@f@52D02kAiBTa>Ax8lysN$X;E z&df`NjFM!o%na`UVj}G2#L~XbGvYx1@>jLE<7M|Vwrh#kSEo*G?^(HD3r*jW(Bpb6 zz9m5(eHWk5xZXOc%)*H8^OqRA z=&cv^APAm32%=E2c+s1u{smt8M+kzK`n}z48>kedC&5SNz4yI0^X7Xqvl$wlMFcBO$j3CwL;XrDI*7utt!R9!Xc*w>xXgsPM*%l1@RD`(15RZAT^ zS5y=BxX!h-#CM0K3j@HQVdCSLk)h??7GWCAMl2v@2GMsJTE&s)5T$6C6W$`r7GnhA znh5fbfL8yvYC|ZCC}XU9CUF0(^T6gmXV#A@fE}zzjQHdV0&=SEo042GIM>2bj4QAGug>P z(N30$r&ir$GTF)MQHjKpsXCBKrB*ZP`b>7zJQ(N34r@*JHj39mFH4@>?^sC591zwl z>z{mrHknQJ%I&3l<;b@8auFg2o2ZqPyOeF%+oZPno@(<=n<*6H*}mfGK0{7`A{B1$ z&voT`x_Y_~NTd-pF-&Lf12x(wgqfn}RITf-q<%1#me@!Un@NeU5SbGrr-bVc;yr@< zYId1cgdyVu8`~t{S4R($etEwe=KSX&eTVlFGV2O$6k8GJvq)2m1iSg_}=WB>2k>M__?K1OmI*VrixfvKEHgL<=x2a9Ab f.Attribute("name").Value, f => f.Value); + Tester.CompileCSharpWithPdb(Path.Combine(TestCasePath, testName + ".expected"), files, options); + + string peFileName = Path.Combine(TestCasePath, testName + ".expected.dll"); + string pdbFileName = Path.Combine(TestCasePath, testName + ".expected.pdb"); + var moduleDefinition = new PEFile(peFileName); + var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchEntireImage); + var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings()); + using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, testName + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite)) { + PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream); + pdbStream.Position = 0; + string resultFile = PdbToXmlConverter.ToXml(pdbStream, moduleDefinition.Reader.GetEntireImage().GetContent().ToArray(), options); + Assert.AreEqual(xmlContent, resultFile); + } + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/PdbGen/.gitignore b/ICSharpCode.Decompiler.Tests/TestCases/PdbGen/.gitignore new file mode 100644 index 000000000..d35b79a63 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/PdbGen/.gitignore @@ -0,0 +1,2 @@ +/*.dll +/*.pdb diff --git a/ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml b/ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml new file mode 100644 index 000000000..bb58f04fa --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs index 2eee6fd26..2b07a86de 100644 --- a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs +++ b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs @@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.DebugInfo var type = reader.GetTypeDefinition(handle); // Generate syntax tree, source and checksum - var name = metadata.GetOrAddDocumentName("ILSpy_Generated_" + type.GetFullTypeName(reader) + "_" + Guid.NewGuid() + ".cs"); + var name = metadata.GetOrAddDocumentName(type.GetFullTypeName(reader).ReflectionName.Replace('.', Path.DirectorySeparatorChar) + ".cs"); var syntaxTree = decompiler.DecompileTypes(new[] { handle }); syntaxTree.InsertChildAfter(null, new Comment(" PDB and source generated by ICSharpCode.Decompiler " + decompilerVersion.FileVersion), Roles.Comment); var sourceText = SyntaxTreeToString(syntaxTree, settings); diff --git a/NuGet.config b/NuGet.config index a2c1835ee..22c4b3475 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,5 +3,6 @@ + \ No newline at end of file