mirror of https://github.com/icsharpcode/ILSpy.git
75 changed files with 21794 additions and 4851 deletions
@ -0,0 +1,383 @@
@@ -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<TKey,TValue>")] |
||||
[TestCase(ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "public class Dictionary<TKey,TValue>")] |
||||
[TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList, "System.Collections.Generic.Dictionary<TKey,TValue>")] |
||||
[TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, "public class System.Collections.Generic.Dictionary<TKey,TValue>")] |
||||
[TestCase(ILSpyMainTreeViewTypeFlags, "Dictionary<TKey,TValue>")] |
||||
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<T>")] |
||||
[TestCase(ShowTypeParameterList | ShowTypeParameterVarianceModifier, "IEnumerable<out T>")] |
||||
[TestCase(All, "public interface System.Collections.Generic.IEnumerable<out T>")] |
||||
[TestCase(ILSpyMainTreeViewTypeFlags, "IEnumerable<T>")] |
||||
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<T>.Enumerator")] |
||||
[TestCase(ShowDeclaringType | ShowTypeParameterList, "List<T>.Enumerator")] |
||||
[TestCase(All, "public struct System.Collections.Generic.List<T>.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<T,TResult>")] |
||||
[TestCase(ShowTypeParameterList | ShowTypeParameterVarianceModifier, "Func<in T,out TResult>")] |
||||
[TestCase(ShowTypeParameterList | ShowReturnType | ShowTypeParameterVarianceModifier, "TResult Func<in T,out TResult>")] |
||||
[TestCase(ShowTypeParameterList | ShowParameterList | ShowTypeParameterVarianceModifier, "Func<in T,out TResult>(T)")] |
||||
[TestCase(ShowTypeParameterList | ShowParameterList | ShowReturnType | ShowTypeParameterVarianceModifier, "TResult Func<in T,out TResult>(T)")] |
||||
[TestCase(All & ~PlaceReturnTypeAfterParameterList, "public delegate TResult System.Func<in T,out TResult>(T arg);")] |
||||
[TestCase(All, "public delegate System.Func<in T,out TResult>(T arg) : TResult;")] |
||||
[TestCase(ILSpyMainTreeViewTypeFlags, "Func<T,TResult>")] |
||||
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
|
||||
} |
||||
} |
||||
@ -0,0 +1,76 @@
@@ -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(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,17 @@
@@ -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; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,58 @@
@@ -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 |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.Immutable; |
||||
using System.Reflection; |
||||
using System.Reflection.Metadata; |
||||
using System.Text; |
||||
using System.Text.RegularExpressions; |
||||
using ICSharpCode.Decompiler.Metadata; |
||||
using ICSharpCode.Decompiler.Util; |
||||
|
||||
namespace ICSharpCode.Decompiler.IL.Transforms |
||||
{ |
||||
class LocalFunctionDecompiler : IILTransform |
||||
{ |
||||
public void Run(ILFunction function, ILTransformContext context) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public static bool IsLocalFunctionMethod(PEFile module, MethodDefinitionHandle methodHandle) |
||||
{ |
||||
var metadata = module.Metadata; |
||||
var method = metadata.GetMethodDefinition(methodHandle); |
||||
|
||||
if ((method.Attributes & MethodAttributes.Assembly) == 0 || !method.IsCompilerGenerated(metadata)) |
||||
return false; |
||||
|
||||
if (!ParseLocalFunctionName(metadata.GetString(method.Name), out _, out _)) |
||||
return false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public static bool IsLocalFunctionDisplayClass(PEFile module, TypeDefinitionHandle typeHandle) |
||||
{ |
||||
var metadata = module.Metadata; |
||||
var type = metadata.GetTypeDefinition(typeHandle); |
||||
|
||||
if ((type.Attributes & TypeAttributes.NestedPrivate) == 0) |
||||
return false; |
||||
if (!type.HasGeneratedName(metadata)) |
||||
return false; |
||||
|
||||
var declaringTypeHandle = type.GetDeclaringType(); |
||||
var declaringType = metadata.GetTypeDefinition(declaringTypeHandle); |
||||
|
||||
foreach (var method in declaringType.GetMethods()) { |
||||
if (!IsLocalFunctionMethod(module, method)) |
||||
continue; |
||||
var md = metadata.GetMethodDefinition(method); |
||||
if (md.DecodeSignature(new FindTypeDecoder(typeHandle), default).ParameterTypes.Any()) |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Newer Roslyn versions use the format "<callerName>g__functionName|x_y"
|
||||
/// Older versions use "<callerName>g__functionNamex_y"
|
||||
/// </summary>
|
||||
static readonly Regex functionNameRegex = new Regex(@"^<(.*)>g__(.*)\|{0,1}\d+_\d+$", RegexOptions.Compiled); |
||||
|
||||
static bool ParseLocalFunctionName(string name, out string callerName, out string functionName) |
||||
{ |
||||
callerName = null; |
||||
functionName = null; |
||||
if (string.IsNullOrWhiteSpace(name)) |
||||
return false; |
||||
var match = functionNameRegex.Match(name); |
||||
callerName = match.Groups[1].Value; |
||||
functionName = match.Groups[2].Value; |
||||
return match.Success; |
||||
} |
||||
|
||||
struct FindTypeDecoder : ISignatureTypeProvider<bool, Unit> |
||||
{ |
||||
TypeDefinitionHandle handle; |
||||
|
||||
public FindTypeDecoder(TypeDefinitionHandle handle) |
||||
{ |
||||
this.handle = handle; |
||||
} |
||||
|
||||
public bool GetArrayType(bool elementType, ArrayShape shape) => elementType; |
||||
public bool GetByReferenceType(bool elementType) => elementType; |
||||
public bool GetFunctionPointerType(MethodSignature<bool> signature) => false; |
||||
public bool GetGenericInstantiation(bool genericType, ImmutableArray<bool> typeArguments) => genericType; |
||||
public bool GetGenericMethodParameter(Unit genericContext, int index) => false; |
||||
public bool GetGenericTypeParameter(Unit genericContext, int index) => false; |
||||
public bool GetModifiedType(bool modifier, bool unmodifiedType, bool isRequired) => unmodifiedType; |
||||
public bool GetPinnedType(bool elementType) => elementType; |
||||
public bool GetPointerType(bool elementType) => elementType; |
||||
public bool GetPrimitiveType(PrimitiveTypeCode typeCode) => false; |
||||
public bool GetSZArrayType(bool elementType) => false; |
||||
|
||||
public bool GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) |
||||
{ |
||||
return this.handle == handle; |
||||
} |
||||
|
||||
public bool GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public bool GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) |
||||
{ |
||||
return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,129 +0,0 @@
@@ -1,129 +0,0 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using ICSharpCode.Decompiler.Metadata; |
||||
using ICSharpCode.Decompiler.Tests.TypeSystem; |
||||
using ICSharpCode.Decompiler.TypeSystem; |
||||
using ICSharpCode.Decompiler.TypeSystem.Implementation; |
||||
using ICSharpCode.ILSpy; |
||||
using NUnit.Framework; |
||||
|
||||
namespace ILSpy.Tests.Languages |
||||
{ |
||||
[TestFixture, Parallelizable(ParallelScope.All)] |
||||
public class CSharpLanguageTests |
||||
{ |
||||
const string ns = "ICSharpCode.Decompiler.Tests.TypeSystem"; |
||||
|
||||
static PEFile LoadAssembly(string filename) |
||||
{ |
||||
return new PEFile(filename, new FileStream(filename, FileMode.Open, FileAccess.Read)); |
||||
} |
||||
|
||||
static readonly Lazy<PEFile> mscorlib = new Lazy<PEFile>( |
||||
delegate { |
||||
return LoadAssembly(typeof(object).Assembly.Location); |
||||
}); |
||||
|
||||
static readonly Lazy<PEFile> systemCore = new Lazy<PEFile>( |
||||
delegate { |
||||
return LoadAssembly(typeof(System.Linq.Enumerable).Assembly.Location); |
||||
}); |
||||
|
||||
static readonly Lazy<PEFile> testAssembly = new Lazy<PEFile>( |
||||
delegate { |
||||
return LoadAssembly(typeof(CSharpLanguageTests).Assembly.Location); |
||||
}); |
||||
|
||||
public static PEFile Mscorlib { get { return mscorlib.Value; } } |
||||
public static PEFile SystemCore { get { return systemCore.Value; } } |
||||
public static PEFile TestAssembly { get { return testAssembly.Value; } } |
||||
|
||||
[OneTimeSetUp] |
||||
public void FixtureSetUp() |
||||
{ |
||||
compilation = new SimpleCompilation(TestAssembly, |
||||
Mscorlib.WithOptions(TypeSystemOptions.Default)); |
||||
language = new CSharpLanguage(); |
||||
} |
||||
|
||||
ICompilation compilation; |
||||
CSharpLanguage language; |
||||
|
||||
ITypeDefinition GetTypeDefinition(Type type) |
||||
{ |
||||
return compilation.FindType(type).GetDefinition(); |
||||
} |
||||
|
||||
void TestType(Type t, string ns, string name) |
||||
{ |
||||
var type = GetTypeDefinition(t); |
||||
Assert.AreEqual(name, language.TypeToString(type, includeNamespace: false)); |
||||
Assert.AreEqual(ns + "." + name, language.TypeToString(type, includeNamespace: true)); |
||||
} |
||||
|
||||
void TestMethod(Type t, Predicate<IMember> filter, string ns, string typeName, string name, string paramListReturnType, string longParamListReturnType = null) |
||||
{ |
||||
var type = GetTypeDefinition(t); |
||||
var method = type.GetMembers(filter, GetMemberOptions.IgnoreInheritedMembers).Single() as IMethod; |
||||
if (method == null) |
||||
throw new ArgumentNullException(); |
||||
if (longParamListReturnType == null) |
||||
longParamListReturnType = paramListReturnType; |
||||
Assert.AreEqual(name + paramListReturnType, language.MethodToString(method, includeDeclaringTypeName: false, includeNamespace: false, includeNamespaceOfDeclaringTypeName: false)); |
||||
Assert.AreEqual(typeName + "." + name + paramListReturnType, language.MethodToString(method, includeDeclaringTypeName: true, includeNamespace: false, includeNamespaceOfDeclaringTypeName: false)); |
||||
Assert.AreEqual(name + longParamListReturnType, language.MethodToString(method, includeDeclaringTypeName: false, includeNamespace: true, includeNamespaceOfDeclaringTypeName: false)); |
||||
Assert.AreEqual(typeName + "." + name + longParamListReturnType, language.MethodToString(method, includeDeclaringTypeName: true, includeNamespace: true, includeNamespaceOfDeclaringTypeName: false)); |
||||
Assert.AreEqual(name + paramListReturnType, language.MethodToString(method, includeDeclaringTypeName: false, includeNamespace: false, includeNamespaceOfDeclaringTypeName: true)); |
||||
Assert.AreEqual(ns + "." + typeName + "." + name + paramListReturnType, language.MethodToString(method, includeDeclaringTypeName: true, includeNamespace: false, includeNamespaceOfDeclaringTypeName: true)); |
||||
Assert.AreEqual(name + longParamListReturnType, language.MethodToString(method, includeDeclaringTypeName: false, includeNamespace: true, includeNamespaceOfDeclaringTypeName: true)); |
||||
Assert.AreEqual(ns + "." + typeName + "." + name + longParamListReturnType, language.MethodToString(method, includeDeclaringTypeName: true, includeNamespace: true, includeNamespaceOfDeclaringTypeName: true)); |
||||
} |
||||
|
||||
[Test] |
||||
public void PrimitiveTypes() |
||||
{ |
||||
TestType(typeof(object), "System", "Object"); |
||||
TestType(typeof(string), "System", "String"); |
||||
TestType(typeof(int), "System", "Int32"); |
||||
} |
||||
|
||||
[Test] |
||||
public void ClassTests() |
||||
{ |
||||
TestType(typeof(SimplePublicClass), ns, "SimplePublicClass"); |
||||
TestType(typeof(GenericClass<,>), ns, "GenericClass<A,B>"); |
||||
TestType(typeof(OuterGeneric<>), ns, "OuterGeneric<X>"); |
||||
TestType(typeof(OuterGeneric<>.Inner), ns + ".OuterGeneric<X>", "Inner"); |
||||
} |
||||
|
||||
[Test] |
||||
public void InterfaceTests() |
||||
{ |
||||
TestType(typeof(IBase1), ns, "IBase1"); |
||||
TestType(typeof(IGenericInterface<>), ns, "IGenericInterface<T>"); |
||||
} |
||||
|
||||
[Test] |
||||
public void EnumTests() |
||||
{ |
||||
TestType(typeof(MyEnum), ns, "MyEnum"); |
||||
TestType(typeof(GenericClass<,>.NestedEnum), ns + ".GenericClass<A,B>", "NestedEnum"); |
||||
} |
||||
|
||||
[Test] |
||||
public void DelegateTests() |
||||
{ |
||||
TestType(typeof(GenericDelegate<,>), ns, "GenericDelegate<T,S>"); |
||||
} |
||||
|
||||
[Test] |
||||
public void MethodTests() |
||||
{ |
||||
TestMethod(typeof(IMarshalAsTests), x => x.Name == "QueryApplicationFile", ns, "IMarshalAsTests", "QueryApplicationFile", "(string, out string, out string, out bool, out bool, out object[]) : void"); |
||||
TestMethod(typeof(MyClassWithCtor), x => x is IMethod m && m.IsConstructor, ns, "MyClassWithCtor", "MyClassWithCtor", "(int)"); |
||||
TestMethod(typeof(OuterGeneric<>), x => x is IMethod m && m.IsConstructor, ns, "OuterGeneric<X>", "OuterGeneric<X>", "()"); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue