├── .gitattributes ├── .gitignore ├── Assets └── EmitDebugging.ruleset ├── EmitDebugging.Tests ├── AssemblyCreationTests.cs ├── AssemblyDebuggingTests.cs ├── CodeDocumentTests.cs ├── CodeLineTests.cs ├── DebuggingTests.cs ├── DebuggingWithBoxingCallTests.cs ├── DebuggingWithBreakingToLabelTests.cs ├── DebuggingWithCallToMethodTests.cs ├── DebuggingWithFilteredExceptionHandlerTests.cs ├── DebuggingWithMethodThatCallsVarArgsMethodTests.cs ├── DebuggingWithMethodThatCreatesSwitchTests.cs ├── DebuggingWithMethodThatDeclaresLocalsAfterEmittingOpcodes.cs ├── DebuggingWithMethodThatDeclaresLocalsBeforeEmittingAnyOpcodes.cs ├── DebuggingWithMethodThatStoresIntegersTests.cs ├── DebuggingWithMethodThatStoresSinglesAndDoublesTests.cs ├── DebuggingWithMethodThatThrowsExceptionTests.cs ├── DebuggingWithMethodThatUsesManagedCalliTests.cs ├── DebuggingWithMethodThatUsesSignatureHelperTests.cs ├── DebuggingWithMethodThatUsesUnmanagedCalliTests.cs ├── DebuggingWithMethodThatWritesLotsOfLocalsToTheConsoleTests.cs ├── DebuggingWithMethodThatWritesToTheConsole.cs ├── DebuggingWithOneScopeTests.cs ├── DebuggingWithOneTypeTests.cs ├── DebuggingWithTryCatchFaultTests.cs ├── DebuggingWithTryCatchFinallyTests.cs ├── DebuggingWithTwoTypesTests.cs ├── DebuggingWithTypeThatImplementsInterfacesTests.cs ├── DebuggingWithTypeThatImplementsInterfacesWithNullReferenceTests.cs ├── DebuggingWithUsingNamespaceTests.cs ├── EmitDebugging.Tests.csproj ├── Extensions │ ├── MethodBaseExtensionsGetAttributesTests.cs │ ├── MethodBaseExtensionsGetCallingConventionsTests.cs │ ├── MethodBaseExtensionsGetGenericParameterDeclarationNamesTests.cs │ ├── TypeBuilderExtensions.cs │ └── TypeExtensionsTests.cs ├── FieldInfoDescriptorTests.cs ├── ManagedCalliDescriptorTests.cs ├── MethodBaseDebuggingTests.cs ├── MethodDescriptorFactoryTests.cs ├── MethodDescriptorTests.cs ├── Properties │ └── AssemblyInfo.cs ├── TypeDebuggingTests.cs ├── TypeDescriptorTests.cs ├── TypeDescriptorTypeBuilderTests.cs ├── Types │ ├── SimpleDerivedGenericType.cs │ ├── SimpleGenericType.cs │ ├── SimpleGenericValueType.cs │ ├── SimpleReferenceType.cs │ ├── SimpleValueType.cs │ └── VarArgMethod.cs ├── UnmanagedCalliDescriptorTests.cs └── packages.config ├── EmitDebugging.sln ├── EmitDebugging ├── AssemblyDebugging.cs ├── CalliDescriptor.cs ├── CodeDocument.cs ├── CodeLine.cs ├── ConstructorMethodDebugging.cs ├── Debugging.cs ├── Descriptor.cs ├── EmitDebugging.csproj ├── Extensions │ ├── MemberInfoExtensions.cs │ ├── MethodBaseExtensions.cs │ └── TypeExtensions.cs ├── FieldInfoDescriptor.cs ├── GlobalSuppressions.cs ├── Indention.cs ├── ManagedCalliDescriptor.cs ├── MethodBaseDebugging.cs ├── MethodDebugging.cs ├── MethodDescriptor.cs ├── MethodDescriptorFactory.cs ├── MethodGenericDeclarationDescriptor.cs ├── MethodGenericDescriptor.cs ├── MethodGenericInvocationDescriptor.cs ├── Properties │ └── AssemblyInfo.cs ├── TypeDebugging.cs ├── TypeDescriptor.cs ├── UnmanagedCalliDescriptor.cs └── packages.config ├── LICENSE.md ├── Method and Type Descriptors.docx ├── Nuget └── 2.0.0.0 │ └── EmitDebugging.nuspec ├── README.md ├── corapi.dll ├── pdb2xml.dll └── raw.dll /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # This is for Roslyn, hopefully eventually this will go away. 45 | 46 | *.sln.ide/ 47 | 48 | # Build results 49 | 50 | [Dd]ebug/ 51 | [Rr]elease/ 52 | x64/ 53 | build/ 54 | [Bb]in/ 55 | [Oo]bj/ 56 | 57 | # MSTest test Results 58 | [Tt]est[Rr]esult*/ 59 | [Bb]uild[Ll]og.* 60 | 61 | *_i.c 62 | *_p.c 63 | *.ilk 64 | *.meta 65 | *.obj 66 | *.pch 67 | *.pdb 68 | *.pgc 69 | *.pgd 70 | *.rsp 71 | *.sbr 72 | *.tlb 73 | *.tli 74 | *.tlh 75 | *.tmp 76 | *.tmp_proj 77 | *.log 78 | *.vspscc 79 | *.vssscc 80 | .builds 81 | *.pidb 82 | *.log 83 | *.scc 84 | *.dll 85 | !corapi.dll 86 | !pdb2xml.dll 87 | !raw.dll 88 | *.exe 89 | *.nupkg 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opensdf 96 | *.sdf 97 | *.cachefile 98 | 99 | # Visual Studio profiler 100 | *.psess 101 | *.vsp 102 | *.vspx 103 | 104 | # Guidance Automation Toolkit 105 | *.gpState 106 | 107 | # ReSharper is a .NET coding add-in 108 | _ReSharper*/ 109 | *.[Rr]e[Ss]harper 110 | 111 | # TeamCity is a build add-in 112 | _TeamCity* 113 | 114 | # DotCover is a Code Coverage Tool 115 | *.dotCover 116 | 117 | # NCrunch 118 | *.ncrunch* 119 | .*crunch*.local.xml 120 | 121 | # Installshield output folder 122 | [Ee]xpress/ 123 | 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.Publish.xml 139 | *.pubxml 140 | 141 | # NuGet Packages Directory 142 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 143 | packages/ 144 | 145 | # Windows Azure Build Output 146 | csx 147 | *.build.csdef 148 | 149 | # Windows Store app package directory 150 | AppPackages/ 151 | 152 | # Others 153 | sql/ 154 | *.Cache 155 | ClientBin/ 156 | [Ss]tyle[Cc]op.* 157 | ~$* 158 | *~ 159 | *.dbmdl 160 | *.[Pp]ublish.xml 161 | *.pfx 162 | *.publishsettings 163 | 164 | # RIA/Silverlight projects 165 | Generated_Code/ 166 | 167 | # Backup & report files from converting an old project file to a newer 168 | # Visual Studio version. Backup files are not needed, because we have git ;-) 169 | _UpgradeReport_Files/ 170 | Backup*/ 171 | UpgradeLog*.XML 172 | UpgradeLog*.htm 173 | 174 | # SQL Server files 175 | App_Data/*.mdf 176 | App_Data/*.ldf 177 | 178 | ############# 179 | ## Windows detritus 180 | ############# 181 | 182 | # Windows image file caches 183 | Thumbs.db 184 | ehthumbs.db 185 | 186 | # Folder config file 187 | Desktop.ini 188 | 189 | # Recycle Bin used on file shares 190 | $RECYCLE.BIN/ 191 | 192 | # Mac crap 193 | .DS_Store 194 | 195 | 196 | ############# 197 | ## Python 198 | ############# 199 | 200 | *.py[co] 201 | 202 | # Packages 203 | *.egg 204 | *.egg-info 205 | dist/ 206 | build/ 207 | eggs/ 208 | parts/ 209 | var/ 210 | sdist/ 211 | develop-eggs/ 212 | .installed.cfg 213 | 214 | # Installer logs 215 | pip-log.txt 216 | 217 | # Unit test / coverage reports 218 | .coverage 219 | .tox 220 | 221 | #Translations 222 | *.mo 223 | 224 | #Mr Developer 225 | .mr.developer.cfg 226 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/AssemblyCreationTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Diagnostics.CodeAnalysis; 5 | using System.Diagnostics.SymbolStore; 6 | using System.Reflection; 7 | using System.Reflection.Emit; 8 | 9 | namespace EmitDebugging.Tests 10 | { 11 | public abstract class AssemblyCreationTests 12 | { 13 | private static void AddDebuggingAttribute(AssemblyBuilder assembly) 14 | { 15 | var debugAttribute = typeof(DebuggableAttribute); 16 | var debugConstructor = debugAttribute.GetConstructor( 17 | new Type[] { typeof(DebuggableAttribute.DebuggingModes) }); 18 | var debugBuilder = new CustomAttributeBuilder( 19 | debugConstructor, new object[] { 20 | DebuggableAttribute.DebuggingModes.DisableOptimizations | 21 | DebuggableAttribute.DebuggingModes.Default }); 22 | assembly.SetCustomAttribute(debugBuilder); 23 | } 24 | 25 | protected static AssemblyDebugging CreateDebuggingAssembly(string name) 26 | { 27 | var assemblyName = new AssemblyName(); 28 | assemblyName.Name = name; 29 | var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly( 30 | assemblyName, AssemblyBuilderAccess.Save); 31 | DebuggingTests.AddDebuggingAttribute(assembly); 32 | 33 | var module = assembly.DefineDynamicModule(assemblyName.Name, 34 | assemblyName.Name + ".dll", true); 35 | 36 | var symbolWriter = module.DefineDocument( 37 | assemblyName.Name + ".il", SymDocumentType.Text, 38 | SymLanguageType.ILAssembly, SymLanguageVendor.Microsoft); 39 | 40 | return new AssemblyDebugging(assemblyName.Name + ".il", assembly, symbolWriter); 41 | } 42 | 43 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 44 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1")] 45 | protected static TypeDebugging CreateDebuggingType( 46 | AssemblyDebugging assembly, ModuleBuilder module, string name) 47 | { 48 | return assembly.GetTypeDebugging(module.DefineType( 49 | assembly.Builder.GetName().Name + "." + name, 50 | TypeAttributes.Class | TypeAttributes.Sealed | 51 | TypeAttributes.Public, typeof(object))); 52 | } 53 | 54 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 55 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1")] 56 | protected static TypeDebugging CreateDebuggingType( 57 | AssemblyDebugging assembly, ModuleBuilder module, string name, HashSet interfacesToImplement) 58 | { 59 | return assembly.GetTypeDebugging(module.DefineType( 60 | assembly.Builder.GetName().Name + "." + name, 61 | TypeAttributes.Class | TypeAttributes.Sealed | 62 | TypeAttributes.Public, typeof(object)), interfacesToImplement); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/AssemblyDebuggingTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using Xunit; 4 | 5 | namespace EmitDebugging.Tests 6 | { 7 | public sealed class AssemblyDebuggingTests 8 | : AssemblyCreationTests 9 | { 10 | [Fact] 11 | [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] 12 | public static void CreateWithNullArgument() 13 | { 14 | Assert.Throws(() => new AssemblyDebugging(null, null, null)); 15 | } 16 | 17 | [Fact] 18 | [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] 19 | public static void CallDisposeAfterDisposing() 20 | { 21 | AssemblyDebugging assembly = null; 22 | 23 | using (assembly = AssemblyCreationTests.CreateDebuggingAssembly("Me")) { } 24 | 25 | assembly.Dispose(); 26 | } 27 | 28 | [Fact] 29 | public static void CallEqualsAfterDisposing() 30 | { 31 | AssemblyDebugging assembly = null; 32 | 33 | using (assembly = AssemblyCreationTests.CreateDebuggingAssembly("Me")) { } 34 | 35 | Assert.Throws(() => assembly.GetTypeDebugging(null)); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/CodeDocumentTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Diagnostics.SymbolStore; 5 | using System.Reflection.Emit; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public static class CodeDocumentTests 11 | { 12 | [Fact] 13 | [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] 14 | public static void CallDisposeAfterDisposing() 15 | { 16 | CodeDocument document = null; 17 | 18 | using (document = new CodeDocument(0, 0)) { } 19 | 20 | document.Dispose(); 21 | } 22 | 23 | [Fact] 24 | public static void CallWriteTextWithCodeLineAfterDisposing() 25 | { 26 | CodeDocument document = null; 27 | 28 | using (document = new CodeDocument(0, 0)) { } 29 | 30 | Assert.Throws(() => document.WriteText(null as CodeLine)); 31 | } 32 | 33 | [Fact] 34 | public static void CallWriteTextWithListOfCodeLineILGeneratorISymbolDocumentWriterAfterDisposing() 35 | { 36 | CodeDocument document = null; 37 | 38 | using (document = new CodeDocument(0, 0)) { } 39 | 40 | Assert.Throws(() => document.WriteText(null as List, 41 | null as ILGenerator, null as ISymbolDocumentWriter)); 42 | } 43 | 44 | [Fact] 45 | public static void CallWriteTextWithIEnumerableOfCodeLineILGeneratorISymbolDocumentWriterAfterDisposing() 46 | { 47 | CodeDocument document = null; 48 | 49 | using (document = new CodeDocument(0, 0)) { } 50 | 51 | Assert.Throws(() => document.WriteText(null as IEnumerable, 52 | null as ILGenerator, null as ISymbolDocumentWriter)); 53 | } 54 | 55 | [Fact] 56 | public static void CallWriteTextWithCodeLineILGeneratorISymbolDocumentWriterAfterDisposing() 57 | { 58 | CodeDocument document = null; 59 | 60 | using (document = new CodeDocument(0, 0)) { } 61 | 62 | Assert.Throws(() => document.WriteText(null as CodeLine, 63 | null as ILGenerator, null as ISymbolDocumentWriter)); 64 | } 65 | 66 | [Fact] 67 | public static void WriteMultipleLinesWithDifferentDebuggableStates() 68 | { 69 | using (var document = new CodeDocument(0, 0)) 70 | { 71 | document.WriteText(new List() 72 | { 73 | new CodeLine("x", true), 74 | new CodeLine("x", false), 75 | new CodeLine("x", true) 76 | }, null, null); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/CodeLineTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection.Emit; 3 | using Xunit; 4 | 5 | namespace EmitDebugging.Tests 6 | { 7 | public static class CodeLineTests 8 | { 9 | [Fact] 10 | public static void CreateCodeLineViaCode() 11 | { 12 | var line = new CodeLine("code"); 13 | Assert.Equal("code", line.Code); 14 | Assert.Equal(Indention.KeepCurrent, line.Indent); 15 | Assert.False(line.IsDebuggable); 16 | Assert.Equal(0, line.Labels.Length); 17 | } 18 | 19 | [Fact] 20 | public static void CreateCodeLineViaCodeAndIndention() 21 | { 22 | var line = new CodeLine("code", Indention.Increase); 23 | Assert.Equal("code", line.Code); 24 | Assert.Equal(Indention.Increase, line.Indent); 25 | Assert.False(line.IsDebuggable); 26 | Assert.Equal(0, line.Labels.Length); 27 | } 28 | 29 | [Fact] 30 | public static void CreateCodeLineViaCodeAndIsDebuggable() 31 | { 32 | var line = new CodeLine("code", true); 33 | Assert.Equal("code", line.Code); 34 | Assert.Equal(Indention.KeepCurrent, line.Indent); 35 | Assert.True(line.IsDebuggable); 36 | Assert.Equal(0, line.Labels.Length); 37 | } 38 | 39 | [Fact] 40 | public static void CreateCodeLineViaCodeAndIndentionAndIsDebuggable() 41 | { 42 | var line = new CodeLine("code", Indention.Decrease, true); 43 | Assert.Equal("code", line.Code); 44 | Assert.Equal(Indention.Decrease, line.Indent); 45 | Assert.True(line.IsDebuggable); 46 | Assert.Equal(0, line.Labels.Length); 47 | } 48 | 49 | [Fact] 50 | public static void CreateCodeLineViaCodeAndIndentionAndLabels() 51 | { 52 | var line = new CodeLine("code", Indention.Increase, new Label()); 53 | Assert.Equal("code", line.Code); 54 | Assert.Equal(Indention.Increase, line.Indent); 55 | Assert.False(line.IsDebuggable); 56 | Assert.Equal(1, line.Labels.Length); 57 | } 58 | 59 | [Fact] 60 | public static void CreateCodeLineViaCodeAndSetCode() 61 | { 62 | var line = new CodeLine("code"); 63 | line.Code = "new code"; 64 | Assert.Equal("new code", line.Code); 65 | } 66 | 67 | [Fact] 68 | public static void CreateCodeLineViaCodeAndSetCodeNull() 69 | { 70 | var line = new CodeLine("code"); 71 | Assert.Throws(() => line.Code = null); 72 | } 73 | 74 | [Fact] 75 | public static void CreateCodeLineViaCodeAsNull() 76 | { 77 | Assert.Throws(() => new CodeLine(null)); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Xml.XPath; 3 | using AssemblyVerifier; 4 | using Xunit; 5 | 6 | namespace EmitDebugging.Tests 7 | { 8 | public abstract class DebuggingTests 9 | : AssemblyCreationTests 10 | { 11 | private static void AssertFileContents(string[] expectedLines, string[] actualLines) 12 | { 13 | Assert.Equal(expectedLines.Length, actualLines.Length); 14 | 15 | for (var i = 0; i < expectedLines.Length; i++) 16 | { 17 | Assert.Equal(expectedLines[i], actualLines[i]); 18 | } 19 | } 20 | 21 | protected abstract void AssertSequencePoints(XPathNavigator navigator); 22 | 23 | protected abstract AssemblyDebugging CreateAssembly(); 24 | 25 | protected string CreateAssemblyAndVerify(bool verifyAssembly) 26 | { 27 | var assembly = this.CreateAssembly(); 28 | var assemblyName = assembly.Builder.GetName().Name; 29 | 30 | assembly.Builder.Save(assemblyName + ".dll"); 31 | 32 | if (verifyAssembly) 33 | { 34 | AssemblyVerification.Verify(assembly.Builder); 35 | } 36 | 37 | return assemblyName; 38 | } 39 | 40 | protected abstract string[] GetExpectedFileLines(); 41 | 42 | protected void RunTest() 43 | { 44 | this.RunTest(true); 45 | } 46 | 47 | protected void RunTest(bool verifyAssembly) 48 | { 49 | var assemblyName = this.CreateAssemblyAndVerify(verifyAssembly); 50 | 51 | DebuggingTests.AssertFileContents(this.GetExpectedFileLines(), 52 | File.ReadAllLines(assemblyName + ".il")); 53 | 54 | XmlPdbReader.Program.PdbToXML(assemblyName + ".pdb", assemblyName + ".xml"); 55 | 56 | this.AssertSequencePoints(new XPathDocument(assemblyName + ".xml").CreateNavigator()); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithBoxingCallTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithBoxingCallTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodWithBoxingCall.SimpleClass.ReturnBoxedInt\"]/sequencepoints/entry"); 18 | Assert.Equal(3, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x6") 33 | { 34 | Assert.Equal("18", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("18", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodWithBoxingCall")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("ReturnBoxedInt", 67 | MethodAttributes.HideBySig | MethodAttributes.Public, 68 | typeof(object), new Type[] { typeof(int) }))) 69 | { 70 | method.Emit(OpCodes.Ldarg_1); 71 | method.Emit(OpCodes.Box, typeof(int)); 72 | method.Emit(OpCodes.Ret); 73 | } 74 | 75 | type.Builder.CreateType(); 76 | } 77 | 78 | return assembly; 79 | } 80 | } 81 | 82 | [Fact] 83 | public void CreateAssemblyAndAssert() 84 | { 85 | this.RunTest(); 86 | } 87 | 88 | protected override string[] GetExpectedFileLines() 89 | { 90 | return new string[] 91 | { 92 | ".assembly MethodWithBoxingCall", 93 | "{", 94 | " .class public sealed ansi MethodWithBoxingCall.SimpleClass extends object", 95 | " {", 96 | " .method public hidebysig specialname instance void .ctor() cil managed", 97 | " {", 98 | " .locals init ()", 99 | " IL_0000: ldarg.0", 100 | " IL_0001: call instance void object::.ctor()", 101 | " IL_0006: ret", 102 | " }", 103 | " ", 104 | " .method public hidebysig instance object ReturnBoxedInt() cil managed", 105 | " {", 106 | " .locals init ()", 107 | " IL_0000: ldarg.1", 108 | " IL_0001: box int32", 109 | " IL_0006: ret", 110 | " }", 111 | " }", 112 | "}" 113 | }; 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithBreakingToLabelTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithBreakingToLabelTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodWithBreakingToLabel.SimpleClass.BreakToLabel\"]/sequencepoints/entry"); 18 | Assert.Equal(6, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x7") 33 | { 34 | Assert.Equal("21", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("21", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodWithBreakingToLabel")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("BreakToLabel", 67 | MethodAttributes.HideBySig | MethodAttributes.Public, 68 | typeof(int), new Type[] { typeof(bool) }))) 69 | { 70 | var trueValue = method.DefineLabel(); 71 | var end = method.DefineLabel(); 72 | method.Emit(OpCodes.Ldarg_1); 73 | method.Emit(OpCodes.Brtrue_S, trueValue); 74 | method.Emit(OpCodes.Ldc_I4_0); 75 | method.Emit(OpCodes.Br_S, end); 76 | method.MarkLabel(trueValue); 77 | method.Emit(OpCodes.Ldc_I4_1); 78 | method.MarkLabel(end); 79 | method.Emit(OpCodes.Ret); 80 | } 81 | 82 | type.Builder.CreateType(); 83 | } 84 | 85 | return assembly; 86 | } 87 | } 88 | 89 | [Fact] 90 | public void CreateAssemblyAndAssert() 91 | { 92 | this.RunTest(); 93 | } 94 | 95 | protected override string[] GetExpectedFileLines() 96 | { 97 | return new string[] 98 | { 99 | ".assembly MethodWithBreakingToLabel", 100 | "{", 101 | " .class public sealed ansi MethodWithBreakingToLabel.SimpleClass extends object", 102 | " {", 103 | " .method public hidebysig specialname instance void .ctor() cil managed", 104 | " {", 105 | " .locals init ()", 106 | " IL_0000: ldarg.0", 107 | " IL_0001: call instance void object::.ctor()", 108 | " IL_0006: ret", 109 | " }", 110 | " ", 111 | " .method public hidebysig instance int32 BreakToLabel() cil managed", 112 | " {", 113 | " .locals init ()", 114 | " IL_0000: ldarg.1", 115 | " IL_0001: brtrue.s IL_0006", 116 | " IL_0003: ldc.i4.0", 117 | " IL_0004: br.s IL_0007", 118 | " IL_0006: ldc.i4.1", 119 | " IL_0007: ret", 120 | " }", 121 | " }", 122 | "}" 123 | }; 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithCallToMethodTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithCallToMethodTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodWithMethodCall.SimpleClass.CallAMethod\"]/sequencepoints/entry"); 18 | Assert.Equal(3, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("63", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x6") 33 | { 34 | Assert.Equal("18", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("18", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodWithMethodCall")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("CallAMethod", 67 | MethodAttributes.HideBySig | MethodAttributes.Public))) 68 | { 69 | method.Emit(OpCodes.Call, typeof(Guid).GetMethod("NewGuid")); 70 | method.Emit(OpCodes.Pop); 71 | method.Emit(OpCodes.Ret); 72 | } 73 | 74 | type.Builder.CreateType(); 75 | } 76 | 77 | return assembly; 78 | } 79 | } 80 | 81 | [Fact] 82 | public void CreateAssemblyAndAssert() 83 | { 84 | this.RunTest(); 85 | } 86 | 87 | protected override string[] GetExpectedFileLines() 88 | { 89 | return new string[] 90 | { 91 | ".assembly MethodWithMethodCall", 92 | "{", 93 | " .class public sealed ansi MethodWithMethodCall.SimpleClass extends object", 94 | " {", 95 | " .method public hidebysig specialname instance void .ctor() cil managed", 96 | " {", 97 | " .locals init ()", 98 | " IL_0000: ldarg.0", 99 | " IL_0001: call instance void object::.ctor()", 100 | " IL_0006: ret", 101 | " }", 102 | " ", 103 | " .method public hidebysig instance void CallAMethod() cil managed", 104 | " {", 105 | " .locals init ()", 106 | " IL_0000: call valuetype System.Guid System.Guid::NewGuid()", 107 | " IL_0005: pop", 108 | " IL_0006: ret", 109 | " }", 110 | " }", 111 | "}" 112 | }; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithFilteredExceptionHandlerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithFilteredExceptionHandlerTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodWithFilteredExceptionHandler.SimpleClass.DivideWithFilter\"]/sequencepoints/entry"); 18 | Assert.Equal(14, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("18", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("18", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("5", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("22", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x1e") 33 | { 34 | Assert.Equal("38", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("38", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodWithFilteredExceptionHandler")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("DivideWithFilter", 67 | MethodAttributes.HideBySig | MethodAttributes.Public, 68 | typeof(int), new Type[] { typeof(int), typeof(int) }))) 69 | { 70 | method.DeclareLocal(typeof(int)); 71 | method.BeginExceptionBlock(); 72 | method.Emit(OpCodes.Ldarg_1); 73 | method.Emit(OpCodes.Ldarg_2); 74 | method.Emit(OpCodes.Div); 75 | method.Emit(OpCodes.Stloc_0); 76 | method.BeginExceptFilterBlock(); 77 | method.Emit(OpCodes.Pop); 78 | method.Emit(OpCodes.Ldarg_1); 79 | method.Emit(OpCodes.Ldc_I4_2); 80 | method.Emit(OpCodes.Rem); 81 | method.Emit(OpCodes.Ldc_I4_0); 82 | method.Emit(OpCodes.Ceq); 83 | method.BeginCatchBlock(null); 84 | method.Emit(OpCodes.Ldc_I4_S, 22); 85 | method.Emit(OpCodes.Stloc_0); 86 | method.EndExceptionBlock(); 87 | method.Emit(OpCodes.Ldloc_0); 88 | method.Emit(OpCodes.Ret); 89 | } 90 | 91 | type.Builder.CreateType(); 92 | } 93 | 94 | return assembly; 95 | } 96 | } 97 | 98 | [Fact] 99 | public void CreateAssemblyAndAssert() 100 | { 101 | this.RunTest(); 102 | } 103 | 104 | protected override string[] GetExpectedFileLines() 105 | { 106 | return new string[] 107 | { 108 | ".assembly MethodWithFilteredExceptionHandler", 109 | "{", 110 | " .class public sealed ansi MethodWithFilteredExceptionHandler.SimpleClass extends object", 111 | " {", 112 | " .method public hidebysig specialname instance void .ctor() cil managed", 113 | " {", 114 | " .locals init ()", 115 | " IL_0000: ldarg.0", 116 | " IL_0001: call instance void object::.ctor()", 117 | " IL_0006: ret", 118 | " }", 119 | " ", 120 | " .method public hidebysig instance int32 DivideWithFilter() cil managed", 121 | " {", 122 | " .locals init ([0] int32 V_0)", 123 | " .try", 124 | " {", 125 | " IL_0000: ldarg.1", 126 | " IL_0001: ldarg.2", 127 | " IL_0002: div", 128 | " IL_0003: stloc.0", 129 | " }", 130 | " filter", 131 | " {", 132 | " IL_0004: pop", 133 | " IL_0005: ldarg.1", 134 | " IL_0006: ldc.i4.2", 135 | " IL_0007: rem", 136 | " IL_0008: ldc.i4.0", 137 | " IL_0009: ceq", 138 | " }", 139 | " catch", 140 | " {", 141 | " IL_000B: ldc.i4.s 22", 142 | " IL_0010: stloc.0", 143 | " }", 144 | " IL_0011: ldloc.0", 145 | " IL_0012: ret", 146 | " }", 147 | " }", 148 | "}", 149 | }; 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatCallsVarArgsMethodTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithMethodThatCallsVarArgsMethodTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodThatCallsVarArgsMethod.SimpleClass.CallVarArgsMethod\"]/sequencepoints/entry"); 18 | Assert.Equal(6, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("22", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("22", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x11") 33 | { 34 | Assert.Equal("27", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("27", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodThatCallsVarArgsMethod")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | MethodInfo varMethod = null; 66 | 67 | using (var varArgsMethod = type.GetMethodDebugging( 68 | type.Builder.DefineMethod("VarArgsMethod", 69 | MethodAttributes.HideBySig | MethodAttributes.Public, 70 | CallingConventions.VarArgs, 71 | null, new Type[] { typeof(string) }))) 72 | { 73 | varArgsMethod.Emit(OpCodes.Ret); 74 | varMethod = varArgsMethod.Builder as MethodInfo; 75 | } 76 | 77 | using (var method = type.GetMethodDebugging( 78 | type.Builder.DefineMethod("CallVarArgsMethod", 79 | MethodAttributes.HideBySig | MethodAttributes.Public))) 80 | { 81 | method.Emit(OpCodes.Ldarg_0); 82 | method.Emit(OpCodes.Ldstr, "Param"); 83 | method.Emit(OpCodes.Ldstr, "VarArgParam"); 84 | method.Emit(OpCodes.Ldc_I4_1); 85 | method.EmitCall(OpCodes.Call, varMethod, 86 | new Type[] { typeof(string), typeof(int) }); 87 | method.Emit(OpCodes.Ret); 88 | } 89 | 90 | type.Builder.CreateType(); 91 | } 92 | 93 | return assembly; 94 | } 95 | } 96 | 97 | [Fact] 98 | public void CreateAssemblyAndAssert() 99 | { 100 | this.RunTest(); 101 | } 102 | 103 | protected override string[] GetExpectedFileLines() 104 | { 105 | return new string[] 106 | { 107 | ".assembly MethodThatCallsVarArgsMethod", 108 | "{", 109 | " .class public sealed ansi MethodThatCallsVarArgsMethod.SimpleClass extends object", 110 | " {", 111 | " .method public hidebysig specialname instance void .ctor() cil managed", 112 | " {", 113 | " .locals init ()", 114 | " IL_0000: ldarg.0", 115 | " IL_0001: call instance void object::.ctor()", 116 | " IL_0006: ret", 117 | " }", 118 | " ", 119 | " .method public hidebysig instance vararg void VarArgsMethod() cil managed", 120 | " {", 121 | " .locals init ()", 122 | " IL_0000: ret", 123 | " }", 124 | " ", 125 | " .method public hidebysig instance void CallVarArgsMethod() cil managed", 126 | " {", 127 | " .locals init ()", 128 | " IL_0000: ldarg.0", 129 | " IL_0001: ldstr \"Param\"", 130 | " IL_0007: ldstr \"VarArgParam\"", 131 | " IL_0013: ldc.i4.1", 132 | " IL_0014: call instance vararg void MethodThatCallsVarArgsMethod.SimpleClass::VarArgsMethod()", 133 | " IL_0019: ret", 134 | " }", 135 | " }", 136 | "}" 137 | }; 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatCreatesSwitchTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithMethodThatCreatesSwitchTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodThatCreatesSwitch.SimpleClass.GenerateSwitch\"]/sequencepoints/entry"); 18 | Assert.Equal(8, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x23") 33 | { 34 | Assert.Equal("24", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("24", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodThatCreatesSwitch")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("GenerateSwitch", 67 | MethodAttributes.HideBySig | MethodAttributes.Public, 68 | typeof(string), new Type[] { typeof(int) }))) 69 | { 70 | var defaultCase = method.DefineLabel(); 71 | var endOfMethod = method.DefineLabel(); 72 | 73 | method.Emit(OpCodes.Ldarg_1); 74 | var jumpTable = new Label[] { method.DefineLabel(), method.DefineLabel() }; 75 | method.Emit(OpCodes.Switch, jumpTable); 76 | 77 | method.Emit(OpCodes.Br_S, defaultCase); 78 | 79 | method.MarkLabel(jumpTable[0]); 80 | method.Emit(OpCodes.Ldstr, "It's zero."); 81 | method.Emit(OpCodes.Br_S, endOfMethod); 82 | 83 | method.MarkLabel(jumpTable[1]); 84 | method.Emit(OpCodes.Ldstr, "It's one."); 85 | method.Emit(OpCodes.Br_S, endOfMethod); 86 | 87 | method.MarkLabel(defaultCase); 88 | method.Emit(OpCodes.Ldstr, "It's something else."); 89 | 90 | method.MarkLabel(endOfMethod); 91 | method.Emit(OpCodes.Ret); 92 | } 93 | 94 | type.Builder.CreateType(); 95 | } 96 | 97 | return assembly; 98 | } 99 | } 100 | 101 | [Fact] 102 | public void CreateAssemblyAndAssert() 103 | { 104 | this.RunTest(false); 105 | } 106 | 107 | protected override string[] GetExpectedFileLines() 108 | { 109 | return new string[] 110 | { 111 | ".assembly MethodThatCreatesSwitch", 112 | "{", 113 | " .class public sealed ansi MethodThatCreatesSwitch.SimpleClass extends object", 114 | " {", 115 | " .method public hidebysig specialname instance void .ctor() cil managed", 116 | " {", 117 | " .locals init ()", 118 | " IL_0000: ldarg.0", 119 | " IL_0001: call instance void object::.ctor()", 120 | " IL_0006: ret", 121 | " }", 122 | " ", 123 | " .method public hidebysig instance string GenerateSwitch() cil managed", 124 | " {", 125 | " .locals init ()", 126 | " IL_0000: ldarg.1", 127 | " IL_0001: switch (IL_0005, IL_0012)", 128 | " IL_0003: br.s IL_001E", 129 | " IL_0005: ldstr \"It's zero.\"", 130 | " IL_0010: br.s IL_0033", 131 | " IL_0012: ldstr \"It's one.\"", 132 | " IL_001C: br.s IL_0033", 133 | " IL_001E: ldstr \"It's something else.\"", 134 | " IL_0033: ret", 135 | " }", 136 | " }", 137 | "}" 138 | }; 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatDeclaresLocalsAfterEmittingOpcodes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Opcodes")] 11 | public sealed class DebuggingWithMethodThatDeclaresLocalsAfterEmittingOpcodes 12 | : DebuggingTests 13 | { 14 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 15 | protected override void AssertSequencePoints(XPathNavigator navigator) 16 | { 17 | var entries = navigator.Select( 18 | "./symbols/methods/method[@name=\"MethodThatDeclaresLocalsAfterEmittingOpcodes.SimpleClass.ReflectArgument\"]/sequencepoints/entry"); 19 | Assert.Equal(6, entries.Count); 20 | 21 | int visitedCount = 0; 22 | 23 | foreach (XPathNavigator entry in entries) 24 | { 25 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 26 | { 27 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 28 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 29 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 30 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 31 | visitedCount++; 32 | } 33 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x5") 34 | { 35 | Assert.Equal("21", entry.GetAttribute("start_row", string.Empty)); 36 | Assert.Equal("21", entry.GetAttribute("end_row", string.Empty)); 37 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 38 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 39 | visitedCount++; 40 | } 41 | } 42 | 43 | Assert.Equal(2, visitedCount); 44 | } 45 | 46 | protected override AssemblyDebugging CreateAssembly() 47 | { 48 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodThatDeclaresLocalsAfterEmittingOpcodes")) 49 | { 50 | using (var type = DebuggingTests.CreateDebuggingType( 51 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 52 | "SimpleClass")) 53 | { 54 | using (var ctor = type.GetMethodDebugging( 55 | type.Builder.DefineConstructor( 56 | MethodAttributes.Public | MethodAttributes.SpecialName | 57 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 58 | CallingConventions.Standard, Type.EmptyTypes))) 59 | { 60 | ctor.Emit(OpCodes.Ldarg_0); 61 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 62 | ctor.Emit(OpCodes.Call, objectCtor); 63 | ctor.Emit(OpCodes.Ret); 64 | } 65 | 66 | using (var method = type.GetMethodDebugging( 67 | type.Builder.DefineMethod("ReflectArgument", 68 | MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.Public, 69 | typeof(int), new Type[] { typeof(int) }))) 70 | { 71 | method.DeclareLocal(typeof(int)); 72 | method.Emit(OpCodes.Ldarg_0); 73 | method.Emit(OpCodes.Stloc_0); 74 | method.DeclareLocal(typeof(int)); 75 | method.Emit(OpCodes.Ldloc_0); 76 | method.Emit(OpCodes.Stloc_1); 77 | method.Emit(OpCodes.Ldloc_1); 78 | method.Emit(OpCodes.Ret); 79 | } 80 | 81 | type.Builder.CreateType(); 82 | } 83 | 84 | return assembly; 85 | } 86 | } 87 | 88 | [Fact] 89 | public void CreateAssemblyAndAssert() 90 | { 91 | this.RunTest(); 92 | } 93 | 94 | protected override string[] GetExpectedFileLines() 95 | { 96 | return new string[] 97 | { 98 | ".assembly MethodThatDeclaresLocalsAfterEmittingOpcodes", 99 | "{", 100 | " .class public sealed ansi MethodThatDeclaresLocalsAfterEmittingOpcodes.SimpleClass extends object", 101 | " {", 102 | " .method public hidebysig specialname instance void .ctor() cil managed", 103 | " {", 104 | " .locals init ()", 105 | " IL_0000: ldarg.0", 106 | " IL_0001: call instance void object::.ctor()", 107 | " IL_0006: ret", 108 | " }", 109 | " ", 110 | " .method public hidebysig static int32 ReflectArgument() cil managed", 111 | " {", 112 | " .locals init ([0] int32 V_0, [1] int32 V_1)", 113 | " IL_0000: ldarg.0", 114 | " IL_0001: stloc.0", 115 | " IL_0002: ldloc.0", 116 | " IL_0003: stloc.1", 117 | " IL_0004: ldloc.1", 118 | " IL_0005: ret", 119 | " }", 120 | " }", 121 | "}" 122 | }; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatDeclaresLocalsBeforeEmittingAnyOpcodes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Opcodes")] 11 | public sealed class DebuggingWithMethodThatDeclaresLocalsBeforeEmittingAnyOpcodes 12 | : DebuggingTests 13 | { 14 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 15 | protected override void AssertSequencePoints(XPathNavigator navigator) 16 | { 17 | var entries = navigator.Select( 18 | "./symbols/methods/method[@name=\"AssemblyWithMethodThatDeclaresLocalsBeforeEmittingAnyOpcodes.SimpleClass.ReflectArgument\"]/sequencepoints/entry"); 19 | Assert.Equal(6, entries.Count); 20 | 21 | int visitedCount = 0; 22 | 23 | foreach (XPathNavigator entry in entries) 24 | { 25 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 26 | { 27 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 28 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 29 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 30 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 31 | visitedCount++; 32 | } 33 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x5") 34 | { 35 | Assert.Equal("21", entry.GetAttribute("start_row", string.Empty)); 36 | Assert.Equal("21", entry.GetAttribute("end_row", string.Empty)); 37 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 38 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 39 | visitedCount++; 40 | } 41 | } 42 | 43 | Assert.Equal(2, visitedCount); 44 | } 45 | 46 | protected override AssemblyDebugging CreateAssembly() 47 | { 48 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("AssemblyWithMethodThatDeclaresLocalsBeforeEmittingAnyOpcodes")) 49 | { 50 | using (var type = DebuggingTests.CreateDebuggingType( 51 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 52 | "SimpleClass")) 53 | { 54 | using (var ctor = type.GetMethodDebugging( 55 | type.Builder.DefineConstructor( 56 | MethodAttributes.Public | MethodAttributes.SpecialName | 57 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 58 | CallingConventions.Standard, Type.EmptyTypes))) 59 | { 60 | ctor.Emit(OpCodes.Ldarg_0); 61 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 62 | ctor.Emit(OpCodes.Call, objectCtor); 63 | ctor.Emit(OpCodes.Ret); 64 | } 65 | 66 | using (var method = type.GetMethodDebugging( 67 | type.Builder.DefineMethod("ReflectArgument", 68 | MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.Public, 69 | typeof(int), new Type[] { typeof(int) }))) 70 | { 71 | method.DeclareLocal(typeof(int)); 72 | method.DeclareLocal(typeof(int)); 73 | method.Emit(OpCodes.Ldarg_0); 74 | method.Emit(OpCodes.Stloc_0); 75 | method.Emit(OpCodes.Ldloc_0); 76 | method.Emit(OpCodes.Stloc_1); 77 | method.Emit(OpCodes.Ldloc_1); 78 | method.Emit(OpCodes.Ret); 79 | } 80 | 81 | type.Builder.CreateType(); 82 | } 83 | 84 | return assembly; 85 | } 86 | } 87 | 88 | [Fact] 89 | public void CreateAssemblyAndAssert() 90 | { 91 | this.RunTest(); 92 | } 93 | 94 | protected override string[] GetExpectedFileLines() 95 | { 96 | return new string[] 97 | { 98 | ".assembly AssemblyWithMethodThatDeclaresLocalsBeforeEmittingAnyOpcodes", 99 | "{", 100 | " .class public sealed ansi AssemblyWithMethodThatDeclaresLocalsBeforeEmittingAnyOpcodes.SimpleClass extends object", 101 | " {", 102 | " .method public hidebysig specialname instance void .ctor() cil managed", 103 | " {", 104 | " .locals init ()", 105 | " IL_0000: ldarg.0", 106 | " IL_0001: call instance void object::.ctor()", 107 | " IL_0006: ret", 108 | " }", 109 | " ", 110 | " .method public hidebysig static int32 ReflectArgument() cil managed", 111 | " {", 112 | " .locals init ([0] int32 V_0, [1] int32 V_1)", 113 | " IL_0000: ldarg.0", 114 | " IL_0001: stloc.0", 115 | " IL_0002: ldloc.0", 116 | " IL_0003: stloc.1", 117 | " IL_0004: ldloc.1", 118 | " IL_0005: ret", 119 | " }", 120 | " }", 121 | "}" 122 | }; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatStoresIntegersTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithMethodThatStoresIntegersTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodWithStoringIntegers.SimpleClass.StoreIntegers\"]/sequencepoints/entry"); 18 | Assert.Equal(9, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("24", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x17") 33 | { 34 | Assert.Equal("24", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("24", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodWithStoringIntegers")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("StoreIntegers", 67 | MethodAttributes.HideBySig | MethodAttributes.Public))) 68 | { 69 | method.DeclareLocal(typeof(short)); 70 | method.DeclareLocal(typeof(int)); 71 | method.DeclareLocal(typeof(long)); 72 | method.DeclareLocal(typeof(byte)); 73 | method.Emit(OpCodes.Ldc_I4_S, (short)3); 74 | method.Emit(OpCodes.Stloc_0); 75 | method.Emit(OpCodes.Ldc_I4, 33); 76 | method.Emit(OpCodes.Stloc_1); 77 | method.Emit(OpCodes.Ldc_I8, 33L); 78 | method.Emit(OpCodes.Stloc_2); 79 | method.Emit(OpCodes.Ldc_I4_S, (byte)3); 80 | method.Emit(OpCodes.Stloc_3); 81 | method.Emit(OpCodes.Ret); 82 | } 83 | 84 | type.Builder.CreateType(); 85 | } 86 | 87 | return assembly; 88 | } 89 | } 90 | 91 | [Fact] 92 | public void CreateAssemblyAndAssert() 93 | { 94 | this.RunTest(); 95 | } 96 | 97 | protected override string[] GetExpectedFileLines() 98 | { 99 | return new string[] 100 | { 101 | ".assembly MethodWithStoringIntegers", 102 | "{", 103 | " .class public sealed ansi MethodWithStoringIntegers.SimpleClass extends object", 104 | " {", 105 | " .method public hidebysig specialname instance void .ctor() cil managed", 106 | " {", 107 | " .locals init ()", 108 | " IL_0000: ldarg.0", 109 | " IL_0001: call instance void object::.ctor()", 110 | " IL_0006: ret", 111 | " }", 112 | " ", 113 | " .method public hidebysig instance void StoreIntegers() cil managed", 114 | " {", 115 | " .locals init ([0] int16 V_0, [1] int32 V_1, [2] int64 V_2, [3] uint8 V_3)", 116 | " IL_0000: ldc.i4.s 3", 117 | " IL_0003: stloc.0", 118 | " IL_0004: ldc.i4 33", 119 | " IL_0009: stloc.1", 120 | " IL_000A: ldc.i8 33", 121 | " IL_0013: stloc.2", 122 | " IL_0014: ldc.i4.s 3", 123 | " IL_0016: stloc.3", 124 | " IL_0017: ret", 125 | " }", 126 | " }", 127 | "}" 128 | }; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatStoresSinglesAndDoublesTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithMethodThatStoresSinglesAndDoublesTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodWithStoringDoublesAndSingles.SimpleClass.StoreDoublesAndSingles\"]/sequencepoints/entry"); 18 | Assert.Equal(5, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("24", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x10") 33 | { 34 | Assert.Equal("20", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("20", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodWithStoringDoublesAndSingles")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("StoreDoublesAndSingles", 67 | MethodAttributes.HideBySig | MethodAttributes.Public))) 68 | { 69 | method.DeclareLocal(typeof(float)); 70 | method.DeclareLocal(typeof(double)); 71 | method.Emit(OpCodes.Ldc_R4, 3.2f); 72 | method.Emit(OpCodes.Stloc_0); 73 | method.Emit(OpCodes.Ldc_R8, 3.2d); 74 | method.Emit(OpCodes.Stloc_1); 75 | method.Emit(OpCodes.Ret); 76 | } 77 | 78 | type.Builder.CreateType(); 79 | } 80 | 81 | return assembly; 82 | } 83 | } 84 | 85 | [Fact] 86 | public void CreateAssemblyAndAssert() 87 | { 88 | this.RunTest(); 89 | } 90 | 91 | protected override string[] GetExpectedFileLines() 92 | { 93 | return new string[] 94 | { 95 | ".assembly MethodWithStoringDoublesAndSingles", 96 | "{", 97 | " .class public sealed ansi MethodWithStoringDoublesAndSingles.SimpleClass extends object", 98 | " {", 99 | " .method public hidebysig specialname instance void .ctor() cil managed", 100 | " {", 101 | " .locals init ()", 102 | " IL_0000: ldarg.0", 103 | " IL_0001: call instance void object::.ctor()", 104 | " IL_0006: ret", 105 | " }", 106 | " ", 107 | " .method public hidebysig instance void StoreDoublesAndSingles() cil managed", 108 | " {", 109 | " .locals init ([0] float32 V_0, [1] float64 V_1)", 110 | " IL_0000: ldc.r4 3.2", 111 | " IL_0005: stloc.0", 112 | " IL_0006: ldc.r8 3.2", 113 | " IL_000F: stloc.1", 114 | " IL_0010: ret", 115 | " }", 116 | " }", 117 | "}" 118 | }; 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatThrowsExceptionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithMethodThatThrowsExceptionTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodThatThrowsException.SimpleClass.ThrowIt\"]/sequencepoints/entry"); 18 | Assert.Equal(2, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("17", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("73", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x6") 33 | { 34 | Assert.Equal("18", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("18", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodThatThrowsException")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("ThrowIt", 67 | MethodAttributes.HideBySig | MethodAttributes.Public))) 68 | { 69 | method.ThrowException(typeof(NotSupportedException)); 70 | method.Emit(OpCodes.Ret); 71 | } 72 | 73 | type.Builder.CreateType(); 74 | } 75 | 76 | return assembly; 77 | } 78 | } 79 | 80 | [Fact] 81 | public void CreateAssemblyAndAssert() 82 | { 83 | this.RunTest(); 84 | } 85 | 86 | protected override string[] GetExpectedFileLines() 87 | { 88 | return new string[] 89 | { 90 | ".assembly MethodThatThrowsException", 91 | "{", 92 | " .class public sealed ansi MethodThatThrowsException.SimpleClass extends object", 93 | " {", 94 | " .method public hidebysig specialname instance void .ctor() cil managed", 95 | " {", 96 | " .locals init ()", 97 | " IL_0000: ldarg.0", 98 | " IL_0001: call instance void object::.ctor()", 99 | " IL_0006: ret", 100 | " }", 101 | " ", 102 | " .method public hidebysig instance void ThrowIt() cil managed", 103 | " {", 104 | " .locals init ()", 105 | " IL_0000: newobj instance void System.NotSupportedException::.ctor()", 106 | " IL_0005: throw class [mscorlib]System.NotSupportedException", 107 | " IL_0006: ret", 108 | " }", 109 | " }", 110 | "}" 111 | }; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatUsesManagedCalliTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Calli")] 11 | public sealed class DebuggingWithMethodThatUsesManagedCalliTests 12 | : DebuggingTests 13 | { 14 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 15 | protected override void AssertSequencePoints(XPathNavigator navigator) 16 | { 17 | var entries = navigator.Select( 18 | "./symbols/methods/method[@name=\"MethodThatUsesManagedCalli.SimpleClass.Calli\"]/sequencepoints/entry"); 19 | Assert.Equal(3, entries.Count); 20 | 21 | int visitedCount = 0; 22 | 23 | foreach (XPathNavigator entry in entries) 24 | { 25 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 26 | { 27 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 28 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 29 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 30 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 31 | visitedCount++; 32 | } 33 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x6") 34 | { 35 | Assert.Equal("18", entry.GetAttribute("start_row", string.Empty)); 36 | Assert.Equal("18", entry.GetAttribute("end_row", string.Empty)); 37 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 38 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 39 | visitedCount++; 40 | } 41 | } 42 | 43 | Assert.Equal(2, visitedCount); 44 | } 45 | 46 | protected override AssemblyDebugging CreateAssembly() 47 | { 48 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodThatUsesManagedCalli")) 49 | { 50 | using (var type = DebuggingTests.CreateDebuggingType( 51 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 52 | "SimpleClass")) 53 | { 54 | using (var ctor = type.GetMethodDebugging( 55 | type.Builder.DefineConstructor( 56 | MethodAttributes.Public | MethodAttributes.SpecialName | 57 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 58 | CallingConventions.Standard, Type.EmptyTypes))) 59 | { 60 | ctor.Emit(OpCodes.Ldarg_0); 61 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 62 | ctor.Emit(OpCodes.Call, objectCtor); 63 | ctor.Emit(OpCodes.Ret); 64 | } 65 | 66 | using (var method = type.GetMethodDebugging( 67 | type.Builder.DefineMethod("Calli", 68 | MethodAttributes.HideBySig | MethodAttributes.Public, null, 69 | new Type[] { typeof(IntPtr) }))) 70 | { 71 | method.Emit(OpCodes.Ldarg_1); 72 | method.EmitCalli(OpCodes.Calli, CallingConventions.Standard | CallingConventions.HasThis, 73 | typeof(int), new Type[] { typeof(long), typeof(string) }, null); 74 | method.Emit(OpCodes.Ret); 75 | } 76 | 77 | using (var method = type.GetMethodDebugging( 78 | type.Builder.DefineMethod("CalliVarArg", 79 | MethodAttributes.HideBySig | MethodAttributes.Public, null, 80 | new Type[] { typeof(IntPtr) }))) 81 | { 82 | method.Emit(OpCodes.Ldarg_1); 83 | method.EmitCalli(OpCodes.Calli, CallingConventions.VarArgs, 84 | typeof(int), new Type[] { typeof(long), typeof(string) }, 85 | new Type[] { typeof(long), typeof(string) }); 86 | method.Emit(OpCodes.Ret); 87 | } 88 | 89 | type.Builder.CreateType(); 90 | } 91 | 92 | return assembly; 93 | } 94 | } 95 | 96 | [Fact] 97 | public void CreateAssemblyAndAssert() 98 | { 99 | // Note: This assembly cannot be verified: 100 | // http://blogs.msdn.com/shawnfa/archive/2004/06/14/155478.aspx 101 | this.RunTest(false); 102 | } 103 | 104 | protected override string[] GetExpectedFileLines() 105 | { 106 | return new string[] 107 | { 108 | ".assembly MethodThatUsesManagedCalli", 109 | "{", 110 | " .class public sealed ansi MethodThatUsesManagedCalli.SimpleClass extends object", 111 | " {", 112 | " .method public hidebysig specialname instance void .ctor() cil managed", 113 | " {", 114 | " .locals init ()", 115 | " IL_0000: ldarg.0", 116 | " IL_0001: call instance void object::.ctor()", 117 | " IL_0006: ret", 118 | " }", 119 | " ", 120 | " .method public hidebysig instance void Calli() cil managed", 121 | " {", 122 | " .locals init ()", 123 | " IL_0000: ldarg.1", 124 | " IL_0001: calli standard hasthis int32(int64, string)", 125 | " IL_0006: ret", 126 | " }", 127 | " ", 128 | " .method public hidebysig instance void CalliVarArg() cil managed", 129 | " {", 130 | " .locals init ()", 131 | " IL_0000: ldarg.1", 132 | " IL_0001: calli varargs int32(int64, string, ..., int64, string)", 133 | " IL_0006: ret", 134 | " }", 135 | " }", 136 | "}" 137 | }; 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatUsesSignatureHelperTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithMethodThatUsesSignatureHelperTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodThatUsesSignatureHelper.SimpleClass.CallViaHelper\"]/sequencepoints/entry"); 18 | Assert.Equal(2, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("30", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x5") 33 | { 34 | Assert.Equal("17", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("17", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodThatUsesSignatureHelper")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("CallViaHelper", 67 | MethodAttributes.HideBySig | MethodAttributes.Public))) 68 | { 69 | var helper = SignatureHelper.GetMethodSigHelper( 70 | assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 71 | CallingConventions.Standard, null); 72 | method.Emit(OpCodes.Calli, helper); 73 | method.Emit(OpCodes.Ret); 74 | } 75 | 76 | type.Builder.CreateType(); 77 | } 78 | 79 | return assembly; 80 | } 81 | } 82 | 83 | [Fact] 84 | public void CreateAssemblyAndAssert() 85 | { 86 | this.RunTest(false); 87 | } 88 | 89 | protected override string[] GetExpectedFileLines() 90 | { 91 | return new string[] 92 | { 93 | ".assembly MethodThatUsesSignatureHelper", 94 | "{", 95 | " .class public sealed ansi MethodThatUsesSignatureHelper.SimpleClass extends object", 96 | " {", 97 | " .method public hidebysig specialname instance void .ctor() cil managed", 98 | " {", 99 | " .locals init ()", 100 | " IL_0000: ldarg.0", 101 | " IL_0001: call instance void object::.ctor()", 102 | " IL_0006: ret", 103 | " }", 104 | " ", 105 | " .method public hidebysig instance void CallViaHelper() cil managed", 106 | " {", 107 | " .locals init ()", 108 | " IL_0000: calli 0x11000001", 109 | " IL_0005: ret", 110 | " }", 111 | " }", 112 | "}" 113 | }; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatUsesUnmanagedCalliTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Runtime.InteropServices; 6 | using System.Xml.XPath; 7 | using Xunit; 8 | 9 | namespace EmitDebugging.Tests 10 | { 11 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Calli")] 12 | public sealed class DebuggingWithMethodThatUsesUnmanagedCalliTests 13 | : DebuggingTests 14 | { 15 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 16 | protected override void AssertSequencePoints(XPathNavigator navigator) 17 | { 18 | var entries = navigator.Select( 19 | "./symbols/methods/method[@name=\"MethodThatUsesUnmanagedCalli.SimpleClass.Calli\"]/sequencepoints/entry"); 20 | Assert.Equal(3, entries.Count); 21 | 22 | int visitedCount = 0; 23 | 24 | foreach (XPathNavigator entry in entries) 25 | { 26 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 27 | { 28 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 29 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 30 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 31 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 32 | visitedCount++; 33 | } 34 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x6") 35 | { 36 | Assert.Equal("18", entry.GetAttribute("start_row", string.Empty)); 37 | Assert.Equal("18", entry.GetAttribute("end_row", string.Empty)); 38 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 39 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 40 | visitedCount++; 41 | } 42 | } 43 | 44 | Assert.Equal(2, visitedCount); 45 | } 46 | 47 | protected override AssemblyDebugging CreateAssembly() 48 | { 49 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodThatUsesUnmanagedCalli")) 50 | { 51 | using (var type = DebuggingTests.CreateDebuggingType( 52 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 53 | "SimpleClass")) 54 | { 55 | using (var ctor = type.GetMethodDebugging( 56 | type.Builder.DefineConstructor( 57 | MethodAttributes.Public | MethodAttributes.SpecialName | 58 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 59 | CallingConventions.Standard, Type.EmptyTypes))) 60 | { 61 | ctor.Emit(OpCodes.Ldarg_0); 62 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 63 | ctor.Emit(OpCodes.Call, objectCtor); 64 | ctor.Emit(OpCodes.Ret); 65 | } 66 | 67 | using (var method = type.GetMethodDebugging( 68 | type.Builder.DefineMethod("Calli", 69 | MethodAttributes.HideBySig | MethodAttributes.Public, null, 70 | new Type[] { typeof(IntPtr) }))) 71 | { 72 | method.Emit(OpCodes.Ldarg_1); 73 | method.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, 74 | null, Type.EmptyTypes); 75 | method.Emit(OpCodes.Ret); 76 | } 77 | 78 | type.Builder.CreateType(); 79 | } 80 | 81 | return assembly; 82 | } 83 | } 84 | 85 | [Fact] 86 | public void CreateAssemblyAndAssert() 87 | { 88 | // Note: This assembly cannot be verified: 89 | // http://blogs.msdn.com/shawnfa/archive/2004/06/14/155478.aspx 90 | this.RunTest(false); 91 | } 92 | 93 | protected override string[] GetExpectedFileLines() 94 | { 95 | return new string[] 96 | { 97 | ".assembly MethodThatUsesUnmanagedCalli", 98 | "{", 99 | " .class public sealed ansi MethodThatUsesUnmanagedCalli.SimpleClass extends object", 100 | " {", 101 | " .method public hidebysig specialname instance void .ctor() cil managed", 102 | " {", 103 | " .locals init ()", 104 | " IL_0000: ldarg.0", 105 | " IL_0001: call instance void object::.ctor()", 106 | " IL_0006: ret", 107 | " }", 108 | " ", 109 | " .method public hidebysig instance void Calli() cil managed", 110 | " {", 111 | " .locals init ()", 112 | " IL_0000: ldarg.1", 113 | " IL_0001: calli unmanaged stdcall void()", 114 | " IL_0006: ret", 115 | " }", 116 | " }", 117 | "}" 118 | }; 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithMethodThatWritesLotsOfLocalsToTheConsoleTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithMethodThatWritesLotsOfLocalsToTheConsoleTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodThatWritesLotsOfLocalsToTheConsole.SimpleClass.WriteToConsole\"]/sequencepoints/entry"); 18 | Assert.Equal(6, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("18", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("76", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x38") 33 | { 34 | Assert.Equal("31", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("31", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodThatWritesLotsOfLocalsToTheConsole")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 60 | ctor.Emit(OpCodes.Ldarg_0); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("WriteToConsole", 67 | MethodAttributes.HideBySig | MethodAttributes.Public))) 68 | { 69 | for (var i = 0; i < 5; i++) 70 | { 71 | method.EmitWriteLine(method.DeclareLocal(typeof(int))); 72 | } 73 | method.Emit(OpCodes.Ret); 74 | } 75 | 76 | type.Builder.CreateType(); 77 | } 78 | 79 | return assembly; 80 | } 81 | } 82 | 83 | [Fact] 84 | public void CreateAssemblyAndAssert() 85 | { 86 | this.RunTest(); 87 | } 88 | 89 | protected override string[] GetExpectedFileLines() 90 | { 91 | return new string[] 92 | { 93 | ".assembly MethodThatWritesLotsOfLocalsToTheConsole", 94 | "{", 95 | " .class public sealed ansi MethodThatWritesLotsOfLocalsToTheConsole.SimpleClass extends object", 96 | " {", 97 | " .method public hidebysig specialname instance void .ctor() cil managed", 98 | " {", 99 | " .locals init ()", 100 | " IL_0000: ldarg.0", 101 | " IL_0001: call instance void object::.ctor()", 102 | " IL_0006: ret", 103 | " }", 104 | " ", 105 | " .method public hidebysig instance void WriteToConsole() cil managed", 106 | " {", 107 | " .locals init ([0] int32 V_0, [1] int32 V_1, [2] int32 V_2, [3] int32 V_3, [4] int32 V_4)", 108 | " IL_0000: call class System.IO.TextWriter System.Console::get_Out()", 109 | " IL_0005: ldloc.0", 110 | " IL_0006: callvirt instance void System.IO.TextWriter::WriteLine(int32)", 111 | " IL_000B: call class System.IO.TextWriter System.Console::get_Out()", 112 | " IL_0010: ldloc.1", 113 | " IL_0011: callvirt instance void System.IO.TextWriter::WriteLine(int32)", 114 | " IL_0016: call class System.IO.TextWriter System.Console::get_Out()", 115 | " IL_001B: ldloc.2", 116 | " IL_001C: callvirt instance void System.IO.TextWriter::WriteLine(int32)", 117 | " IL_0021: call class System.IO.TextWriter System.Console::get_Out()", 118 | " IL_0026: ldloc.3", 119 | " IL_0027: callvirt instance void System.IO.TextWriter::WriteLine(int32)", 120 | " IL_002C: call class System.IO.TextWriter System.Console::get_Out()", 121 | " IL_0031: ldloc 4", 122 | " IL_0033: callvirt instance void System.IO.TextWriter::WriteLine(int32)", 123 | " IL_0038: ret", 124 | " }", 125 | " }", 126 | "}", 127 | }; 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithOneScopeTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithOneScopeTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodWithOneScope.SimpleClass.ContainsOneScope\"]/sequencepoints/entry"); 18 | Assert.Equal(6, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("22", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x5") 33 | { 34 | Assert.Equal("23", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("23", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodWithOneScope")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("ContainsOneScope", 67 | MethodAttributes.HideBySig | MethodAttributes.Public))) 68 | { 69 | var outerLocal = method.DeclareLocal(typeof(int)); 70 | method.Emit(OpCodes.Ldc_I4_3); 71 | method.Emit(OpCodes.Stloc, outerLocal); 72 | method.BeginScope(); 73 | var innerLocal = method.DeclareLocal(typeof(long)); 74 | method.Emit(OpCodes.Ldloc, outerLocal); 75 | method.Emit(OpCodes.Conv_I8); 76 | method.Emit(OpCodes.Stloc, innerLocal); 77 | method.EndScope(); 78 | method.Emit(OpCodes.Ret); 79 | } 80 | 81 | type.Builder.CreateType(); 82 | } 83 | 84 | return assembly; 85 | } 86 | } 87 | 88 | [Fact] 89 | public void CreateAssemblyAndAssert() 90 | { 91 | this.RunTest(); 92 | } 93 | 94 | protected override string[] GetExpectedFileLines() 95 | { 96 | return new string[] 97 | { 98 | ".assembly MethodWithOneScope", 99 | "{", 100 | " .class public sealed ansi MethodWithOneScope.SimpleClass extends object", 101 | " {", 102 | " .method public hidebysig specialname instance void .ctor() cil managed", 103 | " {", 104 | " .locals init ()", 105 | " IL_0000: ldarg.0", 106 | " IL_0001: call instance void object::.ctor()", 107 | " IL_0006: ret", 108 | " }", 109 | " ", 110 | " .method public hidebysig instance void ContainsOneScope() cil managed", 111 | " {", 112 | " .locals init ([0] int32 V_0, [1] int64 V_1)", 113 | " IL_0000: ldc.i4.3", 114 | " IL_0001: stloc V_0", 115 | " {", 116 | " IL_0004: ldloc V_0", 117 | " IL_0007: conv.i8", 118 | " IL_0008: stloc V_1", 119 | " }", 120 | " IL_000B: ret", 121 | " }", 122 | " }", 123 | "}" 124 | }; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithOneTypeTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithOneTypeTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"AssemblyWithOneType.SimpleClass.ReflectArgument\"]/sequencepoints/entry"); 18 | Assert.Equal(2, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x1") 33 | { 34 | Assert.Equal("17", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("17", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("AssemblyWithOneType")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("ReflectArgument", 67 | MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.Public, 68 | typeof(int), new Type[] { typeof(int) }))) 69 | { 70 | method.Emit(OpCodes.Ldarg_0); 71 | method.Emit(OpCodes.Ret); 72 | } 73 | 74 | type.Builder.CreateType(); 75 | } 76 | 77 | return assembly; 78 | } 79 | } 80 | 81 | [Fact] 82 | public void CreateAssemblyAndAssert() 83 | { 84 | this.RunTest(); 85 | } 86 | 87 | protected override string[] GetExpectedFileLines() 88 | { 89 | return new string[] 90 | { 91 | ".assembly AssemblyWithOneType", 92 | "{", 93 | " .class public sealed ansi AssemblyWithOneType.SimpleClass extends object", 94 | " {", 95 | " .method public hidebysig specialname instance void .ctor() cil managed", 96 | " {", 97 | " .locals init ()", 98 | " IL_0000: ldarg.0", 99 | " IL_0001: call instance void object::.ctor()", 100 | " IL_0006: ret", 101 | " }", 102 | " ", 103 | " .method public hidebysig static int32 ReflectArgument() cil managed", 104 | " {", 105 | " .locals init ()", 106 | " IL_0000: ldarg.0", 107 | " IL_0001: ret", 108 | " }", 109 | " }", 110 | "}" 111 | }; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithTryCatchFaultTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithTryCatchFaultTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodWithTryCatchFault.SimpleClass.Divide\"]/sequencepoints/entry"); 18 | Assert.Equal(12, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("20", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("20", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("6", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("23", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x2c") 33 | { 34 | Assert.Equal("42", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("42", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodWithTryCatchFault")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("Divide", 67 | MethodAttributes.HideBySig | MethodAttributes.Public, 68 | typeof(int), new Type[] { typeof(int), typeof(int) }))) 69 | { 70 | method.DeclareLocal(typeof(int)); 71 | method.BeginExceptionBlock(); 72 | method.BeginExceptionBlock(); 73 | method.Emit(OpCodes.Ldarg_1); 74 | method.Emit(OpCodes.Ldarg_2); 75 | method.Emit(OpCodes.Div); 76 | method.Emit(OpCodes.Stloc_0); 77 | method.BeginCatchBlock(typeof(DivideByZeroException)); 78 | method.Emit(OpCodes.Ldc_I4_S, 22); 79 | method.Emit(OpCodes.Stloc_0); 80 | method.BeginCatchBlock(typeof(ArgumentException)); 81 | method.Emit(OpCodes.Ldc_I4_S, 20); 82 | method.Emit(OpCodes.Stloc_0); 83 | method.EndExceptionBlock(); 84 | method.BeginFaultBlock(); 85 | method.Emit(OpCodes.Ldc_I4_S, 21); 86 | method.Emit(OpCodes.Stloc_0); 87 | method.EndExceptionBlock(); 88 | method.Emit(OpCodes.Ldloc_0); 89 | method.Emit(OpCodes.Ret); 90 | } 91 | 92 | type.Builder.CreateType(); 93 | } 94 | 95 | return assembly; 96 | } 97 | } 98 | 99 | [Fact] 100 | public void CreateAssemblyAndAssert() 101 | { 102 | this.RunTest(); 103 | } 104 | 105 | protected override string[] GetExpectedFileLines() 106 | { 107 | return new string[] 108 | { 109 | ".assembly MethodWithTryCatchFault", 110 | "{", 111 | " .class public sealed ansi MethodWithTryCatchFault.SimpleClass extends object", 112 | " {", 113 | " .method public hidebysig specialname instance void .ctor() cil managed", 114 | " {", 115 | " .locals init ()", 116 | " IL_0000: ldarg.0", 117 | " IL_0001: call instance void object::.ctor()", 118 | " IL_0006: ret", 119 | " }", 120 | " ", 121 | " .method public hidebysig instance int32 Divide() cil managed", 122 | " {", 123 | " .locals init ([0] int32 V_0)", 124 | " .try", 125 | " {", 126 | " .try", 127 | " {", 128 | " IL_0000: ldarg.1", 129 | " IL_0001: ldarg.2", 130 | " IL_0002: div", 131 | " IL_0003: stloc.0", 132 | " }", 133 | " catch class [mscorlib]System.DivideByZeroException", 134 | " {", 135 | " IL_0004: ldc.i4.s 22", 136 | " IL_0009: stloc.0", 137 | " }", 138 | " catch class [mscorlib]System.ArgumentException", 139 | " {", 140 | " IL_000A: ldc.i4.s 20", 141 | " IL_000F: stloc.0", 142 | " }", 143 | " }", 144 | " fault", 145 | " {", 146 | " IL_0010: ldc.i4.s 21", 147 | " IL_0015: stloc.0", 148 | " }", 149 | " IL_0016: ldloc.0", 150 | " IL_0017: ret", 151 | " }", 152 | " }", 153 | "}", 154 | }; 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithTryCatchFinallyTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithTryCatchFinallyTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodWithTryCatchFinally.SimpleClass.Divide\"]/sequencepoints/entry"); 18 | Assert.Equal(12, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("20", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("20", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("6", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("23", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x2c") 33 | { 34 | Assert.Equal("42", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("42", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodWithTryCatchFinally")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("Divide", 67 | MethodAttributes.HideBySig | MethodAttributes.Public, 68 | typeof(int), new Type[] { typeof(int), typeof(int) }))) 69 | { 70 | method.DeclareLocal(typeof(int)); 71 | method.BeginExceptionBlock(); 72 | method.BeginExceptionBlock(); 73 | method.Emit(OpCodes.Ldarg_1); 74 | method.Emit(OpCodes.Ldarg_2); 75 | method.Emit(OpCodes.Div); 76 | method.Emit(OpCodes.Stloc_0); 77 | method.BeginCatchBlock(typeof(DivideByZeroException)); 78 | method.Emit(OpCodes.Ldc_I4_S, 22); 79 | method.Emit(OpCodes.Stloc_0); 80 | method.BeginCatchBlock(typeof(ArgumentException)); 81 | method.Emit(OpCodes.Ldc_I4_S, 20); 82 | method.Emit(OpCodes.Stloc_0); 83 | method.EndExceptionBlock(); 84 | method.BeginFinallyBlock(); 85 | method.Emit(OpCodes.Ldc_I4_S, 21); 86 | method.Emit(OpCodes.Stloc_0); 87 | method.EndExceptionBlock(); 88 | method.Emit(OpCodes.Ldloc_0); 89 | method.Emit(OpCodes.Ret); 90 | } 91 | 92 | type.Builder.CreateType(); 93 | } 94 | 95 | return assembly; 96 | } 97 | } 98 | 99 | [Fact] 100 | public void CreateAssemblyAndAssert() 101 | { 102 | this.RunTest(); 103 | } 104 | 105 | protected override string[] GetExpectedFileLines() 106 | { 107 | return new string[] 108 | { 109 | ".assembly MethodWithTryCatchFinally", 110 | "{", 111 | " .class public sealed ansi MethodWithTryCatchFinally.SimpleClass extends object", 112 | " {", 113 | " .method public hidebysig specialname instance void .ctor() cil managed", 114 | " {", 115 | " .locals init ()", 116 | " IL_0000: ldarg.0", 117 | " IL_0001: call instance void object::.ctor()", 118 | " IL_0006: ret", 119 | " }", 120 | " ", 121 | " .method public hidebysig instance int32 Divide() cil managed", 122 | " {", 123 | " .locals init ([0] int32 V_0)", 124 | " .try", 125 | " {", 126 | " .try", 127 | " {", 128 | " IL_0000: ldarg.1", 129 | " IL_0001: ldarg.2", 130 | " IL_0002: div", 131 | " IL_0003: stloc.0", 132 | " }", 133 | " catch class [mscorlib]System.DivideByZeroException", 134 | " {", 135 | " IL_0004: ldc.i4.s 22", 136 | " IL_0009: stloc.0", 137 | " }", 138 | " catch class [mscorlib]System.ArgumentException", 139 | " {", 140 | " IL_000A: ldc.i4.s 20", 141 | " IL_000F: stloc.0", 142 | " }", 143 | " }", 144 | " finally", 145 | " {", 146 | " IL_0010: ldc.i4.s 21", 147 | " IL_0015: stloc.0", 148 | " }", 149 | " IL_0016: ldloc.0", 150 | " IL_0017: ret", 151 | " }", 152 | " }", 153 | "}", 154 | }; 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithTwoTypesTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | using System.Xml.XPath; 5 | using Xunit; 6 | 7 | namespace EmitDebugging.Tests 8 | { 9 | public sealed class DebuggingWithTwoTypesTests 10 | : DebuggingTests 11 | { 12 | protected override void AssertSequencePoints(XPathNavigator navigator) 13 | { 14 | DebuggingWithTwoTypesTests.AssertSequencePointsInFirstType(navigator); 15 | DebuggingWithTwoTypesTests.AssertSequencePointsInSecondType(navigator); 16 | } 17 | 18 | private static void AssertSequencePointsInFirstType(XPathNavigator navigator) 19 | { 20 | var entries = navigator.Select( 21 | "./symbols/methods/method[@name=\"AssemblyWithTwoTypes.FirstClass.ReflectArgument\"]/sequencepoints/entry"); 22 | Assert.Equal(2, entries.Count); 23 | 24 | int visitedCount = 0; 25 | 26 | foreach (XPathNavigator entry in entries) 27 | { 28 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 29 | { 30 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 31 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 32 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 33 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 34 | visitedCount++; 35 | } 36 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x1") 37 | { 38 | Assert.Equal("17", entry.GetAttribute("start_row", string.Empty)); 39 | Assert.Equal("17", entry.GetAttribute("end_row", string.Empty)); 40 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 41 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 42 | visitedCount++; 43 | } 44 | } 45 | 46 | Assert.Equal(2, visitedCount); 47 | } 48 | 49 | private static void AssertSequencePointsInSecondType(XPathNavigator navigator) 50 | { 51 | var entries = navigator.Select( 52 | "./symbols/methods/method[@name=\"AssemblyWithTwoTypes.SecondClass.ReflectArgument\"]/sequencepoints/entry"); 53 | Assert.Equal(2, entries.Count); 54 | 55 | int visitedCount = 0; 56 | 57 | foreach (XPathNavigator entry in entries) 58 | { 59 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 60 | { 61 | Assert.Equal("34", entry.GetAttribute("start_row", string.Empty)); 62 | Assert.Equal("34", entry.GetAttribute("end_row", string.Empty)); 63 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 64 | Assert.Equal("21", entry.GetAttribute("end_column", string.Empty)); 65 | visitedCount++; 66 | } 67 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x1") 68 | { 69 | Assert.Equal("35", entry.GetAttribute("start_row", string.Empty)); 70 | Assert.Equal("35", entry.GetAttribute("end_row", string.Empty)); 71 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 72 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 73 | visitedCount++; 74 | } 75 | } 76 | 77 | Assert.Equal(2, visitedCount); 78 | } 79 | 80 | private static void BuildFirstType(AssemblyDebugging assembly) 81 | { 82 | using (var type = DebuggingTests.CreateDebuggingType( 83 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 84 | "FirstClass")) 85 | { 86 | DebuggingWithTwoTypesTests.BuildMethodsInType(type); 87 | } 88 | } 89 | 90 | private static void BuildMethodsInType(TypeDebugging type) 91 | { 92 | using (var ctor = type.GetMethodDebugging( 93 | type.Builder.DefineConstructor( 94 | MethodAttributes.Public | MethodAttributes.SpecialName | 95 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 96 | CallingConventions.Standard, Type.EmptyTypes))) 97 | { 98 | ctor.Emit(OpCodes.Ldarg_0); 99 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 100 | ctor.Emit(OpCodes.Call, objectCtor); 101 | ctor.Emit(OpCodes.Ret); 102 | } 103 | 104 | using (var method = type.GetMethodDebugging( 105 | type.Builder.DefineMethod("ReflectArgument", 106 | MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.Public, 107 | typeof(int), new Type[] { typeof(int) }))) 108 | { 109 | method.Emit(OpCodes.Ldarg_0); 110 | method.Emit(OpCodes.Ret); 111 | } 112 | 113 | type.Builder.CreateType(); 114 | } 115 | 116 | private static void BuildSecondType(AssemblyDebugging assembly) 117 | { 118 | using (var type = DebuggingTests.CreateDebuggingType( 119 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 120 | "SecondClass")) 121 | { 122 | DebuggingWithTwoTypesTests.BuildMethodsInType(type); 123 | } 124 | } 125 | 126 | protected override AssemblyDebugging CreateAssembly() 127 | { 128 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("AssemblyWithTwoTypes")) 129 | { 130 | DebuggingWithTwoTypesTests.BuildFirstType(assembly); 131 | DebuggingWithTwoTypesTests.BuildSecondType(assembly); 132 | 133 | return assembly; 134 | } 135 | } 136 | 137 | [Fact] 138 | public void CreateAssemblyAndAssert() 139 | { 140 | this.RunTest(); 141 | } 142 | 143 | protected override string[] GetExpectedFileLines() 144 | { 145 | return new string[] 146 | { 147 | ".assembly AssemblyWithTwoTypes", 148 | "{", 149 | " .class public sealed ansi AssemblyWithTwoTypes.FirstClass extends object", 150 | " {", 151 | " .method public hidebysig specialname instance void .ctor() cil managed", 152 | " {", 153 | " .locals init ()", 154 | " IL_0000: ldarg.0", 155 | " IL_0001: call instance void object::.ctor()", 156 | " IL_0006: ret", 157 | " }", 158 | " ", 159 | " .method public hidebysig static int32 ReflectArgument() cil managed", 160 | " {", 161 | " .locals init ()", 162 | " IL_0000: ldarg.0", 163 | " IL_0001: ret", 164 | " }", 165 | " }", 166 | " ", 167 | " .class public sealed ansi AssemblyWithTwoTypes.SecondClass extends object", 168 | " {", 169 | " .method public hidebysig specialname instance void .ctor() cil managed", 170 | " {", 171 | " .locals init ()", 172 | " IL_0000: ldarg.0", 173 | " IL_0001: call instance void object::.ctor()", 174 | " IL_0006: ret", 175 | " }", 176 | " ", 177 | " .method public hidebysig static int32 ReflectArgument() cil managed", 178 | " {", 179 | " .locals init ()", 180 | " IL_0000: ldarg.0", 181 | " IL_0001: ret", 182 | " }", 183 | " }", 184 | "}" 185 | }; 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithTypeThatImplementsInterfacesTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | using System.Xml.XPath; 7 | using Xunit; 8 | 9 | namespace EmitDebugging.Tests 10 | { 11 | public sealed class DebuggingWithTypeThatImplementsInterfacesTests 12 | : DebuggingTests 13 | { 14 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 15 | protected override void AssertSequencePoints(XPathNavigator navigator) 16 | { 17 | var entries = navigator.Select( 18 | "./symbols/methods/method[@name=\"AssemblyWithOneTypeThatImplementsInterfaces.SimpleClass.JustReturn\"]/sequencepoints/entry"); 19 | Assert.Equal(1, entries.Count); 20 | 21 | int visitedCount = 0; 22 | 23 | foreach (XPathNavigator entry in entries) 24 | { 25 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 26 | { 27 | Assert.Equal("29", entry.GetAttribute("start_row", string.Empty)); 28 | Assert.Equal("29", entry.GetAttribute("end_row", string.Empty)); 29 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 30 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 31 | visitedCount++; 32 | } 33 | } 34 | 35 | Assert.Equal(1, visitedCount); 36 | } 37 | 38 | protected override AssemblyDebugging CreateAssembly() 39 | { 40 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("AssemblyWithOneTypeThatImplementsInterfaces")) 41 | { 42 | using (var type = DebuggingTests.CreateDebuggingType(assembly, 43 | assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 44 | "SimpleClass", new HashSet() { typeof(IComparable), typeof(IDisposable) })) 45 | { 46 | using (var ctor = type.GetMethodDebugging( 47 | type.Builder.DefineConstructor( 48 | MethodAttributes.Public | MethodAttributes.SpecialName | 49 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 50 | CallingConventions.Standard, Type.EmptyTypes))) 51 | { 52 | ctor.Emit(OpCodes.Ldarg_0); 53 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 54 | ctor.Emit(OpCodes.Call, objectCtor); 55 | ctor.Emit(OpCodes.Ret); 56 | } 57 | 58 | using (var compareToMethod = type.GetMethodDebugging( 59 | type.Builder.DefineMethod("CompareTo", 60 | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public, 61 | typeof(int), new Type[] { typeof(object) }))) 62 | { 63 | compareToMethod.Emit(OpCodes.Ldc_I4_0); 64 | compareToMethod.Emit(OpCodes.Ret); 65 | var iCompareToMethod = typeof(IComparable).GetMethod("CompareTo"); 66 | type.Builder.DefineMethodOverride(compareToMethod.Builder, iCompareToMethod); 67 | } 68 | 69 | using (var disposeMethod = type.GetMethodDebugging( 70 | type.Builder.DefineMethod("Dispose", 71 | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public))) 72 | { 73 | disposeMethod.Emit(OpCodes.Ret); 74 | var iDisposeMethod = typeof(IDisposable).GetMethod("Dispose"); 75 | type.Builder.DefineMethodOverride(disposeMethod.Builder, iDisposeMethod); 76 | } 77 | 78 | using (var method = type.GetMethodDebugging( 79 | type.Builder.DefineMethod("JustReturn", 80 | MethodAttributes.HideBySig | MethodAttributes.Public))) 81 | { 82 | method.Emit(OpCodes.Ret); 83 | } 84 | 85 | type.Builder.CreateType(); 86 | } 87 | 88 | return assembly; 89 | } 90 | } 91 | 92 | [Fact] 93 | public void CreateAssemblyAndAssert() 94 | { 95 | this.RunTest(); 96 | } 97 | 98 | protected override string[] GetExpectedFileLines() 99 | { 100 | return new string[] 101 | { 102 | ".assembly AssemblyWithOneTypeThatImplementsInterfaces", 103 | "{", 104 | " .class public sealed ansi AssemblyWithOneTypeThatImplementsInterfaces.SimpleClass extends object implements System.IComparable implements System.IDisposable", 105 | " {", 106 | " .method public hidebysig specialname instance void .ctor() cil managed", 107 | " {", 108 | " .locals init ()", 109 | " IL_0000: ldarg.0", 110 | " IL_0001: call instance void object::.ctor()", 111 | " IL_0006: ret", 112 | " }", 113 | " ", 114 | " .method public virtual hidebysig instance int32 CompareTo() cil managed", 115 | " {", 116 | " .locals init ()", 117 | " IL_0000: ldc.i4.0", 118 | " IL_0001: ret", 119 | " }", 120 | " ", 121 | " .method public virtual hidebysig instance void Dispose() cil managed", 122 | " {", 123 | " .locals init ()", 124 | " IL_0000: ret", 125 | " }", 126 | " ", 127 | " .method public hidebysig instance void JustReturn() cil managed", 128 | " {", 129 | " .locals init ()", 130 | " IL_0000: ret", 131 | " }", 132 | " }", 133 | "}" 134 | }; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithTypeThatImplementsInterfacesWithNullReferenceTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | using System.Xml.XPath; 7 | using Xunit; 8 | 9 | namespace EmitDebugging.Tests 10 | { 11 | public sealed class DebuggingWithTypeThatImplementsInterfacesWithNullReferenceTests 12 | : DebuggingTests 13 | { 14 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 15 | protected override void AssertSequencePoints(XPathNavigator navigator) 16 | { 17 | var entries = navigator.Select( 18 | "./symbols/methods/method[@name=\"AssemblyWithOneTypeThatImplementsInterfacesWithNullReference.SimpleClass.JustReturn\"]/sequencepoints/entry"); 19 | Assert.Equal(1, entries.Count); 20 | 21 | int visitedCount = 0; 22 | 23 | foreach (XPathNavigator entry in entries) 24 | { 25 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 26 | { 27 | Assert.Equal("29", entry.GetAttribute("start_row", string.Empty)); 28 | Assert.Equal("29", entry.GetAttribute("end_row", string.Empty)); 29 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 30 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 31 | visitedCount++; 32 | } 33 | } 34 | 35 | Assert.Equal(1, visitedCount); 36 | } 37 | 38 | protected override AssemblyDebugging CreateAssembly() 39 | { 40 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("AssemblyWithOneTypeThatImplementsInterfacesWithNullReference")) 41 | { 42 | using (var type = DebuggingTests.CreateDebuggingType(assembly, 43 | assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 44 | "SimpleClass", new HashSet() { typeof(IComparable), null, typeof(IDisposable) })) 45 | { 46 | using (var ctor = type.GetMethodDebugging( 47 | type.Builder.DefineConstructor( 48 | MethodAttributes.Public | MethodAttributes.SpecialName | 49 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 50 | CallingConventions.Standard, Type.EmptyTypes))) 51 | { 52 | ctor.Emit(OpCodes.Ldarg_0); 53 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 54 | ctor.Emit(OpCodes.Call, objectCtor); 55 | ctor.Emit(OpCodes.Ret); 56 | } 57 | 58 | using (var compareToMethod = type.GetMethodDebugging( 59 | type.Builder.DefineMethod("CompareTo", 60 | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public, 61 | typeof(int), new Type[] { typeof(object) }))) 62 | { 63 | compareToMethod.Emit(OpCodes.Ldc_I4_0); 64 | compareToMethod.Emit(OpCodes.Ret); 65 | var iCompareToMethod = typeof(IComparable).GetMethod("CompareTo"); 66 | type.Builder.DefineMethodOverride(compareToMethod.Builder, iCompareToMethod); 67 | } 68 | 69 | using (var disposeMethod = type.GetMethodDebugging( 70 | type.Builder.DefineMethod("Dispose", 71 | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public))) 72 | { 73 | disposeMethod.Emit(OpCodes.Ret); 74 | var iDisposeMethod = typeof(IDisposable).GetMethod("Dispose"); 75 | type.Builder.DefineMethodOverride(disposeMethod.Builder, iDisposeMethod); 76 | } 77 | 78 | using (var method = type.GetMethodDebugging( 79 | type.Builder.DefineMethod("JustReturn", 80 | MethodAttributes.HideBySig | MethodAttributes.Public))) 81 | { 82 | method.Emit(OpCodes.Ret); 83 | } 84 | 85 | type.Builder.CreateType(); 86 | } 87 | 88 | return assembly; 89 | } 90 | } 91 | 92 | [Fact] 93 | public void CreateAssemblyAndAssert() 94 | { 95 | this.RunTest(); 96 | } 97 | 98 | protected override string[] GetExpectedFileLines() 99 | { 100 | return new string[] 101 | { 102 | ".assembly AssemblyWithOneTypeThatImplementsInterfacesWithNullReference", 103 | "{", 104 | " .class public sealed ansi AssemblyWithOneTypeThatImplementsInterfacesWithNullReference.SimpleClass extends object implements System.IComparable implements System.IDisposable", 105 | " {", 106 | " .method public hidebysig specialname instance void .ctor() cil managed", 107 | " {", 108 | " .locals init ()", 109 | " IL_0000: ldarg.0", 110 | " IL_0001: call instance void object::.ctor()", 111 | " IL_0006: ret", 112 | " }", 113 | " ", 114 | " .method public virtual hidebysig instance int32 CompareTo() cil managed", 115 | " {", 116 | " .locals init ()", 117 | " IL_0000: ldc.i4.0", 118 | " IL_0001: ret", 119 | " }", 120 | " ", 121 | " .method public virtual hidebysig instance void Dispose() cil managed", 122 | " {", 123 | " .locals init ()", 124 | " IL_0000: ret", 125 | " }", 126 | " ", 127 | " .method public hidebysig instance void JustReturn() cil managed", 128 | " {", 129 | " .locals init ()", 130 | " IL_0000: ret", 131 | " }", 132 | " }", 133 | "}" 134 | }; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/DebuggingWithUsingNamespaceTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using System.Xml.XPath; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests 9 | { 10 | public sealed class DebuggingWithUsingNamespaceTests 11 | : DebuggingTests 12 | { 13 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 14 | protected override void AssertSequencePoints(XPathNavigator navigator) 15 | { 16 | var entries = navigator.Select( 17 | "./symbols/methods/method[@name=\"MethodUsingNamespace.SimpleClass.UsingNamespace\"]/sequencepoints/entry"); 18 | Assert.Equal(6, entries.Count); 19 | 20 | int visitedCount = 0; 21 | 22 | foreach (XPathNavigator entry in entries) 23 | { 24 | if (entry.GetAttribute("il_offset", string.Empty) == "0x0") 25 | { 26 | Assert.Equal("16", entry.GetAttribute("start_row", string.Empty)); 27 | Assert.Equal("16", entry.GetAttribute("end_row", string.Empty)); 28 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 29 | Assert.Equal("22", entry.GetAttribute("end_column", string.Empty)); 30 | visitedCount++; 31 | } 32 | else if (entry.GetAttribute("il_offset", string.Empty) == "0x5") 33 | { 34 | Assert.Equal("23", entry.GetAttribute("start_row", string.Empty)); 35 | Assert.Equal("23", entry.GetAttribute("end_row", string.Empty)); 36 | Assert.Equal("4", entry.GetAttribute("start_column", string.Empty)); 37 | Assert.Equal("17", entry.GetAttribute("end_column", string.Empty)); 38 | visitedCount++; 39 | } 40 | } 41 | 42 | Assert.Equal(2, visitedCount); 43 | } 44 | 45 | protected override AssemblyDebugging CreateAssembly() 46 | { 47 | using (var assembly = DebuggingTests.CreateDebuggingAssembly("MethodUsingNamespace")) 48 | { 49 | using (var type = DebuggingTests.CreateDebuggingType( 50 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), 51 | "SimpleClass")) 52 | { 53 | using (var ctor = type.GetMethodDebugging( 54 | type.Builder.DefineConstructor( 55 | MethodAttributes.Public | MethodAttributes.SpecialName | 56 | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, 57 | CallingConventions.Standard, Type.EmptyTypes))) 58 | { 59 | ctor.Emit(OpCodes.Ldarg_0); 60 | var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes); 61 | ctor.Emit(OpCodes.Call, objectCtor); 62 | ctor.Emit(OpCodes.Ret); 63 | } 64 | 65 | using (var method = type.GetMethodDebugging( 66 | type.Builder.DefineMethod("UsingNamespace", 67 | MethodAttributes.HideBySig | MethodAttributes.Public))) 68 | { 69 | var outerLocal = method.DeclareLocal(typeof(int)); 70 | method.Emit(OpCodes.Ldc_I4_3); 71 | method.Emit(OpCodes.Stloc, outerLocal); 72 | method.BeginScope(); 73 | method.UsingNamespace("quux"); 74 | var innerLocal = method.DeclareLocal(typeof(long)); 75 | method.Emit(OpCodes.Ldloc, outerLocal); 76 | method.Emit(OpCodes.Conv_I8); 77 | method.Emit(OpCodes.Stloc, innerLocal); 78 | method.EndScope(); 79 | method.Emit(OpCodes.Ret); 80 | } 81 | 82 | type.Builder.CreateType(); 83 | } 84 | 85 | return assembly; 86 | } 87 | } 88 | 89 | [Fact] 90 | public void CreateAssemblyAndAssert() 91 | { 92 | this.RunTest(); 93 | } 94 | 95 | protected override string[] GetExpectedFileLines() 96 | { 97 | return new string[] 98 | { 99 | ".assembly MethodUsingNamespace", 100 | "{", 101 | " .class public sealed ansi MethodUsingNamespace.SimpleClass extends object", 102 | " {", 103 | " .method public hidebysig specialname instance void .ctor() cil managed", 104 | " {", 105 | " .locals init ()", 106 | " IL_0000: ldarg.0", 107 | " IL_0001: call instance void object::.ctor()", 108 | " IL_0006: ret", 109 | " }", 110 | " ", 111 | " .method public hidebysig instance void UsingNamespace() cil managed", 112 | " {", 113 | " .locals init ([0] int32 V_0, [1] int64 V_1)", 114 | " IL_0000: ldc.i4.3", 115 | " IL_0001: stloc V_0", 116 | " {", 117 | " IL_0004: ldloc V_0", 118 | " IL_0007: conv.i8", 119 | " IL_0008: stloc V_1", 120 | " }", 121 | " IL_000B: ret", 122 | " }", 123 | " }", 124 | "}" 125 | }; 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Extensions/MethodBaseExtensionsGetAttributesTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | using AssemblyVerifier; 5 | using EmitDebugging.Extensions; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests.Extensions 9 | { 10 | public static class MethodBaseExtensionsGetCallingConventionsTests 11 | { 12 | private const string AssemblyName = "MethodBaseExtensionsGetCallingConventionsTests"; 13 | private const string MethodExplicitThisName = "ExplicitThis"; 14 | private const string MethodVarArgName = "VarArg"; 15 | private const string TypeName = "MethodBaseExtensionsGetCallingConventions"; 16 | 17 | static MethodBaseExtensionsGetCallingConventionsTests() 18 | { 19 | var name = new AssemblyName(); 20 | name.Name = MethodBaseExtensionsGetCallingConventionsTests.AssemblyName; 21 | name.Version = new Version(1, 0, 0, 0); 22 | var fileName = name.Name + ".dll"; 23 | 24 | var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( 25 | name, AssemblyBuilderAccess.Save); 26 | 27 | var moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name, fileName, false); 28 | 29 | var typeName = MethodBaseExtensionsGetCallingConventionsTests.GenerateType(name, moduleBuilder); 30 | 31 | assemblyBuilder.Save(fileName); 32 | AssemblyVerification.Verify(assemblyBuilder); 33 | 34 | MethodBaseExtensionsGetCallingConventionsTests.Type = assemblyBuilder.GetType(typeName); 35 | } 36 | 37 | private static string GenerateType(AssemblyName name, ModuleBuilder moduleBuilder) 38 | { 39 | var typeName = name.Name + "." + MethodBaseExtensionsGetCallingConventionsTests.TypeName; 40 | 41 | var typeBuilder = moduleBuilder.DefineType( 42 | typeName, TypeAttributes.Class | TypeAttributes.Public, 43 | typeof(object)); 44 | 45 | typeBuilder.GenerateConstructor(); 46 | MethodBaseExtensionsGetCallingConventionsTests.GenerateMethods(typeBuilder); 47 | typeBuilder.CreateType(); 48 | return typeName; 49 | } 50 | 51 | private static void GenerateMethods(TypeBuilder typeBuilder) 52 | { 53 | MethodBaseExtensionsGetCallingConventionsTests.GenerateVarArgMethod(typeBuilder); 54 | MethodBaseExtensionsGetCallingConventionsTests.GenerateExplicitThisMethod(typeBuilder); 55 | } 56 | 57 | private static void GenerateExplicitThisMethod(TypeBuilder typeBuilder) 58 | { 59 | var methodBuilder = typeBuilder.DefineMethod( 60 | MethodBaseExtensionsGetCallingConventionsTests.MethodExplicitThisName, 61 | MethodAttributes.Public | MethodAttributes.HideBySig | 62 | MethodAttributes.NewSlot | MethodAttributes.Virtual, 63 | CallingConventions.HasThis | CallingConventions.ExplicitThis, null, 64 | new Type[] { typeBuilder.UnderlyingSystemType }); 65 | 66 | var methodGenerator = methodBuilder.GetILGenerator(); 67 | methodGenerator.Emit(OpCodes.Ret); 68 | } 69 | 70 | private static void GenerateVarArgMethod(TypeBuilder typeBuilder) 71 | { 72 | var methodBuilder = typeBuilder.DefineMethod( 73 | MethodBaseExtensionsGetCallingConventionsTests.MethodVarArgName, 74 | MethodAttributes.Public | MethodAttributes.HideBySig | 75 | MethodAttributes.NewSlot | MethodAttributes.Virtual, CallingConventions.VarArgs); 76 | 77 | var methodGenerator = methodBuilder.GetILGenerator(); 78 | methodGenerator.Emit(OpCodes.Ret); 79 | } 80 | 81 | [Fact] 82 | public static void GetCallingConventionsForConstructor() 83 | { 84 | var attributes = MethodBaseExtensionsGetCallingConventionsTests.Type.GetConstructor( 85 | Type.EmptyTypes).GetCallingConventions(); 86 | Assert.Equal(string.Empty, attributes); 87 | } 88 | 89 | //[Fact] 90 | public static void GetCallingConventionsForExplicitThisMethod() 91 | { 92 | var attributes = MethodBaseExtensionsGetCallingConventionsTests.Type.GetMethod( 93 | MethodBaseExtensionsGetCallingConventionsTests.MethodExplicitThisName, 94 | BindingFlags.Public | BindingFlags.Instance).GetCallingConventions(); 95 | Assert.Equal("explicit", attributes); 96 | } 97 | 98 | [Fact] 99 | public static void GetCallingConventionsForVarArgMethod() 100 | { 101 | var attributes = MethodBaseExtensionsGetCallingConventionsTests.Type.GetMethod( 102 | MethodBaseExtensionsGetCallingConventionsTests.MethodVarArgName, 103 | BindingFlags.Public | BindingFlags.Instance).GetCallingConventions(); 104 | Assert.Equal("vararg", attributes); 105 | } 106 | 107 | private static Type Type { get; set; } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Extensions/MethodBaseExtensionsGetGenericParameterDeclarationNamesTests.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using EmitDebugging.Extensions; 3 | using Xunit; 4 | 5 | namespace EmitDebugging.Tests.Extensions 6 | { 7 | public sealed class MethodBaseExtensionsGetGenericParameterDeclarationNamesTests 8 | { 9 | [Fact] 10 | public void GetNamesFromMethodWithManyGenerics() 11 | { 12 | var names = this.GetType().GetMethod( 13 | "ManyGenerics").GetGenericParameterDeclarationNames(); 14 | Assert.Equal(5, names.Count); 15 | Assert.True(names.Contains("T")); 16 | Assert.True(names.Contains("U")); 17 | Assert.True(names.Contains("V")); 18 | Assert.True(names.Contains("W")); 19 | Assert.True(names.Contains("X")); 20 | } 21 | 22 | [Fact] 23 | public void GetNamesFromMethodWithNoGenerics() 24 | { 25 | Assert.Equal(0, this.GetType().GetMethod( 26 | "NoGenerics").GetGenericParameterDeclarationNames().Count); 27 | } 28 | 29 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 30 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U")] 31 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "W")] 32 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X")] 33 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 34 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "V")] 35 | [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")] 36 | public void ManyGenerics() { } 37 | 38 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 39 | public void NoGenerics() { } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Extensions/TypeBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | 5 | namespace EmitDebugging.Tests.Extensions 6 | { 7 | internal static class TypeBuilderExtensions 8 | { 9 | internal static void GenerateConstructor(this TypeBuilder @this) 10 | { 11 | var constructor = @this.DefineConstructor( 12 | MethodAttributes.Public | MethodAttributes.SpecialName | 13 | MethodAttributes.RTSpecialName, 14 | CallingConventions.Standard, Type.EmptyTypes); 15 | 16 | var constructorMethod = typeof(object).GetConstructor(Type.EmptyTypes); 17 | var constructorGenerator = constructor.GetILGenerator(); 18 | 19 | constructorGenerator.Emit(OpCodes.Ldarg_0); 20 | constructorGenerator.Emit(OpCodes.Call, constructorMethod); 21 | constructorGenerator.Emit(OpCodes.Ret); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Extensions/TypeExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | using AssemblyVerifier; 5 | using EmitDebugging.Extensions; 6 | using Xunit; 7 | 8 | namespace EmitDebugging.Tests.Extensions 9 | { 10 | public static class TypeExtensionsTests 11 | { 12 | private const string AssemblyName = "TypeExtensionsTests"; 13 | private const string TypePublicAbstractSerializableAutoName = "PublicAbstractSerializableAuto"; 14 | private const string TypeInternalSealedAnsiBeforeFieldInitName = "InternalSealedAnsiBeforeFieldInit"; 15 | 16 | static TypeExtensionsTests() 17 | { 18 | var name = new AssemblyName(); 19 | name.Name = TypeExtensionsTests.AssemblyName; 20 | name.Version = new Version(1, 0, 0, 0); 21 | var fileName = name.Name + ".dll"; 22 | 23 | var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( 24 | name, AssemblyBuilderAccess.Save); 25 | 26 | var moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name, fileName, false); 27 | 28 | var typePublicName = TypeExtensionsTests.GeneratePublicAbstractSerializableAutoType(name, moduleBuilder); 29 | var typeInternalName = TypeExtensionsTests.GenerateInternalSealedAnsiBeforeFieldInitType(name, moduleBuilder); 30 | 31 | assemblyBuilder.Save(fileName); 32 | AssemblyVerification.Verify(assemblyBuilder); 33 | 34 | TypeExtensionsTests.TypePublicAbstractSerializableAuto = assemblyBuilder.GetType(typePublicName); 35 | TypeExtensionsTests.TypeInternalSealedAnsiBeforeFieldInit = assemblyBuilder.GetType(typeInternalName); 36 | } 37 | 38 | private static string GeneratePublicAbstractSerializableAutoType(AssemblyName name, ModuleBuilder moduleBuilder) 39 | { 40 | var typeName = name.Name + "." + TypeExtensionsTests.TypePublicAbstractSerializableAutoName; 41 | 42 | var typeBuilder = moduleBuilder.DefineType( 43 | typeName, TypeAttributes.Public | TypeAttributes.Abstract | 44 | TypeAttributes.Serializable | TypeAttributes.AutoClass, 45 | typeof(object)); 46 | 47 | typeBuilder.GenerateConstructor(); 48 | typeBuilder.CreateType(); 49 | return typeName; 50 | } 51 | 52 | private static string GenerateInternalSealedAnsiBeforeFieldInitType(AssemblyName name, ModuleBuilder moduleBuilder) 53 | { 54 | var typeName = name.Name + "." + TypeExtensionsTests.TypeInternalSealedAnsiBeforeFieldInitName; 55 | 56 | var typeBuilder = moduleBuilder.DefineType( 57 | typeName, TypeAttributes.NotPublic | TypeAttributes.Sealed | 58 | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit, 59 | typeof(object)); 60 | 61 | typeBuilder.GenerateConstructor(); 62 | typeBuilder.CreateType(); 63 | return typeName; 64 | } 65 | 66 | [Fact] 67 | public static void GetAttributesForPublicAbstractSerializableClass() 68 | { 69 | Assert.Equal("public abstract auto serializable", 70 | TypeExtensionsTests.TypePublicAbstractSerializableAuto.GetAttributes()); 71 | } 72 | 73 | [Fact] 74 | public static void GetAttributesForInternalSealedAnsiBeforeFieldInitClass() 75 | { 76 | Assert.Equal("private sealed ansi beforefieldinit", 77 | TypeExtensionsTests.TypeInternalSealedAnsiBeforeFieldInit.GetAttributes()); 78 | } 79 | 80 | private static Type TypeInternalSealedAnsiBeforeFieldInit { get; set; } 81 | 82 | private static Type TypePublicAbstractSerializableAuto { get; set; } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/FieldInfoDescriptorTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using Xunit; 5 | 6 | namespace EmitDebugging.Tests 7 | { 8 | public sealed class FieldInfoDescriptorTests 9 | { 10 | #pragma warning disable 169 11 | [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] 12 | private Guid someField; 13 | #pragma warning restore 169 14 | 15 | [Fact] 16 | public void GetDescription() 17 | { 18 | Assert.Equal("System.Guid EmitDebugging.Tests.FieldInfoDescriptorTests::someField", 19 | new FieldInfoDescriptor(this.GetType().GetField( 20 | "someField", BindingFlags.NonPublic | BindingFlags.Instance)).Value); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/ManagedCalliDescriptorTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using Xunit; 5 | 6 | namespace EmitDebugging.Tests 7 | { 8 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Calli")] 9 | public static class ManagedCalliDescriptorTests 10 | { 11 | [Fact] 12 | public static void GetDescription() 13 | { 14 | Assert.Equal("standard hasthis int32(uint8, valuetype System.Guid)", 15 | new ManagedCalliDescriptor(CallingConventions.Standard | CallingConventions.HasThis, 16 | typeof(int), new Type[] { typeof(byte), typeof(Guid) }, null).Value); 17 | } 18 | 19 | [Fact] 20 | public static void GetDescriptionWithVarArgArgumentsButConventionIsNotVarArg() 21 | { 22 | Assert.Equal("standard hasthis int32(uint8, valuetype System.Guid)", 23 | new ManagedCalliDescriptor(CallingConventions.Standard | CallingConventions.HasThis, 24 | typeof(int), new Type[] { typeof(byte), typeof(Guid) }, 25 | new Type[] { typeof(byte), typeof(Guid) }).Value); 26 | } 27 | 28 | [Fact] 29 | public static void GetDescriptionWithVarArgConvention() 30 | { 31 | Assert.Equal("varargs int32(uint8, valuetype System.Guid, ..., uint8, valuetype System.Guid)", 32 | new ManagedCalliDescriptor(CallingConventions.VarArgs, 33 | typeof(int), new Type[] { typeof(byte), typeof(Guid) }, 34 | new Type[] { typeof(byte), typeof(Guid) }).Value); 35 | } 36 | 37 | [Fact] 38 | [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "NoVar")] 39 | public static void GetDescriptionWithVarArgConventionAndNoVarArgArgumentsGiven() 40 | { 41 | Assert.Equal("varargs int32(uint8, valuetype System.Guid, ...)", 42 | new ManagedCalliDescriptor(CallingConventions.VarArgs, 43 | typeof(int), new Type[] { typeof(byte), typeof(Guid) }, 44 | Type.EmptyTypes).Value); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/MethodDescriptorFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using Xunit; 5 | 6 | namespace EmitDebugging.Tests 7 | { 8 | public sealed class MethodDescriptorFactoryTests 9 | : AssemblyCreationTests 10 | { 11 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 12 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U")] 13 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 14 | [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")] 15 | public void AGenericMethod() { } 16 | 17 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 18 | public void AMethod() { } 19 | 20 | [Fact] 21 | public void GetDescriptionFromGenericMethod() 22 | { 23 | var descriptor = MethodDescriptorFactory.Create(this.GetType().GetMethod("AGenericMethod")); 24 | Assert.Equal(typeof(MethodGenericDeclarationDescriptor), descriptor.GetType()); 25 | Assert.Equal(".method public hidebysig instance void AGenericMethod() cil managed", 26 | descriptor.Value); 27 | } 28 | 29 | [Fact] 30 | public void GetDescriptionFromGenericMethodInvocation() 31 | { 32 | var method = this.GetType().GetMethod("AGenericMethod").MakeGenericMethod( 33 | new Type[] { typeof(Guid), typeof(Random) }); 34 | var descriptor = MethodDescriptorFactory.Create(method); 35 | Assert.Equal(typeof(MethodGenericInvocationDescriptor), descriptor.GetType()); 36 | Assert.Equal( 37 | "instance void EmitDebugging.Tests.MethodDescriptorFactoryTests::AGenericMethod()", 38 | descriptor.Value); 39 | } 40 | 41 | [Fact] 42 | public void GetDescriptionFromMethod() 43 | { 44 | var descriptor = MethodDescriptorFactory.Create(this.GetType().GetMethod("AMethod"), true); 45 | Assert.Equal(typeof(MethodDescriptor), descriptor.GetType()); 46 | Assert.Equal(".method public hidebysig instance void AMethod() cil managed", 47 | descriptor.Value); 48 | } 49 | 50 | [Fact] 51 | public void GetDescriptionFromMethodWithDifferentContainingAssembly() 52 | { 53 | var descriptor = MethodDescriptorFactory.Create( 54 | this.GetType().GetMethod("AMethod"), typeof(Guid).Assembly); 55 | Assert.Equal(typeof(MethodDescriptor), descriptor.GetType()); 56 | Assert.Equal("instance void [EmitDebugging.Tests]EmitDebugging.Tests.MethodDescriptorFactoryTests::AMethod()", 57 | descriptor.Value); 58 | } 59 | 60 | [Fact] 61 | public void GetDescriptionFromMethodInvocation() 62 | { 63 | var descriptor = MethodDescriptorFactory.Create(this.GetType().GetMethod("AMethod"), false); 64 | Assert.Equal(typeof(MethodDescriptor), descriptor.GetType()); 65 | Assert.Equal("instance void EmitDebugging.Tests.MethodDescriptorFactoryTests::AMethod()", 66 | descriptor.Value); 67 | } 68 | 69 | [Fact] 70 | public static void GetDescriptionFromGenericMethodBuilder() 71 | { 72 | using (var assembly = AssemblyCreationTests.CreateDebuggingAssembly("BuilderGenericDeclaration")) 73 | { 74 | using (var type = AssemblyCreationTests.CreateDebuggingType( 75 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), "Holder")) 76 | { 77 | using (var method = type.GetMethodDebugging( 78 | type.Builder.DefineMethod("Method", 79 | MethodAttributes.HideBySig | MethodAttributes.Public))) 80 | { 81 | method.Builder.DefineGenericParameters("T", "U", "V"); 82 | 83 | var descriptor = MethodDescriptorFactory.Create(method.Builder, true); 84 | Assert.Equal(typeof(MethodGenericDeclarationDescriptor), descriptor.GetType()); 85 | Assert.Equal(".method public hidebysig instance void Method() cil managed", 86 | descriptor.Value); 87 | } 88 | } 89 | } 90 | } 91 | 92 | public static void GetDescriptionFromMethodBuilder() 93 | { 94 | using (var assembly = AssemblyCreationTests.CreateDebuggingAssembly("BuilderGenericDeclaration")) 95 | { 96 | using (var type = AssemblyCreationTests.CreateDebuggingType( 97 | assembly, assembly.Builder.GetDynamicModule(assembly.Builder.GetName().Name), "Holder")) 98 | { 99 | using (var method = type.GetMethodDebugging( 100 | type.Builder.DefineMethod("Method", 101 | MethodAttributes.HideBySig | MethodAttributes.Public))) 102 | { 103 | var descriptor = MethodDescriptorFactory.Create(method.Builder, true); 104 | Assert.Equal(typeof(MethodDescriptor), descriptor.GetType()); 105 | Assert.Equal(".method public hidebysig instance void Method() cil managed", 106 | descriptor.Value); 107 | } 108 | } 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | [assembly: AssemblyCompany("www.jasonbock.net")] 4 | [assembly: AssemblyCopyright("Copyright © jasonbock.net 2014")] 5 | [assembly: AssemblyDescription("An assembly that contains tests for EmitDebugging.")] 6 | [assembly: AssemblyFileVersion("2.0.0.0")] 7 | [assembly: AssemblyProduct("EmitDebugging.Tests")] 8 | [assembly: AssemblyTitle("EmitDebugging.Tests")] 9 | [assembly: AssemblyVersion("2.0.0.0")] -------------------------------------------------------------------------------- /EmitDebugging.Tests/TypeDebuggingTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection.Emit; 4 | using Xunit; 5 | 6 | namespace EmitDebugging.Tests 7 | { 8 | public sealed class TypeDebuggingTests 9 | : AssemblyCreationTests 10 | { 11 | [Fact] 12 | [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] 13 | public static void CallDisposeAfterDisposing() 14 | { 15 | TypeDebugging type = null; 16 | 17 | using (var assembly = AssemblyCreationTests.CreateDebuggingAssembly("Me")) 18 | { 19 | using (type = AssemblyCreationTests.CreateDebuggingType(assembly, 20 | assembly.Builder.GetDynamicModule("Me"), "Type")) { } 21 | 22 | type.Dispose(); 23 | } 24 | } 25 | 26 | [Fact] 27 | public static void CallGetMethodDebuggingWithConstructorBuilderAfterDisposing() 28 | { 29 | TypeDebugging type = null; 30 | 31 | using (var assembly = AssemblyCreationTests.CreateDebuggingAssembly("Me")) 32 | { 33 | using (type = AssemblyCreationTests.CreateDebuggingType(assembly, 34 | assembly.Builder.GetDynamicModule("Me"), "Type")) { } 35 | 36 | Assert.Throws(() => type.GetMethodDebugging(null as ConstructorBuilder)); 37 | } 38 | } 39 | 40 | [Fact] 41 | public static void CallGetMethodDebuggingWithMethodBuilderAfterDisposing() 42 | { 43 | TypeDebugging type = null; 44 | 45 | using (var assembly = AssemblyCreationTests.CreateDebuggingAssembly("Me")) 46 | { 47 | using (type = AssemblyCreationTests.CreateDebuggingType(assembly, 48 | assembly.Builder.GetDynamicModule("Me"), "Type")) { } 49 | 50 | Assert.Throws(() => type.GetMethodDebugging(null as MethodBuilder)); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/TypeDescriptorTypeBuilderTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | using Xunit; 5 | 6 | namespace EmitDebugging.Tests 7 | { 8 | public static class TypeDescriptorTypeBuilderTests 9 | { 10 | static TypeDescriptorTypeBuilderTests() 11 | { 12 | var assemblyName = new AssemblyName(); 13 | assemblyName.Name = "TypeDescriptorTypeBuilderTests"; 14 | var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly( 15 | assemblyName, AssemblyBuilderAccess.Save); 16 | 17 | var module = assembly.DefineDynamicModule(assemblyName.Name, 18 | assemblyName.Name + ".dll", true); 19 | 20 | var genericType = module.DefineType( 21 | assembly.GetName().Name + ".GenericType", 22 | TypeAttributes.Class | TypeAttributes.Sealed | 23 | TypeAttributes.Public, typeof(object)); 24 | genericType.DefineGenericParameters("T", "U", "V"); 25 | genericType.CreateType(); 26 | 27 | var standardType = module.DefineType( 28 | assembly.GetName().Name + ".StandardType", 29 | TypeAttributes.Class | TypeAttributes.Sealed | 30 | TypeAttributes.Public, typeof(object)); 31 | standardType.CreateType(); 32 | 33 | TypeDescriptorTypeBuilderTests.GenericType = genericType; 34 | TypeDescriptorTypeBuilderTests.StandardType = standardType; 35 | } 36 | 37 | [Fact] 38 | public static void GetGenericTypeDescription() 39 | { 40 | Assert.Equal( 41 | "class TypeDescriptorTypeBuilderTests.GenericType`3", 42 | new TypeDescriptor(TypeDescriptorTypeBuilderTests.GenericType).Value); 43 | } 44 | 45 | [Fact] 46 | public static void GetStandardTypeDescription() 47 | { 48 | Assert.Equal("class TypeDescriptorTypeBuilderTests.StandardType", 49 | new TypeDescriptor(TypeDescriptorTypeBuilderTests.StandardType).Value); 50 | } 51 | 52 | private static TypeBuilder GenericType { get; set; } 53 | 54 | private static TypeBuilder StandardType { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Types/SimpleDerivedGenericType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace EmitDebugging.Tests.Types 5 | { 6 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 7 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U")] 8 | public class SimpleDerivedGenericType 9 | : SimpleGenericType 10 | { 11 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 12 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 13 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "b")] 14 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 15 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 16 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "V")] 17 | public void DerivedMethodOne(U a, V b) { } 18 | 19 | public void DerivedCallMethod() 20 | { 21 | var simple = new SimpleDerivedGenericType(); 22 | simple.DerivedMethodOne(new Uri("http://www.somesite.com"), "s"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Types/SimpleGenericType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | 5 | namespace EmitDebugging.Tests.Types 6 | { 7 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 8 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U")] 9 | public class SimpleGenericType 10 | { 11 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "c")] 12 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 13 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 14 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "b")] 15 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 16 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "c")] 17 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 18 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "V")] 19 | public void MethodOne(T a, U b, V c) { } 20 | 21 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 22 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "b")] 23 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 24 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 25 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 26 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "V")] 27 | public void MethodTwo(string a, V b) { } 28 | 29 | public void CallMethod() 30 | { 31 | var simple = new SimpleGenericType(); 32 | simple.MethodOne(null, new Uri("http://www.somesite.com"), "s"); 33 | simple.MethodTwo("a", "b"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Types/SimpleGenericValueType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace EmitDebugging.Tests.Types 5 | { 6 | [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] 7 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 8 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U")] 9 | public struct SimpleGenericValueType 10 | { 11 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "x")] 12 | [SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")] 13 | public string x; 14 | 15 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 16 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "b")] 17 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "c")] 18 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "c")] 19 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 20 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 21 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 22 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "V")] 23 | public void MethodOne(T a, V b, U c) { } 24 | 25 | public void CallMethod() 26 | { 27 | var value = new SimpleGenericValueType(); 28 | value.MethodOne(Guid.NewGuid(), 22, "h"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Types/SimpleReferenceType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace EmitDebugging.Tests.Types 5 | { 6 | public class SimpleReferenceType 7 | { 8 | public SimpleReferenceType() { } 9 | 10 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 11 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 12 | public SimpleReferenceType(string a) 13 | : this() { } 14 | 15 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 16 | private void CallMethods() 17 | { 18 | SimpleReferenceType.MethodThree(12, new SimpleValueType(), new SimpleValueType()); 19 | 20 | var simple = new SimpleReferenceType(); 21 | simple.MethodOne(1, new SimpleValueType()); 22 | 23 | var s = "s"; 24 | var g = Guid.NewGuid(); 25 | var t = new SimpleValueType(); 26 | simple.MethodTwo(ref s, ref g, ref t); 27 | 28 | simple.MethodFour(Guid.NewGuid(), "hi", 44); 29 | 30 | var sa = new string[] { "a", "b", "c" }; 31 | var ta = new SimpleValueType[] { new SimpleValueType() }; 32 | simple.MethodFive(new string[] { "a", "b", "c" }, ref sa, 33 | new SimpleValueType[] { new SimpleValueType() }, ref ta); 34 | 35 | simple.MethodSix(ref s, s); 36 | } 37 | 38 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "b")] 39 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 40 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 41 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "c")] 42 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "d")] 43 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 44 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "c")] 45 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "d")] 46 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 47 | [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "3#")] 48 | [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#")] 49 | public void MethodFive(string[] a, ref string[] b, SimpleValueType[] c, ref SimpleValueType[] d) { } 50 | 51 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 52 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "c")] 53 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 54 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 55 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "V")] 56 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U")] 57 | public virtual void MethodFour(T a, U b, V c) { } 58 | 59 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "b")] 60 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 61 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 62 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 63 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 64 | public string MethodOne(int a, SimpleValueType b) 65 | { 66 | return "this"; 67 | } 68 | 69 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 70 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 71 | public static void MethodSeven(T a) { } 72 | 73 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "b")] 74 | [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T")] 75 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 76 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 77 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 78 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 79 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U")] 80 | [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")] 81 | public void MethodSix(ref T a, U b) { } 82 | 83 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 84 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "b")] 85 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 86 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 87 | public static void MethodThree(long a, params SimpleValueType[] b) { } 88 | 89 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "x")] 90 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "a")] 91 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "b")] 92 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 93 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "x")] 94 | [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#")] 95 | [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "2#")] 96 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] 97 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] 98 | [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")] 99 | public void MethodTwo(ref string x, ref Guid a, ref SimpleValueType b) { } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Types/SimpleValueType.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace EmitDebugging.Tests.Types 4 | { 5 | [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] 6 | public struct SimpleValueType 7 | { 8 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X")] 9 | [SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")] 10 | public int X; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/Types/VarArgMethod.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace EmitDebugging.Tests.Types 4 | { 5 | public static class VarArgMethod 6 | { 7 | [SuppressMessage("Microsoft.Usage", "CA2230:UseParamsForVariableArguments")] 8 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value")] 9 | public static void VarArg(int value, __arglist) { } 10 | 11 | public static void CallVarArg() 12 | { 13 | VarArgMethod.VarArg(22, __arglist(3)); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/UnmanagedCalliDescriptorTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Runtime.InteropServices; 4 | using Xunit; 5 | 6 | namespace EmitDebugging.Tests 7 | { 8 | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Calli")] 9 | public static class UnmanagedCalliDescriptorTests 10 | { 11 | [Fact] 12 | public static void GetDescription() 13 | { 14 | Assert.Equal("unmanaged stdcall int32(uint8, valuetype System.Guid)", 15 | new UnmanagedCalliDescriptor(CallingConvention.StdCall, typeof(int), 16 | new Type[] { typeof(byte), typeof(Guid) }).Value); 17 | } 18 | 19 | [Fact] 20 | public static void GetDescriptionWithNoArguments() 21 | { 22 | Assert.Equal("unmanaged stdcall int32()", 23 | new UnmanagedCalliDescriptor(CallingConvention.StdCall, typeof(int), 24 | Type.EmptyTypes).Value); 25 | } 26 | 27 | [Fact] 28 | public static void GetDescriptionWithNullArguments() 29 | { 30 | Assert.Equal("unmanaged stdcall int32()", 31 | new UnmanagedCalliDescriptor(CallingConvention.StdCall, typeof(int), 32 | null).Value); 33 | } 34 | 35 | [Fact] 36 | public static void GetDescriptionWithNullReturn() 37 | { 38 | Assert.Equal("unmanaged stdcall void(uint8, valuetype System.Guid)", 39 | new UnmanagedCalliDescriptor(CallingConvention.StdCall, null, 40 | new Type[] { typeof(byte), typeof(Guid) }).Value); 41 | } 42 | 43 | [Fact] 44 | public static void GetDescriptionWithVoidReturn() 45 | { 46 | Assert.Equal("unmanaged stdcall void(uint8, valuetype System.Guid)", 47 | new UnmanagedCalliDescriptor(CallingConvention.StdCall, typeof(void), 48 | new Type[] { typeof(byte), typeof(Guid) }).Value); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /EmitDebugging.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /EmitDebugging.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30501.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitDebugging", "EmitDebugging\EmitDebugging.csproj", "{7D266049-5480-41FF-A210-E512996EA6C9}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitDebugging.Tests", "EmitDebugging.Tests\EmitDebugging.Tests.csproj", "{E0CFC0AB-A150-4B6B-BA96-E861992580F6}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {7D266049-5480-41FF-A210-E512996EA6C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {7D266049-5480-41FF-A210-E512996EA6C9}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {7D266049-5480-41FF-A210-E512996EA6C9}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {7D266049-5480-41FF-A210-E512996EA6C9}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {E0CFC0AB-A150-4B6B-BA96-E861992580F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {E0CFC0AB-A150-4B6B-BA96-E861992580F6}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {E0CFC0AB-A150-4B6B-BA96-E861992580F6}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {E0CFC0AB-A150-4B6B-BA96-E861992580F6}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(TestCaseManagementSettings) = postSolution 29 | CategoryFile = EmitDebugging.vsmdi 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /EmitDebugging/AssemblyDebugging.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Diagnostics.SymbolStore; 5 | using System.Reflection.Emit; 6 | 7 | namespace EmitDebugging 8 | { 9 | [SuppressMessage("Microsoft.Interoperability", "CA1405:ComVisibleTypeBaseTypesShouldBeComVisible")] 10 | public sealed class AssemblyDebugging 11 | : Debugging, IDisposable 12 | { 13 | public AssemblyDebugging(string codeFile, AssemblyBuilder assembly, ISymbolDocumentWriter symbolDocument) 14 | : base() 15 | { 16 | if (assembly == null) 17 | { 18 | throw new ArgumentNullException("assembly"); 19 | } 20 | 21 | this.Builder = assembly; 22 | 23 | if (!string.IsNullOrEmpty(codeFile)) 24 | { 25 | this.Document = new CodeDocument(codeFile); 26 | } 27 | 28 | this.SymbolDocument = symbolDocument; 29 | this.BeginAssembly(); 30 | } 31 | 32 | ~AssemblyDebugging() 33 | { 34 | this.Dispose(false); 35 | } 36 | 37 | private void CheckForDisposed() 38 | { 39 | if (this.Disposed) 40 | { 41 | throw new ObjectDisposedException("AssemblyDebugging"); 42 | } 43 | } 44 | 45 | public override void Dispose() 46 | { 47 | this.Dispose(true); 48 | GC.SuppressFinalize(this); 49 | } 50 | 51 | private void Dispose(bool disposing) 52 | { 53 | if (!this.Disposed && disposing) 54 | { 55 | var decrease = Indention.Decrease; 56 | 57 | if (!this.CreatedType) 58 | { 59 | decrease = Indention.KeepCurrent; 60 | } 61 | 62 | this.Document.WriteText(new CodeLine("}", decrease)); 63 | this.Document.Dispose(); 64 | } 65 | 66 | this.Disposed = true; 67 | } 68 | 69 | public TypeDebugging GetTypeDebugging(TypeBuilder type) 70 | { 71 | return this.GetTypeDebugging(type, null); 72 | } 73 | 74 | public TypeDebugging GetTypeDebugging(TypeBuilder type, HashSet interfacesToImplement) 75 | { 76 | this.CheckForDisposed(); 77 | 78 | var increase = Indention.Increase; 79 | 80 | if (this.CreatedType) 81 | { 82 | increase = Indention.KeepCurrent; 83 | 84 | if (this.Document != null) 85 | { 86 | this.Document.WriteText(new CodeLine(string.Empty, increase)); 87 | } 88 | } 89 | else 90 | { 91 | this.CreatedType = true; 92 | } 93 | 94 | return new TypeDebugging(type, interfacesToImplement, this.Document, this.SymbolDocument, increase); 95 | } 96 | 97 | private void BeginAssembly() 98 | { 99 | this.Document.WriteText(new CodeLine(".assembly " + this.Builder.GetName().Name)); 100 | this.Document.WriteText(new CodeLine("{")); 101 | } 102 | 103 | private bool CreatedType 104 | { 105 | get; 106 | set; 107 | } 108 | 109 | private bool Disposed 110 | { 111 | get; 112 | set; 113 | } 114 | 115 | private CodeDocument Document 116 | { 117 | get; 118 | set; 119 | } 120 | 121 | private ISymbolDocumentWriter SymbolDocument 122 | { 123 | get; 124 | set; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /EmitDebugging/CalliDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace EmitDebugging 5 | { 6 | internal abstract class CalliDescriptor : Descriptor 7 | { 8 | protected static List GetArguments(Type[] argumentTypes) 9 | { 10 | var arguments = new List(); 11 | 12 | if(argumentTypes != null && argumentTypes.Length > 0) 13 | { 14 | foreach(var argumentType in argumentTypes) 15 | { 16 | if(argumentType != null) 17 | { 18 | arguments.Add(new TypeDescriptor(argumentType).Value); 19 | } 20 | } 21 | } 22 | 23 | return arguments; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /EmitDebugging/CodeDocument.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Diagnostics.SymbolStore; 5 | using System.IO; 6 | using System.Reflection.Emit; 7 | 8 | namespace EmitDebugging 9 | { 10 | public sealed class CodeDocument 11 | : IDisposable 12 | { 13 | private CodeDocument() 14 | : base() 15 | { 16 | this.Lines = new List(); 17 | } 18 | 19 | internal CodeDocument(string ilFile) 20 | : this() 21 | { 22 | this.Writer = new StreamWriter(ilFile, false); 23 | } 24 | 25 | [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] 26 | internal CodeDocument(int linesOfCode, int indentLevel) 27 | : this() 28 | { 29 | this.LinesOfCode = linesOfCode; 30 | this.IndentLevel = indentLevel; 31 | this.Writer = new StreamWriter(new MemoryStream()); 32 | } 33 | 34 | ~CodeDocument() 35 | { 36 | this.Dispose(false); 37 | } 38 | 39 | private void CheckForDisposed() 40 | { 41 | if (this.Disposed) 42 | { 43 | throw new ObjectDisposedException("CodeDocument"); 44 | } 45 | } 46 | 47 | public void Dispose() 48 | { 49 | this.Dispose(true); 50 | GC.SuppressFinalize(this); 51 | } 52 | 53 | private void Dispose(bool disposing) 54 | { 55 | if (!this.Disposed && disposing) 56 | { 57 | this.Writer.Dispose(); 58 | } 59 | 60 | this.Disposed = true; 61 | } 62 | 63 | internal void WriteText(CodeLine line) 64 | { 65 | this.CheckForDisposed(); 66 | this.WriteText(line, null, null); 67 | } 68 | 69 | internal void WriteText(IEnumerable lines, ILGenerator generator, ISymbolDocumentWriter symbolDocument) 70 | { 71 | this.CheckForDisposed(); 72 | 73 | foreach (var line in lines) 74 | { 75 | this.WriteText(line, generator, symbolDocument); 76 | } 77 | } 78 | 79 | internal void WriteText(CodeLine line, ILGenerator generator, ISymbolDocumentWriter symbolDocument) 80 | { 81 | this.CheckForDisposed(); 82 | 83 | this.IndentLevel += (int)line.Indent; 84 | 85 | var code = new string('\t', this.IndentLevel) + line.Code; 86 | 87 | this.Writer.WriteLine(code); 88 | this.Lines.Add(line); 89 | this.LinesOfCode++; 90 | 91 | if (line.IsDebuggable && generator != null && symbolDocument != null) 92 | { 93 | generator.MarkSequencePoint(symbolDocument, 94 | this.LinesOfCode, this.IndentLevel + 1, 95 | this.LinesOfCode, this.IndentLevel + 1 + line.Code.Length); 96 | } 97 | } 98 | 99 | internal void WriteText(List lines, ILGenerator generator, ISymbolDocumentWriter symbolDocument) 100 | { 101 | this.CheckForDisposed(); 102 | 103 | var startColumn = this.IndentLevel; 104 | var endColumn = this.IndentLevel; 105 | var areAllLinesDebuggable = true; 106 | 107 | foreach (var line in lines) 108 | { 109 | areAllLinesDebuggable &= line.IsDebuggable; 110 | 111 | this.IndentLevel += (int)line.Indent; 112 | 113 | var currentEndColumn = this.IndentLevel + 1 + line.Code.Length; 114 | endColumn = currentEndColumn > endColumn ? currentEndColumn : endColumn; 115 | 116 | var code = new string('\t', this.IndentLevel) + line.Code; 117 | 118 | this.Writer.WriteLine(code); 119 | this.Lines.Add(line); 120 | this.LinesOfCode++; 121 | } 122 | 123 | if (areAllLinesDebuggable && generator != null && symbolDocument != null) 124 | { 125 | generator.MarkSequencePoint(symbolDocument, 126 | this.LinesOfCode - lines.Count + 1, startColumn + 1, 127 | this.LinesOfCode, endColumn + 1); 128 | } 129 | } 130 | 131 | private bool Disposed 132 | { 133 | get; 134 | set; 135 | } 136 | 137 | internal int IndentLevel 138 | { 139 | get; 140 | private set; 141 | } 142 | 143 | internal List Lines 144 | { 145 | get; 146 | private set; 147 | } 148 | 149 | internal int LinesOfCode 150 | { 151 | get; 152 | private set; 153 | } 154 | 155 | private StreamWriter Writer 156 | { 157 | get; 158 | set; 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /EmitDebugging/CodeLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection.Emit; 3 | 4 | namespace EmitDebugging 5 | { 6 | internal sealed class CodeLine 7 | { 8 | private string code; 9 | 10 | private CodeLine() 11 | : base() 12 | { 13 | this.Labels = new Label[] { }; 14 | } 15 | 16 | internal CodeLine(string code) 17 | : this() 18 | { 19 | if (code == null) 20 | { 21 | throw new ArgumentNullException("code"); 22 | } 23 | 24 | this.code = code; 25 | } 26 | 27 | internal CodeLine(string code, Indention indent) 28 | : this(code, indent, false) { } 29 | 30 | internal CodeLine(string code, bool isDebuggable) 31 | : this(code) 32 | { 33 | this.IsDebuggable = isDebuggable; 34 | } 35 | 36 | internal CodeLine(string code, Indention indent, bool isDebuggable) 37 | : this(code, isDebuggable) 38 | { 39 | this.Indent = indent; 40 | } 41 | 42 | internal CodeLine(string code, Indention indent, params Label[] labels) 43 | : this(code, indent, false, labels) { } 44 | 45 | internal CodeLine(string code, Indention indent, bool isDebuggable, params Label[] labels) 46 | : this(code, indent, isDebuggable) 47 | { 48 | this.Labels = labels; 49 | } 50 | 51 | internal string Code 52 | { 53 | get 54 | { 55 | return this.code; 56 | } 57 | set 58 | { 59 | if (value == null) 60 | { 61 | throw new ArgumentNullException("value"); 62 | } 63 | 64 | this.code = value; 65 | } 66 | } 67 | 68 | internal Indention Indent 69 | { 70 | get; 71 | private set; 72 | } 73 | 74 | internal bool IsDebuggable 75 | { 76 | get; 77 | private set; 78 | } 79 | 80 | internal Label[] Labels 81 | { 82 | get; 83 | private set; 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /EmitDebugging/ConstructorMethodDebugging.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Diagnostics.SymbolStore; 3 | using System.Reflection.Emit; 4 | 5 | namespace EmitDebugging 6 | { 7 | [SuppressMessage("Microsoft.Interoperability", "CA1405:ComVisibleTypeBaseTypesShouldBeComVisible")] 8 | public sealed class ConstructorMethodDebugging 9 | : MethodBaseDebugging 10 | { 11 | internal ConstructorMethodDebugging(ConstructorBuilder method, CodeDocument document, 12 | ISymbolDocumentWriter symbolDocument, Indention firstIndent) 13 | : base(method, method.GetILGenerator(), document, symbolDocument, firstIndent) { } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EmitDebugging/Debugging.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmitDebugging 4 | { 5 | public abstract class Debugging 6 | : IDisposable 7 | { 8 | public abstract void Dispose(); 9 | 10 | public T Builder { get; protected set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /EmitDebugging/Descriptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmitDebugging 4 | { 5 | internal abstract class Descriptor 6 | { 7 | protected Descriptor() 8 | { 9 | } 10 | 11 | protected internal string Value 12 | { 13 | get; 14 | protected set; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EmitDebugging/EmitDebugging.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {7D266049-5480-41FF-A210-E512996EA6C9} 9 | Library 10 | Properties 11 | EmitDebugging 12 | EmitDebugging 13 | v4.5.1 14 | 512 15 | SAK 16 | SAK 17 | SAK 18 | SAK 19 | 20 | 21 | 22 | 23 | 3.5 24 | 25 | 26 | 27 | true 28 | full 29 | false 30 | bin\Debug\ 31 | DEBUG;TRACE 32 | prompt 33 | 4 34 | true 35 | true 36 | 37 | 38 | ..\Assets\EmitDebugging.ruleset 39 | false 40 | 41 | 42 | false 43 | false 44 | 45 | 46 | pdbonly 47 | true 48 | bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | true 53 | true 54 | 55 | 56 | ..\Assets\EmitDebugging.ruleset 57 | false 58 | 59 | 60 | false 61 | false 62 | 63 | 64 | 65 | False 66 | ..\packages\Spackle.7.1.0.0\lib\NET4.0\Spackle.dll 67 | 68 | 69 | 70 | 3.5 71 | 72 | 73 | 3.5 74 | 75 | 76 | 3.5 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 119 | -------------------------------------------------------------------------------- /EmitDebugging/Extensions/MemberInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace EmitDebugging.Extensions 5 | { 6 | internal static class MemberInfoExtensions 7 | { 8 | internal static string GetName(this MemberInfo @this, Assembly containingAssembly, 9 | bool isDeclaration) 10 | { 11 | var methodName = string.Empty; 12 | 13 | if(!isDeclaration) 14 | { 15 | methodName += new TypeDescriptor( 16 | @this.DeclaringType, containingAssembly, 17 | @this.DeclaringType.IsGenericType).Value + "::"; 18 | } 19 | 20 | return methodName + @this.Name; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /EmitDebugging/Extensions/MethodBaseExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | 6 | namespace EmitDebugging.Extensions 7 | { 8 | internal static class MethodBaseExtensions 9 | { 10 | internal static string GetAttributes(this MethodBase @this) 11 | { 12 | var attributes = new List(); 13 | 14 | if(@this.IsPublic) 15 | { 16 | attributes.Add("public"); 17 | } 18 | else if(@this.IsFamily) 19 | { 20 | attributes.Add("family"); 21 | } 22 | else if(@this.IsFamilyAndAssembly) 23 | { 24 | attributes.Add("famandassembly"); 25 | } 26 | else if(@this.IsFamilyOrAssembly) 27 | { 28 | attributes.Add("familyorassembly"); 29 | } 30 | else if(@this.IsPrivate) 31 | { 32 | attributes.Add("private"); 33 | } 34 | 35 | if((@this.Attributes & MethodAttributes.VtableLayoutMask) > MethodAttributes.ReuseSlot) 36 | { 37 | attributes.Add("newslot"); 38 | } 39 | 40 | if(@this.IsAbstract) 41 | { 42 | attributes.Add("abstract"); 43 | } 44 | 45 | if(@this.IsFinal) 46 | { 47 | attributes.Add("final"); 48 | } 49 | 50 | if(@this.IsVirtual) 51 | { 52 | attributes.Add("virtual"); 53 | } 54 | 55 | if(@this.IsHideBySig) 56 | { 57 | attributes.Add("hidebysig"); 58 | } 59 | 60 | if(@this.IsSpecialName) 61 | { 62 | attributes.Add("specialname"); 63 | } 64 | 65 | return string.Join(" ", attributes.ToArray()); 66 | } 67 | 68 | internal static string GetCallingConventions(this MethodBase @this) 69 | { 70 | var callingConventions = new List(); 71 | 72 | if((@this.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) 73 | { 74 | callingConventions.Add("vararg"); 75 | } 76 | 77 | if((@this.CallingConvention & CallingConventions.ExplicitThis) == CallingConventions.ExplicitThis) 78 | { 79 | callingConventions.Add("explicit"); 80 | } 81 | 82 | return string.Join(" ", callingConventions.ToArray()).Trim(); 83 | } 84 | 85 | internal static List GetGenericParameterDeclarationNames(this MethodBase @this) 86 | { 87 | return new List(Array.ConvertAll( 88 | @this.GetGenericArguments(), target => target.Name)); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /EmitDebugging/Extensions/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace EmitDebugging.Extensions 6 | { 7 | internal static class TypeExtensions 8 | { 9 | internal static string GetAttributes(this Type @this) 10 | { 11 | var attributes = new List(); 12 | 13 | if(@this.IsPublic) 14 | { 15 | attributes.Add("public"); 16 | } 17 | else if(@this.IsNotPublic) 18 | { 19 | attributes.Add("private"); 20 | } 21 | 22 | if(@this.IsAbstract) 23 | { 24 | attributes.Add("abstract"); 25 | } 26 | 27 | if(@this.IsSealed) 28 | { 29 | attributes.Add("sealed"); 30 | } 31 | 32 | if(@this.IsAutoClass) 33 | { 34 | attributes.Add("auto"); 35 | } 36 | 37 | if(@this.IsAnsiClass) 38 | { 39 | attributes.Add("ansi"); 40 | } 41 | 42 | if(@this.IsSerializable) 43 | { 44 | attributes.Add("serializable"); 45 | } 46 | 47 | if((@this.Attributes & TypeAttributes.BeforeFieldInit) == TypeAttributes.BeforeFieldInit) 48 | { 49 | attributes.Add("beforefieldinit"); 50 | } 51 | 52 | return string.Join(" ", attributes.ToArray()); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /EmitDebugging/FieldInfoDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Reflection; 4 | 5 | namespace EmitDebugging 6 | { 7 | internal sealed class FieldInfoDescriptor : Descriptor 8 | { 9 | internal FieldInfoDescriptor(FieldInfo field) 10 | : base() 11 | { 12 | this.Value = string.Format(CultureInfo.CurrentCulture, "{0} {1}::{2}", 13 | new TypeDescriptor(field.FieldType, false).Value, 14 | new TypeDescriptor(field.DeclaringType, false).Value, 15 | field.Name); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /EmitDebugging/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. 3 | // Project-level suppressions either have no target or are given 4 | // a specific target and scoped to a namespace, type, member, etc. 5 | // 6 | // To add a suppression to this file, right-click the message in the 7 | // Error List, point to "Suppress Message(s)", and click 8 | // "In Project Suppression File". 9 | // You do not need to add suppressions to this file manually. 10 | 11 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "EmitDebugging")] 12 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Calli", Scope = "member", Target = "EmitDebugging.MethodDebugging.#EmitCalli(System.Reflection.Emit.OpCode,System.Runtime.InteropServices.CallingConvention,System.Type,System.Type[])")] 13 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Calli", Scope = "member", Target = "EmitDebugging.MethodDebugging.#EmitCalli(System.Reflection.Emit.OpCode,System.Reflection.CallingConventions,System.Type,System.Type[],System.Type[])")] 14 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Conv", Scope = "member", Target = "EmitDebugging.MethodDebugging.#EmitCalli(System.Reflection.Emit.OpCode,System.Runtime.InteropServices.CallingConvention,System.Type,System.Type[])")] 15 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#", Scope = "member", Target = "EmitDebugging.MethodDebugging.#UsingNamespace(System.String)")] 16 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "str", Scope = "member", Target = "EmitDebugging.MethodDebugging.#Emit(System.Reflection.Emit.OpCode,System.String)")] 17 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "str", Scope = "member", Target = "EmitDebugging.MethodBaseDebugging`1.#Emit(System.Reflection.Emit.OpCode,System.String)")] 18 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Calli", Scope = "member", Target = "EmitDebugging.MethodBaseDebugging`1.#EmitCalli(System.Reflection.Emit.OpCode,System.Reflection.CallingConventions,System.Type,System.Type[],System.Type[])")] 19 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Calli", Scope = "member", Target = "EmitDebugging.MethodBaseDebugging`1.#EmitCalli(System.Reflection.Emit.OpCode,System.Runtime.InteropServices.CallingConvention,System.Type,System.Type[])")] 20 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Conv", Scope = "member", Target = "EmitDebugging.MethodBaseDebugging`1.#EmitCalli(System.Reflection.Emit.OpCode,System.Runtime.InteropServices.CallingConvention,System.Type,System.Type[])")] 21 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#", Scope = "member", Target = "EmitDebugging.MethodBaseDebugging`1.#UsingNamespace(System.String)")] 22 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X", Scope = "member", Target = "EmitDebugging.CodeDocument.#X")] 23 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "token", Scope = "member", Target = "EmitDebugging.MethodBaseDebugging`1.#Emit(System.Reflection.Emit.OpCode,System.Reflection.Emit.SignatureHelper)")] 24 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "EmitDebugging.AssemblyDebugging.#Dispose()")] 25 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "EmitDebugging.Debugging`1.#Dispose()")] 26 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "EmitDebugging.TypeDebugging.#Dispose()")] 27 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "EmitDebugging.MethodBaseDebugging`1.#Dispose()")] 28 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "EmitDebugging.MethodDescriptorFactory.#Create(System.Reflection.MethodBase,System.Reflection.Assembly)")] 29 | -------------------------------------------------------------------------------- /EmitDebugging/Indention.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmitDebugging 4 | { 5 | public enum Indention 6 | { 7 | Decrease = -1, 8 | Increase = 1, 9 | KeepCurrent = 0 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /EmitDebugging/ManagedCalliDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Reflection; 5 | 6 | namespace EmitDebugging 7 | { 8 | internal sealed class ManagedCalliDescriptor : CalliDescriptor 9 | { 10 | internal ManagedCalliDescriptor(CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes) 11 | : base() 12 | { 13 | this.Value = string.Format(CultureInfo.CurrentCulture, "{0} {1}({2})", 14 | ManagedCalliDescriptor.GetConventions(callingConvention), 15 | new TypeDescriptor(returnType).Value, 16 | ManagedCalliDescriptor.GetArguments(callingConvention, parameterTypes, optionalParameterTypes)); 17 | } 18 | 19 | private static string GetArguments(CallingConventions callingConvention, Type[] parameterTypes, Type[] optionalParameterTypes) 20 | { 21 | var arguments = new List(); 22 | arguments.AddRange(CalliDescriptor.GetArguments(parameterTypes)); 23 | 24 | if((callingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) 25 | { 26 | arguments.Add("..."); 27 | arguments.AddRange(CalliDescriptor.GetArguments(optionalParameterTypes)); 28 | } 29 | 30 | return string.Join(", ", arguments.ToArray()); 31 | } 32 | 33 | private static string GetConventions(CallingConventions callingConvention) 34 | { 35 | var conventions = new List(); 36 | 37 | foreach(CallingConventions convention in Enum.GetValues(typeof(CallingConventions))) 38 | { 39 | if((callingConvention & convention) == convention) 40 | { 41 | conventions.Add(convention.ToString().ToLower(CultureInfo.CurrentCulture)); 42 | } 43 | } 44 | 45 | return string.Join(" ", conventions.ToArray()); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /EmitDebugging/MethodDebugging.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Diagnostics.SymbolStore; 3 | using System.Reflection.Emit; 4 | 5 | namespace EmitDebugging 6 | { 7 | [SuppressMessage("Microsoft.Interoperability", "CA1405:ComVisibleTypeBaseTypesShouldBeComVisible")] 8 | public sealed class MethodDebugging 9 | : MethodBaseDebugging 10 | { 11 | internal MethodDebugging(MethodBuilder method, CodeDocument document, 12 | ISymbolDocumentWriter symbolDocument, Indention firstIndent) 13 | : base(method, method.GetILGenerator(), document, symbolDocument, firstIndent) { } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EmitDebugging/MethodDescriptor.cs: -------------------------------------------------------------------------------- 1 | using EmitDebugging.Extensions; 2 | using Spackle.Reflection.Extensions; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.Reflection; 7 | using System.Reflection.Emit; 8 | using System.Text; 9 | 10 | namespace EmitDebugging 11 | { 12 | internal class MethodDescriptor : Descriptor 13 | { 14 | protected MethodDescriptor() 15 | : base() 16 | { 17 | } 18 | 19 | internal MethodDescriptor(MethodBase method, Assembly containingAssembly, bool isDeclaration) 20 | : base() 21 | { 22 | var parts = new List(); 23 | 24 | MethodDescriptor.AddAttributes(method, isDeclaration, parts); 25 | MethodDescriptor.AddLocation(method, isDeclaration, parts); 26 | MethodDescriptor.AddCallingConventions(method, parts); 27 | MethodDescriptor.AddReturnValue(method, containingAssembly, parts); 28 | 29 | parts.Add(method.GetName(containingAssembly, isDeclaration) + 30 | MethodDescriptor.GetMethodArgumentInformation(method, containingAssembly, isDeclaration)); 31 | 32 | if(isDeclaration) 33 | { 34 | parts.Add("cil managed"); 35 | } 36 | 37 | this.Value = string.Join(" ", parts.ToArray()); 38 | } 39 | 40 | private static void AddReturnValue(MethodBase method, Assembly containingAssembly, List parts) 41 | { 42 | var info = method as MethodInfo; 43 | 44 | if(info != null && info.ReturnType != null) 45 | { 46 | parts.Add(new TypeDescriptor(info.ReturnType, containingAssembly).Value); 47 | } 48 | else 49 | { 50 | parts.Add("void"); 51 | } 52 | } 53 | 54 | private static void AddLocation(MethodBase method, bool isDeclaration, List parts) 55 | { 56 | if(method.IsStatic) 57 | { 58 | if(isDeclaration) 59 | { 60 | parts.Add("static"); 61 | } 62 | } 63 | else 64 | { 65 | parts.Add("instance"); 66 | } 67 | } 68 | 69 | private static void AddCallingConventions(MethodBase method, List parts) 70 | { 71 | var callingConventions = method.GetCallingConventions(); 72 | 73 | if(callingConventions.Length > 0) 74 | { 75 | parts.Add(callingConventions); 76 | } 77 | } 78 | 79 | private static void AddAttributes(MethodBase method, bool isDeclaration, List parts) 80 | { 81 | if(isDeclaration) 82 | { 83 | parts.Add(".method"); 84 | parts.Add(method.GetAttributes()); 85 | } 86 | } 87 | 88 | private static string GetMethodArgumentInformation(MethodBase method, Assembly containingAssembly, bool isDeclaration) 89 | { 90 | var information = new StringBuilder(); 91 | 92 | information.Append("("); 93 | var i = 0; 94 | 95 | var argumentTypes = method.GetParameterTypes(); 96 | 97 | if(argumentTypes.Length > 0) 98 | { 99 | var descriptors = new List(); 100 | 101 | foreach(var type in argumentTypes) 102 | { 103 | var argumentDescriptor = new List() { 104 | new TypeDescriptor(type, containingAssembly).Value 105 | }; 106 | 107 | if(isDeclaration) 108 | { 109 | argumentDescriptor.Add("V_" + i.ToString(CultureInfo.CurrentCulture)); 110 | } 111 | 112 | descriptors.Add(string.Join(" ", argumentDescriptor.ToArray())); 113 | 114 | i++; 115 | } 116 | 117 | if(!isDeclaration && 118 | ((method.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)) 119 | { 120 | descriptors.Add("..."); 121 | } 122 | 123 | information.Append(string.Join(", ", descriptors.ToArray())); 124 | } 125 | 126 | information.Append(")"); 127 | return information.ToString(); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /EmitDebugging/MethodDescriptorFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | 5 | namespace EmitDebugging 6 | { 7 | internal static class MethodDescriptorFactory 8 | { 9 | internal static MethodDescriptor Create(MethodBase method) 10 | { 11 | return MethodDescriptorFactory.Create(method, method.DeclaringType.Assembly, false); 12 | } 13 | 14 | internal static MethodDescriptor Create(MethodBase method, bool isDeclaration) 15 | { 16 | return MethodDescriptorFactory.Create(method, method.DeclaringType.Assembly, isDeclaration); 17 | } 18 | 19 | internal static MethodDescriptor Create(MethodBase method, Assembly containingAssembly) 20 | { 21 | return MethodDescriptorFactory.Create(method, containingAssembly, false); 22 | } 23 | 24 | internal static MethodDescriptor Create(MethodBase method, Assembly containingAssembly, bool isDeclaration) 25 | { 26 | MethodDescriptor descriptor = null; 27 | 28 | if(method is MethodBuilder) 29 | { 30 | if(method.IsGenericMethod) 31 | { 32 | descriptor = new MethodGenericDeclarationDescriptor(method, containingAssembly); 33 | } 34 | else 35 | { 36 | descriptor = new MethodDescriptor(method, containingAssembly, isDeclaration); 37 | } 38 | } 39 | else if(method.IsGenericMethodDefinition) 40 | { 41 | descriptor = new MethodGenericDeclarationDescriptor(method, containingAssembly); 42 | } 43 | else if(method.IsGenericMethod) 44 | { 45 | descriptor = new MethodGenericInvocationDescriptor(method, containingAssembly); 46 | } 47 | else 48 | { 49 | descriptor = new MethodDescriptor(method, containingAssembly, isDeclaration); 50 | } 51 | 52 | return descriptor; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /EmitDebugging/MethodGenericDeclarationDescriptor.cs: -------------------------------------------------------------------------------- 1 | using EmitDebugging.Extensions; 2 | using Spackle.Extensions; 3 | using Spackle.Reflection.Extensions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Globalization; 7 | using System.Reflection; 8 | using System.Text; 9 | 10 | namespace EmitDebugging 11 | { 12 | internal sealed class MethodGenericDeclarationDescriptor : MethodGenericDescriptor 13 | { 14 | internal MethodGenericDeclarationDescriptor(MethodBase method, Assembly containingAssembly) 15 | : base() 16 | { 17 | var descriptors = new List(); 18 | 19 | MethodGenericDeclarationDescriptor.AddAttributes(method, descriptors); 20 | MethodGenericDeclarationDescriptor.AddLocation(method, descriptors); 21 | MethodGenericDeclarationDescriptor.AddCallingConventions(method, descriptors); 22 | MethodGenericDeclarationDescriptor.AddReturnType(method, containingAssembly, descriptors); 23 | 24 | descriptors.Add(method.GetName(containingAssembly, true) + 25 | MethodGenericDescriptor.GetGenericDeclarationInformation( 26 | (method as MethodInfo), containingAssembly, true) + 27 | MethodGenericDeclarationDescriptor.GetMethodArgumentInformation(method, containingAssembly)); 28 | descriptors.Add("cil managed"); 29 | 30 | this.Value = string.Join(" ", descriptors.ToArray()); 31 | } 32 | 33 | private static void AddReturnType(MethodBase method, Assembly containingAssembly, List descriptors) 34 | { 35 | descriptors.Add(new TypeDescriptor( 36 | (method as MethodInfo).ReturnType, containingAssembly).Value); 37 | } 38 | 39 | private static void AddCallingConventions(MethodBase method, List descriptors) 40 | { 41 | string callingConventions = method.GetCallingConventions(); 42 | 43 | if(callingConventions.Length > 0) 44 | { 45 | descriptors.Add(callingConventions); 46 | } 47 | } 48 | 49 | private static void AddLocation(MethodBase method, List descriptors) 50 | { 51 | if(method.IsStatic) 52 | { 53 | descriptors.Add("static"); 54 | } 55 | else 56 | { 57 | descriptors.Add("instance"); 58 | } 59 | } 60 | 61 | private static void AddAttributes(MethodBase method, List descriptors) 62 | { 63 | descriptors.Add(".method"); 64 | descriptors.Add(method.GetAttributes()); 65 | } 66 | 67 | private static string GetMethodArgumentInformation(MethodBase method, Assembly containingAssembly) 68 | { 69 | var info = new StringBuilder(); 70 | 71 | info.Append("("); 72 | var num = 0; 73 | 74 | var argumentTypes = method.GetParameterTypes(); 75 | 76 | if(argumentTypes.Length > 0) 77 | { 78 | var list = new List(); 79 | var methodParameterDeclarationNames = method.GetGenericParameterDeclarationNames(); 80 | 81 | foreach(var type in argumentTypes) 82 | { 83 | var arguments = new List(); 84 | 85 | var elementType = type.GetRootElementType(); 86 | 87 | if(elementType.IsGenericParameter) 88 | { 89 | if(methodParameterDeclarationNames.Contains(elementType.Name)) 90 | { 91 | arguments.Add("!!" + type.Name); 92 | } 93 | else 94 | { 95 | arguments.Add("!" + type.Name); 96 | } 97 | } 98 | else 99 | { 100 | arguments.Add(new TypeDescriptor(type, containingAssembly).Value); 101 | } 102 | 103 | arguments.Add("V_" + num.ToString(CultureInfo.CurrentCulture)); 104 | list.Add(string.Join(" ", arguments.ToArray())); 105 | 106 | num++; 107 | } 108 | info.Append(string.Join(", ", list.ToArray())); 109 | } 110 | 111 | info.Append(")"); 112 | 113 | return info.ToString(); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /EmitDebugging/MethodGenericDescriptor.cs: -------------------------------------------------------------------------------- 1 | using EmitDebugging.Extensions; 2 | using Spackle.Extensions; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | using System.Text; 7 | 8 | namespace EmitDebugging 9 | { 10 | internal abstract class MethodGenericDescriptor : MethodDescriptor 11 | { 12 | protected MethodGenericDescriptor() 13 | : base() 14 | { 15 | } 16 | 17 | protected static string GetGenericDeclarationInformation(MethodInfo method, Assembly containingAssembly, bool isDeclaration) 18 | { 19 | var builder = new StringBuilder(); 20 | 21 | if(method != null) 22 | { 23 | var genericArguments = method.GetGenericArguments(); 24 | builder.Append("<"); 25 | 26 | var descriptors = new List(); 27 | 28 | if(genericArguments != null) 29 | { 30 | foreach(var genericArgument in genericArguments) 31 | { 32 | var elementType = genericArgument.GetRootElementType(); 33 | 34 | if(isDeclaration) 35 | { 36 | descriptors.Add(elementType.Name); 37 | } 38 | else 39 | { 40 | descriptors.Add(new TypeDescriptor(elementType, containingAssembly, true).Value); 41 | } 42 | } 43 | } 44 | 45 | builder.Append(string.Join(", ", descriptors.ToArray())); 46 | builder.Append(">"); 47 | } 48 | 49 | return builder.ToString(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /EmitDebugging/MethodGenericInvocationDescriptor.cs: -------------------------------------------------------------------------------- 1 | using EmitDebugging.Extensions; 2 | using Spackle.Extensions; 3 | using Spackle.Reflection.Extensions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Globalization; 7 | using System.Reflection; 8 | using System.Text; 9 | 10 | namespace EmitDebugging 11 | { 12 | internal sealed class MethodGenericInvocationDescriptor : MethodGenericDescriptor 13 | { 14 | private MethodGenericInvocationDescriptor() 15 | : base() 16 | { 17 | } 18 | 19 | internal MethodGenericInvocationDescriptor(MethodBase method, Assembly containingAssembly) 20 | : this() 21 | { 22 | var parts = new List(); 23 | 24 | MethodGenericInvocationDescriptor.AddLocation(method, parts); 25 | MethodGenericInvocationDescriptor.AddCallingConventions(method, parts); 26 | MethodGenericInvocationDescriptor.AddReturnValue(method, containingAssembly, parts); 27 | 28 | parts.Add(method.GetName(containingAssembly, false) + 29 | MethodGenericDescriptor.GetGenericDeclarationInformation( 30 | method as MethodInfo, containingAssembly, false) + 31 | MethodGenericInvocationDescriptor.GetMethodArgumentInformation(method, containingAssembly)); 32 | 33 | this.Value = string.Join(" ", parts.ToArray()); 34 | } 35 | 36 | private static void AddReturnValue(MethodBase method, Assembly containingAssembly, List parts) 37 | { 38 | parts.Add(new TypeDescriptor( 39 | (method as MethodInfo).ReturnType, containingAssembly).Value); 40 | } 41 | 42 | private static void AddCallingConventions(MethodBase method, List parts) 43 | { 44 | var callingConventions = method.GetCallingConventions(); 45 | 46 | if(callingConventions.Length > 0) 47 | { 48 | parts.Add(callingConventions); 49 | } 50 | } 51 | 52 | private static void AddLocation(MethodBase method, List parts) 53 | { 54 | if(!method.IsStatic) 55 | { 56 | parts.Add("instance"); 57 | } 58 | } 59 | 60 | private static string GetMethodArgumentInformation(MethodBase method, Assembly containingAssembly) 61 | { 62 | var info = new StringBuilder(); 63 | 64 | info.Append("("); 65 | var num = 0; 66 | 67 | var descriptors = new List(); 68 | var genericMethodDefinition = (method as MethodInfo).GetGenericMethodDefinition(); 69 | 70 | if(genericMethodDefinition.DeclaringType.IsGenericType) 71 | { 72 | var genericTypeDefinition = genericMethodDefinition.DeclaringType.GetGenericTypeDefinition(); 73 | genericMethodDefinition = MethodBase.GetMethodFromHandle( 74 | genericMethodDefinition.MethodHandle, genericTypeDefinition.TypeHandle) as MethodInfo; 75 | } 76 | 77 | var arguments = genericMethodDefinition.GetParameterTypes(); 78 | 79 | var methodParameterDeclarationNames = genericMethodDefinition.GetGenericParameterDeclarationNames(); 80 | var typeParameterDeclarationNames = GetTypeParameterDeclarationNames(method); 81 | 82 | foreach(var argument in arguments) 83 | { 84 | string descriptor = null; 85 | var elementType = argument.GetRootElementType(); 86 | 87 | if(methodParameterDeclarationNames.Contains(elementType.Name)) 88 | { 89 | descriptor = "!!" + methodParameterDeclarationNames.IndexOf(elementType.Name).ToString(CultureInfo.CurrentCulture) + 90 | argument.Name.Replace(elementType.Name, string.Empty); 91 | } 92 | else if(typeParameterDeclarationNames.Contains(elementType.Name)) 93 | { 94 | descriptor = "!" + typeParameterDeclarationNames.IndexOf(elementType.Name).ToString(CultureInfo.CurrentCulture) + 95 | argument.Name.Replace(elementType.Name, string.Empty); 96 | } 97 | else 98 | { 99 | descriptor = new TypeDescriptor(argument, containingAssembly).Value; 100 | } 101 | 102 | descriptors.Add(descriptor); 103 | num++; 104 | } 105 | 106 | info.Append(string.Join(", ", descriptors.ToArray())); 107 | info.Append(")"); 108 | 109 | return info.ToString(); 110 | } 111 | 112 | private static List GetTypeParameterDeclarationNames(MethodBase method) 113 | { 114 | var list = new List(); 115 | 116 | if(method.DeclaringType.IsGenericType) 117 | { 118 | var genericArguments = method.DeclaringType.GetGenericTypeDefinition().GetGenericArguments(); 119 | 120 | if(genericArguments != null) 121 | { 122 | foreach(var type in genericArguments) 123 | { 124 | list.Add(type.Name); 125 | } 126 | } 127 | } 128 | 129 | return list; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /EmitDebugging/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | [assembly: AssemblyCompany("www.jasonbock.net")] 5 | [assembly: AssemblyCopyright("Copyright © jasonbock.net 2014")] 6 | [assembly: AssemblyDescription("An assembly that emits an IL text file when code is emitted.")] 7 | [assembly: AssemblyFileVersion("2.0.0.0")] 8 | [assembly: AssemblyProduct("EmitDebugging")] 9 | [assembly: AssemblyTitle("EmitDebugging")] 10 | [assembly: AssemblyVersion("2.0.0.0")] 11 | [assembly: InternalsVisibleTo("EmitDebugging.Tests")] -------------------------------------------------------------------------------- /EmitDebugging/TypeDebugging.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Diagnostics.SymbolStore; 5 | using System.Reflection.Emit; 6 | using EmitDebugging.Extensions; 7 | 8 | namespace EmitDebugging 9 | { 10 | [SuppressMessage("Microsoft.Interoperability", "CA1405:ComVisibleTypeBaseTypesShouldBeComVisible")] 11 | public sealed class TypeDebugging 12 | : Debugging, IDisposable 13 | { 14 | internal TypeDebugging(TypeBuilder type, HashSet interfacesToImplement, CodeDocument document, 15 | ISymbolDocumentWriter symbolDocument, Indention firstIndent) 16 | : base() 17 | { 18 | this.Builder = type; 19 | this.Document = document; 20 | this.SymbolDocument = symbolDocument; 21 | this.InterfacesToImplement = interfacesToImplement; 22 | this.AddInterfacesToImplement(); 23 | this.BeginType(firstIndent); 24 | } 25 | 26 | ~TypeDebugging() 27 | { 28 | this.Dispose(false); 29 | } 30 | 31 | private void AddInterfacesToImplement() 32 | { 33 | if (this.InterfacesToImplement != null && this.InterfacesToImplement.Count > 0) 34 | { 35 | foreach (var interfaceToImplement in this.InterfacesToImplement) 36 | { 37 | if (interfaceToImplement != null && interfaceToImplement.IsInterface) 38 | { 39 | this.Builder.AddInterfaceImplementation(interfaceToImplement); 40 | } 41 | } 42 | } 43 | } 44 | 45 | private void CheckForDisposed() 46 | { 47 | if (this.Disposed) 48 | { 49 | throw new ObjectDisposedException("TypeDebugging"); 50 | } 51 | } 52 | 53 | public override void Dispose() 54 | { 55 | this.Dispose(true); 56 | GC.SuppressFinalize(this); 57 | } 58 | 59 | private void Dispose(bool disposing) 60 | { 61 | if ((!this.Disposed && disposing) && (this.Document != null)) 62 | { 63 | Indention decrease = Indention.Decrease; 64 | if (!this.CreatedMethod) 65 | { 66 | decrease = Indention.KeepCurrent; 67 | } 68 | 69 | this.Document.WriteText(new CodeLine("}", decrease)); 70 | } 71 | 72 | this.Disposed = true; 73 | } 74 | 75 | public ConstructorMethodDebugging GetMethodDebugging(ConstructorBuilder method) 76 | { 77 | this.CheckForDisposed(); 78 | return new ConstructorMethodDebugging( 79 | method, this.Document, this.SymbolDocument, this.HandleFirstMethod()); 80 | } 81 | 82 | public MethodDebugging GetMethodDebugging(MethodBuilder method) 83 | { 84 | this.CheckForDisposed(); 85 | return new MethodDebugging( 86 | method, this.Document, this.SymbolDocument, this.HandleFirstMethod()); 87 | } 88 | 89 | private Indention HandleFirstMethod() 90 | { 91 | this.CheckForDisposed(); 92 | 93 | var increase = Indention.Increase; 94 | 95 | if (this.CreatedMethod) 96 | { 97 | increase = Indention.KeepCurrent; 98 | 99 | if (this.Document != null) 100 | { 101 | this.Document.WriteText(new CodeLine(string.Empty, increase)); 102 | } 103 | 104 | return increase; 105 | } 106 | 107 | this.CreatedMethod = true; 108 | return increase; 109 | } 110 | 111 | private void BeginType(Indention firstIndent) 112 | { 113 | if (this.Document != null) 114 | { 115 | var definitionParts = new List(){ 116 | ".class", this.Builder.GetAttributes(), this.Builder.FullName, 117 | "extends", new TypeDescriptor(this.Builder.BaseType, 118 | this.Builder.Assembly).Value }; 119 | 120 | if (this.InterfacesToImplement != null && this.InterfacesToImplement.Count > 0) 121 | { 122 | foreach (var interfaceToImplement in this.InterfacesToImplement) 123 | { 124 | if (interfaceToImplement != null && interfaceToImplement.IsInterface) 125 | { 126 | definitionParts.Add("implements"); 127 | definitionParts.Add(interfaceToImplement.FullName); 128 | } 129 | } 130 | } 131 | 132 | this.Document.WriteText(new CodeLine( 133 | string.Join(" ", definitionParts.ToArray()), firstIndent)); 134 | this.Document.WriteText(new CodeLine("{")); 135 | } 136 | } 137 | 138 | private bool CreatedMethod 139 | { 140 | get; 141 | set; 142 | } 143 | 144 | private bool Disposed 145 | { 146 | get; 147 | set; 148 | } 149 | 150 | private CodeDocument Document 151 | { 152 | get; 153 | set; 154 | } 155 | 156 | private HashSet InterfacesToImplement 157 | { 158 | get; 159 | set; 160 | } 161 | 162 | private ISymbolDocumentWriter SymbolDocument 163 | { 164 | get; 165 | set; 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /EmitDebugging/TypeDescriptor.cs: -------------------------------------------------------------------------------- 1 | using EmitDebugging.Extensions; 2 | using Spackle.Extensions; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.Reflection; 7 | using System.Text; 8 | 9 | namespace EmitDebugging 10 | { 11 | internal sealed class TypeDescriptor : Descriptor 12 | { 13 | internal TypeDescriptor(Type type) 14 | : this(type, type == null ? null : type.Assembly, true) { } 15 | 16 | internal TypeDescriptor(Type type, bool showKind) 17 | : base() 18 | { 19 | this.CreateDescriptor(type, type.Assembly, showKind); 20 | } 21 | 22 | internal TypeDescriptor(Type type, Assembly containingAssembly) 23 | : this(type, containingAssembly, true) 24 | { 25 | } 26 | 27 | internal TypeDescriptor(Type type, Assembly containingAssembly, bool showKind) 28 | : base() 29 | { 30 | this.CreateDescriptor(type, containingAssembly, showKind); 31 | } 32 | 33 | private static void CheckAssembly(Assembly containingAssembly) 34 | { 35 | if (containingAssembly == null) 36 | { 37 | throw new ArgumentNullException("containingAssembly"); 38 | } 39 | } 40 | 41 | private void CreateDescriptor(Type type, Assembly containingAssembly, bool showKind) 42 | { 43 | var builder = new StringBuilder(); 44 | 45 | if(type == null || type == typeof(void)) 46 | { 47 | builder.Append("void"); 48 | } 49 | else 50 | { 51 | TypeDescriptor.CheckAssembly(containingAssembly); 52 | var elementType = type.GetRootElementType(); 53 | 54 | if(TypeDescriptor.IsSpecial(type)) 55 | { 56 | builder.Append(GetSpecialName(type)); 57 | } 58 | else 59 | { 60 | if(type.Assembly.Equals(containingAssembly)) 61 | { 62 | builder.Append(TypeDescriptor.GetTypeKind(type, showKind)) 63 | .Append(" ") 64 | .Append(TypeDescriptor.GetTypeName(type)); 65 | } 66 | else 67 | { 68 | builder.Append(TypeDescriptor.GetTypeKind(type, showKind)) 69 | .Append(" [") 70 | .Append(type.Assembly.GetName().Name).Append("]") 71 | .Append(TypeDescriptor.GetTypeName(type)); 72 | } 73 | 74 | TypeDescriptor.AddGenerics(type, containingAssembly, builder); 75 | 76 | builder.Append(type.Name.Replace(elementType.Name, string.Empty)); 77 | } 78 | } 79 | 80 | this.Value = builder.ToString().Trim(); 81 | } 82 | 83 | private static void AddGenerics(Type type, Assembly containingAssembly, StringBuilder builder) 84 | { 85 | var genericArguments = type.GetGenericArguments(); 86 | 87 | if(genericArguments != null && genericArguments.Length > 0) 88 | { 89 | var genericCount = "`" + 90 | genericArguments.Length.ToString(CultureInfo.CurrentCulture); 91 | 92 | if(!builder.ToString().EndsWith(genericCount, StringComparison.CurrentCulture)) 93 | { 94 | builder.Append(genericCount); 95 | } 96 | 97 | builder.Append("<"); 98 | var genericTypes = new List(); 99 | 100 | foreach(var genericArgument in genericArguments) 101 | { 102 | if(genericArgument.IsGenericParameter) 103 | { 104 | genericTypes.Add(genericArgument.Name); 105 | } 106 | else 107 | { 108 | genericTypes.Add(new TypeDescriptor( 109 | genericArgument.GetRootElementType(), containingAssembly).Value); 110 | } 111 | } 112 | 113 | builder.Append(string.Join(", ", genericTypes.ToArray())); 114 | builder.Append(">"); 115 | } 116 | } 117 | 118 | private static string GetSpecialName(Type type) 119 | { 120 | var specialName = string.Empty; 121 | 122 | var elementType = type.GetRootElementType(); 123 | 124 | if(elementType.Equals(typeof(float))) 125 | { 126 | specialName = "float32"; 127 | } 128 | else if(elementType.Equals(typeof(double))) 129 | { 130 | specialName = "float64"; 131 | } 132 | else if(elementType.Equals(typeof(long))) 133 | { 134 | specialName = "int64"; 135 | } 136 | else if(elementType.Equals(typeof(ulong))) 137 | { 138 | specialName = "uint64"; 139 | } 140 | else if(elementType.Equals(typeof(int))) 141 | { 142 | specialName = "int32"; 143 | } 144 | else if(elementType.Equals(typeof(uint))) 145 | { 146 | specialName = "uint32"; 147 | } 148 | else if(elementType.Equals(typeof(short))) 149 | { 150 | specialName = "int16"; 151 | } 152 | else if(elementType.Equals(typeof(ushort))) 153 | { 154 | specialName = "uint16"; 155 | } 156 | else if(elementType.Equals(typeof(sbyte))) 157 | { 158 | specialName = "int8"; 159 | } 160 | else if(elementType.Equals(typeof(byte))) 161 | { 162 | specialName = "uint8"; 163 | } 164 | else if(elementType.Equals(typeof(string))) 165 | { 166 | specialName = "string"; 167 | } 168 | else if(elementType.Equals(typeof(object))) 169 | { 170 | specialName = "object"; 171 | } 172 | 173 | return specialName + type.Name.Replace(elementType.Name, string.Empty); 174 | } 175 | 176 | private static string GetTypeKind(Type type, bool showKind) 177 | { 178 | var kind = string.Empty; 179 | 180 | if(showKind) 181 | { 182 | if(type.GetRootElementType().IsValueType) 183 | { 184 | kind = "valuetype"; 185 | } 186 | else 187 | { 188 | kind = "class"; 189 | } 190 | } 191 | 192 | return kind; 193 | } 194 | 195 | private static string GetTypeName(Type type) 196 | { 197 | var elementType = type.GetRootElementType(); 198 | return elementType.Namespace + "." + elementType.Name; 199 | } 200 | 201 | private static bool IsSpecial(Type type) 202 | { 203 | var elementType = type.GetRootElementType(); 204 | return elementType.Equals(typeof(float)) | elementType.Equals(typeof(double)) | 205 | elementType.Equals(typeof(long)) | elementType.Equals(typeof(int)) | 206 | elementType.Equals(typeof(ulong)) | elementType.Equals(typeof(uint)) | 207 | elementType.Equals(typeof(short)) | elementType.Equals(typeof(ushort)) | 208 | elementType.Equals(typeof(byte)) | elementType.Equals(typeof(sbyte)) | 209 | elementType.Equals(typeof(void)) | elementType.Equals(typeof(string)) | 210 | elementType.Equals(typeof(object)); 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /EmitDebugging/UnmanagedCalliDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace EmitDebugging 6 | { 7 | internal sealed class UnmanagedCalliDescriptor : CalliDescriptor 8 | { 9 | internal UnmanagedCalliDescriptor(CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes) 10 | : base() 11 | { 12 | this.Value = string.Format(CultureInfo.CurrentCulture, "unmanaged {0} {1}({2})", 13 | unmanagedCallConv.ToString().ToLower(CultureInfo.CurrentCulture), 14 | new TypeDescriptor(returnType).Value, 15 | string.Join(", ", CalliDescriptor.GetArguments(parameterTypes).ToArray())); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /EmitDebugging/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Microsoft Public License (Ms-PL) 2 | 3 | This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 4 | 5 | 1. Definitions 6 | 7 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. 8 | 9 | A "contribution" is the original software, or any additions or changes to the software. 10 | 11 | A "contributor" is any person that distributes its contribution under this license. 12 | 13 | "Licensed patents" are a contributor's patent claims that read directly on its contribution. 14 | 15 | 2. Grant of Rights 16 | 17 | (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. 18 | 19 | (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 20 | 21 | 3. Conditions and Limitations 22 | 23 | (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. 24 | 25 | (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. 26 | 27 | (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. 28 | 29 | (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. 30 | 31 | (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. -------------------------------------------------------------------------------- /Method and Type Descriptors.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonBock/EmitDebugging/cd69bea374c69f638e1b19250642d26bb11d2d8d/Method and Type Descriptors.docx -------------------------------------------------------------------------------- /Nuget/2.0.0.0/EmitDebugging.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | EmitDebugger 5 | 2.0.0.0 6 | Jason Bock 7 | Jason Bock 8 | AAn assembly that emits an IL text file when code is emitted. 9 | https://github.com/JasonBock/EmitDebugger 10 | https://github.com/JasonBock/EmitDebugger 11 | netframework 12 | en-US 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EmitDebugger 2 | ================ 3 | 4 | This is an assembly that generates a .il source file for emitted code with the correct breakpoints built-in for debugging purposes. It has the same binary interface with the Builder classes in System.Reflection.Emit to make it relatively painless to replace current code with this API. 5 | 6 | Note that no more work is going into EmitDebugger. 7 | -------------------------------------------------------------------------------- /corapi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonBock/EmitDebugging/cd69bea374c69f638e1b19250642d26bb11d2d8d/corapi.dll -------------------------------------------------------------------------------- /pdb2xml.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonBock/EmitDebugging/cd69bea374c69f638e1b19250642d26bb11d2d8d/pdb2xml.dll -------------------------------------------------------------------------------- /raw.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonBock/EmitDebugging/cd69bea374c69f638e1b19250642d26bb11d2d8d/raw.dll --------------------------------------------------------------------------------