diff --git a/DecompilerNuGetDemos.workbook b/DecompilerNuGetDemos.workbook
index 387cf91e1..7a487f052 100644
--- a/DecompilerNuGetDemos.workbook
+++ b/DecompilerNuGetDemos.workbook
@@ -6,7 +6,7 @@ platforms:
- DotNetCore
packages:
- id: ICSharpCode.Decompiler
- version: 4.0.0.4285-beta1
+ version: 4.0.0.4319-beta2
---
Setup: load the references required to work with the decompiler
diff --git a/Frontends.sln b/Frontends.sln
index 36c395b93..bd714df16 100644
--- a/Frontends.sln
+++ b/Frontends.sln
@@ -10,11 +10,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E7
doc\IntPtr.txt = doc\IntPtr.txt
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0A344E19-D1FC-4F4C-8883-0844AC669113}"
- ProjectSection(SolutionItems) = preProject
- Rebracer.xml = Rebracer.xml
- EndProjectSection
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.Console", "ICSharpCode.Decompiler.Console\ICSharpCode.Decompiler.Console.csproj", "{8FDA011E-FAF8-4C1F-A695-21E2C6B5375F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.PowerShell", "ICSharpCode.Decompiler.PowerShell\ICSharpCode.Decompiler.PowerShell.csproj", "{FF7D6041-3C52-47D1-A32A-0BFE8EE4EEEB}"
diff --git a/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj b/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj
index 9a66544cd..fed3e71e4 100644
--- a/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj
+++ b/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj
@@ -7,7 +7,7 @@
true
ilspycmd
ilspycmd
- 2.0.0
+ 3.0.0
Command-line decompiler using the ILSpy decompilation engine
Copyright 2011-2018 AlphaSierraPapa
https://github.com/icsharpcode/ILSpy/
@@ -23,8 +23,8 @@
-
-
+
+
diff --git a/ICSharpCode.Decompiler.Console/Program.cs b/ICSharpCode.Decompiler.Console/Program.cs
index b96b7fc27..adf859d34 100644
--- a/ICSharpCode.Decompiler.Console/Program.cs
+++ b/ICSharpCode.Decompiler.Console/Program.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -6,6 +6,9 @@ using McMaster.Extensions.CommandLineUtils;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.Decompiler.Disassembler;
+using System.Threading;
+using System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.Console
{
@@ -24,6 +27,7 @@ namespace ICSharpCode.Decompiler.Console
var outputOption = app.Option("-o|--outputdir ", "The output directory, if omitted decompiler output is written to standard out.", CommandOptionType.SingleValue);
var typeOption = app.Option("-t|--type ", "The fully qualified name of the type to decompile.", CommandOptionType.SingleValue);
var listOption = app.Option("-l|--list ", "Lists all entities of the specified type(s). Valid types: c(lass), i(interface), s(truct), d(elegate), e(num)", CommandOptionType.MultipleValue);
+ var ilViewerOption = app.Option("-il|--ilcode", "Show IL code.", CommandOptionType.NoValue);
app.ExtendedHelpText = Environment.NewLine + "-o is valid with every option and required when using -p.";
app.ThrowOnUnexpectedArgument = false; // Ignore invalid arguments / options
@@ -60,6 +64,14 @@ namespace ICSharpCode.Decompiler.Console
output = File.CreateText(Path.Combine(directory, outputName) + ".list.txt");
}
ListContent(inputAssemblyFileName.Value, output, kinds);
+ } else if (ilViewerOption.HasValue()) {
+ TextWriter output = System.Console.Out;
+ if (outputOption.HasValue()) {
+ string directory = outputOption.Value();
+ string outputName = Path.GetFileNameWithoutExtension(inputAssemblyFileName.Value);
+ output = File.CreateText(Path.Combine(directory, outputName) + ".il");
+ }
+ ShowIL(inputAssemblyFileName.Value, output);
} else {
TextWriter output = System.Console.Out;
if (outputOption.HasValue()) {
@@ -77,7 +89,7 @@ namespace ICSharpCode.Decompiler.Console
static CSharpDecompiler GetDecompiler(string assemblyFileName)
{
- return new CSharpDecompiler(assemblyFileName, new DecompilerSettings() { ThrowOnAssemblyResolveErrors = false });
+ return new CSharpDecompiler(assemblyFileName, new DecompilerSettings() { ThrowOnAssemblyResolveErrors = false });
}
static void ListContent(string assemblyFileName, TextWriter output, ISet kinds)
@@ -91,10 +103,27 @@ namespace ICSharpCode.Decompiler.Console
}
}
+ static void ShowIL(string assemblyFileName, TextWriter output)
+ {
+ CSharpDecompiler decompiler = GetDecompiler(assemblyFileName);
+ ITextOutput textOutput = new PlainTextOutput();
+ ReflectionDisassembler disassembler = new ReflectionDisassembler(textOutput, CancellationToken.None);
+
+ disassembler.DisassembleNamespace(decompiler.TypeSystem.MainModule.RootNamespace.Name,
+ decompiler.TypeSystem.MainModule.PEFile,
+ decompiler.TypeSystem.MainModule.TypeDefinitions.Select(x => (TypeDefinitionHandle)x.MetadataToken));
+
+ output.WriteLine($"// IL code: {decompiler.TypeSystem.MainModule.AssemblyName}");
+ output.WriteLine(textOutput.ToString());
+ output.Flush();
+ }
+
static void DecompileAsProject(string assemblyFileName, string outputDirectory)
{
WholeProjectDecompiler decompiler = new WholeProjectDecompiler();
- decompiler.DecompileProject(new PEFile(assemblyFileName), outputDirectory);
+ var module = new PEFile(assemblyFileName);
+ decompiler.AssemblyResolver = new UniversalAssemblyResolver(assemblyFileName, false, module.Reader.DetectTargetFrameworkId());
+ decompiler.DecompileProject(module, outputDirectory);
}
static void Decompile(string assemblyFileName, TextWriter output, string typeName = null)
diff --git a/ICSharpCode.Decompiler.Console/README.md b/ICSharpCode.Decompiler.Console/README.md
index 27e23b96d..e88acbda1 100644
--- a/ICSharpCode.Decompiler.Console/README.md
+++ b/ICSharpCode.Decompiler.Console/README.md
@@ -21,6 +21,7 @@ Options:
-t|--type The fully qualified name of the type to decompile.
-l|--list Lists all entities of the specified type(s). Valid types: c(lass), i(interface), s(truct),
d(elegate), e(num)
+ -il|--ilcode Show IL code.
-o is valid with every option and required when using -p.
```
diff --git a/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj b/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj
index 6a526d131..bd51bff90 100644
--- a/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj
+++ b/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj
@@ -1,7 +1,9 @@
-
+
netstandard2.0
+ 7.2
+ true
diff --git a/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs b/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs
index 97ac583cd..0b8f5a383 100644
--- a/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs
+++ b/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs
@@ -16,66 +16,106 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.DebugInfo;
+using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util;
using Mono.Cecil;
-
+using Mono.Cecil.Pdb;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.PdbProvider.Cecil
{
public class MonoCecilDebugInfoProvider : IDebugInfoProvider
{
- readonly ModuleDefinition module;
+ readonly Dictionary SequencePoints, IList Variables)> debugInfo;
- public MonoCecilDebugInfoProvider(ModuleDefinition module, string description = null)
+ public unsafe MonoCecilDebugInfoProvider(PEFile module, string pdbFileName, string description = null)
{
- this.module = module;
- this.Description = description ?? "none";
+ if (module == null) {
+ throw new ArgumentNullException(nameof(module));
+ }
+
+ if (!module.Reader.IsEntireImageAvailable) {
+ throw new ArgumentException("This provider needs access to the full image!");
+ }
+
+ this.Description = description ?? $"Loaded from PDB file: {pdbFileName}";
+
+ var image = module.Reader.GetEntireImage();
+ this.debugInfo = new Dictionary SequencePoints, IList Variables)>();
+ using (UnmanagedMemoryStream stream = new UnmanagedMemoryStream(image.Pointer, image.Length))
+ using (var moduleDef = ModuleDefinition.ReadModule(stream)) {
+ moduleDef.ReadSymbols(new PdbReaderProvider().GetSymbolReader(moduleDef, pdbFileName));
+
+ foreach (var method in module.Metadata.MethodDefinitions) {
+ var cecilMethod = moduleDef.LookupToken(MetadataTokens.GetToken(method)) as MethodDefinition;
+ var debugInfo = cecilMethod?.DebugInformation;
+ if (debugInfo == null)
+ continue;
+ IList sequencePoints = EmptyList.Instance;
+ if (debugInfo.HasSequencePoints) {
+ sequencePoints = new List(debugInfo.SequencePoints.Count);
+ foreach (var point in debugInfo.SequencePoints) {
+ sequencePoints.Add(new SequencePoint {
+ Offset = point.Offset,
+ StartLine = point.StartLine,
+ StartColumn = point.StartColumn,
+ EndLine = point.EndLine,
+ EndColumn = point.EndColumn,
+ DocumentUrl = point.Document.Url
+ });
+ }
+ }
+ var variables = new List();
+ foreach (var scope in debugInfo.GetScopes()) {
+ if (!scope.HasVariables)
+ continue;
+ foreach (var v in scope.Variables) {
+ variables.Add(new Variable(v.Index, v.Name));
+ }
+ }
+ this.debugInfo.Add(method, (sequencePoints, variables));
+ }
+ }
}
public string Description { get; }
public IList GetSequencePoints(SRM.MethodDefinitionHandle handle)
{
- var method = this.module.LookupToken(MetadataTokens.GetToken(handle)) as MethodDefinition;
- if (method?.DebugInformation == null || !method.DebugInformation.HasSequencePoints)
+ if (!debugInfo.TryGetValue(handle, out var info)) {
return EmptyList.Instance;
- return method.DebugInformation.SequencePoints.Select(point => new SequencePoint {
- Offset = point.Offset,
- StartLine = point.StartLine,
- StartColumn = point.StartColumn,
- EndLine = point.EndLine,
- EndColumn = point.EndColumn,
- DocumentUrl = point.Document.Url
- }).ToList();
+ }
+
+ return info.SequencePoints;
}
public IList GetVariables(SRM.MethodDefinitionHandle handle)
{
- var method = this.module.LookupToken(MetadataTokens.GetToken(handle)) as MethodDefinition;
- if (method?.DebugInformation == null)
+ if (!debugInfo.TryGetValue(handle, out var info)) {
return EmptyList.Instance;
- return method.DebugInformation.GetScopes()
- .SelectMany(s => s.Variables)
- .Select(v => new Variable { Name = v.Name }).ToList();
+ }
+
+ return info.Variables;
}
public bool TryGetName(SRM.MethodDefinitionHandle handle, int index, out string name)
{
- var method = this.module.LookupToken(MetadataTokens.GetToken(handle)) as MethodDefinition;
name = null;
- if (method?.DebugInformation == null || !method.HasBody)
+ if (!debugInfo.TryGetValue(handle, out var info)) {
return false;
- var variable = method.Body.Variables.FirstOrDefault(v => v.Index == index);
- if (variable == null)
- return false;
- return method.DebugInformation.TryGetName(variable, out name);
+ }
+
+ var variable = info.Variables.FirstOrDefault(v => v.Index == index);
+ name = variable.Name;
+ return name != null;
}
}
}
diff --git a/ICSharpCode.Decompiler.PowerShell/ErrorIds.cs b/ICSharpCode.Decompiler.PowerShell/ErrorIds.cs
index 9554e449e..7d592d8fa 100644
--- a/ICSharpCode.Decompiler.PowerShell/ErrorIds.cs
+++ b/ICSharpCode.Decompiler.PowerShell/ErrorIds.cs
@@ -4,9 +4,9 @@ using System.Text;
namespace ICSharpCode.Decompiler.PowerShell
{
- public static class ErrorIds
- {
- public static readonly string AssemblyLoadFailed = "1";
- public static readonly string DecompilationFailed = "2";
- }
+ public static class ErrorIds
+ {
+ public static readonly string AssemblyLoadFailed = "1";
+ public static readonly string DecompilationFailed = "2";
+ }
}
diff --git a/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs b/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs
index f5fa4579e..faf167052 100644
--- a/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs
+++ b/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs
@@ -4,40 +4,41 @@ using System.IO;
using System.Management.Automation;
using System.Text;
using ICSharpCode.Decompiler.CSharp;
+using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler.PowerShell
{
- [Cmdlet(VerbsCommon.Get, "DecompiledProject")]
- [OutputType(typeof(string))]
- public class GetDecompiledProjectCmdlet : PSCmdlet
- {
- [Parameter(Position = 0, Mandatory = true)]
- public CSharpDecompiler Decompiler { get; set; }
+ [Cmdlet(VerbsCommon.Get, "DecompiledProject")]
+ [OutputType(typeof(string))]
+ public class GetDecompiledProjectCmdlet : PSCmdlet
+ {
+ [Parameter(Position = 0, Mandatory = true)]
+ public CSharpDecompiler Decompiler { get; set; }
- [Parameter(Position = 1, Mandatory = true)]
- [Alias("PSPath", "OutputPath")]
- [ValidateNotNullOrEmpty]
- public string LiteralPath { get; set; }
+ [Parameter(Position = 1, Mandatory = true)]
+ [Alias("PSPath", "OutputPath")]
+ [ValidateNotNullOrEmpty]
+ public string LiteralPath { get; set; }
- protected override void ProcessRecord()
- {
- string path = GetUnresolvedProviderPathFromPSPath(LiteralPath);
- if (!Directory.Exists(path))
- {
- WriteObject("Destination directory must exist prior to decompilation");
- return;
- }
+ protected override void ProcessRecord()
+ {
+ string path = GetUnresolvedProviderPathFromPSPath(LiteralPath);
+ if (!Directory.Exists(path)) {
+ WriteObject("Destination directory must exist prior to decompilation");
+ return;
+ }
- try
- {
- WholeProjectDecompiler decompiler = new WholeProjectDecompiler();
- decompiler.DecompileProject(Decompiler.TypeSystem.MainModule.PEFile, path);
+ try {
+ WholeProjectDecompiler decompiler = new WholeProjectDecompiler();
+ PEFile module = Decompiler.TypeSystem.MainModule.PEFile;
+ decompiler.AssemblyResolver = new UniversalAssemblyResolver(module.FileName, false, module.Reader.DetectTargetFrameworkId());
+ decompiler.DecompileProject(module, path);
- WriteObject("Decompilation finished");
- } catch (Exception e) {
- WriteVerbose(e.ToString());
- WriteError(new ErrorRecord(e, ErrorIds.DecompilationFailed, ErrorCategory.OperationStopped, null));
- }
- }
- }
+ WriteObject("Decompilation finished");
+ } catch (Exception e) {
+ WriteVerbose(e.ToString());
+ WriteError(new ErrorRecord(e, ErrorIds.DecompilationFailed, ErrorCategory.OperationStopped, null));
+ }
+ }
+ }
}
diff --git a/ICSharpCode.Decompiler.PowerShell/GetDecompiledSourceCmdlet.cs b/ICSharpCode.Decompiler.PowerShell/GetDecompiledSourceCmdlet.cs
index 845f69028..a63242ecf 100644
--- a/ICSharpCode.Decompiler.PowerShell/GetDecompiledSourceCmdlet.cs
+++ b/ICSharpCode.Decompiler.PowerShell/GetDecompiledSourceCmdlet.cs
@@ -20,8 +20,7 @@ namespace ICSharpCode.Decompiler.PowerShell
protected override void ProcessRecord()
{
- try
- {
+ try {
StringWriter output = new StringWriter();
if (TypeName == null) {
output.Write(Decompiler.DecompileWholeModuleAsString());
diff --git a/ICSharpCode.Decompiler.PowerShell/GetDecompiledTypesCmdlet.cs b/ICSharpCode.Decompiler.PowerShell/GetDecompiledTypesCmdlet.cs
index 19d910533..16451e041 100644
--- a/ICSharpCode.Decompiler.PowerShell/GetDecompiledTypesCmdlet.cs
+++ b/ICSharpCode.Decompiler.PowerShell/GetDecompiledTypesCmdlet.cs
@@ -9,33 +9,33 @@ using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.PowerShell
{
- [Cmdlet(VerbsCommon.Get, "DecompiledTypes")]
- [OutputType(typeof(ITypeDefinition[]))]
- public class GetDecompiledTypesCmdlet : PSCmdlet
- {
- [Parameter(Position = 0, Mandatory = true)]
- public CSharpDecompiler Decompiler { get; set; }
+ [Cmdlet(VerbsCommon.Get, "DecompiledTypes")]
+ [OutputType(typeof(ITypeDefinition[]))]
+ public class GetDecompiledTypesCmdlet : PSCmdlet
+ {
+ [Parameter(Position = 0, Mandatory = true)]
+ public CSharpDecompiler Decompiler { get; set; }
- [Parameter(Mandatory = true)]
- public string[] Types { get; set; }
+ [Parameter(Mandatory = true)]
+ public string[] Types { get; set; }
- protected override void ProcessRecord()
- {
- HashSet kinds = TypesParser.ParseSelection(Types);
+ protected override void ProcessRecord()
+ {
+ HashSet kinds = TypesParser.ParseSelection(Types);
- try {
- List output = new List();
- foreach (var type in Decompiler.TypeSystem.MainModule.TypeDefinitions) {
- if (!kinds.Contains(type.Kind))
- continue;
- output.Add(type);
- }
+ try {
+ List output = new List();
+ foreach (var type in Decompiler.TypeSystem.MainModule.TypeDefinitions) {
+ if (!kinds.Contains(type.Kind))
+ continue;
+ output.Add(type);
+ }
- WriteObject(output.ToArray());
- } catch (Exception e) {
- WriteVerbose(e.ToString());
- WriteError(new ErrorRecord(e, ErrorIds.DecompilationFailed, ErrorCategory.OperationStopped, null));
- }
- }
- }
+ WriteObject(output.ToArray());
+ } catch (Exception e) {
+ WriteVerbose(e.ToString());
+ WriteError(new ErrorRecord(e, ErrorIds.DecompilationFailed, ErrorCategory.OperationStopped, null));
+ }
+ }
+ }
}
diff --git a/ICSharpCode.Decompiler.PowerShell/GetDecompilerCmdlet.cs b/ICSharpCode.Decompiler.PowerShell/GetDecompilerCmdlet.cs
index 7afddec54..1ce6f300a 100644
--- a/ICSharpCode.Decompiler.PowerShell/GetDecompilerCmdlet.cs
+++ b/ICSharpCode.Decompiler.PowerShell/GetDecompilerCmdlet.cs
@@ -6,29 +6,29 @@ using ICSharpCode.Decompiler.CSharp;
namespace ICSharpCode.Decompiler.PowerShell
{
- [Cmdlet(VerbsCommon.Get, "Decompiler")]
- [OutputType(typeof(CSharpDecompiler))]
- public class GetDecompilerCmdlet : PSCmdlet
- {
- [Parameter(Position = 0, Mandatory = true, HelpMessage = "Path to the assembly you want to decompile")]
- [Alias("PSPath")]
- [ValidateNotNullOrEmpty]
- public string LiteralPath { get; set; }
+ [Cmdlet(VerbsCommon.Get, "Decompiler")]
+ [OutputType(typeof(CSharpDecompiler))]
+ public class GetDecompilerCmdlet : PSCmdlet
+ {
+ [Parameter(Position = 0, Mandatory = true, HelpMessage = "Path to the assembly you want to decompile")]
+ [Alias("PSPath")]
+ [ValidateNotNullOrEmpty]
+ public string LiteralPath { get; set; }
- protected override void ProcessRecord()
- {
- string path = GetUnresolvedProviderPathFromPSPath(LiteralPath);
+ protected override void ProcessRecord()
+ {
+ string path = GetUnresolvedProviderPathFromPSPath(LiteralPath);
- try {
- var decompiler = new CSharpDecompiler(path, new DecompilerSettings() {
+ try {
+ var decompiler = new CSharpDecompiler(path, new DecompilerSettings() {
ThrowOnAssemblyResolveErrors = false
- });
- WriteObject(decompiler);
+ });
+ WriteObject(decompiler);
- } catch (Exception e) {
- WriteVerbose(e.ToString());
- WriteError(new ErrorRecord(e, ErrorIds.AssemblyLoadFailed, ErrorCategory.OperationStopped, null));
- }
- }
- }
+ } catch (Exception e) {
+ WriteVerbose(e.ToString());
+ WriteError(new ErrorRecord(e, ErrorIds.AssemblyLoadFailed, ErrorCategory.OperationStopped, null));
+ }
+ }
+ }
}
diff --git a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
index 2597d3799..9bb7695ce 100644
--- a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
+++ b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
@@ -7,8 +7,8 @@
-
-
+
+
diff --git a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
index 364180edc..ad3399bf9 100644
--- a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
@@ -283,6 +283,12 @@ namespace ICSharpCode.Decompiler.Tests
RunCS(options: options);
}
+ [Test]
+ public void LocalFunctions([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions options)
+ {
+ RunCS(options: options);
+ }
+
void RunCS([CallerMemberName] string testName = null, CSharpCompilerOptions options = CSharpCompilerOptions.UseDebug)
{
string testFileName = testName + ".cs";
diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
index e0d344ba4..f3b3721d5 100644
--- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -63,15 +63,19 @@
+
+
+
+
diff --git a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
index 1f2f12598..12fcbb8fd 100644
--- a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
@@ -118,6 +118,12 @@ namespace ICSharpCode.Decompiler.Tests
Run();
}
+ [Test]
+ public void Issue1256()
+ {
+ Run();
+ }
+
[Test]
public void FSharpLoops_Debug()
{
diff --git a/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs b/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs
new file mode 100644
index 000000000..898852b39
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs
@@ -0,0 +1,383 @@
+// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.Decompiler.CSharp.OutputVisitor;
+using ICSharpCode.Decompiler.Output;
+using ICSharpCode.Decompiler.Tests.TypeSystem;
+using ICSharpCode.Decompiler.TypeSystem;
+using ICSharpCode.Decompiler.TypeSystem.Implementation;
+using NUnit.Framework;
+
+using static ICSharpCode.Decompiler.Output.ConversionFlags;
+
+namespace ICSharpCode.Decompiler.Tests.Output
+{
+ [TestFixture]
+ public class CSharpAmbienceTests
+ {
+ ICompilation compilation;
+ CSharpAmbience ambience;
+
+ [OneTimeSetUp]
+ public void FixtureSetUp()
+ {
+ ambience = new CSharpAmbience();
+
+ compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly,
+ TypeSystemLoaderTests.Mscorlib.WithOptions(TypeSystemOptions.Default));
+ }
+
+ ITypeDefinition GetDefinition(Type type)
+ {
+ if (type == null) {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ var foundType = compilation.FindType(type).GetDefinition();
+ Assert.IsNotNull(foundType);
+ return foundType;
+ }
+
+ const ConversionFlags ILSpyMainTreeViewTypeFlags = ShowTypeParameterList | PlaceReturnTypeAfterParameterList;
+ const ConversionFlags ILSpyMainTreeViewMemberFlags = ILSpyMainTreeViewTypeFlags | ShowParameterList | ShowReturnType | ShowParameterModifiers;
+
+ #region ITypeDefinition tests
+ [TestCase(None, "Dictionary")]
+ [TestCase(ShowDefinitionKeyword, "class Dictionary")]
+ [TestCase(ShowAccessibility, "public Dictionary")]
+ [TestCase(ShowDefinitionKeyword | ShowAccessibility, "public class Dictionary")]
+ [TestCase(ShowTypeParameterList, "Dictionary")]
+ [TestCase(ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "public class Dictionary")]
+ [TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList, "System.Collections.Generic.Dictionary")]
+ [TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "public class System.Collections.Generic.Dictionary")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "Dictionary")]
+ public void GenericType(ConversionFlags flags, string expectedOutput)
+ {
+ var typeDef = GetDefinition(typeof(Dictionary<,>));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef));
+ }
+
+ [TestCase(None, "Object")]
+ [TestCase(ShowDefinitionKeyword, "class Object")]
+ [TestCase(ShowAccessibility, "public Object")]
+ [TestCase(ShowDefinitionKeyword | ShowAccessibility, "public class Object")]
+ [TestCase(ShowTypeParameterList, "Object")]
+ [TestCase(ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "public class Object")]
+ [TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList, "System.Object")]
+ [TestCase(All, "public class System.Object")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "Object")]
+ public void SimpleType(ConversionFlags flags, string expectedOutput)
+ {
+ var typeDef = GetDefinition(typeof(object));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef));
+ }
+
+ [TestCase(None, "IEnumerable")]
+ [TestCase(ShowTypeParameterList, "IEnumerable")]
+ [TestCase(ShowTypeParameterList | ShowTypeParameterVarianceModifier, "IEnumerable")]
+ [TestCase(All, "public interface System.Collections.Generic.IEnumerable")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "IEnumerable")]
+ public void GenericInterface(ConversionFlags flags, string expectedOutput)
+ {
+ var typeDef = GetDefinition(typeof(IEnumerable<>));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef));
+ }
+
+ [TestCase(None, "Enumerator")]
+ [TestCase(ShowDefinitionKeyword, "struct Enumerator")]
+ [TestCase(ShowAccessibility, "public Enumerator")]
+ [TestCase(ShowDefinitionKeyword | ShowAccessibility, "public struct Enumerator")]
+ [TestCase(ShowTypeParameterList, "Enumerator")]
+ [TestCase(ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "public struct Enumerator")]
+ [TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList, "System.Collections.Generic.List.Enumerator")]
+ [TestCase(ShowDeclaringType | ShowTypeParameterList, "List.Enumerator")]
+ [TestCase(All, "public struct System.Collections.Generic.List.Enumerator")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "Enumerator")]
+ public void GenericTypeWithNested(ConversionFlags flags, string expectedOutput)
+ {
+ var typeDef = GetDefinition(typeof(List<>.Enumerator));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef));
+ }
+
+ [TestCase(None, "StaticClass")]
+ [TestCase(ShowDefinitionKeyword, "class StaticClass")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword, "static class StaticClass")]
+ [TestCase(ShowModifiers | ShowAccessibility, "private static StaticClass")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, "private static class StaticClass")]
+ [TestCase(ShowModifiers | ShowTypeParameterList, "static StaticClass")]
+ [TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "private static class StaticClass")]
+ [TestCase(All, "private static class ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.StaticClass")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "StaticClass")]
+ public void StaticClassTest(ConversionFlags flags, string expectedOutput)
+ {
+ var typeDef = GetDefinition(typeof(StaticClass));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef));
+ }
+
+ [TestCase(None, "SealedClass")]
+ [TestCase(ShowDefinitionKeyword, "class SealedClass")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword, "sealed class SealedClass")]
+ [TestCase(ShowModifiers | ShowAccessibility, "private sealed SealedClass")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, "private sealed class SealedClass")]
+ [TestCase(ShowModifiers | ShowTypeParameterList, "sealed SealedClass")]
+ [TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "private sealed class SealedClass")]
+ [TestCase(All, "private sealed class ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.SealedClass")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "SealedClass")]
+ public void SealedClassTest(ConversionFlags flags, string expectedOutput)
+ {
+ var typeDef = GetDefinition(typeof(SealedClass));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef));
+ }
+
+ [TestCase(None, "RefStruct")]
+ [TestCase(ShowDefinitionKeyword, "struct RefStruct")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword, "ref struct RefStruct")]
+ [TestCase(ShowModifiers | ShowAccessibility, "private ref RefStruct")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, "private ref struct RefStruct")]
+ [TestCase(ShowModifiers | ShowTypeParameterList, "ref RefStruct")]
+ [TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "private ref struct RefStruct")]
+ [TestCase(All, "private ref struct ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.RefStruct")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "RefStruct")]
+ public void RefStructTest(ConversionFlags flags, string expectedOutput)
+ {
+ var typeDef = GetDefinition(typeof(RefStruct));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef));
+ }
+
+ [TestCase(None, "ReadonlyStruct")]
+ [TestCase(ShowDefinitionKeyword, "struct ReadonlyStruct")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword, "readonly struct ReadonlyStruct")]
+ [TestCase(ShowModifiers | ShowAccessibility, "private readonly ReadonlyStruct")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, "private readonly struct ReadonlyStruct")]
+ [TestCase(ShowModifiers | ShowTypeParameterList, "readonly ReadonlyStruct")]
+ [TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "private readonly struct ReadonlyStruct")]
+ [TestCase(All, "private readonly struct ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.ReadonlyStruct")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "ReadonlyStruct")]
+ public void ReadonlyStructTest(ConversionFlags flags, string expectedOutput)
+ {
+ var typeDef = GetDefinition(typeof(ReadonlyStruct));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef));
+ }
+
+ [TestCase(None, "ReadonlyRefStruct")]
+ [TestCase(ShowDefinitionKeyword, "struct ReadonlyRefStruct")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword, "readonly ref struct ReadonlyRefStruct")]
+ [TestCase(ShowModifiers | ShowAccessibility, "private readonly ref ReadonlyRefStruct")]
+ [TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, "private readonly ref struct ReadonlyRefStruct")]
+ [TestCase(ShowModifiers | ShowTypeParameterList, "readonly ref ReadonlyRefStruct")]
+ [TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "private readonly ref struct ReadonlyRefStruct")]
+ [TestCase(All, "private readonly ref struct ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.ReadonlyRefStruct")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "ReadonlyRefStruct")]
+ public void ReadonlyRefStructTest(ConversionFlags flags, string expectedOutput)
+ {
+ var typeDef = GetDefinition(typeof(ReadonlyRefStruct));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef));
+ }
+ #endregion
+
+ #region Delegate tests
+ [TestCase(None, "Func")]
+ [TestCase(ShowTypeParameterList, "Func")]
+ [TestCase(ShowTypeParameterList | ShowTypeParameterVarianceModifier, "Func")]
+ [TestCase(ShowTypeParameterList | ShowReturnType | ShowTypeParameterVarianceModifier, "TResult Func")]
+ [TestCase(ShowTypeParameterList | ShowParameterList | ShowTypeParameterVarianceModifier, "Func(T)")]
+ [TestCase(ShowTypeParameterList | ShowParameterList | ShowReturnType | ShowTypeParameterVarianceModifier, "TResult Func(T)")]
+ [TestCase(All & ~PlaceReturnTypeAfterParameterList, "public delegate TResult System.Func(T arg);")]
+ [TestCase(All, "public delegate System.Func(T arg) : TResult;")]
+ [TestCase(ILSpyMainTreeViewTypeFlags, "Func")]
+ public void FuncDelegate(ConversionFlags flags, string expectedOutput)
+ {
+ var func = GetDefinition(typeof(Func<,>));
+ ambience.ConversionFlags = flags;
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(func));
+ }
+ #endregion
+
+ #region IField tests
+ [TestCase(All & ~PlaceReturnTypeAfterParameterList, "private int ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.Program.test;")]
+ [TestCase(ILSpyMainTreeViewMemberFlags, "test : int")]
+ [TestCase(ConversionFlags.All & ~(ConversionFlags.ShowDeclaringType | ConversionFlags.ShowModifiers | ConversionFlags.ShowAccessibility | ConversionFlags.PlaceReturnTypeAfterParameterList), "int test;")]
+ public void SimpleField(ConversionFlags flags, string expectedOutput)
+ {
+ var field = GetDefinition(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "test").Single();
+ ambience.ConversionFlags = flags;
+
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(field));
+ }
+
+ [TestCase(All & ~PlaceReturnTypeAfterParameterList, "private const int ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.Program.TEST2;")]
+ [TestCase(ILSpyMainTreeViewMemberFlags, "TEST2 : int")]
+ public void SimpleConstField(ConversionFlags flags, string expectedOutput)
+ {
+ var field = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "TEST2").Single();
+ ambience.ConversionFlags = flags;
+
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(field));
+ }
+ #endregion
+
+ #region IEvent tests
+ [Test]
+ public void EventWithDeclaringType()
+ {
+ var ev = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetEvents(f => f.Name == "ProgramChanged").Single();
+ ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.ShowDeclaringType;
+ string result = ambience.ConvertSymbol(ev);
+
+ Assert.AreEqual("public event EventHandler Program.ProgramChanged;", result);
+ }
+
+ [Test]
+ public void CustomEvent()
+ {
+ var ev = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetEvents(f => f.Name == "SomeEvent").Single();
+ ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
+ string result = ambience.ConvertSymbol(ev);
+
+ Assert.AreEqual("public event EventHandler SomeEvent;", result);
+ }
+ #endregion
+
+ #region Property tests
+ [TestCase(StandardConversionFlags, "public int Test { get; set; }")]
+ [TestCase(ILSpyMainTreeViewMemberFlags, "Test : int")]
+ public void AutomaticProperty(ConversionFlags flags, string expectedOutput)
+ {
+ var prop = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetProperties(p => p.Name == "Test").Single();
+ ambience.ConversionFlags = flags;
+
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(prop));
+ }
+
+ [TestCase(StandardConversionFlags, "public int this[int index] { get; }")]
+ [TestCase(ILSpyMainTreeViewMemberFlags, "this[int] : int")]
+ public void Indexer(ConversionFlags flags, string expectedOutput)
+ {
+ var prop = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetProperties(p => p.IsIndexer).Single();
+ ambience.ConversionFlags = flags;
+
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(prop));
+ }
+ #endregion
+
+ #region IMethod tests
+ [TestCase(StandardConversionFlags, "public Program(int x);")]
+ [TestCase(ILSpyMainTreeViewMemberFlags, "Program(int)")]
+ public void ConstructorTests(ConversionFlags flags, string expectedOutput)
+ {
+ var prop = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetConstructors().Single();
+ ambience.ConversionFlags = flags;
+
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(prop));
+ }
+
+ [TestCase(StandardConversionFlags, "~Program();")]
+ [TestCase(ILSpyMainTreeViewMemberFlags, "~Program()")]
+ public void DestructorTests(ConversionFlags flags, string expectedOutput)
+ {
+ var dtor = compilation.FindType(typeof(CSharpAmbienceTests.Program))
+ .GetMembers(m => m.SymbolKind == SymbolKind.Destructor, GetMemberOptions.IgnoreInheritedMembers).Single();
+ ambience.ConversionFlags = flags;
+
+ Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(dtor));
+ }
+ #endregion
+
+ #region Test types
+#pragma warning disable 169, 67
+
+ class Test { }
+ static class StaticClass { }
+ sealed class SealedClass { }
+ ref struct RefStruct { }
+ readonly struct ReadonlyStruct { }
+ readonly ref struct ReadonlyRefStruct { }
+
+ class Program
+ {
+ int test;
+ const int TEST2 = 2;
+
+ public int Test { get; set; }
+
+ public int this[int index] {
+ get {
+ return index;
+ }
+ }
+
+ public event EventHandler ProgramChanged;
+
+ public event EventHandler SomeEvent {
+ add { }
+ remove { }
+ }
+
+ public static bool operator +(Program lhs, Program rhs)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static implicit operator Test(Program lhs)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static explicit operator int(Program lhs)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Program(int x)
+ {
+
+ }
+
+ ~Program()
+ {
+
+ }
+
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Hello World!");
+
+ Console.Write("Press any key to continue . . . ");
+ Console.ReadKey(true);
+ }
+
+ public static void InParameter(in int a)
+ {
+
+ }
+ }
+ #endregion
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/LocalFunctions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/LocalFunctions.cs
new file mode 100644
index 000000000..f05d95f27
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/LocalFunctions.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LocalFunctions
+{
+ class LocalFunctions
+ {
+ int field;
+
+ public static void Main(string[] args)
+ {
+ StaticContextNoCapture(10);
+ StaticContextSimpleCapture(10);
+ StaticContextCaptureInForLoop(10);
+ var inst = new LocalFunctions() { field = 10 };
+ inst.ContextNoCapture();
+ inst.ContextSimpleCapture();
+ inst.ContextCaptureInForLoop();
+ }
+
+ public static void StaticContextNoCapture(int length)
+ {
+ for (int i = 0; i < length; i++) {
+ LocalWrite("Hello " + i);
+ }
+
+ void LocalWrite(string s) => Console.WriteLine(s);
+ }
+
+ public static void StaticContextSimpleCapture(int length)
+ {
+ for (int i = 0; i < length; i++) {
+ LocalWrite();
+ }
+
+ void LocalWrite() => Console.WriteLine("Hello " + length);
+ }
+
+ public static void StaticContextCaptureInForLoop(int length)
+ {
+ for (int i = 0; i < length; i++) {
+ void LocalWrite() => Console.WriteLine("Hello " + i + "/" + length);
+ LocalWrite();
+ }
+ }
+
+ public void ContextNoCapture()
+ {
+ for (int i = 0; i < field; i++) {
+ LocalWrite("Hello " + i);
+ }
+
+ void LocalWrite(string s) => Console.WriteLine(s);
+ }
+
+ public void ContextSimpleCapture()
+ {
+ for (int i = 0; i < field; i++) {
+ LocalWrite();
+ }
+
+ void LocalWrite() => Console.WriteLine("Hello " + field);
+ }
+
+ public void ContextCaptureInForLoop()
+ {
+ for (int i = 0; i < field; i++) {
+ void LocalWrite() => Console.WriteLine("Hello " + i + "/" + field);
+ LocalWrite();
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1256.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1256.cs
new file mode 100644
index 000000000..f00a9f8a4
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1256.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
+{
+ internal class Issue1256
+ {
+ public void Method(Enum e, object o, string s)
+ {
+ int num = (int)(object)e;
+ object obj = new object();
+ int num2 = (int)obj;
+ long num3 = (long)o;
+ int num4 = (int)(object)s;
+ int num5 = (int)num3;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1256.il b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1256.il
new file mode 100644
index 000000000..12fe8844b
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1256.il
@@ -0,0 +1,58 @@
+.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1256
+ extends [mscorlib]System.Object
+{
+ // Methods
+ .method public hidebysig
+ instance void Method (
+ class [mscorlib]System.Enum e,
+ object o,
+ string s
+ ) cil managed
+ {
+ // Method begins at RVA 0x2050
+ // Code size 41 (0x29)
+ .maxstack 1
+ .locals init (
+ [0] int32,
+ [1] object,
+ [2] int32,
+ [3] int64,
+ [4] int32,
+ [5] int32
+ )
+
+ IL_0000: nop
+ IL_0001: ldarg.1
+ IL_0002: unbox.any [mscorlib]System.Int32
+ IL_0007: stloc.0
+ IL_0008: newobj instance void [mscorlib]System.Object::.ctor()
+ IL_000d: stloc.1
+ IL_000e: ldloc.1
+ IL_000f: unbox.any [mscorlib]System.Int32
+ IL_0014: stloc.2
+ IL_0015: ldarg.2
+ IL_0016: unbox.any [mscorlib]System.Int64
+ IL_001b: stloc.3
+ IL_001c: ldarg.3
+ IL_001d: unbox.any [mscorlib]System.Int32
+ IL_0022: stloc.s 4
+ IL_0024: ldloc.3
+ IL_0025: conv.i4
+ IL_0026: stloc.s 5
+ IL_0028: ret
+ } // end of method Issue1256::Method
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ // Method begins at RVA 0x2085
+ // Code size 8 (0x8)
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method Issue1256::.ctor
+
+} // end of class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue1256
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs
index 6712769d9..727680634 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs
@@ -48,6 +48,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
+ internal class GenericClassWithCtor
+ {
+ }
+
+ internal class GenericClassWithMultipleCtors
+ {
+ public GenericClassWithMultipleCtors()
+ {
+ }
+
+ public GenericClassWithMultipleCtors(int x)
+ {
+ }
+ }
+
private class AssertTest
{
private struct DataStruct
@@ -78,7 +93,218 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
+ public class Administrator
+ {
+ public int ID {
+ get;
+ set;
+ }
+
+ public string TrueName {
+ get;
+ set;
+ }
+
+ public string Phone {
+ get;
+ set;
+ }
+ }
+
+ public class Contract
+ {
+ public int ID {
+ get;
+ set;
+ }
+
+ public string ContractNo {
+ get;
+ set;
+ }
+
+ public string HouseAddress {
+ get;
+ set;
+ }
+
+ public DateTime SigningTime {
+ get;
+ set;
+ }
+
+ public string BuyerName {
+ get;
+ set;
+ }
+
+ public string BuyerTelephone {
+ get;
+ set;
+ }
+
+ public string Customer {
+ get;
+ set;
+ }
+
+ public string CustTelephone {
+ get;
+ set;
+ }
+
+ public int AdminID {
+ get;
+ set;
+ }
+
+ public int StoreID {
+ get;
+ set;
+ }
+ }
+
+ public class Database
+ {
+ public IQueryable Contracts {
+ get;
+ set;
+ }
+
+ public IQueryable Loan {
+ get;
+ set;
+ }
+
+ public IQueryable Administrator {
+ get;
+ set;
+ }
+
+ public IQueryable Store {
+ get;
+ set;
+ }
+ }
+
+ public class Loan
+ {
+ public string ContractNo {
+ get;
+ set;
+ }
+
+ public DateTime? ShenDate {
+ get;
+ set;
+ }
+
+ public DateTime? LoanDate {
+ get;
+ set;
+ }
+
+ public string Credit {
+ get;
+ set;
+ }
+
+ public string LoanBank {
+ get;
+ set;
+ }
+
+ public string Remarks {
+ get;
+ set;
+ }
+ }
+
+ public class Store
+ {
+ public int ID {
+ get;
+ set;
+ }
+
+ public string Name {
+ get;
+ set;
+ }
+ }
+
+ internal class MyClass
+ {
+ public static MyClass operator +(MyClass a, MyClass b)
+ {
+ return new MyClass();
+ }
+ }
+
+ internal class SimpleType
+ {
+ public const int ConstField = 1;
+
+ public static readonly int StaticReadonlyField = 2;
+
+ public static int StaticField = 3;
+
+ public readonly int ReadonlyField = 2;
+
+ public int Field = 3;
+
+#if CS60
+ public static int StaticReadonlyProperty => 0;
+#else
+ public static int StaticReadonlyProperty {
+ get {
+ return 0;
+ }
+ }
+#endif
+
+ public static int StaticProperty {
+ get;
+ set;
+ }
+
+#if CS60
+ public int ReadonlyProperty => 0;
+#else
+ public int ReadonlyProperty {
+ get {
+ return 0;
+ }
+ }
+#endif
+
+ public int Property {
+ get;
+ set;
+ }
+ }
+
+ internal class SimpleTypeWithCtor
+ {
+ public SimpleTypeWithCtor(int i)
+ {
+ }
+ }
+
+ internal class SimpleTypeWithMultipleCtors
+ {
+ public SimpleTypeWithMultipleCtors()
+ {
+ }
+
+ public SimpleTypeWithMultipleCtors(int i)
+ {
+ }
+ }
+
private int field;
+ private Database db;
+ private dynamic ViewBag;
public static readonly object[] SupportedMethods = new object[2] {
ToCode(null, () => ((IQueryable