Browse Source

Merge branch 'master' of https://github.com/icsharpcode/ILSpy into dynamic

pull/1165/head
Siegfried Pammer 7 years ago
parent
commit
ca1c0710f6
  1. 1
      .gitignore
  2. 3
      .gitmodules
  3. 3
      BuildTools/update-assemblyinfo.ps1
  4. 1
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  5. 6
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  6. 6
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  7. 14
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1157.cs
  8. 173
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1157.il
  9. 57
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.cs
  10. 193
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.il
  11. 175
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.opt.il
  12. 178
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.opt.roslyn.il
  13. 196
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.roslyn.il
  14. 20
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs
  15. 45
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs
  16. 265
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.il
  17. 244
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.opt.il
  18. 257
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.opt.roslyn.il
  19. 270
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.roslyn.il
  20. 3
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  21. 119
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  22. 6
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  23. 14
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs
  24. 6
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs
  25. 2
      ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs
  26. 2
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  27. 30
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs
  28. 68
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  29. 16
      ICSharpCode.Decompiler/DecompilerSettings.cs
  30. 8
      ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs
  31. 3
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  32. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template
  33. 4
      ICSharpCode.Decompiler/IL/ILReader.cs
  34. 9
      ICSharpCode.Decompiler/IL/ILVariable.cs
  35. 2
      ICSharpCode.Decompiler/IL/InstructionFlags.cs
  36. 38
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  37. 43
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  38. 7
      ICSharpCode.Decompiler/IL/Instructions/StLoc.cs
  39. 2
      ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs
  40. 2
      ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs
  41. 134
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
  42. 111
      ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs
  43. 2
      ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs
  44. 3
      ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs
  45. 16
      ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs
  46. 5
      ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs
  47. 4
      ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs
  48. 45
      ILSpy.AddIn/Commands/AssemblyReferenceForILSpy.cs
  49. 53
      ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs
  50. 109
      ILSpy.AddIn/Commands/OpenCodeItemCommand.cs
  51. 25
      ILSpy.AddIn/Commands/OpenILSpyCommand.cs
  52. 27
      ILSpy.AddIn/Commands/OpenProjectOutputCommand.cs
  53. 135
      ILSpy.AddIn/Commands/OpenReferenceCommand.cs
  54. 48
      ILSpy.AddIn/Commands/ProjectItemForILSpy.cs
  55. 78
      ILSpy.AddIn/Commands/ProjectReferenceForILSpy.cs
  56. 12
      ILSpy.AddIn/ILSpy.AddIn.csproj
  57. 21
      ILSpy.AddIn/ILSpyAddIn.vsct
  58. 14
      ILSpy.AddIn/ILSpyAddInPackage.cs
  59. 821
      ILSpy.AddIn/SyntaxNodeExtensions.cs
  60. 121
      ILSpy.AddIn/Utils.cs
  61. 2
      ILSpy.AddIn/source.extension.vsixmanifest.template
  62. 12
      ILSpy.sln
  63. 4
      ILSpy/MainWindow.xaml.cs
  64. 1
      cecil

1
.gitignore vendored

@ -11,6 +11,7 @@ _ReSharper*/ @@ -11,6 +11,7 @@ _ReSharper*/
*.patch
.vs/
/ILSpy.AddIn/Packages/*
/ILSpy.AddIn/source.extension.vsixmanifest
/ICSharpCode.Decompiler.Tests/TestCases/Correctness/*.exe
/ICSharpCode.Decompiler.Tests/TestCases/Correctness/*.exe.config
/ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec

3
.gitmodules vendored

@ -1,6 +1,3 @@ @@ -1,6 +1,3 @@
[submodule "cecil"]
path = cecil
url = https://github.com/jbevain/cecil.git
[submodule "ILSpy-tests"]
path = ILSpy-tests
url = https://github.com/icsharpcode/ILSpy-tests

3
BuildTools/update-assemblyinfo.ps1

@ -67,7 +67,8 @@ $templateFiles = ( @@ -67,7 +67,8 @@ $templateFiles = (
@{Input=$globalAssemblyInfoTemplateFile; Output="ILSpy/Properties/AssemblyInfo.cs"},
@{Input="ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs"; Output="ICSharpCode.Decompiler/Properties/AssemblyInfo.cs"},
@{Input="ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template"; Output="ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec"},
@{Input="ILSpy/Properties/app.config.template"; Output = "ILSpy/app.config"}
@{Input="ILSpy/Properties/app.config.template"; Output = "ILSpy/app.config"},
@{Input="ILSpy.AddIn/source.extension.vsixmanifest.template"; Output = "ILSpy.AddIn/source.extension.vsixmanifest"}
);
[string]$mutexId = "ILSpyUpdateAssemblyInfo" + (Get-Location).ToString().GetHashCode();
Write-Host $mutexId;

1
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -69,6 +69,7 @@ @@ -69,6 +69,7 @@
<Compile Include="TestCases\Correctness\RefLocalsAndReturns.cs" />
<Compile Include="TestCases\Pretty\DynamicTests.cs" />
<Compile Include="TestCases\Pretty\Issue1080.cs" />
<Compile Include="TestCases\Pretty\NamedArguments.cs" />
<Compile Include="TestCases\Pretty\QualifierTests.cs" />
<Compile Include="TestCases\Pretty\RefLocalsAndReturns.cs" />
<Compile Include="TestCases\Pretty\TupleTests.cs" />

6
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -112,6 +112,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -112,6 +112,12 @@ namespace ICSharpCode.Decompiler.Tests
Run();
}
[Test]
public void Issue1157()
{
Run();
}
[Test, Ignore("?")]
public void FSharpLoops_Debug()
{

6
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -291,6 +291,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -291,6 +291,12 @@ namespace ICSharpCode.Decompiler.Tests
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void NamedArguments([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Issue1080([ValueSource(nameof(roslynOnlyOptions))] CSharpCompilerOptions cscOptions)
{

14
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1157.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
using System;
namespace Issue1157
{
internal abstract class BaseClass
{
public abstract event EventHandler IDontKnowMeHereOut;
}
internal class OtherClass : BaseClass
{
public override event EventHandler IDontKnowMeHereOut;
}
}

173
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1157.il

@ -0,0 +1,173 @@ @@ -0,0 +1,173 @@
.assembly Issue1157
{
.hash algorithm 0x00008004 // SHA1
.ver 1:0:0:0
}
.module Issue1157.exe
// MVID: {4C6C7F98-AEB2-4A19-BE6F-43171E6113F1}
.corflags 0x00020003 // ILOnly, Required32Bit, Preferred32Bit
.class private auto ansi abstract beforefieldinit Issue1157.BaseClass
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig specialname newslot abstract virtual
instance void add_IDontKnowMeHereOut (
class [mscorlib]System.EventHandler 'value'
) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
} // end of method BaseClass::add_IDontKnowMeHereOut
.method public hidebysig specialname newslot abstract virtual
instance void remove_IDontKnowMeHereOut (
class [mscorlib]System.EventHandler 'value'
) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
} // end of method BaseClass::remove_IDontKnowMeHereOut
.method family hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2063
// 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 BaseClass::.ctor
// Events
.event [mscorlib]System.EventHandler IDontKnowMeHereOut
{
.addon instance void Issue1157.BaseClass::add_IDontKnowMeHereOut(class [mscorlib]System.EventHandler)
.removeon instance void Issue1157.BaseClass::remove_IDontKnowMeHereOut(class [mscorlib]System.EventHandler)
}
} // end of class Issue1157.BaseClass
.class private auto ansi beforefieldinit Issue1157.OtherClass
extends Issue1157.BaseClass
{
// Fields
.field private class [mscorlib]System.EventHandler IDontKnowMeHereOut
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
// Methods
.method public hidebysig specialname virtual
instance void add_IDontKnowMeHereOut (
class [mscorlib]System.EventHandler 'value'
) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x206c
// Code size 41 (0x29)
.maxstack 3
.locals init (
[0] class [mscorlib]System.EventHandler,
[1] class [mscorlib]System.EventHandler,
[2] class [mscorlib]System.EventHandler
)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler Issue1157.OtherClass::IDontKnowMeHereOut
IL_0006: stloc.0
// loop start (head: IL_0007)
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler Issue1157.OtherClass::IDontKnowMeHereOut
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&, !!0, !!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: bne.un.s IL_0007
// end loop
IL_0028: ret
} // end of method OtherClass::add_IDontKnowMeHereOut
.method public hidebysig specialname virtual
instance void remove_IDontKnowMeHereOut (
class [mscorlib]System.EventHandler 'value'
) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x20a4
// Code size 41 (0x29)
.maxstack 3
.locals init (
[0] class [mscorlib]System.EventHandler,
[1] class [mscorlib]System.EventHandler,
[2] class [mscorlib]System.EventHandler
)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler Issue1157.OtherClass::IDontKnowMeHereOut
IL_0006: stloc.0
// loop start (head: IL_0007)
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler Issue1157.OtherClass::IDontKnowMeHereOut
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&, !!0, !!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: bne.un.s IL_0007
// end loop
IL_0028: ret
} // end of method OtherClass::remove_IDontKnowMeHereOut
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20d9
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void Issue1157.BaseClass::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method OtherClass::.ctor
// Events
.event [mscorlib]System.EventHandler IDontKnowMeHereOut
{
.addon instance void Issue1157.OtherClass::add_IDontKnowMeHereOut(class [mscorlib]System.EventHandler)
.removeon instance void Issue1157.OtherClass::remove_IDontKnowMeHereOut(class [mscorlib]System.EventHandler)
}
} // end of class Issue1157.OtherClass

57
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.cs

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
// Copyright (c) 2018 Daniel Grunwald
//
// 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.
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public class NamedArguments
{
private class ClassWithNamedArgCtor
{
internal ClassWithNamedArgCtor(bool arg1 = false, bool arg2 = false)
{
}
internal ClassWithNamedArgCtor()
: this(arg2: Get(1) != 1, arg1: Get(2) == 2)
{
}
}
public void Use(int a, int b, int c)
{
}
public static int Get(int i)
{
return i;
}
public void Test()
{
Use(Get(1), Get(2), Get(3));
Use(Get(1), c: Get(2), b: Get(3));
Use(b: Get(1), a: Get(2), c: Get(3));
}
public void NotNamedArgs()
{
int b = Get(1);
Use(Get(2), b, Get(3));
}
}
}

193
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.il

@ -0,0 +1,193 @@ @@ -0,0 +1,193 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly NamedArguments
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module NamedArguments.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments
extends [mscorlib]System.Object
{
.class auto ansi nested private beforefieldinit ClassWithNamedArgCtor
extends [mscorlib]System.Object
{
.method assembly hidebysig specialname rtspecialname
instance void .ctor([opt] bool arg1,
[opt] bool arg2) cil managed
{
.param [1] = bool(false)
.param [2] = bool(false)
// Code size 10 (0xa)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: nop
IL_0009: ret
} // end of method ClassWithNamedArgCtor::.ctor
.method assembly hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 33 (0x21)
.maxstack 3
.locals init (bool V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0007: ldc.i4.1
IL_0008: ceq
IL_000a: ldc.i4.0
IL_000b: ceq
IL_000d: stloc.0
IL_000e: ldc.i4.2
IL_000f: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0014: ldc.i4.2
IL_0015: ceq
IL_0017: ldloc.0
IL_0018: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments/ClassWithNamedArgCtor::.ctor(bool,
bool)
IL_001d: nop
IL_001e: nop
IL_001f: nop
IL_0020: ret
} // end of method ClassWithNamedArgCtor::.ctor
} // end of class ClassWithNamedArgCtor
.method public hidebysig instance void
Use(int32 a,
int32 b,
int32 c) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method NamedArguments::Use
.method public hidebysig static int32 Get(int32 i) cil managed
{
// Code size 7 (0x7)
.maxstack 1
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: stloc.0
IL_0003: br.s IL_0005
IL_0005: ldloc.0
IL_0006: ret
} // end of method NamedArguments::Get
.method public hidebysig instance void
Test() cil managed
{
// Code size 81 (0x51)
.maxstack 4
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0008: ldc.i4.2
IL_0009: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_000e: ldc.i4.3
IL_000f: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0014: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_0019: nop
IL_001a: ldarg.0
IL_001b: ldc.i4.1
IL_001c: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0021: ldc.i4.2
IL_0022: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0027: stloc.0
IL_0028: ldc.i4.3
IL_0029: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_002e: ldloc.0
IL_002f: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_0034: nop
IL_0035: ldarg.0
IL_0036: ldc.i4.1
IL_0037: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_003c: stloc.0
IL_003d: ldc.i4.2
IL_003e: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0043: ldloc.0
IL_0044: ldc.i4.3
IL_0045: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_004a: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_004f: nop
IL_0050: ret
} // end of method NamedArguments::Test
.method public hidebysig instance void
NotNamedArgs() cil managed
{
// Code size 29 (0x1d)
.maxstack 4
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0007: stloc.0
IL_0008: ldarg.0
IL_0009: ldc.i4.2
IL_000a: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_000f: ldloc.0
IL_0010: ldc.i4.3
IL_0011: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0016: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_001b: nop
IL_001c: ret
} // end of method NamedArguments::NotNamedArgs
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method NamedArguments::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

175
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.opt.il

@ -0,0 +1,175 @@ @@ -0,0 +1,175 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly NamedArguments.opt
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module NamedArguments.opt.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments
extends [mscorlib]System.Object
{
.class auto ansi nested private beforefieldinit ClassWithNamedArgCtor
extends [mscorlib]System.Object
{
.method assembly hidebysig specialname rtspecialname
instance void .ctor([opt] bool arg1,
[opt] bool arg2) cil managed
{
.param [1] = bool(false)
.param [2] = bool(false)
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method ClassWithNamedArgCtor::.ctor
.method assembly hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 30 (0x1e)
.maxstack 3
.locals init (bool V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0007: ldc.i4.1
IL_0008: ceq
IL_000a: ldc.i4.0
IL_000b: ceq
IL_000d: stloc.0
IL_000e: ldc.i4.2
IL_000f: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0014: ldc.i4.2
IL_0015: ceq
IL_0017: ldloc.0
IL_0018: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments/ClassWithNamedArgCtor::.ctor(bool,
bool)
IL_001d: ret
} // end of method ClassWithNamedArgCtor::.ctor
} // end of class ClassWithNamedArgCtor
.method public hidebysig instance void
Use(int32 a,
int32 b,
int32 c) cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method NamedArguments::Use
.method public hidebysig static int32 Get(int32 i) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ret
} // end of method NamedArguments::Get
.method public hidebysig instance void
Test() cil managed
{
// Code size 77 (0x4d)
.maxstack 4
.locals init (int32 V_0,
int32 V_1)
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0007: ldc.i4.2
IL_0008: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_000d: ldc.i4.3
IL_000e: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0013: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_0018: ldarg.0
IL_0019: ldc.i4.1
IL_001a: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_001f: ldc.i4.2
IL_0020: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0025: stloc.0
IL_0026: ldc.i4.3
IL_0027: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_002c: ldloc.0
IL_002d: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_0032: ldarg.0
IL_0033: ldc.i4.1
IL_0034: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0039: stloc.1
IL_003a: ldc.i4.2
IL_003b: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0040: ldloc.1
IL_0041: ldc.i4.3
IL_0042: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0047: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_004c: ret
} // end of method NamedArguments::Test
.method public hidebysig instance void
NotNamedArgs() cil managed
{
// Code size 27 (0x1b)
.maxstack 4
.locals init (int32 V_0)
IL_0000: ldc.i4.1
IL_0001: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0006: stloc.0
IL_0007: ldarg.0
IL_0008: ldc.i4.2
IL_0009: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_000e: ldloc.0
IL_000f: ldc.i4.3
IL_0010: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0015: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_001a: ret
} // end of method NamedArguments::NotNamedArgs
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method NamedArguments::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

178
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.opt.roslyn.il

@ -0,0 +1,178 @@ @@ -0,0 +1,178 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly NamedArguments
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module NamedArguments.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments
extends [mscorlib]System.Object
{
.class auto ansi nested private beforefieldinit ClassWithNamedArgCtor
extends [mscorlib]System.Object
{
.method assembly hidebysig specialname rtspecialname
instance void .ctor([opt] bool arg1,
[opt] bool arg2) cil managed
{
.param [1] = bool(false)
.param [2] = bool(false)
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method ClassWithNamedArgCtor::.ctor
.method assembly hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 30 (0x1e)
.maxstack 3
.locals init (bool V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0007: ldc.i4.1
IL_0008: ceq
IL_000a: ldc.i4.0
IL_000b: ceq
IL_000d: stloc.0
IL_000e: ldc.i4.2
IL_000f: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0014: ldc.i4.2
IL_0015: ceq
IL_0017: ldloc.0
IL_0018: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments/ClassWithNamedArgCtor::.ctor(bool,
bool)
IL_001d: ret
} // end of method ClassWithNamedArgCtor::.ctor
} // end of class ClassWithNamedArgCtor
.method public hidebysig instance void
Use(int32 a,
int32 b,
int32 c) cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method NamedArguments::Use
.method public hidebysig static int32 Get(int32 i) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ret
} // end of method NamedArguments::Get
.method public hidebysig instance void
Test() cil managed
{
// Code size 77 (0x4d)
.maxstack 4
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0007: ldc.i4.2
IL_0008: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_000d: ldc.i4.3
IL_000e: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0013: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_0018: ldarg.0
IL_0019: ldc.i4.1
IL_001a: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_001f: ldc.i4.2
IL_0020: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0025: stloc.0
IL_0026: ldc.i4.3
IL_0027: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_002c: ldloc.0
IL_002d: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_0032: ldarg.0
IL_0033: ldc.i4.1
IL_0034: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0039: stloc.0
IL_003a: ldc.i4.2
IL_003b: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0040: ldloc.0
IL_0041: ldc.i4.3
IL_0042: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0047: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_004c: ret
} // end of method NamedArguments::Test
.method public hidebysig instance void
NotNamedArgs() cil managed
{
// Code size 27 (0x1b)
.maxstack 4
.locals init (int32 V_0)
IL_0000: ldc.i4.1
IL_0001: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0006: stloc.0
IL_0007: ldarg.0
IL_0008: ldc.i4.2
IL_0009: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_000e: ldloc.0
IL_000f: ldc.i4.3
IL_0010: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0015: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_001a: ret
} // end of method NamedArguments::NotNamedArgs
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method NamedArguments::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

196
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NamedArguments.roslyn.il

@ -0,0 +1,196 @@ @@ -0,0 +1,196 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly NamedArguments
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module NamedArguments.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments
extends [mscorlib]System.Object
{
.class auto ansi nested private beforefieldinit ClassWithNamedArgCtor
extends [mscorlib]System.Object
{
.method assembly hidebysig specialname rtspecialname
instance void .ctor([opt] bool arg1,
[opt] bool arg2) cil managed
{
.param [1] = bool(false)
.param [2] = bool(false)
// Code size 9 (0x9)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ret
} // end of method ClassWithNamedArgCtor::.ctor
.method assembly hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 32 (0x20)
.maxstack 3
.locals init (bool V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0007: ldc.i4.1
IL_0008: ceq
IL_000a: ldc.i4.0
IL_000b: ceq
IL_000d: stloc.0
IL_000e: ldc.i4.2
IL_000f: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0014: ldc.i4.2
IL_0015: ceq
IL_0017: ldloc.0
IL_0018: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments/ClassWithNamedArgCtor::.ctor(bool,
bool)
IL_001d: nop
IL_001e: nop
IL_001f: ret
} // end of method ClassWithNamedArgCtor::.ctor
} // end of class ClassWithNamedArgCtor
.method public hidebysig instance void
Use(int32 a,
int32 b,
int32 c) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method NamedArguments::Use
.method public hidebysig static int32 Get(int32 i) cil managed
{
// Code size 7 (0x7)
.maxstack 1
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: stloc.0
IL_0003: br.s IL_0005
IL_0005: ldloc.0
IL_0006: ret
} // end of method NamedArguments::Get
.method public hidebysig instance void
Test() cil managed
{
// Code size 81 (0x51)
.maxstack 4
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0008: ldc.i4.2
IL_0009: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_000e: ldc.i4.3
IL_000f: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0014: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_0019: nop
IL_001a: ldarg.0
IL_001b: ldc.i4.1
IL_001c: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0021: ldc.i4.2
IL_0022: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0027: stloc.0
IL_0028: ldc.i4.3
IL_0029: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_002e: ldloc.0
IL_002f: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_0034: nop
IL_0035: ldarg.0
IL_0036: ldc.i4.1
IL_0037: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_003c: stloc.0
IL_003d: ldc.i4.2
IL_003e: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0043: ldloc.0
IL_0044: ldc.i4.3
IL_0045: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_004a: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_004f: nop
IL_0050: ret
} // end of method NamedArguments::Test
.method public hidebysig instance void
NotNamedArgs() cil managed
{
// Code size 29 (0x1d)
.maxstack 4
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0007: stloc.0
IL_0008: ldarg.0
IL_0009: ldc.i4.2
IL_000a: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_000f: ldloc.0
IL_0010: ldc.i4.3
IL_0011: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Get(int32)
IL_0016: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments::Use(int32,
int32,
int32)
IL_001b: nop
IL_001c: ret
} // end of method NamedArguments::NotNamedArgs
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 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 NamedArguments::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.NamedArguments
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

20
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2018 Daniel Grunwald
//
// 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;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{

45
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs

@ -14,6 +14,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -14,6 +14,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
event Action Event;
}
private abstract class BaseClass
{
public abstract event EventHandler ThisIsAnAbstractEvent;
}
private class OtherClass : BaseClass
{
public override event EventHandler ThisIsAnAbstractEvent;
}
private class Impl : IBase
{
int IBase.Test {
@ -32,6 +42,41 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -32,6 +42,41 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
private interface IChange
{
int Property {
get;
set;
}
event EventHandler Changed;
}
private class Change : IChange
{
private EventHandler Changed;
private int backingField;
int IChange.Property {
get {
return backingField;
}
set {
backingField = value;
}
}
event EventHandler IChange.Changed {
add {
Changed = (EventHandler)Delegate.Combine(Changed, value);
}
remove {
Changed = (EventHandler)Delegate.Remove(Changed, value);
}
}
}
[NonSerialized]
private int someField;

265
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.il

@ -56,8 +56,8 @@ @@ -56,8 +56,8 @@
.event [mscorlib]System.Action Event
{
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase::remove_Event(class [mscorlib]System.Action)
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase::add_Event(class [mscorlib]System.Action)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase::remove_Event(class [mscorlib]System.Action)
} // end of event IBase::Event
.property instance int32 Test()
{
@ -66,6 +66,137 @@ @@ -66,6 +66,137 @@
} // end of property IBase::Test
} // end of class IBase
.class abstract auto ansi nested private beforefieldinit BaseClass
extends [mscorlib]System.Object
{
.method public hidebysig newslot specialname abstract virtual
instance void add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
} // end of method BaseClass::add_ThisIsAnAbstractEvent
.method public hidebysig newslot specialname abstract virtual
instance void remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
} // end of method BaseClass::remove_ThisIsAnAbstractEvent
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method BaseClass::.ctor
.event [mscorlib]System.EventHandler ThisIsAnAbstractEvent
{
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
} // end of event BaseClass::ThisIsAnAbstractEvent
} // end of class BaseClass
.class auto ansi nested private beforefieldinit OtherClass
extends ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass
{
.field private class [mscorlib]System.EventHandler ThisIsAnAbstractEvent
.method public hidebysig specialname virtual
instance void add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
// Code size 48 (0x30)
.maxstack 3
.locals init (class [mscorlib]System.EventHandler V_0,
class [mscorlib]System.EventHandler V_1,
class [mscorlib]System.EventHandler V_2,
bool V_3)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,
!!0,
!!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: ceq
IL_0028: ldc.i4.0
IL_0029: ceq
IL_002b: stloc.3
IL_002c: ldloc.3
IL_002d: brtrue.s IL_0007
IL_002f: ret
} // end of method OtherClass::add_ThisIsAnAbstractEvent
.method public hidebysig specialname virtual
instance void remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
// Code size 48 (0x30)
.maxstack 3
.locals init (class [mscorlib]System.EventHandler V_0,
class [mscorlib]System.EventHandler V_1,
class [mscorlib]System.EventHandler V_2,
bool V_3)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,
!!0,
!!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: ceq
IL_0028: ldc.i4.0
IL_0029: ceq
IL_002b: stloc.3
IL_002c: ldloc.3
IL_002d: brtrue.s IL_0007
IL_002f: ret
} // end of method OtherClass::remove_ThisIsAnAbstractEvent
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::.ctor()
IL_0006: ret
} // end of method OtherClass::.ctor
.event [mscorlib]System.EventHandler ThisIsAnAbstractEvent
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
} // end of event OtherClass::ThisIsAnAbstractEvent
} // end of class OtherClass
.class auto ansi nested private beforefieldinit Impl
extends [mscorlib]System.Object
implements ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase
@ -123,8 +254,8 @@ @@ -123,8 +254,8 @@
.event [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Event
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.add_Event(class [mscorlib]System.Action)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.remove_Event(class [mscorlib]System.Action)
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.add_Event(class [mscorlib]System.Action)
} // end of event Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Event
.property instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Test()
{
@ -133,6 +264,134 @@ @@ -133,6 +264,134 @@
} // end of property Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Test
} // end of class Impl
.class interface abstract auto ansi nested private IChange
{
.method public hidebysig newslot specialname abstract virtual
instance int32 get_Property() cil managed
{
} // end of method IChange::get_Property
.method public hidebysig newslot specialname abstract virtual
instance void set_Property(int32 'value') cil managed
{
} // end of method IChange::set_Property
.method public hidebysig newslot specialname abstract virtual
instance void add_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
} // end of method IChange::add_Changed
.method public hidebysig newslot specialname abstract virtual
instance void remove_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
} // end of method IChange::remove_Changed
.event [mscorlib]System.EventHandler Changed
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::add_Changed(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::remove_Changed(class [mscorlib]System.EventHandler)
} // end of event IChange::Changed
.property instance int32 Property()
{
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::set_Property(int32)
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::get_Property()
} // end of property IChange::Property
} // end of class IChange
.class auto ansi nested private beforefieldinit Change
extends [mscorlib]System.Object
implements ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange
{
.field private class [mscorlib]System.EventHandler Changed
.field private int32 backingField
.method private hidebysig newslot specialname virtual final
instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property() cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::get_Property
// Code size 12 (0xc)
.maxstack 1
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::backingField
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property(int32 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::set_Property
// Code size 9 (0x9)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::backingField
IL_0008: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::add_Changed
// Code size 25 (0x19)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0008: ldarg.1
IL_0009: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_000e: castclass [mscorlib]System.EventHandler
IL_0013: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0018: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::remove_Changed
// Code size 25 (0x19)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0008: ldarg.1
IL_0009: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_000e: castclass [mscorlib]System.EventHandler
IL_0013: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0018: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Change::.ctor
.event [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Changed
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed(class [mscorlib]System.EventHandler)
} // end of event Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Changed
.property instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Property()
{
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property(int32)
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property()
} // end of property Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Property
} // end of class Change
.field private notserialized int32 someField
.field private class [mscorlib]System.EventHandler AutomaticEvent
.field private notserialized class [mscorlib]System.EventHandler AutomaticEventWithInitializer
@ -417,8 +676,8 @@ @@ -417,8 +676,8 @@
} // end of event PropertiesAndEvents::AutomaticEventWithInitializer
.event [mscorlib]System.EventHandler CustomEvent
{
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents::remove_CustomEvent(class [mscorlib]System.EventHandler)
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents::add_CustomEvent(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents::remove_CustomEvent(class [mscorlib]System.EventHandler)
} // end of event PropertiesAndEvents::CustomEvent
.property instance int32 Value()
{

244
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.opt.il

@ -56,8 +56,8 @@ @@ -56,8 +56,8 @@
.event [mscorlib]System.Action Event
{
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase::remove_Event(class [mscorlib]System.Action)
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase::add_Event(class [mscorlib]System.Action)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase::remove_Event(class [mscorlib]System.Action)
} // end of event IBase::Event
.property instance int32 Test()
{
@ -66,6 +66,125 @@ @@ -66,6 +66,125 @@
} // end of property IBase::Test
} // end of class IBase
.class abstract auto ansi nested private beforefieldinit BaseClass
extends [mscorlib]System.Object
{
.method public hidebysig newslot specialname abstract virtual
instance void add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
} // end of method BaseClass::add_ThisIsAnAbstractEvent
.method public hidebysig newslot specialname abstract virtual
instance void remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
} // end of method BaseClass::remove_ThisIsAnAbstractEvent
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method BaseClass::.ctor
.event [mscorlib]System.EventHandler ThisIsAnAbstractEvent
{
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
} // end of event BaseClass::ThisIsAnAbstractEvent
} // end of class BaseClass
.class auto ansi nested private beforefieldinit OtherClass
extends ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass
{
.field private class [mscorlib]System.EventHandler ThisIsAnAbstractEvent
.method public hidebysig specialname virtual
instance void add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
// Code size 41 (0x29)
.maxstack 3
.locals init (class [mscorlib]System.EventHandler V_0,
class [mscorlib]System.EventHandler V_1,
class [mscorlib]System.EventHandler V_2)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,
!!0,
!!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: bne.un.s IL_0007
IL_0028: ret
} // end of method OtherClass::add_ThisIsAnAbstractEvent
.method public hidebysig specialname virtual
instance void remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
// Code size 41 (0x29)
.maxstack 3
.locals init (class [mscorlib]System.EventHandler V_0,
class [mscorlib]System.EventHandler V_1,
class [mscorlib]System.EventHandler V_2)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,
!!0,
!!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: bne.un.s IL_0007
IL_0028: ret
} // end of method OtherClass::remove_ThisIsAnAbstractEvent
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::.ctor()
IL_0006: ret
} // end of method OtherClass::.ctor
.event [mscorlib]System.EventHandler ThisIsAnAbstractEvent
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
} // end of event OtherClass::ThisIsAnAbstractEvent
} // end of class OtherClass
.class auto ansi nested private beforefieldinit Impl
extends [mscorlib]System.Object
implements ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase
@ -119,8 +238,8 @@ @@ -119,8 +238,8 @@
.event [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Event
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.add_Event(class [mscorlib]System.Action)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.remove_Event(class [mscorlib]System.Action)
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.add_Event(class [mscorlib]System.Action)
} // end of event Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Event
.property instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Test()
{
@ -129,6 +248,125 @@ @@ -129,6 +248,125 @@
} // end of property Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Test
} // end of class Impl
.class interface abstract auto ansi nested private IChange
{
.method public hidebysig newslot specialname abstract virtual
instance int32 get_Property() cil managed
{
} // end of method IChange::get_Property
.method public hidebysig newslot specialname abstract virtual
instance void set_Property(int32 'value') cil managed
{
} // end of method IChange::set_Property
.method public hidebysig newslot specialname abstract virtual
instance void add_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
} // end of method IChange::add_Changed
.method public hidebysig newslot specialname abstract virtual
instance void remove_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
} // end of method IChange::remove_Changed
.event [mscorlib]System.EventHandler Changed
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::add_Changed(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::remove_Changed(class [mscorlib]System.EventHandler)
} // end of event IChange::Changed
.property instance int32 Property()
{
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::set_Property(int32)
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::get_Property()
} // end of property IChange::Property
} // end of class IChange
.class auto ansi nested private beforefieldinit Change
extends [mscorlib]System.Object
implements ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange
{
.field private class [mscorlib]System.EventHandler Changed
.field private int32 backingField
.method private hidebysig newslot specialname virtual final
instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property() cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::get_Property
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::backingField
IL_0006: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property(int32 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::set_Property
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::backingField
IL_0007: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::add_Changed
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_000d: castclass [mscorlib]System.EventHandler
IL_0012: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0017: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::remove_Changed
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_000d: castclass [mscorlib]System.EventHandler
IL_0012: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0017: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Change::.ctor
.event [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Changed
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed(class [mscorlib]System.EventHandler)
} // end of event Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Changed
.property instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Property()
{
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property(int32)
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property()
} // end of property Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Property
} // end of class Change
.field private notserialized int32 someField
.field private class [mscorlib]System.EventHandler AutomaticEvent
.field private notserialized class [mscorlib]System.EventHandler AutomaticEventWithInitializer
@ -370,8 +608,8 @@ @@ -370,8 +608,8 @@
} // end of event PropertiesAndEvents::AutomaticEventWithInitializer
.event [mscorlib]System.EventHandler CustomEvent
{
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents::remove_CustomEvent(class [mscorlib]System.EventHandler)
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents::add_CustomEvent(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents::remove_CustomEvent(class [mscorlib]System.EventHandler)
} // end of event PropertiesAndEvents::CustomEvent
.property instance int32 Value()
{

257
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.opt.roslyn.il

@ -72,6 +72,130 @@ @@ -72,6 +72,130 @@
} // end of property IBase::Test
} // end of class IBase
.class abstract auto ansi nested private beforefieldinit BaseClass
extends [mscorlib]System.Object
{
.method public hidebysig newslot specialname abstract virtual
instance void add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
} // end of method BaseClass::add_ThisIsAnAbstractEvent
.method public hidebysig newslot specialname abstract virtual
instance void remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
} // end of method BaseClass::remove_ThisIsAnAbstractEvent
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method BaseClass::.ctor
.event [mscorlib]System.EventHandler ThisIsAnAbstractEvent
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
} // end of event BaseClass::ThisIsAnAbstractEvent
} // end of class BaseClass
.class auto ansi nested private beforefieldinit OtherClass
extends ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass
{
.field private class [mscorlib]System.EventHandler ThisIsAnAbstractEvent
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname virtual
instance void add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 41 (0x29)
.maxstack 3
.locals init (class [mscorlib]System.EventHandler V_0,
class [mscorlib]System.EventHandler V_1,
class [mscorlib]System.EventHandler V_2)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,
!!0,
!!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: bne.un.s IL_0007
IL_0028: ret
} // end of method OtherClass::add_ThisIsAnAbstractEvent
.method public hidebysig specialname virtual
instance void remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 41 (0x29)
.maxstack 3
.locals init (class [mscorlib]System.EventHandler V_0,
class [mscorlib]System.EventHandler V_1,
class [mscorlib]System.EventHandler V_2)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,
!!0,
!!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: bne.un.s IL_0007
IL_0028: ret
} // end of method OtherClass::remove_ThisIsAnAbstractEvent
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::.ctor()
IL_0006: ret
} // end of method OtherClass::.ctor
.event [mscorlib]System.EventHandler ThisIsAnAbstractEvent
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
} // end of event OtherClass::ThisIsAnAbstractEvent
} // end of class OtherClass
.class auto ansi nested private beforefieldinit Impl
extends [mscorlib]System.Object
implements ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase
@ -135,12 +259,133 @@ @@ -135,12 +259,133 @@
} // end of property Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Test
} // end of class Impl
.class interface abstract auto ansi nested private IChange
{
.method public hidebysig newslot specialname abstract virtual
instance int32 get_Property() cil managed
{
} // end of method IChange::get_Property
.method public hidebysig newslot specialname abstract virtual
instance void set_Property(int32 'value') cil managed
{
} // end of method IChange::set_Property
.method public hidebysig newslot specialname abstract virtual
instance void add_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
} // end of method IChange::add_Changed
.method public hidebysig newslot specialname abstract virtual
instance void remove_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
} // end of method IChange::remove_Changed
.event [mscorlib]System.EventHandler Changed
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::add_Changed(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::remove_Changed(class [mscorlib]System.EventHandler)
} // end of event IChange::Changed
.property instance int32 Property()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::set_Property(int32)
} // end of property IChange::Property
} // end of class IChange
.class auto ansi nested private beforefieldinit Change
extends [mscorlib]System.Object
implements ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange
{
.field private class [mscorlib]System.EventHandler Changed
.field private int32 backingField
.method private hidebysig newslot specialname virtual final
instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property() cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::get_Property
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::backingField
IL_0006: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property(int32 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::set_Property
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::backingField
IL_0007: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::add_Changed
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_000d: castclass [mscorlib]System.EventHandler
IL_0012: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0017: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::remove_Changed
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_000d: castclass [mscorlib]System.EventHandler
IL_0012: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0017: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Change::.ctor
.event [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Changed
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed(class [mscorlib]System.EventHandler)
} // end of event Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Changed
.property instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Property()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property(int32)
} // end of property Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Property
} // end of class Change
.class auto ansi serializable sealed nested private beforefieldinit '<>c'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static initonly class ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c' '<>9'
.field public static class [mscorlib]System.EventHandler '<>9__18_0'
.field public static class [mscorlib]System.EventHandler '<>9__22_0'
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
@ -162,13 +407,13 @@ @@ -162,13 +407,13 @@
} // end of method '<>c'::.ctor
.method assembly hidebysig instance void
'<.ctor>b__18_0'(object '<p0>',
'<.ctor>b__22_0'(object '<p0>',
class [mscorlib]System.EventArgs '<p1>') cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method '<>c'::'<.ctor>b__18_0'
} // end of method '<>c'::'<.ctor>b__22_0'
} // end of class '<>c'
@ -380,18 +625,18 @@ @@ -380,18 +625,18 @@
// Code size 44 (0x2c)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldsfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9__18_0'
IL_0001: ldsfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9__22_0'
IL_0006: dup
IL_0007: brtrue.s IL_0020
IL_0009: pop
IL_000a: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c' ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9'
IL_000f: ldftn instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<.ctor>b__18_0'(object,
IL_000f: ldftn instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<.ctor>b__22_0'(object,
class [mscorlib]System.EventArgs)
IL_0015: newobj instance void [mscorlib]System.EventHandler::.ctor(object,
native int)
IL_001a: dup
IL_001b: stsfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9__18_0'
IL_001b: stsfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9__22_0'
IL_0020: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents::AutomaticEventWithInitializer
IL_0025: ldarg.0
IL_0026: call instance void [mscorlib]System.Object::.ctor()

270
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.roslyn.il

@ -72,6 +72,133 @@ @@ -72,6 +72,133 @@
} // end of property IBase::Test
} // end of class IBase
.class abstract auto ansi nested private beforefieldinit BaseClass
extends [mscorlib]System.Object
{
.method public hidebysig newslot specialname abstract virtual
instance void add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
} // end of method BaseClass::add_ThisIsAnAbstractEvent
.method public hidebysig newslot specialname abstract virtual
instance void remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
} // end of method BaseClass::remove_ThisIsAnAbstractEvent
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 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 BaseClass::.ctor
.event [mscorlib]System.EventHandler ThisIsAnAbstractEvent
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
} // end of event BaseClass::ThisIsAnAbstractEvent
} // end of class BaseClass
.class auto ansi nested private beforefieldinit OtherClass
extends ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass
{
.field private class [mscorlib]System.EventHandler ThisIsAnAbstractEvent
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
.method public hidebysig specialname virtual
instance void add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 41 (0x29)
.maxstack 3
.locals init (class [mscorlib]System.EventHandler V_0,
class [mscorlib]System.EventHandler V_1,
class [mscorlib]System.EventHandler V_2)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,
!!0,
!!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: bne.un.s IL_0007
IL_0028: ret
} // end of method OtherClass::add_ThisIsAnAbstractEvent
.method public hidebysig specialname virtual
instance void remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 41 (0x29)
.maxstack 3
.locals init (class [mscorlib]System.EventHandler V_0,
class [mscorlib]System.EventHandler V_1,
class [mscorlib]System.EventHandler V_2)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass [mscorlib]System.EventHandler
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::ThisIsAnAbstractEvent
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,
!!0,
!!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: bne.un.s IL_0007
IL_0028: ret
} // end of method OtherClass::remove_ThisIsAnAbstractEvent
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/BaseClass::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method OtherClass::.ctor
.event [mscorlib]System.EventHandler ThisIsAnAbstractEvent
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::add_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/OtherClass::remove_ThisIsAnAbstractEvent(class [mscorlib]System.EventHandler)
} // end of event OtherClass::ThisIsAnAbstractEvent
} // end of class OtherClass
.class auto ansi nested private beforefieldinit Impl
extends [mscorlib]System.Object
implements ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IBase
@ -140,12 +267,143 @@ @@ -140,12 +267,143 @@
} // end of property Impl::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IBase.Test
} // end of class Impl
.class interface abstract auto ansi nested private IChange
{
.method public hidebysig newslot specialname abstract virtual
instance int32 get_Property() cil managed
{
} // end of method IChange::get_Property
.method public hidebysig newslot specialname abstract virtual
instance void set_Property(int32 'value') cil managed
{
} // end of method IChange::set_Property
.method public hidebysig newslot specialname abstract virtual
instance void add_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
} // end of method IChange::add_Changed
.method public hidebysig newslot specialname abstract virtual
instance void remove_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
} // end of method IChange::remove_Changed
.event [mscorlib]System.EventHandler Changed
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::add_Changed(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::remove_Changed(class [mscorlib]System.EventHandler)
} // end of event IChange::Changed
.property instance int32 Property()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::set_Property(int32)
} // end of property IChange::Property
} // end of class IChange
.class auto ansi nested private beforefieldinit Change
extends [mscorlib]System.Object
implements ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange
{
.field private class [mscorlib]System.EventHandler Changed
.field private int32 backingField
.method private hidebysig newslot specialname virtual final
instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property() cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::get_Property
// Code size 12 (0xc)
.maxstack 1
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::backingField
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property(int32 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::set_Property
// Code size 9 (0x9)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::backingField
IL_0008: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::add_Changed
// Code size 25 (0x19)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0008: ldarg.1
IL_0009: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_000e: castclass [mscorlib]System.EventHandler
IL_0013: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0018: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed
.method private hidebysig newslot specialname virtual final
instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed(class [mscorlib]System.EventHandler 'value') cil managed
{
.override ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/IChange::remove_Changed
// Code size 25 (0x19)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0008: ldarg.1
IL_0009: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_000e: castclass [mscorlib]System.EventHandler
IL_0013: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::Changed
IL_0018: ret
} // end of method Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 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 Change::.ctor
.event [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Changed
{
.addon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.add_Changed(class [mscorlib]System.EventHandler)
.removeon instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.remove_Changed(class [mscorlib]System.EventHandler)
} // end of event Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Changed
.property instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Property()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.set_Property(int32)
} // end of property Change::ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents.IChange.Property
} // end of class Change
.class auto ansi serializable sealed nested private beforefieldinit '<>c'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static initonly class ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c' '<>9'
.field public static class [mscorlib]System.EventHandler '<>9__18_0'
.field public static class [mscorlib]System.EventHandler '<>9__22_0'
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
@ -168,14 +426,14 @@ @@ -168,14 +426,14 @@
} // end of method '<>c'::.ctor
.method assembly hidebysig instance void
'<.ctor>b__18_0'(object '<p0>',
'<.ctor>b__22_0'(object '<p0>',
class [mscorlib]System.EventArgs '<p1>') cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method '<>c'::'<.ctor>b__18_0'
} // end of method '<>c'::'<.ctor>b__22_0'
} // end of class '<>c'
@ -394,18 +652,18 @@ @@ -394,18 +652,18 @@
// Code size 45 (0x2d)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldsfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9__18_0'
IL_0001: ldsfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9__22_0'
IL_0006: dup
IL_0007: brtrue.s IL_0020
IL_0009: pop
IL_000a: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c' ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9'
IL_000f: ldftn instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<.ctor>b__18_0'(object,
IL_000f: ldftn instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<.ctor>b__22_0'(object,
class [mscorlib]System.EventArgs)
IL_0015: newobj instance void [mscorlib]System.EventHandler::.ctor(object,
native int)
IL_001a: dup
IL_001b: stsfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9__18_0'
IL_001b: stsfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents/'<>c'::'<>9__22_0'
IL_0020: stfld class [mscorlib]System.EventHandler ICSharpCode.Decompiler.Tests.TestCases.Pretty.PropertiesAndEvents::AutomaticEventWithInitializer
IL_0025: ldarg.0
IL_0026: call instance void [mscorlib]System.Object::.ctor()

3
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -134,7 +134,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -134,7 +134,8 @@ namespace ICSharpCode.Decompiler.CSharp
new NullPropagationStatementTransform(),
new TransformArrayInitializers(),
new TransformCollectionAndObjectInitializers(),
new TransformExpressionTrees()
new TransformExpressionTrees(),
new NamedArgumentTransform()
),
}
},

119
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -74,10 +74,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -74,10 +74,13 @@ namespace ICSharpCode.Decompiler.CSharp
elementRRs.ToImmutableArray()
)).WithILInstruction(inst);
}
return Build(inst.OpCode, inst.Method, inst.Arguments, inst.ConstrainedTo).WithILInstruction(inst);
return Build(inst.OpCode, inst.Method, inst.Arguments, constrainedTo: inst.ConstrainedTo)
.WithILInstruction(inst);
}
public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method, IReadOnlyList<ILInstruction> callArguments,
public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method,
IReadOnlyList<ILInstruction> callArguments,
IReadOnlyList<int> argumentToParameterMap = null,
IType constrainedTo = null)
{
// Used for Call, CallVirt and NewObj
@ -108,16 +111,32 @@ namespace ICSharpCode.Decompiler.CSharp @@ -108,16 +111,32 @@ namespace ICSharpCode.Decompiler.CSharp
}
int firstParamIndex = (method.IsStatic || callOpCode == OpCode.NewObj) ? 0 : 1;
Debug.Assert(firstParamIndex == 0 || argumentToParameterMap == null
|| argumentToParameterMap[0] == -1);
// Translate arguments to the expected parameter types
var arguments = new List<TranslatedExpression>(method.Parameters.Count);
string[] argumentNames = null;
Debug.Assert(callArguments.Count == firstParamIndex + method.Parameters.Count);
var expectedParameters = method.Parameters.ToList();
var expectedParameters = new List<IParameter>(arguments.Count); // parameters, but in argument order
bool isExpandedForm = false;
for (int i = 0; i < method.Parameters.Count; i++) {
var parameter = expectedParameters[i];
var arg = expressionBuilder.Translate(callArguments[firstParamIndex + i], parameter.Type);
if (parameter.IsParams && i + 1 == method.Parameters.Count) {
for (int i = firstParamIndex; i < callArguments.Count; i++) {
IParameter parameter;
if (argumentToParameterMap != null) {
if (argumentNames == null && argumentToParameterMap[i] != i - firstParamIndex) {
// Starting at the first argument that is out-of-place,
// assign names to that argument and all following arguments:
argumentNames = new string[method.Parameters.Count];
}
parameter = method.Parameters[argumentToParameterMap[i]];
if (argumentNames != null) {
argumentNames[arguments.Count] = parameter.Name;
}
} else {
parameter = method.Parameters[i - firstParamIndex];
}
var arg = expressionBuilder.Translate(callArguments[i], parameter.Type);
if (parameter.IsParams && i + 1 == callArguments.Count && argumentToParameterMap == null) {
// Parameter is marked params
// If the argument is an array creation, inline all elements into the call and add missing default values.
// Otherwise handle it normally.
@ -138,7 +157,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -138,7 +157,8 @@ namespace ICSharpCode.Decompiler.CSharp
expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction());
}
}
if (IsUnambiguousCall(expectedTargetDetails, method, target.ResolveResult, Empty<IType>.Array, expandedArguments, out _) == OverloadResolutionErrors.None) {
Debug.Assert(argumentNames == null);
if (IsUnambiguousCall(expectedTargetDetails, method, target.ResolveResult, Empty<IType>.Array, expandedArguments, argumentNames, out _) == OverloadResolutionErrors.None) {
isExpandedForm = true;
expectedParameters = expandedParameters;
arguments = expandedArguments.SelectList(a => new TranslatedExpression(a.Expression.Detach()));
@ -147,11 +167,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -147,11 +167,14 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
arguments.Add(arg.ConvertTo(parameter.Type, expressionBuilder, allowImplicitConversion: true));
arg = arg.ConvertTo(parameter.Type, expressionBuilder, allowImplicitConversion: true);
if (parameter.IsOut) {
arguments[i] = ExpressionBuilder.ChangeDirectionExpressionToOut(arguments[i]);
}
arguments.Add(arg);
expectedParameters.Add(parameter);
}
if (method is VarArgInstanceMethod) {
@ -160,19 +183,22 @@ namespace ICSharpCode.Decompiler.CSharp @@ -160,19 +183,22 @@ namespace ICSharpCode.Decompiler.CSharp
argListArg.UndocumentedExpressionType = UndocumentedExpressionType.ArgList;
int paramIndex = regularParameterCount;
var builder = expressionBuilder;
Debug.Assert(argumentToParameterMap == null && argumentNames == null);
argListArg.Arguments.AddRange(arguments.Skip(regularParameterCount).Select(arg => arg.ConvertTo(expectedParameters[paramIndex++].Type, builder).Expression));
var argListRR = new ResolveResult(SpecialType.ArgList);
arguments = arguments.Take(regularParameterCount)
.Concat(new[] { argListArg.WithoutILInstruction().WithRR(argListRR) }).ToList();
method = (IMethod)method.MemberDefinition;
method = ((VarArgInstanceMethod)method).BaseMethod;
expectedParameters = method.Parameters.ToList();
}
var argumentResolveResults = arguments.Select(arg => arg.ResolveResult).ToList();
if (callOpCode == OpCode.NewObj) {
ResolveResult rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm);
ResolveResult rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults,
isExpandedForm: isExpandedForm, argumentToParameterMap: argumentToParameterMap);
if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) {
Debug.Assert(argumentToParameterMap == null && argumentNames == null);
var argumentExpressions = arguments.SelectArray(arg => arg.Expression);
AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
if (CanInferAnonymousTypePropertyNamesFromArguments(argumentExpressions, expectedParameters)) {
@ -189,7 +215,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -189,7 +215,7 @@ namespace ICSharpCode.Decompiler.CSharp
return atce
.WithRR(rr);
} else {
if (IsUnambiguousCall(expectedTargetDetails, method, null, Empty<IType>.Array, arguments, out _) != OverloadResolutionErrors.None) {
if (IsUnambiguousCall(expectedTargetDetails, method, null, Empty<IType>.Array, arguments, argumentNames, out _) != OverloadResolutionErrors.None) {
for (int i = 0; i < arguments.Count; i++) {
if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) {
if (arguments[i].Expression is LambdaExpression lambda) {
@ -200,17 +226,21 @@ namespace ICSharpCode.Decompiler.CSharp @@ -200,17 +226,21 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
}
return new ObjectCreateExpression(expressionBuilder.ConvertType(method.DeclaringType), arguments.SelectArray(arg => arg.Expression))
.WithRR(rr);
return new ObjectCreateExpression(
expressionBuilder.ConvertType(method.DeclaringType),
GetArgumentExpressions(arguments, argumentNames)
).WithRR(rr);
}
} else {
int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0);
if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || expectedParameters.Count == allowedParamCount)) {
Debug.Assert(argumentToParameterMap == null && argumentNames == null);
return HandleAccessorCall(expectedTargetDetails, method, target, arguments.ToList());
} else if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate && !IsNullConditional(target)) {
return new InvocationExpression(target, arguments.Select(arg => arg.Expression))
return new InvocationExpression(target, GetArgumentExpressions(arguments, argumentNames))
.WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm));
} else if (IsDelegateEqualityComparison(method, arguments)) {
Debug.Assert(argumentToParameterMap == null && argumentNames == null);
return HandleDelegateEqualityComparison(method, arguments)
.WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm));
} else if (method.IsOperator && method.Name == "op_Implicit" && arguments.Count == 1) {
@ -236,7 +266,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -236,7 +266,7 @@ namespace ICSharpCode.Decompiler.CSharp
var targetResolveResult = requireTarget ? target.ResolveResult : null;
IParameterizedMember foundMethod;
OverloadResolutionErrors errors;
while ((errors = IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, typeArguments, arguments, out foundMethod)) != OverloadResolutionErrors.None) {
while ((errors = IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, typeArguments, arguments, argumentNames, out foundMethod)) != OverloadResolutionErrors.None) {
switch (errors) {
case OverloadResolutionErrors.TypeInferenceFailed:
case OverloadResolutionErrors.WrongNumberOfTypeArguments:
@ -301,13 +331,28 @@ namespace ICSharpCode.Decompiler.CSharp @@ -301,13 +331,28 @@ namespace ICSharpCode.Decompiler.CSharp
if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType())))
typeArgumentList.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
var argumentExpressions = arguments.Select(arg => arg.Expression);
var argumentExpressions = GetArgumentExpressions(arguments, argumentNames);
return new InvocationExpression(targetExpr, argumentExpressions)
.WithRR(new CSharpInvocationResolveResult(target.ResolveResult, foundMethod, argumentResolveResults, isExpandedForm: isExpandedForm));
}
}
}
private IEnumerable<Expression> GetArgumentExpressions(List<TranslatedExpression> arguments, string[] argumentNames)
{
if (argumentNames == null) {
return arguments.Select(arg => arg.Expression);
} else {
return arguments.Zip(argumentNames,
(arg, name) => {
if (name == null)
return arg.Expression;
else
return new NamedArgumentExpression(name, arg);
});
}
}
static bool IsNullConditional(Expression expr)
{
return expr is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.NullConditional;
@ -374,11 +419,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -374,11 +419,16 @@ namespace ICSharpCode.Decompiler.CSharp
OverloadResolutionErrors IsUnambiguousCall(ExpectedTargetDetails expectedTargetDetails, IMethod method,
ResolveResult target, IType[] typeArguments, IList<TranslatedExpression> arguments,
string[] argumentNames,
out IParameterizedMember foundMember)
{
foundMember = null;
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
var or = new OverloadResolution(resolver.Compilation, arguments.SelectArray(a => a.ResolveResult), typeArguments: typeArguments);
var or = new OverloadResolution(resolver.Compilation,
arguments.SelectArray(a => a.ResolveResult),
argumentNames: argumentNames,
typeArguments: typeArguments,
conversions: expressionBuilder.resolver.conversions);
if (expectedTargetDetails.CallOpCode == OpCode.NewObj) {
foreach (IMethod ctor in method.DeclaringType.GetConstructors()) {
if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == method.DeclaringTypeDefinition)) {
@ -406,7 +456,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -406,7 +456,7 @@ namespace ICSharpCode.Decompiler.CSharp
return OverloadResolutionErrors.None;
}
static bool CanInferAnonymousTypePropertyNamesFromArguments(IList<Expression> args, IList<IParameter> parameters)
static bool CanInferAnonymousTypePropertyNamesFromArguments(IList<Expression> args, IReadOnlyList<IParameter> parameters)
{
for (int i = 0; i < args.Count; i++) {
string inferredName;
@ -617,5 +667,34 @@ namespace ICSharpCode.Decompiler.CSharp @@ -617,5 +667,34 @@ namespace ICSharpCode.Decompiler.CSharp
Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false)));
return oce;
}
internal TranslatedExpression CallWithNamedArgs(Block block)
{
Debug.Assert(block.Kind == BlockKind.CallWithNamedArgs);
var call = (CallInstruction)block.FinalInstruction;
var arguments = new ILInstruction[call.Arguments.Count];
var argumentToParameterMap = new int[arguments.Length];
int firstParamIndex = call.IsInstanceCall ? 1 : 0;
// Arguments from temporary variables (VariableKind.NamedArgument):
int pos = 0;
foreach (StLoc stloc in block.Instructions) {
Debug.Assert(stloc.Variable.LoadInstructions.Single().Parent == call);
arguments[pos] = stloc.Value;
argumentToParameterMap[pos] = stloc.Variable.LoadInstructions.Single().ChildIndex - firstParamIndex;
pos++;
}
// Remaining argument:
foreach (var arg in call.Arguments) {
if (arg.MatchLdLoc(out var v) && v.Kind == VariableKind.NamedArgument) {
continue; // already handled in loop above
}
arguments[pos] = arg;
argumentToParameterMap[pos] = arg.ChildIndex - firstParamIndex;
pos++;
}
Debug.Assert(pos == arguments.Length);
return Build(call.OpCode, call.Method, arguments, argumentToParameterMap, call.ConstrainedTo)
.WithILInstruction(call).WithILInstruction(block);
}
}
}

6
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1935,6 +1935,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1935,6 +1935,10 @@ namespace ICSharpCode.Decompiler.CSharp
return TranslatePostfixOperator(block);
case BlockKind.CallInlineAssign:
return TranslateSetterCallAssignment(block);
case BlockKind.CallWithNamedArgs:
return WrapInRef(
new CallBuilder(this, typeSystem, settings).CallWithNamedArgs(block),
((CallInstruction)block.FinalInstruction).Method.ReturnType);
default:
return ErrorExpression("Unknown block type: " + block.Kind);
}
@ -1985,7 +1989,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1985,7 +1989,7 @@ namespace ICSharpCode.Decompiler.CSharp
indexVariables.Add(indexStore.Variable, indexStore.Value);
continue;
}
var info = IL.Transforms.AccessPathElement.GetAccessPath(inst, initObjRR.Type);
var info = IL.Transforms.AccessPathElement.GetAccessPath(inst, initObjRR.Type, allowDictionaryInitializer: settings.DictionaryInitializers);
if (info.Kind == IL.Transforms.AccessPathKind.Invalid) continue;
if (currentPath == null) {
currentPath = info.Path;

14
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs

@ -72,11 +72,17 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -72,11 +72,17 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
if (expr is CastExpression)
return Unary;
if (expr is PrimitiveExpression) {
var value = ((PrimitiveExpression)expr).Value;
if (value is int && (int)value < 0)
if (expr is PrimitiveExpression primitive) {
var value = primitive.Value;
if (value is int i && i < 0)
return Unary;
if (value is long && (long)value < 0)
if (value is long l && l < 0)
return Unary;
if (value is float f && f < 0)
return Unary;
if (value is double d && d < 0)
return Unary;
if (value is decimal de && de < 0)
return Unary;
}
BinaryOperatorExpression boe = expr as BinaryOperatorExpression;

6
ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs

@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
/// </summary>
public readonly bool IsExpandedForm;
readonly IList<int> argumentToParameterMap;
readonly IReadOnlyList<int> argumentToParameterMap;
/// <summary>
/// If IsExtensionMethodInvocation is true this property holds the reduced method.
@ -70,7 +70,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -70,7 +70,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
bool isExtensionMethodInvocation = false,
bool isExpandedForm = false,
bool isDelegateInvocation = false,
IList<int> argumentToParameterMap = null,
IReadOnlyList<int> argumentToParameterMap = null,
IList<ResolveResult> initializerStatements = null,
IType returnTypeOverride = null
)
@ -93,7 +93,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -93,7 +93,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
///
/// parameterIndex = ArgumentToParameterMap[argumentIndex]
/// </summary>
public IList<int> GetArgumentToParameterMap()
public IReadOnlyList<int> GetArgumentToParameterMap()
{
return argumentToParameterMap;
}

2
ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs

@ -843,7 +843,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -843,7 +843,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
///
/// parameterIndex = GetArgumentToParameterMap()[argumentIndex]
/// </summary>
public IList<int> GetArgumentToParameterMap()
public IReadOnlyList<int> GetArgumentToParameterMap()
{
if (bestCandidate != null)
return bestCandidate.ArgumentToParameterMap;

2
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -734,6 +734,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -734,6 +734,8 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override Statement VisitBlock(Block block)
{
if (block.Kind != BlockKind.ControlFlow)
return Default(block);
// Block without container
BlockStatement blockStatement = new BlockStatement();
foreach (var inst in block.Instructions) {

30
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs

@ -113,12 +113,28 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -113,12 +113,28 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
var firstArgument = invocationExpression.Arguments.First();
if (firstArgument is NamedArgumentExpression)
return;
var target = firstArgument.GetResolveResult();
if (target is ConstantResolveResult crr && crr.ConstantValue == null) {
target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion);
}
var args = invocationExpression.Arguments.Skip(1).Select(a => a.GetResolveResult()).ToArray();
if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args))
ResolveResult[] args = new ResolveResult[invocationExpression.Arguments.Count - 1];
string[] argNames = null;
int pos = 0;
foreach (var arg in invocationExpression.Arguments.Skip(1)) {
if (arg is NamedArgumentExpression nae) {
if (argNames == null) {
argNames = new string[args.Length];
}
argNames[pos] = nae.Name;
args[pos] = nae.Expression.GetResolveResult();
} else {
args[pos] = arg.GetResolveResult();
}
pos++;
}
if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames))
return;
if (firstArgument is NullReferenceExpression)
firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach()));
@ -131,16 +147,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -131,16 +147,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
}
public static bool CanTransformToExtensionMethodCall(CSharpResolver resolver, IMethod method, IReadOnlyList<IType> typeArguments, ResolveResult target, ResolveResult[] arguments)
public static bool CanTransformToExtensionMethodCall(CSharpResolver resolver, IMethod method,
IReadOnlyList<IType> typeArguments, ResolveResult target, ResolveResult[] arguments, string[] argumentNames)
{
var rr = resolver.ResolveMemberAccess(target, method.Name, typeArguments, NameLookupMode.InvocationTarget) as MethodGroupResolveResult;
if (rr == null)
return false;
// TODO : add support for argument names as soon as named arguments are implemented in the decompiler.
var or = rr.PerformOverloadResolution(resolver.CurrentTypeResolveContext.Compilation, arguments, allowExtensionMethods: true);
if (or == null || or.IsAmbiguous || !method.Equals(or.GetBestCandidateWithSubstitutedTypeArguments()))
var or = rr.PerformOverloadResolution(resolver.CurrentTypeResolveContext.Compilation, arguments, argumentNames, allowExtensionMethods: true);
if (or == null || or.IsAmbiguous)
return false;
return true;
return method.Equals(or.GetBestCandidateWithSubstitutedTypeArguments());
}
}
}

68
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -488,6 +488,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -488,6 +488,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
PropertyDeclaration TransformAutomaticProperties(PropertyDeclaration property)
{
if (!property.PrivateImplementationType.IsNull)
return null;
PropertyDefinition cecilProperty = context.TypeSystem.GetCecil(property.GetSymbol() as IProperty) as PropertyDefinition;
if (cecilProperty == null || cecilProperty.GetMethod == null)
return null;
@ -601,16 +603,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -601,16 +603,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
#region Automatic Events
static readonly Expression fieldReferencePattern = new Choice {
new IdentifierExpression(Pattern.AnyString),
new MemberReferenceExpression {
Target = new Choice { new ThisReferenceExpression(), new TypeReferenceExpression { Type = new AnyNode() } },
MemberName = Pattern.AnyString
}
};
static readonly Accessor automaticEventPatternV2 = new Accessor {
Attributes = { new Repeat(new AnyNode()) },
Body = new BlockStatement {
new AssignmentExpression {
Left = new NamedNode(
"field",
new MemberReferenceExpression {
Target = new Choice { new ThisReferenceExpression(), new TypeReferenceExpression { Type = new AnyNode() } },
MemberName = Pattern.AnyString
}),
Left = new NamedNode("field", fieldReferencePattern),
Operator = AssignmentOperatorType.Assign,
Right = new CastExpression(
new AnyNode("type"),
@ -626,12 +631,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -626,12 +631,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
new AssignmentExpression {
Left = new NamedNode("var1", new IdentifierExpression(Pattern.AnyString)),
Operator = AssignmentOperatorType.Assign,
Right = new NamedNode(
"field",
new MemberReferenceExpression {
Target = new Choice { new ThisReferenceExpression(), new TypeReferenceExpression { Type = new AnyNode() } },
MemberName = Pattern.AnyString
})
Right = new NamedNode("field", fieldReferencePattern)
},
new DoWhileStatement {
EmbeddedStatement = new BlockStatement {
@ -704,8 +704,20 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -704,8 +704,20 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
if (!m.Success)
return false;
if (m.Get<MemberReferenceExpression>("field").Single().MemberName != ev.Name)
return false; // field name must match event name
Expression fieldExpression = m.Get<Expression>("field").Single();
// field name must match event name
switch (fieldExpression) {
case IdentifierExpression identifier:
if (identifier.Identifier != ev.Name)
return false;
break;
case MemberReferenceExpression memberRef:
if (memberRef.MemberName != ev.Name)
return false;
break;
default:
return false;
}
if (!ev.ReturnType.IsMatch(m.Get("type").Single()))
return false; // variable types must match event type
var combineMethod = m.Get<AstNode>("delegateCombine").Single().Parent.GetSymbol() as IMethod;
@ -725,37 +737,34 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -725,37 +737,34 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
"System.Diagnostics.DebuggerBrowsableAttribute"
};
bool CheckAutomaticEventV4(CustomEventDeclaration ev, out Match addMatch, out Match removeMatch)
bool CheckAutomaticEventV4(CustomEventDeclaration ev)
{
addMatch = removeMatch = default(Match);
addMatch = automaticEventPatternV4.Match(ev.AddAccessor);
Match addMatch = automaticEventPatternV4.Match(ev.AddAccessor);
if (!CheckAutomaticEventMatch(addMatch, ev, true))
return false;
removeMatch = automaticEventPatternV4.Match(ev.RemoveAccessor);
Match removeMatch = automaticEventPatternV4.Match(ev.RemoveAccessor);
if (!CheckAutomaticEventMatch(removeMatch, ev, false))
return false;
return true;
}
bool CheckAutomaticEventV2(CustomEventDeclaration ev, out Match addMatch, out Match removeMatch)
bool CheckAutomaticEventV2(CustomEventDeclaration ev)
{
addMatch = removeMatch = default(Match);
addMatch = automaticEventPatternV2.Match(ev.AddAccessor);
Match addMatch = automaticEventPatternV2.Match(ev.AddAccessor);
if (!CheckAutomaticEventMatch(addMatch, ev, true))
return false;
removeMatch = automaticEventPatternV2.Match(ev.RemoveAccessor);
Match removeMatch = automaticEventPatternV2.Match(ev.RemoveAccessor);
if (!CheckAutomaticEventMatch(removeMatch, ev, false))
return false;
return true;
}
bool CheckAutomaticEventV4MCS(CustomEventDeclaration ev, out Match addMatch, out Match removeMatch)
bool CheckAutomaticEventV4MCS(CustomEventDeclaration ev)
{
addMatch = removeMatch = default(Match);
addMatch = automaticEventPatternV4MCS.Match(ev.AddAccessor);
Match addMatch = automaticEventPatternV4MCS.Match(ev.AddAccessor);
if (!CheckAutomaticEventMatch(addMatch, ev, true))
return false;
removeMatch = automaticEventPatternV4MCS.Match(ev.RemoveAccessor);
Match removeMatch = automaticEventPatternV4MCS.Match(ev.RemoveAccessor);
if (!CheckAutomaticEventMatch(removeMatch, ev, false))
return false;
return true;
@ -763,9 +772,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -763,9 +772,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
EventDeclaration TransformAutomaticEvents(CustomEventDeclaration ev)
{
Match m1, m2;
if (!CheckAutomaticEventV4(ev, out m1, out m2) && !CheckAutomaticEventV2(ev, out m1, out m2) && !CheckAutomaticEventV4MCS(ev, out m1, out m2))
if (!ev.PrivateImplementationType.IsNull)
return null;
if (!ev.Modifiers.HasFlag(Modifiers.Abstract)) {
if (!CheckAutomaticEventV4(ev) && !CheckAutomaticEventV2(ev) && !CheckAutomaticEventV4MCS(ev))
return null;
}
RemoveCompilerGeneratedAttribute(ev.AddAccessor.Attributes, attributeTypesToRemoveFromAutoEvents);
EventDeclaration ed = new EventDeclaration();
ev.Attributes.MoveTo(ed.Attributes);

16
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -60,6 +60,7 @@ namespace ICSharpCode.Decompiler @@ -60,6 +60,7 @@ namespace ICSharpCode.Decompiler
}
if (languageVersion < CSharp.LanguageVersion.CSharp4) {
dynamic = false;
namedArguments = false;
// * named and optional arguments (not supported yet)
}
if (languageVersion < CSharp.LanguageVersion.CSharp5) {
@ -650,6 +651,21 @@ namespace ICSharpCode.Decompiler @@ -650,6 +651,21 @@ namespace ICSharpCode.Decompiler
}
}
bool namedArguments = true;
/// <summary>
/// Gets/Sets whether named arguments should be used.
/// </summary>
public bool NamedArguments {
get { return namedArguments; }
set {
if (namedArguments != value) {
namedArguments = value;
OnPropertyChanged();
}
}
}
#region Options to aid VB decompilation
bool assumeArrayLengthFitsIntoInt32 = true;

8
ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs

@ -241,6 +241,14 @@ namespace ICSharpCode.Decompiler.Documentation @@ -241,6 +241,14 @@ namespace ICSharpCode.Decompiler.Documentation
type = type.NestedTypes.FirstOrDefault(t => t.Name == name);
}
}
if (type == null && module.HasExportedTypes) {
foreach (var exportedType in module.ExportedTypes) {
if (exportedType.Name == name && exportedType.Namespace == ns) {
type = exportedType.Resolve();
break;
}
}
}
return type;
}
#endregion

3
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -50,7 +50,7 @@ @@ -50,7 +50,7 @@
<ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.2.0" />
<PackageReference Include="Mono.Cecil" Version="0.10.0-beta7" />
<PackageReference Include="Mono.Cecil" Version="0.10.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
</ItemGroup>
@ -299,6 +299,7 @@ @@ -299,6 +299,7 @@
<Compile Include="IL\Transforms\EarlyExpressionTransforms.cs" />
<Compile Include="IL\Instructions\ExpressionTreeCast.cs" />
<Compile Include="IL\Transforms\HighLevelLoopTransform.cs" />
<Compile Include="IL\Transforms\NamedArgumentTransform.cs" />
<Compile Include="IL\Transforms\IntroduceDynamicTypeOnLocals.cs" />
<Compile Include="IL\Transforms\NullPropagationTransform.cs" />
<Compile Include="IL\Transforms\ProxyCallReplacer.cs" />

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template

@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
<tags>C# Decompiler ILSpy</tags>
<dependencies>
<dependency id="Humanizer.Core" version="2.2.0" />
<dependency id="Mono.Cecil" version="0.10.0-beta7" />
<dependency id="Mono.Cecil" version="0.10.0" />
<dependency id="System.Collections.Immutable" version="1.3.1" />
<dependency id="System.ValueTuple" version="4.3.0" />
</dependencies>

4
ICSharpCode.Decompiler/IL/ILReader.cs

@ -1149,7 +1149,9 @@ namespace ICSharpCode.Decompiler.IL @@ -1149,7 +1149,9 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction Stloc(int v)
{
return new StLoc(localVariables[v], Pop(localVariables[v].StackType));
return new StLoc(localVariables[v], Pop(localVariables[v].StackType)) {
ILStackWasEmpty = currentStack.IsEmpty
};
}
private ILInstruction LdElem(IType type)

9
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -57,7 +57,11 @@ namespace ICSharpCode.Decompiler.IL @@ -57,7 +57,11 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Variable created from stack slot.
/// </summary>
StackSlot
StackSlot,
/// <summary>
/// Variable in BlockKind.CallWithNamedArgs
/// </summary>
NamedArgument,
}
public class ILVariable
@ -309,6 +313,9 @@ namespace ICSharpCode.Decompiler.IL @@ -309,6 +313,9 @@ namespace ICSharpCode.Decompiler.IL
case VariableKind.UsingLocal:
output.Write("using ");
break;
case VariableKind.NamedArgument:
output.Write("named_arg ");
break;
default:
throw new ArgumentOutOfRangeException();
}

2
ICSharpCode.Decompiler/IL/InstructionFlags.cs

@ -70,7 +70,7 @@ namespace ICSharpCode.Decompiler.IL @@ -70,7 +70,7 @@ namespace ICSharpCode.Decompiler.IL
/// The instruction contains some kind of internal control flow.
/// </summary>
/// <remarks>
/// If this flag is not set, the all descendants of the instruction are fully evaluated (modulo MayThrow/MayBranch)
/// If this flag is not set, all descendants of the instruction are fully evaluated (modulo MayThrow/MayBranch)
/// in left-to-right pre-order.
///
/// Note that branch instructions don't have this flag set, because their control flow is not internal

38
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// 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.Diagnostics;
using System.Linq;
@ -114,6 +115,22 @@ namespace ICSharpCode.Decompiler.IL @@ -114,6 +115,22 @@ namespace ICSharpCode.Decompiler.IL
case BlockKind.CallInlineAssign:
Debug.Assert(MatchInlineAssignBlock(out _, out _));
break;
case BlockKind.CallWithNamedArgs:
Debug.Assert(finalInstruction is CallInstruction);
foreach (var inst in Instructions) {
var stloc = inst as StLoc;
Debug.Assert(stloc != null, "Instructions in CallWithNamedArgs must be assignments");
Debug.Assert(stloc.Variable.Kind == VariableKind.NamedArgument);
Debug.Assert(stloc.Variable.IsSingleDefinition && stloc.Variable.LoadCount == 1);
Debug.Assert(stloc.Variable.LoadInstructions.Single().Parent == finalInstruction);
}
var call = (CallInstruction)finalInstruction;
if (call.IsInstanceCall) {
// special case: with instance calls, Instructions[0] must be for the this parameter
ILVariable v = ((StLoc)Instructions[0]).Variable;
Debug.Assert(call.Arguments[0].MatchLdLoc(v));
}
break;
}
}
@ -136,6 +153,8 @@ namespace ICSharpCode.Decompiler.IL @@ -136,6 +153,8 @@ namespace ICSharpCode.Decompiler.IL
ILRange.WriteTo(output, options);
output.Write("Block ");
output.WriteDefinition(Label, this);
if (Kind != BlockKind.ControlFlow)
output.Write($" ({Kind})");
if (Parent is BlockContainer)
output.Write(" (incoming: {0})", IncomingEdgeCount);
output.Write(' ');
@ -311,6 +330,23 @@ namespace ICSharpCode.Decompiler.IL @@ -311,6 +330,23 @@ namespace ICSharpCode.Decompiler.IL
/// final: ldloc s
/// }
/// </example>
CallInlineAssign
CallInlineAssign,
/// <summary>
/// Call using named arguments.
/// </summary>
/// <remarks>
/// Each instruction is assigning to a new local.
/// The final instruction is a call.
/// The locals for this block have exactly one store and
/// exactly one load, which must be an immediate argument to the call.
/// </remarks>
/// <example>
/// Block {
/// stloc arg0 = ...
/// stloc arg1 = ...
/// final: call M(..., arg1, arg0, ...)
/// }
/// </example>
CallWithNamedArgs,
}
}

43
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs

@ -18,10 +18,8 @@ @@ -18,10 +18,8 @@
using System;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL
{
@ -60,24 +58,20 @@ namespace ICSharpCode.Decompiler.IL @@ -60,24 +58,20 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
public bool ILStackWasEmpty;
/// <summary>
/// Gets the mapping of arguments to method parameters. Must be a 1-to-1 mapping.
/// Normally this is index == value for static calls and newobj, and value + 1 == index for instance method calls.
/// |ArgumentToParameterMap| == |Arguments|.
/// </summary>
public int[] ArgumentToParameterMap;
protected CallInstruction(OpCode opCode, IMethod method) : base(opCode)
{
Debug.Assert(method != null);
this.Method = method;
int firstParameter = OpCode != OpCode.NewObj && !Method.IsStatic ? 1 : 0;
this.ArgumentToParameterMap = new int[method.Parameters.Count + firstParameter];
for (int i = 0; i < ArgumentToParameterMap.Length; i++)
ArgumentToParameterMap[i] = -firstParameter + i;
this.Arguments = new InstructionCollection<ILInstruction>(this, 0);
}
/// <summary>
/// Gets whether this is an instance call (i.e. whether the first argument is the 'this' pointer).
/// </summary>
public bool IsInstanceCall {
get { return !(Method.IsStatic || OpCode == OpCode.NewObj); }
}
/// <summary>
/// Gets the parameter for the argument with the specified index.
/// Returns null for the <c>this</c> parameter.
@ -126,24 +120,13 @@ namespace ICSharpCode.Decompiler.IL @@ -126,24 +120,13 @@ namespace ICSharpCode.Decompiler.IL
base.CheckInvariant(phase);
int firstArgument = (OpCode != OpCode.NewObj && !Method.IsStatic) ? 1 : 0;
Debug.Assert(Method.Parameters.Count + firstArgument == Arguments.Count);
Debug.Assert(Method.Parameters.Count + firstArgument == ArgumentToParameterMap.Length);
if (firstArgument == 1) {
Debug.Assert(Arguments[0].ResultType == ExpectedTypeForThisPointer(ConstrainedTo ?? Method.DeclaringType),
$"Stack type mismatch in 'this' argument in call to {Method.Name}()");
Debug.Assert(ArgumentToParameterMap[0] == -1, "'this' argument must always be mapped at position 0");
}
int paramCount = Method.Parameters.Count;
if (paramCount > 0) {
BitSet bitSet = new BitSet(paramCount);
for (int i = 0; i < paramCount; ++i) {
int mappedTo = ArgumentToParameterMap[firstArgument + i];
Debug.Assert(mappedTo >= 0 && mappedTo < paramCount, $"mapping out of [0..{paramCount}[, was: {mappedTo}");
Debug.Assert(!bitSet[mappedTo], $"argument {mappedTo} is already mapped to a different parameter");
bitSet.Set(mappedTo);
Debug.Assert(Arguments[firstArgument + i].ResultType == Method.Parameters[mappedTo].Type.GetStackType(),
$"Stack type mismatch in parameter {mappedTo} (argument {firstArgument + i}) in call to {Method.Name}()");
}
Debug.Assert(bitSet.All(0, paramCount - 1), "Not all arguments are mapped to a parameter");
for (int i = 0; i < Method.Parameters.Count; ++i) {
Debug.Assert(Arguments[firstArgument + i].ResultType == Method.Parameters[i].Type.GetStackType(),
$"Stack type mismatch in parameter {i} in call to {Method.Name}()");
}
}
@ -161,12 +144,9 @@ namespace ICSharpCode.Decompiler.IL @@ -161,12 +144,9 @@ namespace ICSharpCode.Decompiler.IL
output.Write(' ');
Method.WriteTo(output);
output.Write('(');
int firstIndex = (OpCode != OpCode.NewObj && !Method.IsStatic) ? -1 : 0;
for (int i = 0; i < Arguments.Count; i++) {
if (i > 0)
output.Write(", ");
if (ArgumentToParameterMap[i] != firstIndex + i)
output.Write($"{ArgumentToParameterMap[i]}: ");
Arguments[i].WriteTo(output, options);
}
output.Write(')');
@ -177,8 +157,7 @@ namespace ICSharpCode.Decompiler.IL @@ -177,8 +157,7 @@ namespace ICSharpCode.Decompiler.IL
CallInstruction o = other as CallInstruction;
return o != null && this.OpCode == o.OpCode && this.Method.Equals(o.Method) && this.IsTail == o.IsTail
&& object.Equals(this.ConstrainedTo, o.ConstrainedTo)
&& Patterns.ListMatch.DoMatch(this.Arguments, o.Arguments, ref match)
&& ArgumentToParameterMap.SequenceEqual(o.ArgumentToParameterMap);
&& Patterns.ListMatch.DoMatch(this.Arguments, o.Arguments, ref match);
}
}

7
ICSharpCode.Decompiler/IL/Instructions/StLoc.cs

@ -27,6 +27,13 @@ namespace ICSharpCode.Decompiler.IL @@ -27,6 +27,13 @@ namespace ICSharpCode.Decompiler.IL
/// This field is only used in ILReader and BlockBuilder, and should be ignored by ILAst transforms.
/// </summary>
internal bool IsStackAdjustment;
/// <summary>
/// Gets whether the IL stack was empty after this store.
/// Only set for store instructions from the IL; not for stores to the stack
/// or other stores generated by transforms.
/// </summary>
internal bool ILStackWasEmpty;
internal override void CheckInvariant(ILPhase phase)
{

2
ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
continue;
}
if (CachedDelegateInitializationWithLocal(inst)) {
ILInlining.InlineOneIfPossible(block, i, true, context);
ILInlining.InlineOneIfPossible(block, i, InliningOptions.Aggressive, context);
continue;
}
if (CachedDelegateInitializationRoslynInStaticWithLocal(inst) || CachedDelegateInitializationRoslynWithLocal(inst)) {

2
ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs

@ -125,7 +125,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -125,7 +125,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
expr.ReplaceWith(clone);
}
block.Instructions.RemoveAt(i);
int c = ILInlining.InlineInto(block, i, aggressive: false, context: context);
int c = ILInlining.InlineInto(block, i, InliningOptions.None, context: context);
i -= c + 1;
}
}

134
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -23,6 +23,14 @@ using ICSharpCode.Decompiler.TypeSystem; @@ -23,6 +23,14 @@ using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL.Transforms
{
[Flags]
public enum InliningOptions
{
None = 0,
Aggressive = 1,
IntroduceNamedArguments = 2,
}
/// <summary>
/// Performs inlining transformations.
/// </summary>
@ -44,7 +52,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -44,7 +52,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms
public void Run(Block block, int pos, StatementTransformContext context)
{
InlineOneIfPossible(block, pos, aggressive: IsCatchWhenBlock(block), context: context);
InlineOneIfPossible(block, pos, OptionsForBlock(block), context: context);
}
internal static InliningOptions OptionsForBlock(Block block)
{
InliningOptions options = InliningOptions.None;
if (IsCatchWhenBlock(block))
options |= InliningOptions.Aggressive;
return options;
}
public static bool InlineAllInBlock(ILFunction function, Block block, ILTransformContext context)
@ -58,14 +74,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -58,14 +74,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
bool modified = false;
var instructions = block.Instructions;
for (int i = 0; i < instructions.Count;) {
if (instructions[i] is StLoc inst
&& InlineOneIfPossible(block, i, aggressive: IsCatchWhenBlock(block) || IsInConstructorInitializer(function, inst, ref ctorCallStart), context: context)) {
modified = true;
i = Math.Max(0, i - 1);
// Go back one step
} else {
i++;
if (instructions[i] is StLoc inst) {
InliningOptions options = InliningOptions.None;
if (IsCatchWhenBlock(block) || IsInConstructorInitializer(function, inst, ref ctorCallStart))
options = InliningOptions.Aggressive;
if (InlineOneIfPossible(block, i, options, context)) {
modified = true;
i = Math.Max(0, i - 1);
// Go back one step
continue;
}
}
i++;
}
return modified;
}
@ -100,13 +120,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -100,13 +120,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Inlines instructions before pos into block.Instructions[pos].
/// </summary>
/// <returns>The number of instructions that were inlined.</returns>
public static int InlineInto(Block block, int pos, bool aggressive, ILTransformContext context)
public static int InlineInto(Block block, int pos, InliningOptions options, ILTransformContext context)
{
if (pos >= block.Instructions.Count)
return 0;
int count = 0;
while (--pos >= 0) {
if (InlineOneIfPossible(block, pos, aggressive, context))
if (InlineOneIfPossible(block, pos, options, context))
count++;
else
break;
@ -119,13 +139,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -119,13 +139,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
public static bool InlineIfPossible(Block block, int pos, ILTransformContext context)
{
return InlineOneIfPossible(block, pos, true, context);
return InlineOneIfPossible(block, pos, InliningOptions.Aggressive, context);
}
/// <summary>
/// Inlines the stloc instruction at block.Instructions[pos] into the next instruction, if possible.
/// </summary>
public static bool InlineOneIfPossible(Block block, int pos, bool aggressive, ILTransformContext context)
public static bool InlineOneIfPossible(Block block, int pos, InliningOptions options, ILTransformContext context)
{
context.CancellationToken.ThrowIfCancellationRequested();
StLoc stloc = block.Instructions[pos] as StLoc;
@ -141,7 +161,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -141,7 +161,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// but we can't avoid it this easily without breaking lots of tests.
//if (v.Type.IsSmallIntegerType())
// return false; // stloc might perform implicit truncation
return InlineOne(stloc, aggressive, context);
return InlineOne(stloc, options, context);
}
/// <summary>
@ -150,12 +170,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -150,12 +170,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Note that this method does not check whether 'v' has only one use;
/// the caller is expected to validate whether inlining 'v' has any effects on other uses of 'v'.
/// </summary>
public static bool InlineOne(StLoc stloc, bool aggressive, ILTransformContext context)
public static bool InlineOne(StLoc stloc, InliningOptions options, ILTransformContext context)
{
ILVariable v = stloc.Variable;
Block block = (Block)stloc.Parent;
int pos = stloc.ChildIndex;
if (DoInline(v, stloc.Value, block.Instructions.ElementAtOrDefault(pos + 1), aggressive, context)) {
if (DoInline(v, stloc.Value, block.Instructions.ElementAtOrDefault(pos + 1), options, context)) {
// Assign the ranges of the stloc instruction:
stloc.Value.AddILRange(stloc.ILRange);
// Remove the stloc instruction:
@ -188,17 +208,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -188,17 +208,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Note that this method does not check whether 'v' has only one use;
/// the caller is expected to validate whether inlining 'v' has any effects on other uses of 'v'.
/// </summary>
static bool DoInline(ILVariable v, ILInstruction inlinedExpression, ILInstruction next, bool aggressive, ILTransformContext context)
static bool DoInline(ILVariable v, ILInstruction inlinedExpression, ILInstruction next, InliningOptions options, ILTransformContext context)
{
ILInstruction loadInst;
if (FindLoadInNext(next, v, inlinedExpression, out loadInst) == true) {
var r = FindLoadInNext(next, v, inlinedExpression, out var loadInst);
if (r == FindResult.Found) {
if (loadInst.OpCode == OpCode.LdLoca) {
if (!IsGeneratedValueTypeTemporary(next, (LdLoca)loadInst, v, inlinedExpression))
return false;
} else {
Debug.Assert(loadInst.OpCode == OpCode.LdLoc);
if (!aggressive && v.Kind != VariableKind.StackSlot && !NonAggressiveInlineInto(next, loadInst, inlinedExpression, v))
bool aggressive = (options & InliningOptions.Aggressive) != 0;
if (!aggressive && v.Kind != VariableKind.StackSlot
&& !NonAggressiveInlineInto(next, loadInst, inlinedExpression, v)) {
return false;
}
}
context.Step($"Inline variable '{v.Name}'", inlinedExpression);
@ -213,6 +236,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -213,6 +236,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
loadInst.ReplaceWith(inlinedExpression);
}
return true;
} else if (r == FindResult.NamedArgument && (options & InliningOptions.IntroduceNamedArguments) != 0) {
return NamedArgumentTransform.DoInline(v, (StLoc)inlinedExpression.Parent, (LdLoc)loadInst,
options, context);
}
return false;
}
@ -351,59 +377,97 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -351,59 +377,97 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
public static bool CanInlineInto(ILInstruction expr, ILVariable v, ILInstruction expressionBeingMoved)
{
ILInstruction loadInst;
return FindLoadInNext(expr, v, expressionBeingMoved, out loadInst) == true;
return FindLoadInNext(expr, v, expressionBeingMoved, out _) == FindResult.Found;
}
internal enum FindResult
{
/// <summary>
/// Found a load; inlining is possible.
/// </summary>
Found,
/// <summary>
/// Load not found and re-ordering not possible. Stop the search.
/// </summary>
Stop,
/// <summary>
/// Load not found, but the expressionBeingMoved can be re-ordered with regards to the
/// tested expression, so we may continue searching for the matching load.
/// </summary>
Continue,
/// <summary>
/// Found a load in call, but re-ordering not possible with regards to the
/// other call arguments.
/// Inlining is not possible, but we might convert the call to named arguments.
/// </summary>
NamedArgument,
}
/// <summary>
/// Finds the position to inline to.
/// </summary>
/// <returns>true = found; false = cannot continue search; null = not found</returns>
static bool? FindLoadInNext(ILInstruction expr, ILVariable v, ILInstruction expressionBeingMoved, out ILInstruction loadInst)
internal static FindResult FindLoadInNext(ILInstruction expr, ILVariable v, ILInstruction expressionBeingMoved, out ILInstruction loadInst)
{
loadInst = null;
if (expr == null)
return false;
return FindResult.Stop;
if (expr.MatchLdLoc(v) || expr.MatchLdLoca(v)) {
// Match found, we can inline
loadInst = expr;
return true;
} else if (expr is Block block && block.Instructions.Count > 0) {
// Inlining into inline-blocks? only for some block types, and only into the first instruction.
return FindResult.Found;
} else if (expr is Block block) {
// Inlining into inline-blocks?
switch (block.Kind) {
case BlockKind.ArrayInitializer:
case BlockKind.CollectionInitializer:
case BlockKind.ObjectInitializer:
return FindLoadInNext(block.Instructions[0], v, expressionBeingMoved, out loadInst) ?? false;
// Allow inlining into the first instruction of the block
if (block.Instructions.Count == 0)
return FindResult.Stop;
return NoContinue(FindLoadInNext(block.Instructions[0], v, expressionBeingMoved, out loadInst));
// If FindLoadInNext() returns null, we still can't continue searching
// because we can't inline over the remainder of the block.
case BlockKind.CallWithNamedArgs:
return NamedArgumentTransform.CanExtendNamedArgument(block, v, expressionBeingMoved, out loadInst);
default:
return false;
return FindResult.Stop;
}
} else if (expr is BlockContainer container && container.EntryPoint.IncomingEdgeCount == 1) {
// Possibly a switch-container, allow inlining into the switch instruction:
return FindLoadInNext(container.EntryPoint.Instructions[0], v, expressionBeingMoved, out loadInst) ?? false;
return NoContinue(FindLoadInNext(container.EntryPoint.Instructions[0], v, expressionBeingMoved, out loadInst));
// If FindLoadInNext() returns null, we still can't continue searching
// because we can't inline over the remainder of the blockcontainer.
} else if (expr is NullableRewrap) {
// Inlining into nullable.rewrap is OK unless the expression being inlined
// contains a nullable.wrap that isn't being re-wrapped within the expression being inlined.
if (expressionBeingMoved.HasFlag(InstructionFlags.MayUnwrapNull))
return false;
return FindResult.Stop;
}
foreach (var child in expr.Children) {
if (!child.SlotInfo.CanInlineInto)
return false;
return FindResult.Stop;
// Recursively try to find the load instruction
bool? r = FindLoadInNext(child, v, expressionBeingMoved, out loadInst);
if (r != null)
FindResult r = FindLoadInNext(child, v, expressionBeingMoved, out loadInst);
if (r != FindResult.Continue) {
if (r == FindResult.Stop && expr is CallInstruction call)
return NamedArgumentTransform.CanIntroduceNamedArgument(call, child, v, out loadInst);
return r;
}
}
if (IsSafeForInlineOver(expr, expressionBeingMoved))
return null; // continue searching
return FindResult.Continue; // continue searching
else
return FindResult.Stop; // abort, inlining not possible
}
private static FindResult NoContinue(FindResult findResult)
{
if (findResult == FindResult.Continue)
return FindResult.Stop;
else
return false; // abort, inlining not possible
return findResult;
}
/// <summary>

111
ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs

@ -0,0 +1,111 @@ @@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL.Transforms
{
using FindResult = ILInlining.FindResult;
class NamedArgumentTransform : IStatementTransform
{
public static FindResult CanIntroduceNamedArgument(CallInstruction call, ILInstruction child, ILVariable v, out ILInstruction loadInst)
{
loadInst = null;
Debug.Assert(child.Parent == call);
if (call.IsInstanceCall && child.ChildIndex == 0)
return FindResult.Stop; // cannot use named arg to move expressionBeingMoved before this pointer
if (call.Method.IsOperator || call.Method.IsAccessor)
return FindResult.Stop; // cannot use named arg for operators or accessors
if (call.Method is VarArgInstanceMethod)
return FindResult.Stop; // CallBuilder doesn't support named args when using varargs
if (call.Method.IsConstructor) {
IType type = call.Method.DeclaringType;
if (type.Kind == TypeKind.Delegate || type.IsAnonymousType())
return FindResult.Stop;
}
if (call.Method.Parameters.Any(p => string.IsNullOrEmpty(p.Name)))
return FindResult.Stop; // cannot use named arguments
for (int i = child.ChildIndex; i < call.Arguments.Count; i++) {
if (call.Arguments[i] is LdLoc ldloc && ldloc.Variable == v) {
loadInst = ldloc;
return FindResult.NamedArgument;
}
}
return FindResult.Stop;
}
internal static FindResult CanExtendNamedArgument(Block block, ILVariable v, ILInstruction expressionBeingMoved, out ILInstruction loadInst)
{
Debug.Assert(block.Kind == BlockKind.CallWithNamedArgs);
var firstArg = ((StLoc)block.Instructions[0]).Value;
var r = ILInlining.FindLoadInNext(firstArg, v, expressionBeingMoved, out loadInst);
if (r == FindResult.Found || r == FindResult.NamedArgument) {
return r; // OK, inline into first instruction of block
}
var call = (CallInstruction)block.FinalInstruction;
if (call.IsInstanceCall) {
// For instance calls, block.Instructions[0] is the argument
// for the 'this' pointer. We can only insert at position 1.
if (r == FindResult.Stop) {
// error: can't move expressionBeingMoved after block.Instructions[0]
return FindResult.Stop;
}
// Because we always ensure block.Instructions[0] is the 'this' argument,
// it's possible that the place we actually need to inline into
// is within block.Instructions[1]:
if (block.Instructions.Count > 1) {
r = ILInlining.FindLoadInNext(block.Instructions[1], v, expressionBeingMoved, out loadInst);
if (r == FindResult.Found || r == FindResult.NamedArgument) {
return r; // OK, inline into block.Instructions[1]
}
}
}
foreach (var arg in call.Arguments) {
if (arg.MatchLdLoc(v)) {
loadInst = arg;
return FindResult.NamedArgument;
}
}
return FindResult.Stop;
}
internal static bool DoInline(ILVariable v, StLoc originalStore, LdLoc loadInst, InliningOptions options, ILTransformContext context)
{
if ((options & InliningOptions.Aggressive) == 0 && originalStore.ILStackWasEmpty)
return false;
context.Step($"Introduce named argument '{v.Name}'", originalStore);
var call = (CallInstruction)loadInst.Parent;
if (!(call.Parent is Block namedArgBlock) || namedArgBlock.Kind != BlockKind.CallWithNamedArgs) {
// create namedArgBlock:
namedArgBlock = new Block(BlockKind.CallWithNamedArgs);
call.ReplaceWith(namedArgBlock);
namedArgBlock.FinalInstruction = call;
if (call.IsInstanceCall) {
IType thisVarType = call.Method.DeclaringType;
if (CallInstruction.ExpectedTypeForThisPointer(thisVarType) == StackType.Ref) {
thisVarType = new ByReferenceType(thisVarType);
}
var function = call.Ancestors.OfType<ILFunction>().First();
var thisArgVar = function.RegisterVariable(VariableKind.NamedArgument, thisVarType, "this_arg");
namedArgBlock.Instructions.Add(new StLoc(thisArgVar, call.Arguments[0]));
call.Arguments[0] = new LdLoc(thisArgVar);
}
}
v.Kind = VariableKind.NamedArgument;
namedArgBlock.Instructions.Insert(call.IsInstanceCall ? 1 : 0, originalStore);
return true;
}
public void Run(Block block, int pos, StatementTransformContext context)
{
if (!context.Settings.NamedArguments)
return;
var options = ILInlining.OptionsForBlock(block);
options |= InliningOptions.IntroduceNamedArguments;
ILInlining.InlineOneIfPossible(block, pos, options, context: context);
}
}
}

2
ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.Step("NullCoalescingTransform (reference types)", stloc);
stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, fallbackValue);
block.Instructions.RemoveAt(pos + 1); // remove if instruction
ILInlining.InlineOneIfPossible(block, pos, false, context);
ILInlining.InlineOneIfPossible(block, pos, InliningOptions.None, context);
return true;
}
return false;

3
ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs

@ -266,7 +266,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -266,7 +266,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var typeArgs = call.Method.TypeArguments.ToArray();
var resolveContext = new CSharp.TypeSystem.CSharpTypeResolveContext(context.TypeSystem.Compilation.MainAssembly, context.UsingScope);
var resolver = new CSharp.Resolver.CSharpResolver(resolveContext);
return CSharp.Transforms.IntroduceExtensionMethods.CanTransformToExtensionMethodCall(resolver, call.Method, typeArgs, targetType, paramTypes);
return CSharp.Transforms.IntroduceExtensionMethods.CanTransformToExtensionMethodCall(
resolver, call.Method, typeArgs, targetType, paramTypes, argumentNames: null);
}
static bool IsGetter(IMethod method)

16
ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs

@ -259,7 +259,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -259,7 +259,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
switchValueVar = switchValueVarCopy;
int conditionOffset = 1;
Block currentCaseBlock = isInternedBlock;
List<(string, Block)> values = new List<(string, Block)>();
var values = new List<(string, ILInstruction)>();
if (!switchValueVarCopy.IsSingleDefinition)
return false;
// each case starts with:
// if (comp(ldloc switchValueVar == ldstr "case label")) br caseBlock
@ -274,20 +277,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -274,20 +277,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms
break;
if (!right.MatchLdStr(out string value))
break;
if (!caseBlockJump.MatchBranch(out var caseBlock))
if (!(caseBlockJump.MatchBranch(out var caseBlock) || caseBlockJump.MatchLeave((BlockContainer)currentCaseBlock.Parent)))
break;
if (!currentCaseBlock.Instructions[conditionOffset + 1].MatchBranch(out currentCaseBlock))
break;
conditionOffset = 0;
values.Add((value, caseBlock));
values.Add((value, caseBlockJump.Clone()));
}
if (values.Count != switchValueVarCopy.LoadCount)
return false;
// switch contains case null:
if (currentCaseBlock != defaultOrNullBlock) {
values.Add((null, defaultOrNullBlock));
values.Add((null, new Branch(defaultOrNullBlock)));
}
var sections = new List<SwitchSection>(values.SelectWithIndex((index, b) => new SwitchSection { Labels = new LongSet(index), Body = new Branch(b.Item2) }));
var sections = new List<SwitchSection>(values.SelectWithIndex((index, b) => new SwitchSection { Labels = new LongSet(index), Body = b.Item2 }));
sections.Add(new SwitchSection { Labels = new LongSet(new LongInterval(0, sections.Count)).Invert(), Body = new Branch(currentCaseBlock) });
var stringToInt = new StringToInt(switchValue, values.SelectArray(item => item.Item1));
var inst = new SwitchInstruction(stringToInt);

5
ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs

@ -175,7 +175,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -175,7 +175,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
possibleIndexVariables.Add(stloc.Variable, (stloc.ChildIndex, stloc.Value));
return true;
}
(var kind, var newPath, var values, var targetVariable) = AccessPathElement.GetAccessPath(instructions[pos], rootType, possibleIndexVariables);
(var kind, var newPath, var values, var targetVariable) = AccessPathElement.GetAccessPath(instructions[pos], rootType, possibleIndexVariables, allowDictionaryInitializer: context.Settings.DictionaryInitializers);
if (kind == AccessPathKind.Invalid || target != targetVariable)
return false;
// Treat last element separately:
@ -240,7 +240,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -240,7 +240,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
public override string ToString() => $"[{Member}, {Indices}]";
public static (AccessPathKind Kind, List<AccessPathElement> Path, List<ILInstruction> Values, ILVariable Target) GetAccessPath(
ILInstruction instruction, IType rootType, Dictionary<ILVariable, (int Index, ILInstruction Value)> possibleIndexVariables = null)
ILInstruction instruction, IType rootType, Dictionary<ILVariable, (int Index, ILInstruction Value)> possibleIndexVariables = null, bool allowDictionaryInitializer = false)
{
List<AccessPathElement> path = new List<AccessPathElement>();
ILVariable target = null;
@ -259,6 +259,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -259,6 +259,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var property = method.AccessorOwner as IProperty;
var isGetter = method.Equals(property?.Getter);
var indices = call.Arguments.Skip(1).Take(call.Arguments.Count - (isGetter ? 1 : 2)).ToArray();
if (indices.Length > 0 && !allowDictionaryInitializer) goto default;
if (possibleIndexVariables != null) {
// Mark all index variables as used
foreach (var index in indices.OfType<IInstructionWithVariableOperand>()) {

4
ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs

@ -44,7 +44,9 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -44,7 +44,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
this.parameters = paramList.ToArray();
}
public IMethod BaseMethod => baseMethod;
public int RegularParameterCount {
get { return baseMethod.Parameters.Count - 1; }
}

45
ILSpy.AddIn/Commands/AssemblyReferenceForILSpy.cs

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VSLangProj;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
/// <summary>
/// Represents an assembly reference item in Solution Explorer, which can be opened in ILSpy.
/// </summary>
class AssemblyReferenceForILSpy
{
Reference reference;
AssemblyReferenceForILSpy(Reference reference)
{
this.reference = reference;
}
/// <summary>
/// Detects whether the given selected item represents a supported project.
/// </summary>
/// <param name="itemData">Data object of selected item to check.</param>
/// <returns><see cref="AssemblyReferenceForILSpy"/> instance or <c>null</c>, if item is not a supported project.</returns>
public static AssemblyReferenceForILSpy Detect(object itemData)
{
return (itemData is Reference reference) ? new AssemblyReferenceForILSpy(reference) : null;
}
/// <summary>
/// If possible retrieves parameters to use for launching ILSpy instance.
/// </summary>
/// <param name="projectReferences">List of current project's references.</param>
/// <returns>Parameters object or <c>null, if not applicable.</c></returns>
public ILSpyParameters GetILSpyParameters(Dictionary<string, string> projectReferences)
{
if (projectReferences.TryGetValue(reference.Name, out var path))
return new ILSpyParameters(new[] { path });
return null;
}
}
}

53
ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnvDTE;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
/// <summary>
/// Represents a NuGet package item in Solution Explorer, which can be opened in ILSpy.
/// </summary>
class NuGetReferenceForILSpy
{
ProjectItem projectItem;
NuGetReferenceForILSpy(ProjectItem projectItem)
{
this.projectItem = projectItem;
}
/// <summary>
/// Detects whether the given selected item represents a supported project.
/// </summary>
/// <param name="itemData">Data object of selected item to check.</param>
/// <returns><see cref="NuGetReferenceForILSpy"/> instance or <c>null</c>, if item is not a supported project.</returns>
public static NuGetReferenceForILSpy Detect(object itemData)
{
if (itemData is ProjectItem projectItem) {
var properties = Utils.GetProperties(projectItem.Properties, "Type");
if ((properties[0] as string) == "Package") {
return new NuGetReferenceForILSpy(projectItem);
}
}
return null;
}
/// <summary>
/// If possible retrieves parameters to use for launching ILSpy instance.
/// </summary>
/// <returns>Parameters object or <c>null, if not applicable.</c></returns>
public ILSpyParameters GetILSpyParameters()
{
var properties = Utils.GetProperties(projectItem.Properties, "Name", "Version", "Path");
if (properties[0] != null && properties[1] != null && properties[2] != null) {
return new ILSpyParameters(new[] { $"{properties[2]}\\{properties[0]}.{properties[1]}.nupkg" });
}
return null;
}
}
}

109
ILSpy.AddIn/Commands/OpenCodeItemCommand.cs

@ -3,7 +3,9 @@ using System.IO; @@ -3,7 +3,9 @@ using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
@ -18,10 +20,19 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -18,10 +20,19 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
protected override void OnBeforeQueryStatus(object sender, EventArgs e)
{
OleMenuCommand menuItem = sender as OleMenuCommand;
if (menuItem != null) {
if (sender is OleMenuCommand menuItem) {
menuItem.Visible = false;
// Enable this item only if this is a .cs file!
if (Utils.GetCurrentViewHost(owner, f => f.EndsWith(".cs")) == null)
return;
// Enable this item only if this is a Roslyn document
if (GetRoslynDocument() == null)
return;
var document = owner.DTE.ActiveDocument;
menuItem.Enabled =
menuItem.Visible =
(document != null) &&
(document.ProjectItem != null) &&
(document.ProjectItem.ContainingProject != null) &&
@ -30,24 +41,98 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -30,24 +41,98 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
}
}
protected override async void OnExecute(object sender, EventArgs e)
Document GetRoslynDocument()
{
var document = owner.DTE.ActiveDocument;
var selection = (EnvDTE.TextPoint)((EnvDTE.TextSelection)document.Selection).ActivePoint;
var id = owner.Workspace.CurrentSolution.GetDocumentIdsWithFilePath(document.FullName).FirstOrDefault();
if (id == null)
return null;
if (id == null) return;
var roslynDocument = owner.Workspace.CurrentSolution.GetDocument(id);
return owner.Workspace.CurrentSolution.GetDocument(id);
}
EnvDTE.TextPoint GetEditorSelection()
{
var document = owner.DTE.ActiveDocument;
return ((EnvDTE.TextSelection)document.Selection).ActivePoint;
}
protected override async void OnExecute(object sender, EventArgs e)
{
var textView = Utils.GetCurrentViewHost(owner)?.TextView;
if (textView == null)
return;
SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition;
var roslynDocument = GetRoslynDocument();
var ast = await roslynDocument.GetSyntaxRootAsync().ConfigureAwait(false);
var model = await roslynDocument.GetSemanticModelAsync().ConfigureAwait(false);
var node = ast.FindNode(new Microsoft.CodeAnalysis.Text.TextSpan(selection.AbsoluteCharOffset, 1));
if (node == null)
var node = ast.FindNode(new TextSpan(caretPosition.Position, 0), false, true);
if (node == null) {
owner.ShowMessage("Can't show ILSpy for this code element!");
return;
var symbol = model.GetSymbolInfo(node).Symbol;
if (symbol == null)
}
var symbol = GetSymbolResolvableByILSpy(model, node);
if (symbol == null) {
owner.ShowMessage("Can't show ILSpy for this code element!");
return;
var refs = GetReferences(roslynDocument.Project).Select(fn => fn.Value).Where(f => File.Exists(f)).ToArray();
OpenAssembliesInILSpy(refs, "/navigateTo:" + symbol.GetDocumentationCommentId());
}
var roslynProject = roslynDocument.Project;
var refsmap = GetReferences(roslynProject);
// Add our own project as well (not among references)
var project = owner.DTE.Solution.Projects.OfType<EnvDTE.Project>()
.FirstOrDefault(p => p.FileName == roslynProject.FilePath);
if (project != null) {
string projectOutputPath = GetProjectOutputPath(project, roslynProject);
refsmap.Add(roslynDocument.Project.AssemblyName, projectOutputPath);
}
var refs = refsmap.Select(fn => fn.Value).Where(f => File.Exists(f));
OpenAssembliesInILSpy(new ILSpyParameters(refs, "/navigateTo:" +
(symbol.OriginalDefinition ?? symbol).GetDocumentationCommentId()));
}
ISymbol GetSymbolResolvableByILSpy(SemanticModel model, SyntaxNode node)
{
var current = node;
while (current != null) {
var symbol = model.GetSymbolInfo(current).Symbol;
if (symbol == null) {
symbol = model.GetDeclaredSymbol(current);
}
// ILSpy can only resolve some symbol types, so allow them, discard everything else
if (symbol != null) {
switch (symbol.Kind) {
case SymbolKind.ArrayType:
case SymbolKind.Event:
case SymbolKind.Field:
case SymbolKind.Method:
case SymbolKind.NamedType:
case SymbolKind.Namespace:
case SymbolKind.PointerType:
case SymbolKind.Property:
break;
default:
symbol = null;
break;
}
}
if (symbol != null)
return symbol;
current = current is IStructuredTriviaSyntax
? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent
: current.Parent;
}
return null;
}
internal static void Register(ILSpyAddInPackage owner)

25
ILSpy.AddIn/Commands/OpenILSpyCommand.cs

@ -11,6 +11,18 @@ using Mono.Cecil; @@ -11,6 +11,18 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
public class ILSpyParameters
{
public ILSpyParameters(IEnumerable<string> assemblyFileNames, params string[] arguments)
{
this.AssemblyFileNames = assemblyFileNames;
this.Arguments = arguments;
}
public IEnumerable<string> AssemblyFileNames { get; private set; }
public string[] Arguments { get; private set; }
}
abstract class ILSpyCommand
{
protected ILSpyAddInPackage owner;
@ -36,18 +48,21 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -36,18 +48,21 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
return Path.Combine(basePath, "ILSpy.exe");
}
protected void OpenAssembliesInILSpy(IEnumerable<string> assemblyFileNames, params string[] arguments)
protected void OpenAssembliesInILSpy(ILSpyParameters parameters)
{
foreach (string assemblyFileName in assemblyFileNames) {
if (parameters == null)
return;
foreach (string assemblyFileName in parameters.AssemblyFileNames) {
if (!File.Exists(assemblyFileName)) {
owner.ShowMessage("Could not find assembly '{0}', please ensure the project and all references were built correctly!", assemblyFileName);
return;
}
}
string commandLineArguments = Utils.ArgumentArrayToCommandLine(assemblyFileNames.ToArray());
if (arguments != null) {
commandLineArguments = string.Concat(commandLineArguments, " ", Utils.ArgumentArrayToCommandLine(arguments));
string commandLineArguments = Utils.ArgumentArrayToCommandLine(parameters.AssemblyFileNames.ToArray());
if (parameters.Arguments != null) {
commandLineArguments = string.Concat(commandLineArguments, " ", Utils.ArgumentArrayToCommandLine(parameters.Arguments));
}
System.Diagnostics.Process.Start(GetILSpyPath(), commandLineArguments);

27
ILSpy.AddIn/Commands/OpenProjectOutputCommand.cs

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
using Microsoft.VisualStudio.Shell;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
@ -13,18 +14,24 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -13,18 +14,24 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
{
}
protected override void OnBeforeQueryStatus(object sender, EventArgs e)
{
if (sender is OleMenuCommand menuItem) {
menuItem.Visible = false;
var selectedItem = owner.DTE.SelectedItems.Item(1);
menuItem.Visible = (ProjectItemForILSpy.Detect(owner, selectedItem) != null);
}
}
protected override void OnExecute(object sender, EventArgs e)
{
if (owner.DTE.SelectedItems.Count != 1) return;
var project = owner.DTE.SelectedItems.Item(1).Project;
var roslynProject = owner.Workspace.CurrentSolution.Projects.FirstOrDefault(p => p.FilePath == project.FileName);
string outputFileName = Path.GetFileName(roslynProject.OutputFilePath);
//get the directory path based on the project file.
string projectPath = Path.GetDirectoryName(project.FullName);
//get the output path based on the active configuration
string projectOutputPath = project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();
//combine the project path and output path to get the bin path
OpenAssembliesInILSpy(new[] { Path.Combine(projectPath, projectOutputPath, outputFileName) });
if (owner.DTE.SelectedItems.Count != 1)
return;
var projectItemWrapper = ProjectItemForILSpy.Detect(owner, owner.DTE.SelectedItems.Item(1));
if (projectItemWrapper != null) {
OpenAssembliesInILSpy(projectItemWrapper.GetILSpyParameters(owner));
}
}
internal static void Register(ILSpyAddInPackage owner)

135
ILSpy.AddIn/Commands/OpenReferenceCommand.cs

@ -3,6 +3,7 @@ using System.Collections.Generic; @@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using EnvDTE;
using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio.Shell;
using Mono.Cecil;
using VSLangProj;
@ -17,109 +18,70 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -17,109 +18,70 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
{
}
protected override void OnBeforeQueryStatus(object sender, EventArgs e)
{
if (sender is OleMenuCommand menuItem) {
menuItem.Visible = false;
var selectedItemData = owner.GetSelectedItemsData<object>().FirstOrDefault();
if (selectedItemData == null)
return;
/*
* Assure that we only show the context menu item on items we intend:
* - Project references
* - NuGet package references
*/
if ((AssemblyReferenceForILSpy.Detect(selectedItemData) != null)
|| (ProjectReferenceForILSpy.Detect(selectedItemData) != null)
|| (NuGetReferenceForILSpy.Detect(selectedItemData) != null)) {
menuItem.Visible = true;
}
}
}
protected override void OnExecute(object sender, EventArgs e)
{
var explorer = owner.DTE.ToolWindows.SolutionExplorer;
var item = ((object[])explorer.SelectedItems).FirstOrDefault() as UIHierarchyItem;
var itemObject = owner.GetSelectedItemsData<object>().FirstOrDefault();
if (itemObject == null)
return;
if (item == null) return;
if (item.Object is Reference reference) {
var referenceItem = AssemblyReferenceForILSpy.Detect(itemObject);
if (referenceItem != null) {
Reference reference = itemObject as Reference;
var project = reference.ContainingProject;
var roslynProject = owner.Workspace.CurrentSolution.Projects.FirstOrDefault(p => p.FilePath == project.FileName);
var references = GetReferences(roslynProject);
var parameters = referenceItem.GetILSpyParameters(references);
if (references.TryGetValue(reference.Name, out var path))
OpenAssembliesInILSpy(new[] { path });
OpenAssembliesInILSpy(parameters);
else
owner.ShowMessage("Could not find reference '{0}', please ensure the project and all references were built correctly!", reference.Name);
} else {
dynamic referenceObject = item.Object;
if (TryGetProjectFileName(referenceObject, out string fileName)) {
var roslynProject = owner.Workspace.CurrentSolution.Projects.FirstOrDefault(p => p.FilePath == fileName);
var references = GetReferences(roslynProject);
if (references.TryGetValue(referenceObject.Name, out string path)) {
OpenAssembliesInILSpy(new[] { path });
return;
}
} else {
var values = GetProperties(referenceObject.Properties, "Type", "FusionName", "ResolvedPath");
if (values[0] == "Package") {
values = GetProperties(referenceObject.Properties, "Name", "Version", "Path");
if (values[0] != null && values[1] != null && values[2] != null) {
OpenAssembliesInILSpy(new[] { $"{values[2]}\\{values[0]}.{values[1]}.nupkg" });
return;
}
} else if (values[2] != null) {
OpenAssembliesInILSpy(new[] { $"{values[2]}" });
return;
} else if (!string.IsNullOrWhiteSpace(values[1])) {
OpenAssembliesInILSpy(new string[] { GacInterop.FindAssemblyInNetGac(AssemblyNameReference.Parse(values[1])) });
return;
}
}
owner.ShowMessage("Could not find reference '{0}', please ensure the project and all references were built correctly!", referenceObject.Name);
}
}
private bool TryGetProjectFileName(dynamic referenceObject, out string fileName)
{
try {
fileName = referenceObject.Project.FileName;
return true;
} catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) {
fileName = null;
return false;
// Handle NuGet references
var nugetRefItem = NuGetReferenceForILSpy.Detect(itemObject);
if (nugetRefItem != null) {
OpenAssembliesInILSpy(nugetRefItem.GetILSpyParameters());
}
}
private string[] GetProperties(Properties properties, params string[] names)
{
string[] values = new string[names.Length];
foreach (dynamic p in properties) {
try {
for (int i = 0; i < names.Length; i++) {
if (names[i] == p.Name) {
values[i] = p.Value;
break;
}
}
} catch {
continue;
}
}
return values;
}
private object GetPropertyObject(EnvDTE.Properties properties, string name)
{
foreach (dynamic p in properties) {
try {
if (name == p.Name) {
return p.Object;
// Handle project references
var projectRefItem = ProjectReferenceForILSpy.Detect(itemObject);
if (projectRefItem != null) {
var projectItem = itemObject as ProjectItem;
string fileName = projectItem.ContainingProject?.FileName;
if (!string.IsNullOrEmpty(fileName)) {
var roslynProject = owner.Workspace.CurrentSolution.Projects.FirstOrDefault(p => p.FilePath == fileName);
var references = GetReferences(roslynProject);
if (references.TryGetValue(projectItem.Name, out string path)) {
OpenAssembliesInILSpy(projectRefItem.GetILSpyParameters(references));
return;
}
} catch {
continue;
}
}
return null;
}
private bool HasProperties(EnvDTE.Properties properties, params string[] names)
{
return properties.Count > 0 && names.Any(n => HasProperty(properties, n));
}
private bool HasProperty(EnvDTE.Properties properties, string name)
{
foreach (dynamic p in properties) {
try {
if (name == p.Name) {
return true;
}
} catch {
continue;
}
OpenAssembliesInILSpy(projectRefItem.GetILSpyParameters());
return;
}
return false;
}
internal static void Register(ILSpyAddInPackage owner)
@ -127,4 +89,5 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -127,4 +89,5 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
instance = new OpenReferenceCommand(owner);
}
}
}

48
ILSpy.AddIn/Commands/ProjectItemForILSpy.cs

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
using System.IO;
using System.Linq;
using EnvDTE;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
/// <summary>
/// Represents a project item in Solution Explorer, which can be opened in ILSpy.
/// </summary>
class ProjectItemForILSpy
{
SelectedItem item;
Project project;
Microsoft.CodeAnalysis.Project roslynProject;
ProjectItemForILSpy(Project project, Microsoft.CodeAnalysis.Project roslynProject, SelectedItem item)
{
this.project = project;
this.roslynProject = roslynProject;
this.item = item;
}
/// <summary>
/// Detects whether the given <see cref="SelectedItem"/> represents a supported project.
/// </summary>
/// <param name="item">Selected item to check.</param>
/// <returns><see cref="ProjectItemForILSpy"/> instance or <c>null</c>, if item is not a supported project.</returns>
public static ProjectItemForILSpy Detect(ILSpyAddInPackage package, SelectedItem item)
{
var project = item.Project;
var roslynProject = package.Workspace.CurrentSolution.Projects.FirstOrDefault(p => p.FilePath == project.FileName);
if (roslynProject == null)
return null;
return new ProjectItemForILSpy(project, roslynProject, item);
}
/// <summary>
/// If possible retrieves parameters to use for launching ILSpy instance.
/// </summary>
/// <param name="package">Package instance.</param>
/// <returns>Parameters object or <c>null, if not applicable.</c></returns>
public ILSpyParameters GetILSpyParameters(ILSpyAddInPackage package)
{
return new ILSpyParameters(new[] { Utils.GetProjectOutputAssembly(project, roslynProject) });
}
}
}

78
ILSpy.AddIn/Commands/ProjectReferenceForILSpy.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnvDTE;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
/// <summary>
/// Represents a project reference item in Solution Explorer, which can be opened in ILSpy.
/// </summary>
class ProjectReferenceForILSpy
{
ProjectItem projectItem;
string fusionName;
string resolvedPath;
ProjectReferenceForILSpy(ProjectItem projectItem, string fusionName, string resolvedPath)
{
this.projectItem = projectItem;
this.fusionName = fusionName;
this.resolvedPath = resolvedPath;
}
/// <summary>
/// Detects whether the given selected item represents a supported project.
/// </summary>
/// <param name="itemData">Data object of selected item to check.</param>
/// <returns><see cref="ProjectReferenceForILSpy"/> instance or <c>null</c>, if item is not a supported project.</returns>
public static ProjectReferenceForILSpy Detect(object itemData)
{
if (itemData is ProjectItem projectItem) {
var properties = Utils.GetProperties(projectItem.Properties, "FusionName", "ResolvedPath");
string fusionName = properties[0] as string;
string resolvedPath = properties[1] as string;
if ((fusionName != null) || (resolvedPath != null)) {
return new ProjectReferenceForILSpy(projectItem, fusionName, resolvedPath);
}
}
return null;
}
/// <summary>
/// If possible retrieves parameters to use for launching ILSpy instance.
/// </summary>
/// <param name="projectReferences">List of current project's references.</param>
/// <returns>Parameters object or <c>null, if not applicable.</c></returns>
public ILSpyParameters GetILSpyParameters(Dictionary<string, string> projectReferences)
{
string fileName = projectItem.ContainingProject?.FileName;
if (!string.IsNullOrEmpty(fileName)) {
if (projectReferences.TryGetValue(projectItem.Name, out string path)) {
return new ILSpyParameters(new[] { path });
}
}
return null;
}
/// <summary>
/// If possible retrieves parameters to use for launching ILSpy instance.
/// </summary>
/// <returns>Parameters object or <c>null, if not applicable.</c></returns>
public ILSpyParameters GetILSpyParameters()
{
if (resolvedPath != null) {
return new ILSpyParameters(new[] { $"{resolvedPath}" });
} else if (!string.IsNullOrWhiteSpace(fusionName)) {
return new ILSpyParameters(new string[] { GacInterop.FindAssemblyInNetGac(AssemblyNameReference.Parse(fusionName)) });
}
return null;
}
}
}

12
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -49,9 +49,12 @@ @@ -49,9 +49,12 @@
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.4.0" />
<PackageReference Include="Microsoft.VisualStudio.ComponentModelHost" Version="15.6.27413" />
<PackageReference Include="Microsoft.VisualStudio.Editor" Version="15.6.27740" />
<PackageReference Include="Microsoft.VisualStudio.LanguageServices" Version="2.4.0" />
<PackageReference Include="Microsoft.VisualStudio.Shell.14.0" Version="14.3.25407" />
<PackageReference Include="Mono.Cecil" Version="0.10.0-beta7" />
<PackageReference Include="Microsoft.VisualStudio.Text.UI" Version="15.6.27740" />
<PackageReference Include="Microsoft.VisualStudio.Text.UI.Wpf" Version="15.6.27740" />
<PackageReference Include="Mono.Cecil" Version="0.10.0" />
<PackageReference Include="VSLangProj" Version="7.0.3301" />
</ItemGroup>
@ -63,6 +66,10 @@ @@ -63,6 +66,10 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Commands\AssemblyReferenceForILSpy.cs" />
<Compile Include="Commands\NuGetReferenceForILSpy.cs" />
<Compile Include="Commands\ProjectItemForILSpy.cs" />
<Compile Include="Commands\ProjectReferenceForILSpy.cs" />
<Compile Include="Commands\OpenCodeItemCommand.cs" />
<Compile Include="Commands\OpenILSpyCommand.cs" />
<Compile Include="Commands\OpenProjectOutputCommand.cs" />
@ -77,6 +84,7 @@ @@ -77,6 +84,7 @@
<Compile Include="ILSpyAddInPackage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PkgCmdID.cs" />
<Compile Include="SyntaxNodeExtensions.cs" />
<Compile Include="Utils.cs" />
</ItemGroup>
@ -100,6 +108,8 @@ @@ -100,6 +108,8 @@
</ItemGroup>
<ItemGroup>
<None Include="ILSpyAddIn.vsct" />
<None Include="source.extension.vsixmanifest.template" />
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>

21
ILSpy.AddIn/ILSpyAddIn.vsct

@ -51,6 +51,10 @@ @@ -51,6 +51,10 @@
<Group guid="guidILSpyAddInCmdSet" id="OpenILSpyCodeItemGroup" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN"/>
</Group>
<Group guid="guidILSpyAddInCmdSet" id="OpenILSpyRefGroup" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_REFERENCE"/>
</Group>
</Groups>
<!--Buttons section. -->
@ -78,6 +82,8 @@ @@ -78,6 +82,8 @@
<Button guid="guidILSpyAddInCmdSet" id="cmdidOpenProjectOutputInILSpy" priority="0x0600" type="Button">
<Parent guid="guidILSpyAddInCmdSet" id="OpenILSpyProjGroup" />
<Icon guid="guidImages" id="bmpLogo" />
<CommandFlag>DynamicVisibility</CommandFlag>
<CommandFlag>DefaultInvisible</CommandFlag>
<Strings>
<ButtonText>Open output in ILSpy</ButtonText>
</Strings>
@ -86,6 +92,8 @@ @@ -86,6 +92,8 @@
<Button guid="guidILSpyAddInCmdSet" id="cmdidOpenCodeItemInILSpy" priority="0x0600" type="Button">
<Parent guid="guidILSpyAddInCmdSet" id="OpenILSpyCodeItemGroup" />
<Icon guid="guidImages" id="bmpLogo" />
<CommandFlag>DynamicVisibility</CommandFlag>
<CommandFlag>DefaultInvisible</CommandFlag>
<Strings>
<ButtonText>Open code in ILSpy</ButtonText>
</Strings>
@ -112,19 +120,6 @@ @@ -112,19 +120,6 @@
</Bitmaps>
</Commands>
<CommandPlacements>
<!--
<CommandPlacement guid="guidILSpyAddInCmdSet" id="cmdidOpenReferenceInILSpy" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDG_VS_CTXT_REFERENCE"/>
</CommandPlacement>
-->
<!-- HACK : since there is no special ID for the new .NET Standard 2.0 reference nodes,
use the ITEM_OPEN id and hide the item if not applicable. -->
<CommandPlacement guid="guidILSpyAddInCmdSet" id="cmdidOpenReferenceInILSpy" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDG_VS_CTXT_ITEM_OPEN"/>
</CommandPlacement>
</CommandPlacements>
<Symbols>
<!-- This is the package guid. -->
<GuidSymbol name="guidILSpyAddInPkg" value="{a9120dbe-164a-4891-842f-fb7829273838}" />

14
ILSpy.AddIn/ILSpyAddInPackage.cs

@ -13,6 +13,7 @@ using System.Linq; @@ -13,6 +13,7 @@ using System.Linq;
using ICSharpCode.ILSpy.AddIn.Commands;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.LanguageServices;
using EnvDTE;
namespace ICSharpCode.ILSpy.AddIn
{
@ -84,7 +85,7 @@ namespace ICSharpCode.ILSpy.AddIn @@ -84,7 +85,7 @@ namespace ICSharpCode.ILSpy.AddIn
OpenILSpyCommand.Register(this);
OpenProjectOutputCommand.Register(this);
OpenReferenceCommand.Register(this);
//OpenCodeItemCommand.Register(this);
OpenCodeItemCommand.Register(this);
}
#endregion
@ -109,5 +110,16 @@ namespace ICSharpCode.ILSpy.AddIn @@ -109,5 +110,16 @@ namespace ICSharpCode.ILSpy.AddIn
)
);
}
public IEnumerable<T> GetSelectedItemsData<T>()
{
if (DTE.ToolWindows.SolutionExplorer.SelectedItems is IEnumerable<UIHierarchyItem> hierarchyItems) {
foreach (var item in hierarchyItems) {
if (item.Object is T typedItem) {
yield return typedItem;
}
}
}
}
}
}

821
ILSpy.AddIn/SyntaxNodeExtensions.cs

@ -0,0 +1,821 @@ @@ -0,0 +1,821 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System.Threading.Tasks;
namespace ICSharpCode.ILSpy.AddIn
{
static class SyntaxNodeExtensions
{
public static IEnumerable<SyntaxNode> GetAncestors(this SyntaxNode node)
{
var current = node.Parent;
while (current != null)
{
yield return current;
current = current is IStructuredTriviaSyntax
? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent
: current.Parent;
}
}
public static IEnumerable<TNode> GetAncestors<TNode>(this SyntaxNode node)
where TNode : SyntaxNode
{
var current = node.Parent;
while (current != null)
{
if (current is TNode)
{
yield return (TNode)current;
}
current = current is IStructuredTriviaSyntax
? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent
: current.Parent;
}
}
public static TNode GetAncestor<TNode>(this SyntaxNode node)
where TNode : SyntaxNode
{
if (node == null)
{
return default(TNode);
}
return node.GetAncestors<TNode>().FirstOrDefault();
}
public static TNode GetAncestorOrThis<TNode>(this SyntaxNode node)
where TNode : SyntaxNode
{
if (node == null)
{
return default(TNode);
}
return node.GetAncestorsOrThis<TNode>().FirstOrDefault();
}
public static IEnumerable<TNode> GetAncestorsOrThis<TNode>(this SyntaxNode node)
where TNode : SyntaxNode
{
var current = node;
while (current != null)
{
if (current is TNode)
{
yield return (TNode)current;
}
current = current is IStructuredTriviaSyntax
? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent
: current.Parent;
}
}
public static bool HasAncestor<TNode>(this SyntaxNode node)
where TNode : SyntaxNode
{
return node.GetAncestors<TNode>().Any();
}
public static bool CheckParent<T>(this SyntaxNode node, Func<T, bool> valueChecker) where T : SyntaxNode
{
if (node == null)
{
return false;
}
var parentNode = node.Parent as T;
if (parentNode == null)
{
return false;
}
return valueChecker(parentNode);
}
/// <summary>
/// Returns true if is a given token is a child token of of a certain type of parent node.
/// </summary>
/// <typeparam name="TParent">The type of the parent node.</typeparam>
/// <param name="node">The node that we are testing.</param>
/// <param name="childGetter">A function that, when given the parent node, returns the child token we are interested in.</param>
public static bool IsChildNode<TParent>(this SyntaxNode node, Func<TParent, SyntaxNode> childGetter)
where TParent : SyntaxNode
{
var ancestor = node.GetAncestor<TParent>();
if (ancestor == null)
{
return false;
}
var ancestorNode = childGetter(ancestor);
return node == ancestorNode;
}
/// <summary>
/// Returns true if this node is found underneath the specified child in the given parent.
/// </summary>
public static bool IsFoundUnder<TParent>(this SyntaxNode node, Func<TParent, SyntaxNode> childGetter)
where TParent : SyntaxNode
{
var ancestor = node.GetAncestor<TParent>();
if (ancestor == null)
{
return false;
}
var child = childGetter(ancestor);
// See if node passes through child on the way up to ancestor.
return node.GetAncestorsOrThis<SyntaxNode>().Contains(child);
}
public static SyntaxNode GetCommonRoot(this SyntaxNode node1, SyntaxNode node2)
{
//Contract.ThrowIfTrue(node1.RawKind == 0 || node2.RawKind == 0);
// find common starting node from two nodes.
// as long as two nodes belong to same tree, there must be at least one common root (Ex, compilation unit)
var ancestors = node1.GetAncestorsOrThis<SyntaxNode>();
var set = new HashSet<SyntaxNode>(node2.GetAncestorsOrThis<SyntaxNode>());
return ancestors.First(set.Contains);
}
public static int Width(this SyntaxNode node)
{
return node.Span.Length;
}
public static int FullWidth(this SyntaxNode node)
{
return node.FullSpan.Length;
}
public static SyntaxNode FindInnermostCommonNode(
this IEnumerable<SyntaxNode> nodes,
Func<SyntaxNode, bool> predicate)
{
IEnumerable<SyntaxNode> blocks = null;
foreach (var node in nodes)
{
blocks = blocks == null
? node.AncestorsAndSelf().Where(predicate)
: blocks.Intersect(node.AncestorsAndSelf().Where(predicate));
}
return blocks == null ? null : blocks.First();
}
public static TSyntaxNode FindInnermostCommonNode<TSyntaxNode>(this IEnumerable<SyntaxNode> nodes)
where TSyntaxNode : SyntaxNode
{
return (TSyntaxNode)nodes.FindInnermostCommonNode(n => n is TSyntaxNode);
}
/// <summary>
/// create a new root node from the given root after adding annotations to the tokens
///
/// tokens should belong to the given root
/// </summary>
public static SyntaxNode AddAnnotations(this SyntaxNode root, IEnumerable<Tuple<SyntaxToken, SyntaxAnnotation>> pairs)
{
// Contract.ThrowIfNull(root);
// Contract.ThrowIfNull(pairs);
var tokenMap = pairs.GroupBy(p => p.Item1, p => p.Item2).ToDictionary(g => g.Key, g => g.ToArray());
return root.ReplaceTokens(tokenMap.Keys, (o, n) => o.WithAdditionalAnnotations(tokenMap[o]));
}
/// <summary>
/// create a new root node from the given root after adding annotations to the nodes
///
/// nodes should belong to the given root
/// </summary>
public static SyntaxNode AddAnnotations(this SyntaxNode root, IEnumerable<Tuple<SyntaxNode, SyntaxAnnotation>> pairs)
{
// Contract.ThrowIfNull(root);
// Contract.ThrowIfNull(pairs);
var tokenMap = pairs.GroupBy(p => p.Item1, p => p.Item2).ToDictionary(g => g.Key, g => g.ToArray());
return root.ReplaceNodes(tokenMap.Keys, (o, n) => o.WithAdditionalAnnotations(tokenMap[o]));
}
public static TextSpan GetContainedSpan(this IEnumerable<SyntaxNode> nodes)
{
// Contract.ThrowIfNull(nodes);
// Contract.ThrowIfFalse(nodes.Any());
TextSpan fullSpan = nodes.First().Span;
foreach (var node in nodes)
{
fullSpan = TextSpan.FromBounds(
Math.Min(fullSpan.Start, node.SpanStart),
Math.Max(fullSpan.End, node.Span.End));
}
return fullSpan;
}
public static IEnumerable<TextSpan> GetContiguousSpans(
this IEnumerable<SyntaxNode> nodes, Func<SyntaxNode, SyntaxToken> getLastToken = null)
{
SyntaxNode lastNode = null;
TextSpan? textSpan = null;
foreach (var node in nodes)
{
if (lastNode == null)
{
textSpan = node.Span;
}
else
{
var lastToken = getLastToken == null
? lastNode.GetLastToken()
: getLastToken(lastNode);
if (lastToken.GetNextToken(includeDirectives: true) == node.GetFirstToken())
{
// Expand the span
textSpan = TextSpan.FromBounds(textSpan.Value.Start, node.Span.End);
}
else
{
// Return the last span, and start a new one
yield return textSpan.Value;
textSpan = node.Span;
}
}
lastNode = node;
}
if (textSpan.HasValue)
{
yield return textSpan.Value;
}
}
//public static bool OverlapsHiddenPosition(this SyntaxNode node, CancellationToken cancellationToken)
//{
// return node.OverlapsHiddenPosition(node.Span, cancellationToken);
//}
//public static bool OverlapsHiddenPosition(this SyntaxNode node, TextSpan span, CancellationToken cancellationToken)
//{
// return node.SyntaxTree.OverlapsHiddenPosition(span, cancellationToken);
//}
//public static bool OverlapsHiddenPosition(this SyntaxNode declaration, SyntaxNode startNode, SyntaxNode endNode, CancellationToken cancellationToken)
//{
// var start = startNode.Span.End;
// var end = endNode.SpanStart;
// var textSpan = TextSpan.FromBounds(start, end);
// return declaration.OverlapsHiddenPosition(textSpan, cancellationToken);
//}
public static IEnumerable<T> GetAnnotatedNodes<T>(this SyntaxNode node, SyntaxAnnotation syntaxAnnotation) where T : SyntaxNode
{
return node.GetAnnotatedNodesAndTokens(syntaxAnnotation).Select(n => n.AsNode()).OfType<T>();
}
public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2)
{
if (node == null)
{
return false;
}
var csharpKind = node.Kind();
return csharpKind == kind1 || csharpKind == kind2;
}
public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3)
{
if (node == null)
{
return false;
}
var csharpKind = node.Kind();
return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3;
}
public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3, SyntaxKind kind4)
{
if (node == null)
{
return false;
}
var csharpKind = node.Kind();
return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3 || csharpKind == kind4;
}
public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3, SyntaxKind kind4, SyntaxKind kind5)
{
if (node == null)
{
return false;
}
var csharpKind = node.Kind();
return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3 || csharpKind == kind4 || csharpKind == kind5;
}
/// <summary>
/// Returns the list of using directives that affect <paramref name="node"/>. The list will be returned in
/// top down order.
/// </summary>
public static IEnumerable<UsingDirectiveSyntax> GetEnclosingUsingDirectives(this SyntaxNode node)
{
return node.GetAncestorOrThis<CompilationUnitSyntax>().Usings
.Concat(node.GetAncestorsOrThis<NamespaceDeclarationSyntax>()
.Reverse()
.SelectMany(n => n.Usings));
}
public static bool IsUnsafeContext(this SyntaxNode node)
{
if (node.GetAncestor<UnsafeStatementSyntax>() != null)
{
return true;
}
return node.GetAncestors<MemberDeclarationSyntax>().Any(
m => m.GetModifiers().Any(SyntaxKind.UnsafeKeyword));
}
public static bool IsInStaticContext(this SyntaxNode node)
{
// this/base calls are always static.
if (node.FirstAncestorOrSelf<ConstructorInitializerSyntax>() != null)
{
return true;
}
var memberDeclaration = node.FirstAncestorOrSelf<MemberDeclarationSyntax>();
if (memberDeclaration == null)
{
return false;
}
switch (memberDeclaration.Kind())
{
case SyntaxKind.MethodDeclaration:
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.EventDeclaration:
case SyntaxKind.IndexerDeclaration:
return memberDeclaration.GetModifiers().Any(SyntaxKind.StaticKeyword);
case SyntaxKind.FieldDeclaration:
// Inside a field one can only access static members of a type.
return true;
case SyntaxKind.DestructorDeclaration:
return false;
}
// Global statements are not a static context.
if (node.FirstAncestorOrSelf<GlobalStatementSyntax>() != null)
{
return false;
}
// any other location is considered static
return true;
}
public static NamespaceDeclarationSyntax GetInnermostNamespaceDeclarationWithUsings(this SyntaxNode contextNode)
{
var usingDirectiveAncsestor = contextNode.GetAncestor<UsingDirectiveSyntax>();
if (usingDirectiveAncsestor == null)
{
return contextNode.GetAncestorsOrThis<NamespaceDeclarationSyntax>().FirstOrDefault(n => n.Usings.Count > 0);
}
else
{
// We are inside a using directive. In this case, we should find and return the first 'parent' namespace with usings.
var containingNamespace = usingDirectiveAncsestor.GetAncestor<NamespaceDeclarationSyntax>();
if (containingNamespace == null)
{
// We are inside a top level using directive (i.e. one that's directly in the compilation unit).
return null;
}
else
{
return containingNamespace.GetAncestors<NamespaceDeclarationSyntax>().FirstOrDefault(n => n.Usings.Count > 0);
}
}
}
/// <summary>
/// Returns all of the trivia to the left of this token up to the previous token (concatenates
/// the previous token's trailing trivia and this token's leading trivia).
/// </summary>
public static IEnumerable<SyntaxTrivia> GetAllPrecedingTriviaToPreviousToken(this SyntaxToken token)
{
var prevToken = token.GetPreviousToken(includeSkipped: true);
if (prevToken.Kind() == SyntaxKind.None)
{
return token.LeadingTrivia;
}
return prevToken.TrailingTrivia.Concat(token.LeadingTrivia);
}
public static bool IsBreakableConstruct(this SyntaxNode node)
{
switch (node.Kind())
{
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForEachStatement:
return true;
}
return false;
}
public static bool IsContinuableConstruct(this SyntaxNode node)
{
switch (node.Kind())
{
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForEachStatement:
return true;
}
return false;
}
public static bool IsReturnableConstruct(this SyntaxNode node)
{
switch (node.Kind())
{
case SyntaxKind.AnonymousMethodExpression:
case SyntaxKind.SimpleLambdaExpression:
case SyntaxKind.ParenthesizedLambdaExpression:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.DestructorDeclaration:
case SyntaxKind.GetAccessorDeclaration:
case SyntaxKind.SetAccessorDeclaration:
case SyntaxKind.OperatorDeclaration:
case SyntaxKind.AddAccessorDeclaration:
case SyntaxKind.RemoveAccessorDeclaration:
return true;
}
return false;
}
public static bool IsAnyArgumentList(this SyntaxNode node)
{
return node.IsKind(SyntaxKind.ArgumentList) ||
node.IsKind(SyntaxKind.AttributeArgumentList) ||
node.IsKind(SyntaxKind.BracketedArgumentList) ||
node.IsKind(SyntaxKind.TypeArgumentList);
}
public static bool IsAnyLambda(this SyntaxNode node)
{
return
node.IsKind(SyntaxKind.ParenthesizedLambdaExpression) ||
node.IsKind(SyntaxKind.SimpleLambdaExpression);
}
public static bool IsAnyLambdaOrAnonymousMethod(this SyntaxNode node)
{
return node.IsAnyLambda() || node.IsKind(SyntaxKind.AnonymousMethodExpression);
}
public static bool IsAnyAssignExpression(this SyntaxNode node)
{
return SyntaxFacts.IsAssignmentExpression(node.Kind());
}
public static bool IsParentKind(this SyntaxNode node, SyntaxKind kind)
{
return node != null && node.Parent.IsKind(kind);
}
public static bool IsParentKind(this SyntaxToken node, SyntaxKind kind)
{
return node.Parent != null && node.Parent.IsKind(kind);
}
public static bool IsCompoundAssignExpression(this SyntaxNode node)
{
switch (node.Kind())
{
case SyntaxKind.AddAssignmentExpression:
case SyntaxKind.SubtractAssignmentExpression:
case SyntaxKind.MultiplyAssignmentExpression:
case SyntaxKind.DivideAssignmentExpression:
case SyntaxKind.ModuloAssignmentExpression:
case SyntaxKind.AndAssignmentExpression:
case SyntaxKind.ExclusiveOrAssignmentExpression:
case SyntaxKind.OrAssignmentExpression:
case SyntaxKind.LeftShiftAssignmentExpression:
case SyntaxKind.RightShiftAssignmentExpression:
return true;
}
return false;
}
public static bool IsLeftSideOfAssignExpression(this SyntaxNode node)
{
return node.IsParentKind(SyntaxKind.SimpleAssignmentExpression) &&
((AssignmentExpressionSyntax)node.Parent).Left == node;
}
public static bool IsLeftSideOfAnyAssignExpression(this SyntaxNode node)
{
return node.Parent.IsAnyAssignExpression() &&
((AssignmentExpressionSyntax)node.Parent).Left == node;
}
public static bool IsRightSideOfAnyAssignExpression(this SyntaxNode node)
{
return node.Parent.IsAnyAssignExpression() &&
((AssignmentExpressionSyntax)node.Parent).Right == node;
}
public static bool IsVariableDeclaratorValue(this SyntaxNode node)
{
return
node.IsParentKind(SyntaxKind.EqualsValueClause) &&
node.Parent.IsParentKind(SyntaxKind.VariableDeclarator) &&
((EqualsValueClauseSyntax)node.Parent).Value == node;
}
public static BlockSyntax FindInnermostCommonBlock(this IEnumerable<SyntaxNode> nodes)
{
return nodes.FindInnermostCommonNode<BlockSyntax>();
}
public static IEnumerable<SyntaxNode> GetAncestorsOrThis(this SyntaxNode node, Func<SyntaxNode, bool> predicate)
{
var current = node;
while (current != null)
{
if (predicate(current))
{
yield return current;
}
current = current.Parent;
}
}
public static SyntaxNode GetParent(this SyntaxNode node)
{
return node != null ? node.Parent : null;
}
public static ValueTuple<SyntaxToken, SyntaxToken> GetBraces(this SyntaxNode node)
{
var namespaceNode = node as NamespaceDeclarationSyntax;
if (namespaceNode != null)
{
return ValueTuple.Create(namespaceNode.OpenBraceToken, namespaceNode.CloseBraceToken);
}
var baseTypeNode = node as BaseTypeDeclarationSyntax;
if (baseTypeNode != null)
{
return ValueTuple.Create(baseTypeNode.OpenBraceToken, baseTypeNode.CloseBraceToken);
}
var accessorListNode = node as AccessorListSyntax;
if (accessorListNode != null)
{
return ValueTuple.Create(accessorListNode.OpenBraceToken, accessorListNode.CloseBraceToken);
}
var blockNode = node as BlockSyntax;
if (blockNode != null)
{
return ValueTuple.Create(blockNode.OpenBraceToken, blockNode.CloseBraceToken);
}
var switchStatementNode = node as SwitchStatementSyntax;
if (switchStatementNode != null)
{
return ValueTuple.Create(switchStatementNode.OpenBraceToken, switchStatementNode.CloseBraceToken);
}
var anonymousObjectCreationExpression = node as AnonymousObjectCreationExpressionSyntax;
if (anonymousObjectCreationExpression != null)
{
return ValueTuple.Create(anonymousObjectCreationExpression.OpenBraceToken, anonymousObjectCreationExpression.CloseBraceToken);
}
var initializeExpressionNode = node as InitializerExpressionSyntax;
if (initializeExpressionNode != null)
{
return ValueTuple.Create(initializeExpressionNode.OpenBraceToken, initializeExpressionNode.CloseBraceToken);
}
return new ValueTuple<SyntaxToken, SyntaxToken>();
}
public static SyntaxTokenList GetModifiers(this SyntaxNode member)
{
if (member != null)
{
switch (member.Kind())
{
case SyntaxKind.EnumDeclaration:
return ((EnumDeclarationSyntax)member).Modifiers;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.StructDeclaration:
return ((TypeDeclarationSyntax)member).Modifiers;
case SyntaxKind.DelegateDeclaration:
return ((DelegateDeclarationSyntax)member).Modifiers;
case SyntaxKind.FieldDeclaration:
return ((FieldDeclarationSyntax)member).Modifiers;
case SyntaxKind.EventFieldDeclaration:
return ((EventFieldDeclarationSyntax)member).Modifiers;
case SyntaxKind.ConstructorDeclaration:
return ((ConstructorDeclarationSyntax)member).Modifiers;
case SyntaxKind.DestructorDeclaration:
return ((DestructorDeclarationSyntax)member).Modifiers;
case SyntaxKind.PropertyDeclaration:
return ((PropertyDeclarationSyntax)member).Modifiers;
case SyntaxKind.EventDeclaration:
return ((EventDeclarationSyntax)member).Modifiers;
case SyntaxKind.IndexerDeclaration:
return ((IndexerDeclarationSyntax)member).Modifiers;
case SyntaxKind.OperatorDeclaration:
return ((OperatorDeclarationSyntax)member).Modifiers;
case SyntaxKind.ConversionOperatorDeclaration:
return ((ConversionOperatorDeclarationSyntax)member).Modifiers;
case SyntaxKind.MethodDeclaration:
return ((MethodDeclarationSyntax)member).Modifiers;
case SyntaxKind.GetAccessorDeclaration:
case SyntaxKind.SetAccessorDeclaration:
case SyntaxKind.AddAccessorDeclaration:
case SyntaxKind.RemoveAccessorDeclaration:
return ((AccessorDeclarationSyntax)member).Modifiers;
}
}
return default(SyntaxTokenList);
}
public static SyntaxNode WithModifiers(this SyntaxNode member, SyntaxTokenList modifiers)
{
if (member != null)
{
switch (member.Kind())
{
case SyntaxKind.EnumDeclaration:
return ((EnumDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.StructDeclaration:
return ((TypeDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.DelegateDeclaration:
return ((DelegateDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.FieldDeclaration:
return ((FieldDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.EventFieldDeclaration:
return ((EventFieldDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.ConstructorDeclaration:
return ((ConstructorDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.DestructorDeclaration:
return ((DestructorDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.PropertyDeclaration:
return ((PropertyDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.EventDeclaration:
return ((EventDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.IndexerDeclaration:
return ((IndexerDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.OperatorDeclaration:
return ((OperatorDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.ConversionOperatorDeclaration:
return ((ConversionOperatorDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.MethodDeclaration:
return ((MethodDeclarationSyntax)member).WithModifiers(modifiers);
case SyntaxKind.GetAccessorDeclaration:
case SyntaxKind.SetAccessorDeclaration:
case SyntaxKind.AddAccessorDeclaration:
case SyntaxKind.RemoveAccessorDeclaration:
return ((AccessorDeclarationSyntax)member).WithModifiers(modifiers);
}
}
return null;
}
public static TypeDeclarationSyntax WithModifiers(
this TypeDeclarationSyntax node, SyntaxTokenList modifiers)
{
switch (node.Kind())
{
case SyntaxKind.ClassDeclaration:
return ((ClassDeclarationSyntax)node).WithModifiers(modifiers);
case SyntaxKind.InterfaceDeclaration:
return ((InterfaceDeclarationSyntax)node).WithModifiers(modifiers);
case SyntaxKind.StructDeclaration:
return ((StructDeclarationSyntax)node).WithModifiers(modifiers);
}
throw new InvalidOperationException();
}
public static bool CheckTopLevel(this SyntaxNode node, TextSpan span)
{
var block = node as BlockSyntax;
if (block != null)
{
return block.ContainsInBlockBody(span);
}
var field = node as FieldDeclarationSyntax;
if (field != null)
{
foreach (var variable in field.Declaration.Variables)
{
if (variable.Initializer != null && variable.Initializer.Span.Contains(span))
{
return true;
}
}
}
var global = node as GlobalStatementSyntax;
if (global != null)
{
return true;
}
var constructorInitializer = node as ConstructorInitializerSyntax;
if (constructorInitializer != null)
{
return constructorInitializer.ContainsInArgument(span);
}
return false;
}
public static bool ContainsInArgument(this ConstructorInitializerSyntax initializer, TextSpan textSpan)
{
if (initializer == null)
{
return false;
}
return initializer.ArgumentList.Arguments.Any(a => a.Span.Contains(textSpan));
}
public static bool ContainsInBlockBody(this BlockSyntax block, TextSpan textSpan)
{
if (block == null)
{
return false;
}
var blockSpan = TextSpan.FromBounds(block.OpenBraceToken.Span.End, block.CloseBraceToken.SpanStart);
return blockSpan.Contains(textSpan);
}
public static bool IsDelegateOrConstructorOrMethodParameterList(this SyntaxNode node)
{
if (!node.IsKind(SyntaxKind.ParameterList))
{
return false;
}
return
node.IsParentKind(SyntaxKind.MethodDeclaration) ||
node.IsParentKind(SyntaxKind.ConstructorDeclaration) ||
node.IsParentKind(SyntaxKind.DelegateDeclaration);
}
}
}

121
ILSpy.AddIn/Utils.cs

@ -1,7 +1,16 @@ @@ -1,7 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using EnvDTE;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.LanguageServices;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
namespace ICSharpCode.ILSpy.AddIn
{
@ -111,5 +120,117 @@ namespace ICSharpCode.ILSpy.AddIn @@ -111,5 +120,117 @@ namespace ICSharpCode.ILSpy.AddIn
}
return result;
}
public static bool TryGetProjectFileName(dynamic referenceObject, out string fileName)
{
try {
fileName = referenceObject.Project.FileName;
return true;
} catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) {
fileName = null;
return false;
}
}
public static object[] GetProperties(Properties properties, params string[] names)
{
var values = new object[names.Length];
foreach (object p in properties) {
try {
if (p is Property property) {
for (int i = 0; i < names.Length; i++) {
if (names[i] == property.Name) {
values[i] = property.Value;
break;
}
}
}
} catch {
continue;
}
}
return values;
}
public static List<(string, object)> GetAllProperties(Properties properties)
{
var result = new List<(string, object)>();
for (int i = 0; i < properties.Count; i++) {
try {
if (properties.Item(i) is Property p) {
result.Add((p.Name, p.Value));
}
} catch {
continue;
}
}
return result;
}
public static ITextSelection GetSelectionInCurrentView(IServiceProvider serviceProvider, Func<string, bool> predicate)
{
IWpfTextViewHost viewHost = GetCurrentViewHost(serviceProvider, predicate);
if (viewHost == null)
return null;
return viewHost.TextView.Selection;
}
public static IWpfTextViewHost GetCurrentViewHost(IServiceProvider serviceProvider, Func<string, bool> predicate)
{
IWpfTextViewHost viewHost = GetCurrentViewHost(serviceProvider);
if (viewHost == null)
return null;
ITextDocument textDocument = viewHost.GetTextDocument();
if (textDocument == null || !predicate(textDocument.FilePath))
return null;
return viewHost;
}
public static IWpfTextViewHost GetCurrentViewHost(IServiceProvider serviceProvider)
{
IVsTextManager txtMgr = (IVsTextManager)serviceProvider.GetService(typeof(SVsTextManager));
IVsTextView vTextView = null;
int mustHaveFocus = 1;
txtMgr.GetActiveView(mustHaveFocus, null, out vTextView);
IVsUserData userData = vTextView as IVsUserData;
if (userData == null)
return null;
object holder;
Guid guidViewHost = DefGuidList.guidIWpfTextViewHost;
userData.GetData(ref guidViewHost, out holder);
return holder as IWpfTextViewHost;
}
public static ITextDocument GetTextDocument(this IWpfTextViewHost viewHost)
{
ITextDocument textDocument = null;
viewHost.TextView.TextDataModel.DocumentBuffer.Properties.TryGetProperty(typeof(ITextDocument), out textDocument);
return textDocument;
}
public static VisualStudioWorkspace GetWorkspace(IServiceProvider serviceProvider)
{
return (VisualStudioWorkspace)serviceProvider.GetService(typeof(VisualStudioWorkspace));
}
public static string GetProjectOutputAssembly(Project project, Microsoft.CodeAnalysis.Project roslynProject)
{
string outputFileName = Path.GetFileName(roslynProject.OutputFilePath);
// Get the directory path based on the project file.
string projectPath = Path.GetDirectoryName(project.FullName);
// Get the output path based on the active configuration
string projectOutputPath = project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();
// Combine the project path and output path to get the bin path
return Path.Combine(projectPath, projectOutputPath, outputFileName);
}
}
}

2
ILSpy.AddIn/source.extension.vsixmanifest → ILSpy.AddIn/source.extension.vsixmanifest.template

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="a9120dbe-164a-4891-842f-fb7829273838" Version="1.8.0.0" Language="en-US" Publisher="ic#code" />
<Identity Id="a9120dbe-164a-4891-842f-fb7829273838" Version="$INSERTVERSION$" Language="en-US" Publisher="ic#code" />
<DisplayName>ILSpy</DisplayName>
<Description xml:space="preserve">Integrates the ILSpy decompiler into Visual Studio.</Description>
<MoreInfo>http://www.ilspy.net</MoreInfo>

12
ILSpy.sln

@ -14,16 +14,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy", "ILSpy\ILSpy.csproj @@ -14,16 +14,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy", "ILSpy\ILSpy.csproj
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.TreeView", "SharpTreeView\ICSharpCode.TreeView.csproj", "{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler", "ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj", "{984CC812-9470-4A13-AFF9-CC44068D666C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.Tests", "ICSharpCode.Decompiler.Tests\ICSharpCode.Decompiler.Tests.csproj", "{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestPlugin", "TestPlugin\TestPlugin.csproj", "{F32EBCC8-0E53-4421-867E-05B3D6E10C70}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler", "ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj", "{A6BAD2BA-76BA-461C-8B6D-418607591247}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler.Tests", "ILSpy.BamlDecompiler.Tests\ILSpy.BamlDecompiler.Tests.csproj", "{1169E6D1-1899-43D4-A500-07CE4235B388}"
@ -49,10 +45,6 @@ Global @@ -49,10 +45,6 @@ Global
{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|Any CPU.Build.0 = Release|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU
{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU
{984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -65,10 +57,6 @@ Global @@ -65,10 +57,6 @@ Global
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|Any CPU.Build.0 = Release|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.ActiveCfg = Release|Any CPU

4
ILSpy/MainWindow.xaml.cs

@ -290,7 +290,9 @@ namespace ICSharpCode.ILSpy @@ -290,7 +290,9 @@ namespace ICSharpCode.ILSpy
MemberReference mr = XmlDocKeyProvider.FindMemberByKey(def, args.NavigateTo);
if (mr != null) {
found = true;
JumpToReference(mr);
// Defer JumpToReference call to allow an assembly that was loaded while
// resolving a type-forwarder in FindMemberByKey to appear in the assembly list.
Dispatcher.BeginInvoke(new Action(() => JumpToReference(mr)), DispatcherPriority.Loaded);
break;
}
}

1
cecil

@ -1 +0,0 @@ @@ -1 +0,0 @@
Subproject commit 14e6162ae535afacb69eb6df399bbc46779a4587
Loading…
Cancel
Save