Browse Source

Merge branch 'master' into feature/ReferenceAssemblyOverly

pull/3013/head
Giuseppe Lippolis 10 months ago
parent
commit
7794fbe2be
  1. 30
      .editorconfig
  2. 4
      BuildTools/format.bat
  3. 7
      Directory.Packages.props
  4. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  5. 13
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs
  6. 14
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs
  7. 8
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/MonoFixed.cs
  8. 12
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs
  9. 53
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstructorInitializers.cs
  10. 16
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  11. 28
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
  12. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  13. 62
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.cs
  14. 12
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.Expected.cs
  15. 63
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  16. 9
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  17. 2
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
  18. 70
      ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs
  19. 53
      ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs
  20. 21
      ICSharpCode.Decompiler/DecompilerSettings.cs
  21. 21
      ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs
  22. 37
      ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs
  23. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  24. 3
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.ruleset
  25. 9
      ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowGraph.cs
  26. 238
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
  27. 2
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  28. 15
      ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
  29. 4
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  30. 10
      ICSharpCode.Decompiler/NRExtensions.cs
  31. 4
      ICSharpCode.Decompiler/Properties/AssemblyInfo.cs
  32. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs
  33. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs
  34. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs
  35. 3
      ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs
  36. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs
  37. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs
  38. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs
  39. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs
  40. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs
  41. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs
  42. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs
  43. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs
  44. 7
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs
  45. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs
  46. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs
  47. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs
  48. 1
      ICSharpCode.ILSpyX/AssemblyListManager.cs
  49. 13
      ICSharpCode.ILSpyX/LoadedAssembly.cs
  50. 47
      ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs
  51. 4
      ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs
  52. 2
      ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs
  53. 2
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  54. 4
      ILSpy.ReadyToRun/ReadyToRunLanguage.cs
  55. 2
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
  56. 6
      ILSpy.sln
  57. 2
      ILSpy/AboutPage.cs
  58. 65
      ILSpy/Analyzers/AnalyzeCommand.cs
  59. 42
      ILSpy/Analyzers/AnalyzerRootNode.cs
  60. 24
      ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
  61. 29
      ILSpy/Analyzers/AnalyzerTreeNode.cs
  62. 178
      ILSpy/Analyzers/AnalyzerTreeView.cs
  63. 23
      ILSpy/Analyzers/AnalyzerTreeView.xaml
  64. 42
      ILSpy/Analyzers/AnalyzerTreeView.xaml.cs
  65. 130
      ILSpy/Analyzers/AnalyzerTreeViewModel.cs
  66. 2
      ILSpy/Analyzers/CopyAnalysisResultsContextMenuEntry.cs
  67. 2
      ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs
  68. 22
      ILSpy/App.xaml.cs
  69. 2
      ILSpy/Commands/BrowseBackCommand.cs
  70. 2
      ILSpy/Commands/BrowseForwardCommand.cs
  71. 3
      ILSpy/Commands/CheckForUpdatesCommand.cs
  72. 2
      ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs
  73. 6
      ILSpy/Commands/DecompileAllCommand.cs
  74. 2
      ILSpy/Commands/DecompileCommand.cs
  75. 2
      ILSpy/Commands/DecompileInNewViewCommand.cs
  76. 2
      ILSpy/Commands/DisassembleAllCommand.cs
  77. 3
      ILSpy/Commands/ExitCommand.cs
  78. 10
      ILSpy/Commands/ExportCommandAttribute.cs
  79. 2
      ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs
  80. 3
      ILSpy/Commands/GeneratePdbContextMenuEntry.cs
  81. 3
      ILSpy/Commands/ManageAssemblyListsCommand.cs
  82. 2
      ILSpy/Commands/OpenCommand.cs
  83. 3
      ILSpy/Commands/OpenFromGacCommand.cs
  84. 3
      ILSpy/Commands/Pdb2XmlCommand.cs
  85. 2
      ILSpy/Commands/RefreshCommand.cs
  86. 3
      ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
  87. 6
      ILSpy/Commands/SaveCodeContextMenuEntry.cs
  88. 2
      ILSpy/Commands/SaveCommand.cs
  89. 15
      ILSpy/Commands/ScopeSearchToAssembly.cs
  90. 16
      ILSpy/Commands/ScopeSearchToNamespace.cs
  91. 3
      ILSpy/Commands/SearchMsdnContextMenuEntry.cs
  92. 6
      ILSpy/Commands/SelectPdbContextMenuEntry.cs
  93. 6
      ILSpy/Commands/SetThemeCommand.cs
  94. 41
      ILSpy/Commands/ShowCFGContextMenuEntry.cs
  95. 3
      ILSpy/Commands/SortAssemblyListCommand.cs
  96. 12
      ILSpy/ContextMenuEntry.cs
  97. 44
      ILSpy/Controls/BoolToVisibilityConverter.cs
  98. 8
      ILSpy/Controls/CultureSelectionConverter.cs
  99. 46
      ILSpy/Controls/TreeView/Converters.cs
  100. 12
      ILSpy/Controls/TreeView/SharpTreeView.cs
  101. Some files were not shown because too many files have changed in this diff Show More

30
.editorconfig

@ -12,7 +12,7 @@ indent_size = 2 @@ -12,7 +12,7 @@ indent_size = 2
[*.{yml,yaml}]
indent_style = space
indent_size = 2
[*.csproj]
[*.{csproj,props}]
indent_style = space
indent_size = 2
[*.config]
@ -119,3 +119,31 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false @@ -119,3 +119,31 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Naming rules
# Naming styles:
dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case
# Symbol groups:
# all non-private fields
dotnet_naming_symbols.fields_symbols.applicable_accessibilities = *
dotnet_naming_symbols.fields_symbols.applicable_kinds = field
# all private/protected fields except constants
dotnet_naming_symbols.private_fields_symbols.applicable_accessibilities = private,protected,private_protected
dotnet_naming_symbols.private_fields_symbols.applicable_kinds = field
# Naming rules:
# all non-private fields are pascal case
dotnet_naming_rule.fields_rule.severity = warning
dotnet_naming_rule.fields_rule.style = upper_camel_case_style
dotnet_naming_rule.fields_rule.symbols = fields_symbols
# all private fields are camel case
dotnet_naming_rule.private_fields_rule.severity = warning
dotnet_naming_rule.private_fields_rule.style = lower_camel_case_style
dotnet_naming_rule.private_fields_rule.symbols = private_fields_symbols
# Errors and warnings
# MEF006: No importing constructor
dotnet_diagnostic.MEF006.severity = silent

4
BuildTools/format.bat

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
@rem This file can be used to trigger the commit hook's formatting,
@rem modifying the local formatting even if not committing all changes.
"%ProgramFiles%\Git\usr\bin\bash.exe" BuildTools\pre-commit --format
pushd %~dp0\..
"%ProgramFiles%\Git\usr\bin\bash.exe" BuildTools\pre-commit --format
popd

7
Directory.Packages.props

@ -45,7 +45,12 @@ @@ -45,7 +45,12 @@
<PackageVersion Include="System.Reflection.Metadata" Version="8.0.0" />
<PackageVersion Include="System.Resources.Extensions" Version="8.0.0" />
<PackageVersion Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
<PackageVersion Include="TomsToolbox.Wpf.Styles" Version="2.17.3" />
<PackageVersion Include="TomsToolbox.Wpf.Composition" Version="2.18.1" />
<PackageVersion Include="TomsToolbox.Wpf.Composition.Mef" Version="2.18.1" />
<PackageVersion Include="TomsToolbox.Wpf.Styles" Version="2.18.1" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
</ItemGroup>
<ItemGroup>
<GlobalPackageReference Include="TomsToolbox.Composition.Analyzer" Version="2.18.1" />
</ItemGroup>
</Project>

2
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -93,6 +93,7 @@ @@ -93,6 +93,7 @@
<None Include="TestCases\ILPretty\GuessAccessors.cs" />
<None Include="TestCases\ILPretty\GuessAccessors.il" />
<None Include="TestCases\ILPretty\Issue2260SwitchString.il" />
<None Include="TestCases\ILPretty\MonoFixed.il" />
<None Include="TestCases\ILPretty\UnknownTypes.cs" />
<None Include="TestCases\ILPretty\UnknownTypes.il" />
<None Include="TestCases\ILPretty\EvalOrder.cs" />
@ -128,6 +129,7 @@ @@ -128,6 +129,7 @@
<Compile Include="Output\InsertParenthesesVisitorTests.cs" />
<Compile Include="ProjectDecompiler\TargetFrameworkTests.cs" />
<Compile Include="TestAssemblyResolver.cs" />
<Compile Include="TestCases\ILPretty\MonoFixed.cs" />
<Compile Include="Util\ResourceReaderWriterTests.cs" />
<None Include="TestCases\VBPretty\VBAutomaticEvents.vb" />
<Compile Include="TestCases\VBPretty\VBAutomaticEvents.cs" />

13
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs

@ -50,24 +50,17 @@ public static class Program @@ -50,24 +50,17 @@ public static class Program
[Serializable]
[SpecialName]
[CompilationMapping(SourceConstructFlags.Closure)]
internal sealed class getSeq_00405 : GeneratedSequenceBase<int>
internal sealed class getSeq_00405(int pc, int current) : GeneratedSequenceBase<int>()
{
[DebuggerNonUserCode]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
public int pc;
public int pc = pc;
[DebuggerNonUserCode]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
public int current;
public getSeq_00405(int pc, int current)
{
this.pc = pc;
this.current = current;
base._002Ector();
}
public int current = current;
public override int GenerateNext(ref IEnumerable<int> next)
{

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

@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@
// C:\Users\Siegfried\Documents\Visual Studio 2017\Projects\ConsoleApp13\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
// ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// Global type: <Module>
@ -51,24 +50,17 @@ public static class Program @@ -51,24 +50,17 @@ public static class Program
[Serializable]
[SpecialName]
[CompilationMapping(SourceConstructFlags.Closure)]
internal sealed class getSeq_00405 : GeneratedSequenceBase<int>
internal sealed class getSeq_00405(int pc, int current) : GeneratedSequenceBase<int>()
{
[DebuggerNonUserCode]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
public int pc;
public int pc = pc;
[DebuggerNonUserCode]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
public int current;
public getSeq_00405(int pc, int current)
{
this.pc = pc;
this.current = current;
base._002Ector();
}
public int current = current;
public override int GenerateNext(ref IEnumerable<int> next)
{

8
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/MonoFixed.cs

@ -6,13 +6,13 @@ public class MonoFixed @@ -6,13 +6,13 @@ public class MonoFixed
{
fixed (char* ptr = text)
{
fixed (char* ptr2 = Environment.UserName)
fixed (char* userName = Environment.UserName)
{
fixed (char* ptr3 = text)
fixed (char* ptr2 = text)
{
*ptr = 'c';
*ptr2 = 'd';
*ptr3 = 'e';
*userName = 'd';
*ptr2 = 'e';
}
}
}

12
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs

@ -250,7 +250,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -250,7 +250,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
throw null;
}
catch (Exception ex2) when (i == 0)
catch (Exception ex) when (i == 0)
{
Console.WriteLine("First!");
if (i == 1)
@ -258,9 +258,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -258,9 +258,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
throw;
}
await Task.Yield();
Console.WriteLine(ex2.StackTrace);
Console.WriteLine(ex.StackTrace);
}
catch (Exception ex3) when (True())
catch (Exception ex2) when (True())
{
Console.WriteLine("Second!");
if (i == 1)
@ -268,9 +268,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -268,9 +268,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
throw;
}
await Task.Yield();
Console.WriteLine(ex3.StackTrace);
Console.WriteLine(ex2.StackTrace);
}
catch (Exception ex)
catch (Exception ex3)
{
Console.WriteLine("Third!");
if (i == 1)
@ -278,7 +278,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -278,7 +278,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
throw;
}
await Task.Yield();
Console.WriteLine(ex.StackTrace);
Console.WriteLine(ex3.StackTrace);
}
catch when (i == 0)
{

53
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstructorInitializers.cs

@ -80,5 +80,58 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -80,5 +80,58 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe static int StaticSizeOf = sizeof(SimpleStruct);
public unsafe int SizeOf = sizeof(SimpleStruct);
}
#if CS120
public class ClassWithPrimaryCtorUsingGlobalParameter(int a)
{
public void Print()
{
Console.WriteLine(a);
}
}
public class ClassWithPrimaryCtorUsingGlobalParameterAssignedToField(int a)
{
private readonly int a = a;
public void Print()
{
Console.WriteLine(a);
}
}
public class ClassWithPrimaryCtorUsingGlobalParameterAssignedToFieldAndUsedInMethod(int a)
{
#pragma warning disable CS9124 // Parameter is captured into the state of the enclosing type and its value is also used to initialize a field, property, or event.
private readonly int _a = a;
#pragma warning restore CS9124 // Parameter is captured into the state of the enclosing type and its value is also used to initialize a field, property, or event.
public void Print()
{
Console.WriteLine(a);
}
}
public class ClassWithPrimaryCtorUsingGlobalParameterAssignedToProperty(int a)
{
public int A { get; set; } = a;
public void Print()
{
Console.WriteLine(A);
}
}
public class ClassWithPrimaryCtorUsingGlobalParameterAssignedToEvent(EventHandler a)
{
public event EventHandler A = a;
public void Print()
{
Console.WriteLine(this.A);
}
}
#endif
}
}

16
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -353,19 +353,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction @@ -353,19 +353,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction
public static void NameConflict()
{
// i is captured variable,
// j is parameter in anonymous method
// i is local in main method,
// j is captured variable,
// k is parameter in anonymous method
// l is local in anonymous method,
// k is local in main method
// Ensure that the decompiler doesn't introduce name conflicts
List<Action<int>> list = new List<Action<int>>();
for (int k = 0; k < 10; k++)
for (int i = 0; i < 10; i++)
{
int i;
for (i = 0; i < 10; i++)
int j;
for (j = 0; j < 10; j++)
{
list.Add(delegate (int j) {
for (int l = 0; l < i; l += j)
list.Add(delegate (int k) {
for (int l = 0; l < j; l += k)
{
Console.WriteLine();
}

28
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs

@ -39,10 +39,10 @@ namespace LocalFunctions @@ -39,10 +39,10 @@ namespace LocalFunctions
#pragma warning disable CS0219
T2 t2 = default(T2);
object z = this;
for (int j = 0; j < 10; j++)
for (int i = 0; i < 10; i++)
{
int i = 0;
i += NonStaticMethod6<object>(0);
int i2 = 0;
i2 += NonStaticMethod6<object>(0);
#if CS90
[My]
[return: My]
@ -56,7 +56,7 @@ namespace LocalFunctions @@ -56,7 +56,7 @@ namespace LocalFunctions
return NonStaticMethod6_1<T1>() + NonStaticMethod6_1<T2>() + z.GetHashCode();
int NonStaticMethod6_1<T4>()
{
return i + l + NonStaticMethod6<T4>(0) + StaticMethod1<decimal>();
return i2 + l + NonStaticMethod6<T4>(0) + StaticMethod1<decimal>();
}
}
}
@ -119,10 +119,10 @@ namespace LocalFunctions @@ -119,10 +119,10 @@ namespace LocalFunctions
{
T2 t2 = default(T2);
object z = this;
for (int j = 0; j < 10; j++)
for (int i = 0; i < 10; i++)
{
int i = 0;
i += StaticInvokeAsFunc(NonStaticMethod6<object>);
int i2 = 0;
i2 += StaticInvokeAsFunc(NonStaticMethod6<object>);
int NonStaticMethod6<T3>()
{
t2 = default(T2);
@ -130,7 +130,7 @@ namespace LocalFunctions @@ -130,7 +130,7 @@ namespace LocalFunctions
return StaticInvokeAsFunc(NonStaticMethod6_1<T1>) + StaticInvokeAsFunc(NonStaticMethod6_1<T2>) + z.GetHashCode();
int NonStaticMethod6_1<T4>()
{
return i + l + StaticInvokeAsFunc(NonStaticMethod6<T4>) + StaticInvokeAsFunc(StaticMethod1<decimal>);
return i2 + l + StaticInvokeAsFunc(NonStaticMethod6<T4>) + StaticInvokeAsFunc(StaticMethod1<decimal>);
}
}
}
@ -743,12 +743,12 @@ namespace LocalFunctions @@ -743,12 +743,12 @@ namespace LocalFunctions
int ZZZ_1()
{
t0 = 0;
int t = t0;
int t3 = t0;
return new Func<int>(ZZZ_1_0)();
int ZZZ_1_0()
{
t0 = 0;
t = 0;
t3 = 0;
return 0;
}
}
@ -779,14 +779,14 @@ namespace LocalFunctions @@ -779,14 +779,14 @@ namespace LocalFunctions
int ZZZ_1()
{
t0 = 0;
int t1 = t0;
int t3 = t0;
#if !OPT
Func<int> func = delegate {
#else
return ((Func<int>)delegate {
#endif
t0 = 0;
t1 = 0;
t3 = 0;
return 0;
#if !OPT
};
@ -822,14 +822,14 @@ namespace LocalFunctions @@ -822,14 +822,14 @@ namespace LocalFunctions
int ZZZ_1()
{
t0 = 0;
int t1 = t0;
int t3 = t0;
#if !OPT
Func<int> func = delegate {
#else
return ((Func<int>)delegate {
#endif
t0 = 0;
t1 = 0;
t3 = 0;
return 0;
#if !OPT
};

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -431,9 +431,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -431,9 +431,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe void PinFixedMember(ref StructWithFixedSizeMembers m)
{
fixed (int* ptr = m.Integers)
fixed (int* integers = m.Integers)
{
UsePointer(ptr);
UsePointer(integers);
}
}

62
ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNamingWithoutSymbols.cs

@ -1,4 +1,7 @@ @@ -1,4 +1,7 @@
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
using System;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal class VariableNamingWithoutSymbols
{
@ -25,5 +28,62 @@ @@ -25,5 +28,62 @@
string text2 = c.Text;
#endif
}
private static IDisposable GetData()
{
return null;
}
private static void UseData(IDisposable data)
{
}
private static IEnumerable<int> GetItems()
{
throw null;
}
private static byte[] GetMemory()
{
throw null;
}
private static void Test(int item)
{
foreach (int item2 in GetItems())
{
Console.WriteLine(item2);
}
}
private static void Test(IDisposable data)
{
#if CS80
using IDisposable data2 = GetData();
UseData(data2);
#else
using (IDisposable data2 = GetData())
{
UseData(data2);
}
#endif
}
private unsafe static void Test(byte[] memory)
{
fixed (byte* memory2 = GetMemory())
{
Console.WriteLine(*memory2);
}
}
private static void ForLoopNamingConflict(int i)
{
for (int j = 0; j < i; j++)
{
Console.WriteLine(i + " of " + j);
}
}
}
}

12
ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.Expected.cs

@ -96,25 +96,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly @@ -96,25 +96,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly
thisField = this,
field1 = i
};
int field1 = default(int);
string field2 = default(string);
int field5 = default(int);
string field4 = default(string);
DisplayClass field3 = default(DisplayClass);
while (true)
{
switch (Rand())
{
case 1:
field1 = Rand();
field5 = Rand();
continue;
case 2:
field2 = Rand().ToString();
field4 = Rand().ToString();
continue;
case 3:
field3 = displayClass;
continue;
}
Console.WriteLine(field1);
Console.WriteLine(field2);
Console.WriteLine(field5);
Console.WriteLine(field4);
Console.WriteLine(field3);
}
}

63
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -337,6 +337,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -337,6 +337,8 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (settings.AnonymousMethods && IsAnonymousMethodCacheField(field, metadata))
return true;
if (settings.UsePrimaryConstructorSyntaxForNonRecordTypes && IsPrimaryConstructorParameterBackingField(field, metadata))
return true;
if (settings.AutomaticProperties && IsAutomaticPropertyBackingField(field, metadata, out var propertyName))
{
if (!settings.GetterOnlyAutomaticProperties && IsGetterOnlyProperty(propertyName))
@ -390,6 +392,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -390,6 +392,11 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
}
static bool IsPrimaryConstructorParameterBackingField(SRM.FieldDefinition field, MetadataReader metadata)
{
var name = metadata.GetString(field.Name);
return name.StartsWith("<", StringComparison.Ordinal) && name.EndsWith(">P", StringComparison.Ordinal);
}
static bool IsSwitchOnStringCache(SRM.FieldDefinition field, MetadataReader metadata)
{
@ -1303,12 +1310,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1303,12 +1310,12 @@ namespace ICSharpCode.Decompiler.CSharp
// e.g. DelegateDeclaration
return entityDecl;
}
bool isRecord = typeDef.Kind switch {
TypeKind.Class => settings.RecordClasses && typeDef.IsRecord,
TypeKind.Struct => settings.RecordStructs && typeDef.IsRecord,
bool isRecordLike = typeDef.Kind switch {
TypeKind.Class => (settings.RecordClasses && typeDef.IsRecord) || settings.UsePrimaryConstructorSyntaxForNonRecordTypes,
TypeKind.Struct => (settings.RecordStructs && typeDef.IsRecord) || settings.UsePrimaryConstructorSyntaxForNonRecordTypes,
_ => false,
};
RecordDecompiler recordDecompiler = isRecord ? new RecordDecompiler(typeSystem, typeDef, settings, CancellationToken) : null;
RecordDecompiler recordDecompiler = isRecordLike ? new RecordDecompiler(typeSystem, typeDef, settings, CancellationToken) : null;
if (recordDecompiler != null)
decompileRun.RecordDecompilers.Add(typeDef, recordDecompiler);
@ -1318,33 +1325,41 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1318,33 +1325,41 @@ namespace ICSharpCode.Decompiler.CSharp
{
ParameterDeclaration pd = typeSystemAstBuilder.ConvertParameter(p);
(IProperty prop, IField field) = recordDecompiler.GetPropertyInfoByPrimaryConstructorParameter(p);
Syntax.Attribute[] attributes = prop.GetAttributes().Select(attr => typeSystemAstBuilder.ConvertAttribute(attr)).ToArray();
if (attributes.Length > 0)
if (prop != null)
{
var section = new AttributeSection {
AttributeTarget = "property"
};
section.Attributes.AddRange(attributes);
pd.Attributes.Add(section);
var attributes = prop?.GetAttributes().Select(attr => typeSystemAstBuilder.ConvertAttribute(attr)).ToArray();
if (attributes?.Length > 0)
{
var section = new AttributeSection {
AttributeTarget = "property"
};
section.Attributes.AddRange(attributes);
pd.Attributes.Add(section);
}
}
attributes = field.GetAttributes()
.Where(a => !PatternStatementTransform.attributeTypesToRemoveFromAutoProperties.Contains(a.AttributeType.FullName))
.Select(attr => typeSystemAstBuilder.ConvertAttribute(attr)).ToArray();
if (attributes.Length > 0)
if (field != null && (recordDecompiler.FieldIsGenerated(field) || typeDef.IsRecord))
{
var section = new AttributeSection {
AttributeTarget = "field"
};
section.Attributes.AddRange(attributes);
pd.Attributes.Add(section);
var attributes = field.GetAttributes()
.Where(a => !PatternStatementTransform.attributeTypesToRemoveFromAutoProperties.Contains(a.AttributeType.FullName))
.Select(attr => typeSystemAstBuilder.ConvertAttribute(attr)).ToArray();
if (attributes.Length > 0)
{
var section = new AttributeSection {
AttributeTarget = "field"
};
section.Attributes.AddRange(attributes);
pd.Attributes.Add(section);
}
}
typeDecl.PrimaryConstructorParameters.Add(pd);
}
}
// With C# 9 records, the relative order of fields and properties matters:
IEnumerable<IMember> fieldsAndProperties = recordDecompiler?.FieldsAndProperties
?? typeDef.Fields.Concat<IMember>(typeDef.Properties);
IEnumerable<IMember> fieldsAndProperties = isRecordLike && typeDef.IsRecord
? recordDecompiler.FieldsAndProperties
: typeDef.Fields.Concat<IMember>(typeDef.Properties);
// For COM interop scenarios, the relative order of virtual functions/properties matters:
IEnumerable<IMember> allOrderedMembers = RequiresNativeOrdering(typeDef) ? GetMembersWithNativeOrdering(typeDef) :
@ -1481,6 +1496,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1481,6 +1496,10 @@ namespace ICSharpCode.Decompiler.CSharp
{
return;
}
if (recordDecompiler?.FieldIsGenerated(field) == true)
{
return;
}
entityDecl = DoDecompile(field, decompileRun, decompilationContext.WithCurrentMember(field));
entityMap.Add(field, entityDecl);
break;

9
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs

@ -85,6 +85,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -85,6 +85,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
break;
case ClassType.RecordStruct:
writer.WriteKeyword(Roles.RecordKeyword, "record");
writer.Space();
writer.WriteKeyword(Roles.StructKeyword, "struct");
break;
default:
@ -181,8 +182,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -181,8 +182,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody && !(node is TypeDeclaration))
{
IProperty property = symbol as IProperty;
if (property != null)
if (symbol is IProperty property)
{
writer.Space();
writer.WriteToken(Roles.LBrace, "{");
@ -195,7 +195,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -195,7 +195,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
if (property.CanSet)
{
writer.WriteKeyword(PropertyDeclaration.SetKeywordRole, "set");
if ((ConversionFlags & ConversionFlags.SupportInitAccessors) != 0 && property.Setter.IsInitOnly)
writer.WriteKeyword(PropertyDeclaration.InitKeywordRole, "init");
else
writer.WriteKeyword(PropertyDeclaration.SetKeywordRole, "set");
writer.WriteToken(Roles.Semicolon, ";");
writer.Space();
}

2
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs

@ -692,7 +692,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -692,7 +692,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
if (separateAtDots)
currentSegmentLength = 0;
}
else if (treatAsFileName && (c == '/' || c == '\\') && currentSegmentLength > 0)
else if (treatAsFileName && (c == '/' || c == '\\') && currentSegmentLength > 1)
{
// if we treat this as a file name, we've started a new segment
b.Append(c);

70
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -43,8 +43,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -43,8 +43,8 @@ namespace ICSharpCode.Decompiler.CSharp
readonly IType baseClass;
readonly Dictionary<IField, IProperty> backingFieldToAutoProperty = new Dictionary<IField, IProperty>();
readonly Dictionary<IProperty, IField> autoPropertyToBackingField = new Dictionary<IProperty, IField>();
readonly Dictionary<IParameter, IProperty> primaryCtorParameterToAutoProperty = new Dictionary<IParameter, IProperty>();
readonly Dictionary<IProperty, IParameter> autoPropertyToPrimaryCtorParameter = new Dictionary<IProperty, IParameter>();
readonly Dictionary<IParameter, IMember> primaryCtorParameterToAutoPropertyOrBackingField = new Dictionary<IParameter, IMember>();
readonly Dictionary<IMember, IParameter> autoPropertyOrBackingFieldToPrimaryCtorParameter = new Dictionary<IMember, IParameter>();
public RecordDecompiler(IDecompilerTypeSystem dts, ITypeDefinition recordTypeDef, DecompilerSettings settings, CancellationToken cancellationToken)
{
@ -78,6 +78,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -78,6 +78,8 @@ namespace ICSharpCode.Decompiler.CSharp
bool IsAutoProperty(IProperty p, out IField field)
{
field = null;
if (p.IsStatic)
return false;
if (p.Parameters.Count != 0)
return false;
if (p.Getter != null)
@ -158,8 +160,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -158,8 +160,18 @@ namespace ICSharpCode.Decompiler.CSharp
IMethod DetectPrimaryConstructor()
{
if (!settings.UsePrimaryConstructorSyntax)
return null;
if (recordTypeDef.IsRecord)
{
if (!settings.UsePrimaryConstructorSyntax)
return null;
}
else
{
if (!settings.UsePrimaryConstructorSyntaxForNonRecordTypes)
return null;
if (isStruct)
return null;
}
var subst = recordTypeDef.AsParameterizedType().GetSubstitution();
foreach (var method in recordTypeDef.Methods)
@ -170,8 +182,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -170,8 +182,8 @@ namespace ICSharpCode.Decompiler.CSharp
var m = method.Specialize(subst);
if (IsPrimaryConstructor(m, method))
return method;
primaryCtorParameterToAutoProperty.Clear();
autoPropertyToPrimaryCtorParameter.Clear();
primaryCtorParameterToAutoPropertyOrBackingField.Clear();
autoPropertyOrBackingFieldToPrimaryCtorParameter.Clear();
}
return null;
@ -205,10 +217,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -205,10 +217,18 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
if (!(value.Kind == VariableKind.Parameter && value.Index == i))
return false;
if (!backingFieldToAutoProperty.TryGetValue(field, out var property))
return false;
primaryCtorParameterToAutoProperty.Add(unspecializedMethod.Parameters[i], property);
autoPropertyToPrimaryCtorParameter.Add(property, unspecializedMethod.Parameters[i]);
IMember backingMember;
if (backingFieldToAutoProperty.TryGetValue(field, out var property))
{
backingMember = property;
}
else
{
backingMember = field;
}
primaryCtorParameterToAutoPropertyOrBackingField.Add(unspecializedMethod.Parameters[i], backingMember);
autoPropertyOrBackingFieldToPrimaryCtorParameter.Add(backingMember, unspecializedMethod.Parameters[i]);
}
if (!isStruct)
@ -261,6 +281,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -261,6 +281,9 @@ namespace ICSharpCode.Decompiler.CSharp
/// </summary>
public bool MethodIsGenerated(IMethod method)
{
if (!recordTypeDef.IsRecord)
return false;
if (IsCopyConstructor(method))
{
return IsGeneratedCopyConstructor(method);
@ -320,6 +343,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -320,6 +343,9 @@ namespace ICSharpCode.Decompiler.CSharp
internal bool PropertyIsGenerated(IProperty property)
{
if (!recordTypeDef.IsRecord)
return false;
switch (property.Name)
{
case "EqualityContract" when !isStruct:
@ -329,17 +355,35 @@ namespace ICSharpCode.Decompiler.CSharp @@ -329,17 +355,35 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
internal bool FieldIsGenerated(IField field)
{
if (!settings.UsePrimaryConstructorSyntaxForNonRecordTypes)
return false;
var name = field.Name;
return name.StartsWith("<", StringComparison.Ordinal)
&& name.EndsWith(">P", StringComparison.Ordinal)
&& field.IsCompilerGenerated();
}
public bool IsPropertyDeclaredByPrimaryConstructor(IProperty property)
{
var subst = recordTypeDef.AsParameterizedType().GetSubstitution();
return primaryCtor != null
&& autoPropertyToPrimaryCtorParameter.ContainsKey((IProperty)property.Specialize(subst));
&& autoPropertyOrBackingFieldToPrimaryCtorParameter.ContainsKey((IProperty)property.Specialize(subst));
}
internal (IProperty prop, IField field) GetPropertyInfoByPrimaryConstructorParameter(IParameter parameter)
{
var prop = primaryCtorParameterToAutoProperty[parameter];
return (prop, autoPropertyToBackingField[prop]);
var member = primaryCtorParameterToAutoPropertyOrBackingField[parameter];
if (member is IField field)
return (null, field);
return ((IProperty)member, autoPropertyToBackingField[(IProperty)member]);
}
internal IParameter GetPrimaryConstructorParameterFromBackingField(IField field)
{
return autoPropertyOrBackingFieldToPrimaryCtorParameter[field];
}
public bool IsCopyConstructor(IMethod method)

53
ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs

@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -24,7 +23,9 @@ using System.Reflection; @@ -24,7 +23,9 @@ using System.Reflection;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
@ -37,10 +38,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -37,10 +38,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public class TransformFieldAndConstructorInitializers : DepthFirstAstVisitor, IAstTransform
{
TransformContext context;
Dictionary<IField, IL.ILVariable> fieldToVariableMap;
public void Run(AstNode node, TransformContext context)
{
this.context = context;
this.fieldToVariableMap = new();
try
{
@ -56,6 +59,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -56,6 +59,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
finally
{
this.context = null;
this.fieldToVariableMap = null;
}
}
@ -131,6 +135,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -131,6 +135,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
newBaseType.BaseType = baseType;
ci.Arguments.MoveTo(newBaseType.Arguments);
}
if (constructorDeclaration.Parent is TypeDeclaration { PrimaryConstructorParameters: var parameters })
{
foreach (var (cpd, ppd) in constructorDeclaration.Parameters.Zip(parameters))
{
ppd.CopyAnnotationsFrom(cpd);
}
}
constructorDeclaration.Remove();
}
}
@ -203,18 +214,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -203,18 +214,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (fieldOrPropertyOrEventDecl is CustomEventDeclaration)
break;
Expression initializer = m.Get<Expression>("initializer").Single();
// 'this'/'base' cannot be used in initializers
if (initializer.DescendantsAndSelf.Any(n => n is ThisReferenceExpression || n is BaseReferenceExpression))
break;
if (initializer.Annotation<ILVariableResolveResult>()?.Variable.Kind == IL.VariableKind.Parameter)
var v = initializer.Annotation<ILVariableResolveResult>()?.Variable;
if (v?.Kind == IL.VariableKind.Parameter)
{
// remove record ctor parameter assignments
if (!IsPropertyDeclaredByPrimaryCtor(fieldOrPropertyOrEvent as IProperty, record))
if (!IsPropertyDeclaredByPrimaryCtor(fieldOrPropertyOrEvent, record))
break;
isStructPrimaryCtor = true;
if (fieldOrPropertyOrEvent is IField f)
fieldToVariableMap.Add(f, v);
}
else
{
@ -264,11 +276,21 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -264,11 +276,21 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
}
bool IsPropertyDeclaredByPrimaryCtor(IProperty p, RecordDecompiler record)
bool IsPropertyDeclaredByPrimaryCtor(IMember m, RecordDecompiler record)
{
if (p == null || record == null)
if (record == null)
return false;
return record.IsPropertyDeclaredByPrimaryConstructor(p);
switch (m)
{
case IProperty p:
return record.IsPropertyDeclaredByPrimaryConstructor(p);
case IField f:
return true;
case IEvent e:
return true;
default:
return false;
}
}
void RemoveSingleEmptyConstructor(IEnumerable<AstNode> members, ITypeDefinition contextTypeDefinition)
@ -443,5 +465,20 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -443,5 +465,20 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return false;
}
}
public override void VisitIdentifier(Identifier identifier)
{
if (identifier.Parent?.GetSymbol() is not IField field)
{
return;
}
if (!fieldToVariableMap.TryGetValue(field, out var v))
{
return;
}
identifier.Parent.RemoveAnnotations<MemberResolveResult>();
identifier.Parent.AddAnnotation(new ILVariableResolveResult(v));
identifier.ReplaceWith(Identifier.Create(v.Name));
}
}
}

21
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -162,12 +162,13 @@ namespace ICSharpCode.Decompiler @@ -162,12 +162,13 @@ namespace ICSharpCode.Decompiler
if (languageVersion < CSharp.LanguageVersion.CSharp12_0)
{
refReadOnlyParameters = false;
usePrimaryConstructorSyntaxForNonRecordTypes = false;
}
}
public CSharp.LanguageVersion GetMinimumRequiredVersion()
{
if (refReadOnlyParameters)
if (refReadOnlyParameters || usePrimaryConstructorSyntaxForNonRecordTypes)
return CSharp.LanguageVersion.CSharp12_0;
if (scopedRef || requiredMembers || numericIntPtr || utf8StringLiterals || unsignedRightShift || checkedOperators)
return CSharp.LanguageVersion.CSharp11_0;
@ -2015,6 +2016,24 @@ namespace ICSharpCode.Decompiler @@ -2015,6 +2016,24 @@ namespace ICSharpCode.Decompiler
}
}
bool usePrimaryConstructorSyntaxForNonRecordTypes = true;
/// <summary>
/// Use primary constructor syntax with classes and structs.
/// </summary>
[Category("C# 12.0 / VS 2022.8")]
[Description("DecompilerSettings.UsePrimaryConstructorSyntaxForNonRecordTypes")]
public bool UsePrimaryConstructorSyntaxForNonRecordTypes {
get { return usePrimaryConstructorSyntaxForNonRecordTypes; }
set {
if (usePrimaryConstructorSyntaxForNonRecordTypes != value)
{
usePrimaryConstructorSyntaxForNonRecordTypes = value;
OnPropertyChanged();
}
}
}
bool separateLocalVariableDeclarations = false;
/// <summary>

21
ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs

@ -91,14 +91,25 @@ namespace ICSharpCode.Decompiler.Documentation @@ -91,14 +91,25 @@ namespace ICSharpCode.Decompiler.Documentation
fileName = LookupLocalizedXmlDoc(Path.Combine(frameworkPath, "v1.1.4322", assemblyFileName));
break;
case TargetRuntime.Net_2_0:
fileName = LookupLocalizedXmlDoc(Path.Combine(frameworkPath, "v2.0.50727", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, "v3.5"))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, "v3.0"))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v3.5\Profile\Client"));
fileName = LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, "v3.5", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v3.5\Profile\Client", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, "v3.0", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(frameworkPath, "v2.0.50727", assemblyFileName));
break;
case TargetRuntime.Net_4_0:
default:
fileName = LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.0", assemblyFileName))
fileName = LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.8.1", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.8", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.7.2", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.7.1", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.7", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.6.2", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.6.1", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.6", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.5.2", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.5.1", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.5", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.0", assemblyFileName))
?? LookupLocalizedXmlDoc(Path.Combine(frameworkPath, "v4.0.30319", assemblyFileName));
break;
}

37
ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs

@ -129,42 +129,5 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -129,42 +129,5 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
}
return false;
}
#if DEBUG
internal static GraphVizGraph ExportGraph(IReadOnlyList<ControlFlowNode> nodes, Func<ControlFlowNode, string> labelFunc = null)
{
if (labelFunc == null)
{
labelFunc = node => {
var block = node.UserData as IL.Block;
return block != null ? block.Label : node.UserData?.ToString();
};
}
GraphVizGraph g = new GraphVizGraph();
GraphVizNode[] n = new GraphVizNode[nodes.Count];
for (int i = 0; i < n.Length; i++)
{
n[i] = new GraphVizNode(nodes[i].UserIndex);
n[i].shape = "box";
n[i].label = labelFunc(nodes[i]);
g.AddNode(n[i]);
}
foreach (var source in nodes)
{
foreach (var target in source.Successors)
{
g.AddEdge(new GraphVizEdge(source.UserIndex, target.UserIndex));
}
if (source.ImmediateDominator != null)
{
g.AddEdge(
new GraphVizEdge(source.ImmediateDominator.UserIndex, source.UserIndex) {
color = "green"
});
}
}
return g;
}
#endif
}
}

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -475,7 +475,6 @@ @@ -475,7 +475,6 @@
<Compile Include="TypeSystem\TupleType.cs" />
<Compile Include="TypeSystem\TypeProvider.cs" />
<Compile Include="Util\FileUtility.cs" />
<Compile Include="Util\GraphVizGraph.cs" />
<Compile Include="Util\KeyComparer.cs" />
<Compile Include="Util\LongDict.cs" />
<Compile Include="Util\ResourcesFile.cs" />

3
ICSharpCode.Decompiler/ICSharpCode.Decompiler.ruleset

@ -79,4 +79,7 @@ @@ -79,4 +79,7 @@
<Rule Id="ProhibitedModifiersAnalyzer" Action="None" />
<Rule Id="RECS0001" Action="Info" />
</Rules>
<Rules AnalyzerId="TomsToolbox.Composition.Analyzer" RuleNamespace="TomsToolbox.Composition.Analyzer">
<Rule Id="MEF006" Action="Hidden" />
</Rules>
</RuleSet>

9
ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowGraph.cs

@ -1,10 +1,6 @@ @@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.Decompiler.Util;
@ -36,6 +32,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -36,6 +32,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// </summary>
internal readonly ControlFlowNode[] cfg;
/// <inheritdoc cref="cfg"/>
public IReadOnlyList<ControlFlowNode> Nodes => cfg;
/// <summary>
/// Dictionary from Block to ControlFlowNode.
/// Unlike the cfg array, this can be used to discover control flow nodes even after

238
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -55,7 +55,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -55,7 +55,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILTransformContext context;
List<string> currentLowerCaseTypeOrMemberNames;
Dictionary<string, int> reservedVariableNames;
Dictionary<MethodDefinitionHandle, string> localFunctionMapping;
HashSet<ILVariable> loopCounters;
const char maxLoopVariableName = 'n';
int numDisplayClassLocals;
@ -75,7 +74,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -75,7 +74,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
currentLowerCaseTypeOrMemberNames.Add(name);
AddExistingName(reservedVariableNames, name);
}
localFunctionMapping = new Dictionary<MethodDefinitionHandle, string>();
loopCounters = CollectLoopCounters(function);
foreach (var f in function.Descendants.OfType<ILFunction>())
{
@ -153,10 +151,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -153,10 +151,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
numDisplayClassLocals = 0;
foreach (ILFunction f in function.Descendants.OfType<ILFunction>().Reverse())
{
PerformAssignment(f);
}
PerformAssignment(function);
}
static IEnumerable<string> CollectAllLowerCaseMemberNames(ITypeDefinition type)
@ -195,128 +190,131 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -195,128 +190,131 @@ namespace ICSharpCode.Decompiler.IL.Transforms
void PerformAssignment(ILFunction function)
{
// remove unused variables before assigning names
function.Variables.RemoveDead();
Dictionary<int, string> assignedLocalSignatureIndices = new Dictionary<int, string>();
foreach (var v in function.Variables.OrderBy(v => v.Name))
var localFunctionMapping = new Dictionary<MethodDefinitionHandle, string>();
var variableMapping = new Dictionary<ILVariable, string>(ILVariableEqualityComparer.Instance);
var assignedLocalSignatureIndices = new Dictionary<(ILFunction, int), string>();
foreach (var inst in function.Descendants)
{
switch (v.Kind)
if (inst is ILFunction { Kind: ILFunctionKind.LocalFunction } localFunction)
{
case VariableKind.Parameter:
// Parameter names are handled in ILReader.CreateILVariable
// and CSharpDecompiler.FixParameterNames
break;
case VariableKind.InitializerTarget: // keep generated names
AddExistingName(reservedVariableNames, v.Name);
break;
case VariableKind.DisplayClassLocal:
v.Name = "CS$<>8__locals" + (numDisplayClassLocals++);
break;
case VariableKind.Local when v.Index != null:
if (assignedLocalSignatureIndices.TryGetValue(v.Index.Value, out string name))
// assign names to local functions
if (!LocalFunctionDecompiler.ParseLocalFunctionName(localFunction.Name, out _, out var newName) || !IsValidName(newName))
newName = null;
if (newName == null)
{
string nameWithoutNumber = "f";
if (!reservedVariableNames.TryGetValue(nameWithoutNumber, out int currentIndex))
{
// make sure all local ILVariables that refer to the same slot in the locals signature
// are assigned the same name.
v.Name = name;
currentIndex = 1;
}
int count = Math.Max(1, currentIndex) + 1;
reservedVariableNames[nameWithoutNumber] = count;
if (count > 1)
{
newName = nameWithoutNumber + count.ToString();
}
else
{
AssignName();
// Remember the newly assigned name:
assignedLocalSignatureIndices.Add(v.Index.Value, v.Name);
newName = nameWithoutNumber;
}
break;
default:
AssignName();
break;
}
localFunction.Name = newName;
localFunction.ReducedMethod.Name = newName;
localFunctionMapping[(MethodDefinitionHandle)localFunction.ReducedMethod.MetadataToken] = newName;
}
void AssignName()
else if (inst is IInstructionWithVariableOperand i)
{
if (v.HasGeneratedName || !IsValidName(v.Name) || ConflictWithLocal(v))
var v = i.Variable;
// if there is already a valid name for the variable slot, just use it
if (variableMapping.TryGetValue(v, out string name))
{
// don't use the name from the debug symbols if it looks like a generated name
v.Name = null;
v.Name = name;
continue;
}
else
switch (v.Kind)
{
// use the name from the debug symbols and update index appended to duplicates
string nameWithoutNumber = SplitName(v.Name, out int newIndex);
if (!reservedVariableNames.TryGetValue(nameWithoutNumber, out int currentIndex))
{
currentIndex = 1;
}
reservedVariableNames[nameWithoutNumber] = Math.Max(newIndex, currentIndex);
case VariableKind.Parameter:
// Parameter names are handled in ILReader.CreateILVariable
// and CSharpDecompiler.FixParameterNames
break;
case VariableKind.InitializerTarget: // keep generated names
AddExistingName(reservedVariableNames, v.Name);
break;
case VariableKind.DisplayClassLocal:
v.Name = "CS$<>8__locals" + (numDisplayClassLocals++);
break;
case VariableKind.Local when v.Index != null:
if (assignedLocalSignatureIndices.TryGetValue((v.Function, v.Index.Value), out name))
{
// make sure all local ILVariables that refer to the same slot in the locals signature
// are assigned the same name.
v.Name = name;
}
else
{
v.Name = AssignName(v, variableMapping);
// Remember the newly assigned name:
assignedLocalSignatureIndices.Add((v.Function, v.Index.Value), v.Name);
}
break;
default:
v.Name = AssignName(v, variableMapping);
break;
}
}
else if (inst is (Call or LdFtn) and IInstructionWithMethodOperand m)
{
// update references to local functions
if (m.Method is LocalFunctionMethod lf
&& localFunctionMapping.TryGetValue((MethodDefinitionHandle)lf.MetadataToken, out var name))
{
lf.Name = name;
}
}
}
foreach (var localFunction in function.LocalFunctions)
}
string AssignName(ILVariable v, Dictionary<ILVariable, string> variableMapping)
{
// variable has no valid name
string newName = v.Name;
if (v.HasGeneratedName || !IsValidName(newName))
{
if (!LocalFunctionDecompiler.ParseLocalFunctionName(localFunction.Name, out _, out var newName) || !IsValidName(newName))
newName = null;
localFunction.Name = newName;
localFunction.ReducedMethod.Name = newName;
// don't use the name from the debug symbols if it looks like a generated name
// generate a new one based on how the variable is used
newName = GenerateNameForVariable(v);
}
// Now generate names:
var mapping = new Dictionary<ILVariable, string>(ILVariableEqualityComparer.Instance);
foreach (var inst in function.Descendants.OfType<IInstructionWithVariableOperand>())
// use the existing name and update index appended to future conflicts
string nameWithoutNumber = SplitName(newName, out int newIndex);
if (reservedVariableNames.TryGetValue(nameWithoutNumber, out int lastUsedIndex))
{
var v = inst.Variable;
if (!mapping.TryGetValue(v, out string name))
// name without number was already used
if (v.Type.IsKnownType(KnownTypeCode.Int32) && loopCounters.Contains(v))
{
if (string.IsNullOrEmpty(v.Name))
v.Name = GenerateNameForVariable(v);
mapping.Add(v, v.Name);
// special case for loop counters,
// we don't want them to be named i, i2, ..., but i, j, ...
newName = GenerateNameForVariable(v);
}
else
{
v.Name = name;
}
}
foreach (var localFunction in function.LocalFunctions)
{
var newName = localFunction.Name;
if (newName == null)
{
string nameWithoutNumber = "f";
if (!reservedVariableNames.TryGetValue(nameWithoutNumber, out int currentIndex))
{
currentIndex = 1;
}
int count = Math.Max(1, currentIndex) + 1;
reservedVariableNames[nameWithoutNumber] = count;
if (count > 1)
if (newIndex > lastUsedIndex)
{
newName = nameWithoutNumber + count.ToString();
// new index is larger than last, so we can use it
}
else
{
newName = nameWithoutNumber;
// new index is smaller or equal, so we use the next value
newIndex = lastUsedIndex + 1;
}
// resolve conflicts by appending the index to the new name:
newName = nameWithoutNumber + newIndex.ToString();
}
localFunction.Name = newName;
localFunction.ReducedMethod.Name = newName;
localFunctionMapping[(MethodDefinitionHandle)localFunction.ReducedMethod.MetadataToken] = newName;
}
foreach (var inst in function.Descendants)
{
LocalFunctionMethod localFunction;
switch (inst)
{
case Call call:
localFunction = call.Method as LocalFunctionMethod;
break;
case LdFtn ldftn:
localFunction = ldftn.Method as LocalFunctionMethod;
break;
default:
localFunction = null;
break;
}
if (localFunction == null || !localFunctionMapping.TryGetValue((MethodDefinitionHandle)localFunction.MetadataToken, out var name))
continue;
localFunction.Name = name;
}
// update the last used index
reservedVariableNames[nameWithoutNumber] = newIndex;
variableMapping.Add(v, newName);
return newName;
}
/// <remarks>
@ -326,6 +324,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -326,6 +324,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
switch (arg)
{
case GetPinnableReference _:
case LdObj _:
case LdFlda _:
case LdsFlda _:
@ -336,16 +335,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -336,16 +335,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
bool ConflictWithLocal(ILVariable v)
{
if (v.Kind == VariableKind.UsingLocal || v.Kind == VariableKind.ForeachLocal)
{
if (reservedVariableNames.ContainsKey(v.Name))
return true;
}
return false;
}
internal static bool IsValidName(string varName)
{
if (string.IsNullOrWhiteSpace(varName))
@ -431,6 +420,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -431,6 +420,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!currentLowerCaseTypeOrMemberNames.Contains(name))
proposedNameForStores.Add(name);
}
else if (store is PinnedRegion pinnedRegion)
{
var name = GetNameFromInstruction(pinnedRegion.Init);
if (!currentLowerCaseTypeOrMemberNames.Contains(name))
proposedNameForStores.Add(name);
}
}
if (proposedNameForStores.Count == 1)
{
@ -462,32 +457,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -462,32 +457,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms
proposedName = GetNameByType(variable.Type);
}
// remove any numbers from the proposed name
proposedName = SplitName(proposedName, out int number);
if (!reservedVariableNames.ContainsKey(proposedName))
{
reservedVariableNames.Add(proposedName, 0);
}
int count = ++reservedVariableNames[proposedName];
Debug.Assert(!string.IsNullOrWhiteSpace(proposedName));
if (count > 1)
{
return proposedName + count.ToString();
}
else
{
return proposedName;
}
// for generated names remove number-suffixes
return SplitName(proposedName, out _);
}
static string GetNameFromInstruction(ILInstruction inst)
{
switch (inst)
{
case GetPinnableReference getPinnableReference:
return GetNameFromInstruction(getPinnableReference.Argument);
case LdObj ldobj:
return GetNameFromInstruction(ldobj.Target);
case LdFlda ldflda:
if (ldflda.Field.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
return GetNameFromInstruction(ldflda.Target);
return CleanUpVariableName(ldflda.Field.Name);
case LdsFlda ldsflda:
return CleanUpVariableName(ldsflda.Field.Name);
@ -567,6 +551,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -567,6 +551,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
if (m.Name == "Concat" && m.DeclaringType.IsKnownType(KnownTypeCode.String))
return true;
if (m.Name == "GetPinnableReference")
return true;
return false;
}

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

@ -898,7 +898,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -898,7 +898,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
context.Step("TransformCatchVariable", entryPoint.Instructions[0]);
exceptionVar.Kind = VariableKind.ExceptionLocal;
exceptionVar.Name = handler.Variable.Name;
exceptionVar.Type = handler.Variable.Type;
exceptionVar.HasGeneratedName = handler.Variable.HasGeneratedName;
handler.Variable = exceptionVar;
if (isCatchBlock)
{

15
ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs

@ -249,21 +249,24 @@ namespace ICSharpCode.Decompiler.Metadata @@ -249,21 +249,24 @@ namespace ICSharpCode.Decompiler.Metadata
static string GetClosestVersionFolder(string basePath, Version version)
{
var foundVersions = new DirectoryInfo(basePath).GetDirectories()
.Select(d => ConvertToVersion(d.Name))
.Select(ConvertToVersion)
.Where(v => v.version != null);
foreach (var folder in foundVersions.OrderBy(v => v.version))
{
if (folder.version >= version)
return folder.directoryName;
if (folder.version >= version
&& folder.directory.EnumerateFiles("*.dll", SearchOption.AllDirectories).Any())
{
return folder.directory.Name;
}
}
return version.ToString();
}
internal static (Version version, string directoryName) ConvertToVersion(string name)
internal static (Version version, DirectoryInfo directory) ConvertToVersion(DirectoryInfo directory)
{
string RemoveTrailingVersionInfo()
{
string shortName = name;
string shortName = directory.Name;
int dashIndex = shortName.IndexOf('-');
if (dashIndex > 0)
{
@ -274,7 +277,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -274,7 +277,7 @@ namespace ICSharpCode.Decompiler.Metadata
try
{
return (new Version(RemoveTrailingVersionInfo()), name);
return (new Version(RemoveTrailingVersionInfo()), directory);
}
catch (Exception ex)
{

4
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -386,11 +386,11 @@ namespace ICSharpCode.Decompiler.Metadata @@ -386,11 +386,11 @@ namespace ICSharpCode.Decompiler.Metadata
string FindClosestVersionDirectory(string basePath, Version? version)
{
string? path = null;
foreach (var folder in new DirectoryInfo(basePath).GetDirectories().Select(d => DotNetCorePathFinder.ConvertToVersion(d.Name))
foreach (var folder in new DirectoryInfo(basePath).GetDirectories().Select(DotNetCorePathFinder.ConvertToVersion)
.Where(v => v.Item1 != null).OrderByDescending(v => v.Item1))
{
if (path == null || version == null || folder.Item1 >= version)
path = folder.Item2;
path = folder.Item2.Name;
}
return path ?? version?.ToString() ?? ".";
}

10
ICSharpCode.Decompiler/NRExtensions.cs

@ -16,7 +16,7 @@ @@ -16,7 +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.Reflection.Metadata;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.TypeSystem;
@ -99,5 +99,13 @@ namespace ICSharpCode.Decompiler @@ -99,5 +99,13 @@ namespace ICSharpCode.Decompiler
return null;
return docProvider.GetDocumentation(entity);
}
internal static System.Reflection.TypeAttributes GetMetadataAttributes(this ITypeDefinition type)
{
var metadata = type.ParentModule.MetadataFile?.Metadata;
if (metadata == null || type.MetadataToken.IsNil)
return 0;
return metadata.GetTypeDefinition((TypeDefinitionHandle)type.MetadataToken).Attributes;
}
}
}

4
ICSharpCode.Decompiler/Properties/AssemblyInfo.cs

@ -19,10 +19,6 @@ using System.Runtime.InteropServices; @@ -19,10 +19,6 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("ICSharpCode.Decompiler.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004dcf3979c4e902efa4dd2163a039701ed5822e6f1134d77737296abbb97bf0803083cfb2117b4f5446a217782f5c7c634f9fe1fc60b4c11d62c5b3d33545036706296d31903ddcf750875db38a8ac379512f51620bb948c94d0831125fbc5fe63707cbb93f48c1459c4d1749eb7ac5e681a2f0d6d7c60fa527a3c0b8f92b02bf")]
#if DEBUG
[assembly: InternalsVisibleTo("ILSpy, PublicKey=00240000048000009400000006020000002400005253413100040000010001004dcf3979c4e902efa4dd2163a039701ed5822e6f1134d77737296abbb97bf0803083cfb2117b4f5446a217782f5c7c634f9fe1fc60b4c11d62c5b3d33545036706296d31903ddcf750875db38a8ac379512f51620bb948c94d0831125fbc5fe63707cbb93f48c1459c4d1749eb7ac5e681a2f0d6d7c60fa527a3c0b8f92b02bf")]
#endif
[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
Justification = "AssemblyInformationalVersion does not need to be a parsable version")]

2
ICSharpCode.ILSpyX/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Reflection.Metadata;
using System.Threading;
@ -29,6 +30,7 @@ using ICSharpCode.Decompiler.Util; @@ -29,6 +30,7 @@ using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
[ExportAnalyzer(Header = "Applied To", Order = 10)]
[PartCreationPolicy(CreationPolicy.Shared)]
class AttributeAppliedToAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)

2
ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows events that implement an interface event.
/// </summary>
[ExportAnalyzer(Header = "Implemented By", Order = 10)]
[PartCreationPolicy(CreationPolicy.Shared)]
class EventImplementedByAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)

2
ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows events that override an event.
/// </summary>
[ExportAnalyzer(Header = "Overridden By", Order = 20)]
[PartCreationPolicy(CreationPolicy.Shared)]
class EventOverriddenByAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)

3
ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
@ -35,6 +36,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -35,6 +36,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Finds methods where this field is read.
/// </summary>
[ExportAnalyzer(Header = "Assigned By", Order = 20)]
[PartCreationPolicy(CreationPolicy.Shared)]
class AssignedByFieldAccessAnalyzer : FieldAccessAnalyzer
{
public AssignedByFieldAccessAnalyzer() : base(true) { }
@ -44,6 +46,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -44,6 +46,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Finds methods where this field is written.
/// </summary>
[ExportAnalyzer(Header = "Read By", Order = 10)]
[PartCreationPolicy(CreationPolicy.Shared)]
class ReadByFieldAccessAnalyzer : FieldAccessAnalyzer
{
public ReadByFieldAccessAnalyzer() : base(false) { }

2
ICSharpCode.ILSpyX/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows members from all corresponding interfaces the selected member implements.
/// </summary>
[ExportAnalyzer(Header = "Implements", Order = 40)]
[PartCreationPolicy(CreationPolicy.Shared)]
class MemberImplementsInterfaceAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)

2
ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows methods that implement an interface method.
/// </summary>
[ExportAnalyzer(Header = "Implemented By", Order = 40)]
[PartCreationPolicy(CreationPolicy.Shared)]
class MethodImplementedByAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)

2
ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows methods that override a method.
/// </summary>
[ExportAnalyzer(Header = "Overridden By", Order = 30)]
[PartCreationPolicy(CreationPolicy.Shared)]
class MethodOverriddenByAnalyzer : IAnalyzer
{
const GetMemberOptions Options = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;

2
ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
@ -32,6 +33,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -32,6 +33,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows entities that are used by a method.
/// </summary>
[ExportAnalyzer(Header = "Used By", Order = 20)]
[PartCreationPolicy(CreationPolicy.Shared)]
class MethodUsedByAnalyzer : IAnalyzer
{
const GetMemberOptions Options = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;

2
ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Reflection.Metadata;
@ -32,6 +33,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -32,6 +33,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows entities that are used by a method.
/// </summary>
[ExportAnalyzer(Header = "Uses", Order = 10)]
[PartCreationPolicy(CreationPolicy.Shared)]
class MethodUsesAnalyzer : IAnalyzer
{
public bool Show(ISymbol symbol) => symbol is IMethod method && method.HasBody;

2
ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
@ -31,6 +32,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -31,6 +32,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows entities that are used by a method.
/// </summary>
[ExportAnalyzer(Header = "Used By", Order = 20)]
[PartCreationPolicy(CreationPolicy.Shared)]
class MethodVirtualUsedByAnalyzer : IAnalyzer
{
const GetMemberOptions Options = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;

2
ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows properties that implement an interface property.
/// </summary>
[ExportAnalyzer(Header = "Implemented By", Order = 10)]
[PartCreationPolicy(CreationPolicy.Shared)]
class PropertyImplementedByAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)

2
ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows properties that override a property.
/// </summary>
[ExportAnalyzer(Header = "Overridden By", Order = 20)]
[PartCreationPolicy(CreationPolicy.Shared)]
class PropertyOverriddenByAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)

7
ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs

@ -17,17 +17,18 @@ @@ -17,17 +17,18 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
using ICSharpCode.Decompiler.TypeSystem;
/// <summary>
/// Finds all entities that expose a type.
/// </summary>
[ExportAnalyzer(Header = "Exposed By", Order = 40)]
[PartCreationPolicy(CreationPolicy.Shared)]
class TypeExposedByAnalyzer : IAnalyzer
{
public bool Show(ISymbol entity) => entity is ITypeDefinition;
@ -143,4 +144,4 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -143,4 +144,4 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
return visitor.Found;
}
}
}
}

2
ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using ICSharpCode.Decompiler.TypeSystem;
@ -27,6 +28,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -27,6 +28,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Finds all extension methods defined for a type.
/// </summary>
[ExportAnalyzer(Header = "Extension Methods", Order = 50)]
[PartCreationPolicy(CreationPolicy.Shared)]
class TypeExtensionMethodsAnalyzer : IAnalyzer
{
public bool Show(ISymbol symbol) => symbol is ITypeDefinition entity && !entity.IsStatic;

2
ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
@ -33,6 +34,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -33,6 +34,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows methods that instantiate a type.
/// </summary>
[ExportAnalyzer(Header = "Instantiated By", Order = 20)]
[PartCreationPolicy(CreationPolicy.Shared)]
class TypeInstantiatedByAnalyzer : IAnalyzer
{
const GetMemberOptions Options = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;

2
ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
@ -34,6 +35,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin @@ -34,6 +35,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin
/// Shows entities that use a type.
/// </summary>
[ExportAnalyzer(Header = "Used By", Order = 30)]
[PartCreationPolicy(CreationPolicy.Shared)]
class TypeUsedByAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)

1
ICSharpCode.ILSpyX/AssemblyListManager.cs

@ -56,6 +56,7 @@ namespace ICSharpCode.ILSpyX @@ -56,6 +56,7 @@ namespace ICSharpCode.ILSpyX
}
public bool ApplyWinRTProjections { get; set; }
public bool UseDebugSymbols { get; set; }
public ObservableCollection<string> AssemblyLists { get; } = new ObservableCollection<string>();

13
ICSharpCode.ILSpyX/LoadedAssembly.cs

@ -209,14 +209,19 @@ namespace ICSharpCode.ILSpyX @@ -209,14 +209,19 @@ namespace ICSharpCode.ILSpyX
/// </remarks>
public ICompilation? GetTypeSystemOrNull()
{
return LazyInitializer.EnsureInitialized(ref this.typeSystem, () => {
var value = Volatile.Read(ref this.typeSystem);
if (value == null)
{
var module = GetMetadataFileOrNull();
if (module == null || module.IsMetadataOnly)
return null!;
return new SimpleCompilation(
return null;
value = new SimpleCompilation(
module.WithOptions(TypeSystemOptions.Default | TypeSystemOptions.Uncached | TypeSystemOptions.KeepModifiers),
MinimalCorlib.Instance);
});
value = LazyInit.GetOrSet(ref this.typeSystem, value);
}
return value;
}
readonly object typeSystemWithOptionsLockObj = new object();

47
ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs

@ -98,31 +98,38 @@ namespace ICSharpCode.ILSpyX.PdbProvider @@ -98,31 +98,38 @@ namespace ICSharpCode.ILSpyX.PdbProvider
var debugInfo = metadata.GetMethodDebugInformation(method);
var sequencePoints = new List<Decompiler.DebugInfo.SequencePoint>();
foreach (var point in debugInfo.GetSequencePoints())
try
{
string documentFileName;
if (!point.Document.IsNil)
{
var document = metadata.GetDocument(point.Document);
documentFileName = metadata.GetString(document.Name);
}
else
foreach (var point in debugInfo.GetSequencePoints())
{
documentFileName = "";
string documentFileName;
if (!point.Document.IsNil)
{
var document = metadata.GetDocument(point.Document);
documentFileName = metadata.GetString(document.Name);
}
else
{
documentFileName = "";
}
sequencePoints.Add(new Decompiler.DebugInfo.SequencePoint() {
Offset = point.Offset,
StartLine = point.StartLine,
StartColumn = point.StartColumn,
EndLine = point.EndLine,
EndColumn = point.EndColumn,
DocumentUrl = documentFileName
});
}
sequencePoints.Add(new Decompiler.DebugInfo.SequencePoint() {
Offset = point.Offset,
StartLine = point.StartLine,
StartColumn = point.StartColumn,
EndLine = point.EndLine,
EndColumn = point.EndColumn,
DocumentUrl = documentFileName
});
return sequencePoints;
}
catch (BadImageFormatException)
{
return EmptyList<Decompiler.DebugInfo.SequencePoint>.Instance;
}
return sequencePoints;
}
public IList<Variable> GetVariables(MethodDefinitionHandle method)

4
ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.ILSpyX.Search @@ -52,7 +52,7 @@ namespace ICSharpCode.ILSpyX.Search
public AssemblySearchKind AssemblySearchKind;
public MemberSearchKind MemberSearchKind;
public string[] Keywords;
public Regex RegEx;
public Regex? RegEx;
public bool FullNameSearch;
public bool OmitGenerics;
public string InNamespace;
@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpyX.Search @@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpyX.Search
public abstract class AbstractSearchStrategy
{
protected readonly string[] searchTerm;
protected readonly Regex regex;
protected readonly Regex? regex;
protected readonly bool fullNameSearch;
protected readonly bool omitGenerics;
protected readonly SearchRequest searchRequest;

2
ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs

@ -182,7 +182,7 @@ namespace ICSharpCode.ILSpyX.TreeView @@ -182,7 +182,7 @@ namespace ICSharpCode.ILSpyX.TreeView
#endregion
#region OnChildrenChanged
internal protected virtual void OnChildrenChanged(NotifyCollectionChangedEventArgs e)
protected internal virtual void OnChildrenChanged(NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
{

2
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -32,6 +32,7 @@ using ICSharpCode.ILSpyX.Abstractions; @@ -32,6 +32,7 @@ using ICSharpCode.ILSpyX.Abstractions;
namespace ILSpy.BamlDecompiler
{
[Export(typeof(IResourceNodeFactory))]
[PartCreationPolicy(CreationPolicy.Shared)]
public sealed class BamlResourceNodeFactory : IResourceNodeFactory
{
public ITreeNode CreateNode(Resource resource)
@ -44,6 +45,7 @@ namespace ILSpy.BamlDecompiler @@ -44,6 +45,7 @@ namespace ILSpy.BamlDecompiler
}
[Export(typeof(IResourceFileHandler))]
[PartCreationPolicy(CreationPolicy.Shared)]
public sealed class BamlResourceFileHandler : IResourceFileHandler
{
public string EntryType => "Page";

4
ILSpy.ReadyToRun/ReadyToRunLanguage.cs

@ -33,6 +33,7 @@ using ICSharpCode.Decompiler; @@ -33,6 +33,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using ILCompiler.Reflection.ReadyToRun;
@ -95,6 +96,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -95,6 +96,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
#endif
[Export(typeof(Language))]
[PartCreationPolicy(CreationPolicy.Shared)]
internal class ReadyToRunLanguage : Language
{
private static readonly ConditionalWeakTable<MetadataFile, ReadyToRunReaderCacheEntry> readyToRunReaders = new ConditionalWeakTable<MetadataFile, ReadyToRunReaderCacheEntry>();
@ -173,7 +175,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -173,7 +175,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
.GroupBy(m => m.MethodHandle)
.ToDictionary(g => g.Key, g => g.ToArray());
}
var displaySettings = MainWindow.Instance.CurrentDisplaySettings;
var displaySettings = SettingsService.Instance.DisplaySettings;
bool showMetadataTokens = displaySettings.ShowMetadataTokens;
bool showMetadataTokensInBase10 = displaySettings.ShowMetadataTokensInBase10;
#if STRESS

2
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Windows.Controls;
using System.Xml.Linq;
@ -26,6 +27,7 @@ using ICSharpCode.ILSpyX.Settings; @@ -26,6 +27,7 @@ using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.ReadyToRun
{
[ExportOptionPage(Title = nameof(global::ILSpy.ReadyToRun.Properties.Resources.ReadyToRun), Order = 40)]
[PartCreationPolicy(CreationPolicy.NonShared)]
partial class ReadyToRunOptionPage : UserControl, IOptionPage
{
public ReadyToRunOptionPage()

6
ILSpy.sln

@ -36,6 +36,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.ILSpyX", "ICSha @@ -36,6 +36,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.ILSpyX", "ICSha
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.BamlDecompiler", "ICSharpCode.BamlDecompiler\ICSharpCode.BamlDecompiler.csproj", "{81A30182-3378-4952-8880-F44822390040}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D0858E90-DCD5-4FD9-AA53-7262FAB8BEDB}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
Directory.Packages.props = Directory.Packages.props
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU

2
ILSpy/AboutPage.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows;
@ -36,6 +37,7 @@ using ICSharpCode.ILSpyX.Settings; @@ -36,6 +37,7 @@ using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._Help), Header = nameof(Resources._About), MenuOrder = 99999)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class AboutPage : SimpleCommand
{
public override void Execute(object parameter)

65
ILSpy/Analyzers/AnalyzeCommand.cs

@ -16,10 +16,9 @@ @@ -16,10 +16,9 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel.Composition;
using System.Linq;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TreeNodes;
@ -27,8 +26,11 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -27,8 +26,11 @@ using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Analyzers
{
[ExportContextMenuEntry(Header = nameof(Resources.Analyze), Icon = "Images/Search", Category = nameof(Resources.Analyze), InputGestureText = "Ctrl+R", Order = 100)]
internal sealed class AnalyzeCommand : SimpleCommand, IContextMenuEntry
[PartCreationPolicy(CreationPolicy.Shared)]
internal sealed class AnalyzeContextMenuCommand : IContextMenuEntry
{
private static readonly AnalyzerTreeViewModel AnalyzerTreeView = App.ExportProvider.GetExportedValue<AnalyzerTreeViewModel>();
public bool IsVisible(TextViewContext context)
{
if (context.TreeView is AnalyzerTreeView && context.SelectedTreeNodes != null && context.SelectedTreeNodes.All(n => n.Parent.IsRoot))
@ -41,70 +43,49 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -41,70 +43,49 @@ namespace ICSharpCode.ILSpy.Analyzers
public bool IsEnabled(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return context.Reference != null && context.Reference.Reference is IEntity;
foreach (IMemberTreeNode node in context.SelectedTreeNodes)
{
if (!IsValidReference(node.Member))
return false;
return context.Reference is { Reference: IEntity };
}
return true;
return context.SelectedTreeNodes
.OfType<IMemberTreeNode>()
.All(node => IsValidReference(node.Member));
}
bool IsValidReference(object reference)
static bool IsValidReference(object reference)
{
return reference is IEntity && !(reference is IField f && f.IsConst);
return reference is IEntity and not IField { IsConst: true };
}
public void Execute(TextViewContext context)
{
AnalyzerTreeView analyzerTreeView = MainWindow.Instance.AnalyzerTreeView;
if (analyzerTreeView == null)
{
return;
}
if (context.SelectedTreeNodes != null)
{
foreach (IMemberTreeNode node in context.SelectedTreeNodes)
foreach (var node in context.SelectedTreeNodes.OfType<IMemberTreeNode>().ToArray())
{
analyzerTreeView.Analyze(node.Member);
AnalyzerTreeView.Analyze(node.Member);
}
}
else if (context.Reference != null && context.Reference.Reference is IEntity entity)
else if (context.Reference is { Reference: IEntity entity })
{
analyzerTreeView.Analyze(entity);
AnalyzerTreeView.Analyze(entity);
}
}
}
internal sealed class AnalyzeCommand : SimpleCommand
{
private static readonly AnalyzerTreeViewModel AnalyzerTreeView = App.ExportProvider.GetExportedValue<AnalyzerTreeViewModel>();
public override bool CanExecute(object parameter)
{
AnalyzerTreeView analyzerTreeView = MainWindow.Instance.AnalyzerTreeView;
if (analyzerTreeView != null && analyzerTreeView.IsKeyboardFocusWithin)
{
return analyzerTreeView.SelectedItems.OfType<object>().All(n => n is IMemberTreeNode);
}
else
{
return MainWindow.Instance.SelectedNodes.All(n => n is IMemberTreeNode);
}
return MainWindow.Instance.SelectedNodes.All(n => n is IMemberTreeNode);
}
public override void Execute(object parameter)
{
AnalyzerTreeView analyzerTreeView = MainWindow.Instance.AnalyzerTreeView;
if (analyzerTreeView != null && analyzerTreeView.IsKeyboardFocusWithin)
{
foreach (IMemberTreeNode node in MainWindow.Instance.AnalyzerTreeView.SelectedItems.OfType<IMemberTreeNode>().ToArray())
{
MainWindow.Instance.AnalyzerTreeView.Analyze(node.Member);
}
}
else
foreach (var node in MainWindow.Instance.SelectedNodes.OfType<IMemberTreeNode>())
{
foreach (IMemberTreeNode node in MainWindow.Instance.SelectedNodes)
{
MainWindow.Instance.AnalyzerTreeView.Analyze(node.Member);
}
AnalyzerTreeView.Analyze(node.Member);
}
}
}

42
ILSpy/Analyzers/AnalyzerRootNode.cs

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.TreeView;
namespace ICSharpCode.ILSpy.Analyzers;
public sealed class AnalyzerRootNode : AnalyzerTreeNode
{
public AnalyzerRootNode()
{
MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => CurrentAssemblyList_Changed(sender, e);
}
void CurrentAssemblyList_Changed(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Reset)
{
this.Children.Clear();
}
else
{
var removedAssemblies = e.OldItems?.Cast<LoadedAssembly>().ToArray() ?? [];
var addedAssemblies = e.NewItems?.Cast<LoadedAssembly>().ToArray() ?? [];
HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
}
}
public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies)
{
this.Children.RemoveAll(
delegate (SharpTreeNode n) {
AnalyzerTreeNode an = n as AnalyzerTreeNode;
return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
});
return true;
}
}

24
ILSpy/Analyzers/AnalyzerSearchTreeNode.cs

@ -86,29 +86,17 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -86,29 +86,17 @@ namespace ICSharpCode.ILSpy.Analyzers
switch (symbol)
{
case IModule module:
return new AnalyzedModuleTreeNode(module) {
Language = this.Language
};
return new AnalyzedModuleTreeNode(module) { };
case ITypeDefinition td:
return new AnalyzedTypeTreeNode(td) {
Language = this.Language
};
return new AnalyzedTypeTreeNode(td) { };
case IField fd:
return new AnalyzedFieldTreeNode(fd) {
Language = this.Language
};
return new AnalyzedFieldTreeNode(fd) { };
case IMethod md:
return new AnalyzedMethodTreeNode(md) {
Language = this.Language
};
return new AnalyzedMethodTreeNode(md) { };
case IProperty pd:
return new AnalyzedPropertyTreeNode(pd) {
Language = this.Language
};
return new AnalyzedPropertyTreeNode(pd) { };
case IEvent ed:
return new AnalyzedEventTreeNode(ed) {
Language = this.Language
};
return new AnalyzedEventTreeNode(ed) { };
default:
throw new ArgumentOutOfRangeException(nameof(symbol), $"Symbol {symbol.GetType().FullName} is not supported.");
}

29
ILSpy/Analyzers/AnalyzerTreeNode.cs

@ -17,9 +17,8 @@ @@ -17,9 +17,8 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.TreeView;
@ -27,23 +26,11 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -27,23 +26,11 @@ namespace ICSharpCode.ILSpy.Analyzers
{
public abstract class AnalyzerTreeNode : SharpTreeNode
{
private Language language;
public Language Language {
get { return language; }
set {
if (language != value)
{
language = value;
foreach (var child in this.Children.OfType<AnalyzerTreeNode>())
child.Language = value;
}
}
}
public Language Language => SettingsService.Instance.SessionSettings.LanguageSettings.Language;
public override bool CanDelete()
{
return Parent != null && Parent.IsRoot;
return Parent is { IsRoot: true };
}
public override void DeleteCore()
@ -56,16 +43,6 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -56,16 +43,6 @@ namespace ICSharpCode.ILSpy.Analyzers
DeleteCore();
}
internal protected override void OnChildrenChanged(NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (AnalyzerTreeNode a in e.NewItems.OfType<AnalyzerTreeNode>())
a.Language = this.Language;
}
base.OnChildrenChanged(e);
}
/// <summary>
/// Handles changes to the assembly list.
/// </summary>

178
ILSpy/Analyzers/AnalyzerTreeView.cs

@ -1,178 +0,0 @@ @@ -1,178 +0,0 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Analyzers.TreeNodes;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpy.Controls.TreeView;
using ICSharpCode.ILSpyX.TreeView;
namespace ICSharpCode.ILSpy.Analyzers
{
/// <summary>
/// Analyzer tree view.
/// </summary>
public class AnalyzerTreeView : SharpTreeView
{
FilterSettings filterSettings;
public AnalyzerTreeView()
{
this.ShowRoot = false;
this.Root = new AnalyzerRootNode { Language = MainWindow.Instance.CurrentLanguage };
this.BorderThickness = new Thickness(0);
ContextMenuProvider.Add(this);
MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged;
DockWorkspace.Instance.PropertyChanged += DockWorkspace_PropertyChanged;
filterSettings = MainWindow.Instance.SessionSettings.FilterSettings;
filterSettings.PropertyChanged += FilterSettings_PropertyChanged;
}
private void DockWorkspace_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(DockWorkspace.Instance.ActiveTabPage):
filterSettings.PropertyChanged -= FilterSettings_PropertyChanged;
filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings;
filterSettings.PropertyChanged += FilterSettings_PropertyChanged;
break;
}
}
private void FilterSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Language":
case "LanguageVersion":
((AnalyzerRootNode)this.Root).Language = MainWindow.Instance.CurrentLanguage;
break;
}
}
void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Reset)
{
this.Root.Children.Clear();
}
else
{
List<LoadedAssembly> removedAssemblies = new List<LoadedAssembly>();
if (e.OldItems != null)
removedAssemblies.AddRange(e.OldItems.Cast<LoadedAssembly>());
List<LoadedAssembly> addedAssemblies = new List<LoadedAssembly>();
if (e.NewItems != null)
addedAssemblies.AddRange(e.NewItems.Cast<LoadedAssembly>());
((AnalyzerRootNode)this.Root).HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
}
}
public void Show()
{
DockWorkspace.Instance.ShowToolPane(AnalyzerPaneModel.PaneContentId);
}
public void Show(AnalyzerTreeNode node)
{
Show();
node.IsExpanded = true;
this.Root.Children.Add(node);
this.SelectedItem = node;
this.FocusNode(node);
}
public void ShowOrFocus(AnalyzerTreeNode node)
{
if (node is AnalyzerEntityTreeNode)
{
var an = node as AnalyzerEntityTreeNode;
var found = this.Root.Children.OfType<AnalyzerEntityTreeNode>().FirstOrDefault(n => n.Member == an.Member);
if (found != null)
{
Show();
found.IsExpanded = true;
this.SelectedItem = found;
this.FocusNode(found);
return;
}
}
Show(node);
}
public void Analyze(IEntity entity)
{
if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
if (entity.MetadataToken.IsNil)
{
MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy");
return;
}
switch (entity)
{
case ITypeDefinition td:
ShowOrFocus(new AnalyzedTypeTreeNode(td));
break;
case IField fd:
if (!fd.IsConst)
ShowOrFocus(new AnalyzedFieldTreeNode(fd));
break;
case IMethod md:
ShowOrFocus(new AnalyzedMethodTreeNode(md));
break;
case IProperty pd:
ShowOrFocus(new AnalyzedPropertyTreeNode(pd));
break;
case IEvent ed:
ShowOrFocus(new AnalyzedEventTreeNode(ed));
break;
default:
throw new ArgumentOutOfRangeException(nameof(entity), $"Entity {entity.GetType().FullName} is not supported.");
}
}
sealed class AnalyzerRootNode : AnalyzerTreeNode
{
public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies)
{
this.Children.RemoveAll(
delegate (SharpTreeNode n) {
AnalyzerTreeNode an = n as AnalyzerTreeNode;
return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
});
return true;
}
}
}
}

23
ILSpy/Analyzers/AnalyzerTreeView.xaml

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
<treeView:SharpTreeView
x:Class="ICSharpCode.ILSpy.Analyzers.AnalyzerTreeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:toms="urn:TomsToolbox"
xmlns:treeView="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView"
xmlns:analyzers="clr-namespace:ICSharpCode.ILSpy.Analyzers"
mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance analyzers:AnalyzerTreeViewModel}"
ShowRoot="False"
BorderThickness="0"
Root="{Binding Root}"
toms:MultiSelectorExtensions.SelectionBinding="{Binding SelectedItems}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
SelectionChanged="AnalyzerTreeView_OnSelectionChanged">
<UIElement.InputBindings>
<KeyBinding Key="R" Modifiers="Control" Command="{Binding AnalyzeCommand}" />
</UIElement.InputBindings>
</treeView:SharpTreeView>

42
ILSpy/Docking/PaneTemplateSelector.cs → ILSpy/Analyzers/AnalyzerTreeView.xaml.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -16,33 +16,35 @@ @@ -16,33 +16,35 @@
// 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.ObjectModel;
using System.Linq;
using System.Windows;
using System.ComponentModel.Composition;
using System.Windows.Controls;
namespace ICSharpCode.ILSpy.Docking
{
public class TemplateMapping
{
public Type Type { get; set; }
public DataTemplate Template { get; set; }
}
using ICSharpCode.ILSpyX.TreeView;
using TomsToolbox.Wpf.Composition.Mef;
public class PaneTemplateSelector : DataTemplateSelector
namespace ICSharpCode.ILSpy.Analyzers
{
/// <summary>
/// Interaction logic for AnalyzerTreeView.xaml
/// </summary>
[DataTemplate(typeof(AnalyzerTreeViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export]
public partial class AnalyzerTreeView
{
public Collection<TemplateMapping> Mappings { get; set; } = new Collection<TemplateMapping>();
public AnalyzerTreeView()
{
InitializeComponent();
ContextMenuProvider.Add(this);
}
public override DataTemplate SelectTemplate(object item, DependencyObject container)
private void AnalyzerTreeView_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (item == null)
if (SelectedItem is SharpTreeNode sharpTreeNode)
{
return base.SelectTemplate(item, container);
FocusNode(sharpTreeNode);
}
return Mappings.FirstOrDefault(m => m.Type == item.GetType())?.Template
?? base.SelectTemplate(item, container);
}
}
}

130
ILSpy/Analyzers/AnalyzerTreeViewModel.cs

@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Analyzers.TreeNodes;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy.Analyzers
{
[ExportToolPane]
[PartCreationPolicy(CreationPolicy.Shared)]
[Export]
public class AnalyzerTreeViewModel : ToolPaneModel
{
private AnalyzerTreeNode selectedItem;
public const string PaneContentId = "analyzerPane";
public AnalyzerTreeViewModel()
{
ContentId = PaneContentId;
Title = Properties.Resources.Analyze;
ShortcutKey = new(Key.R, ModifierKeys.Control);
AssociatedCommand = ILSpyCommands.Analyze;
}
public AnalyzerRootNode Root { get; } = new();
public AnalyzerTreeNode SelectedItem {
get => selectedItem;
set => SetProperty(ref selectedItem, value);
}
public ICommand AnalyzeCommand => new DelegateCommand(AnalyzeSelected);
public ObservableCollection<AnalyzerTreeNode> SelectedItems { get; } = [];
private void AnalyzeSelected()
{
foreach (var node in SelectedItems.OfType<IMemberTreeNode>())
{
Analyze(node.Member);
}
}
void AddOrSelect(AnalyzerTreeNode node)
{
Show();
AnalyzerTreeNode target = default;
if (node is AnalyzerEntityTreeNode { Member: { } member })
{
target = this.Root.Children.OfType<AnalyzerEntityTreeNode>().FirstOrDefault(item => item.Member == member);
}
if (target == null)
{
this.Root.Children.Add(node);
target = node;
}
target.IsExpanded = true;
this.SelectedItem = target;
}
public void Analyze(IEntity entity)
{
if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
if (entity.MetadataToken.IsNil)
{
MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy");
return;
}
switch (entity)
{
case ITypeDefinition td:
AddOrSelect(new AnalyzedTypeTreeNode(td));
break;
case IField fd:
if (!fd.IsConst)
AddOrSelect(new AnalyzedFieldTreeNode(fd));
break;
case IMethod md:
AddOrSelect(new AnalyzedMethodTreeNode(md));
break;
case IProperty pd:
AddOrSelect(new AnalyzedPropertyTreeNode(pd));
break;
case IEvent ed:
AddOrSelect(new AnalyzedEventTreeNode(ed));
break;
default:
throw new ArgumentOutOfRangeException(nameof(entity), $@"Entity {entity.GetType().FullName} is not supported.");
}
}
}
}

2
ILSpy/Analyzers/CopyAnalysisResultsContextMenuEntry.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.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Windows;
@ -23,6 +24,7 @@ using System.Windows; @@ -23,6 +24,7 @@ using System.Windows;
namespace ICSharpCode.ILSpy.Analyzers
{
[ExportContextMenuEntry(Header = "Copy results", Category = "Analyze", Order = 200)]
[PartCreationPolicy(CreationPolicy.Shared)]
internal sealed class CopyAnalysisResultsContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

2
ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs

@ -16,11 +16,13 @@ @@ -16,11 +16,13 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel.Composition;
using System.Linq;
namespace ICSharpCode.ILSpy.Analyzers
{
[ExportContextMenuEntry(Header = "Remove", Icon = "images/Delete", Category = "Analyze", Order = 200)]
[PartCreationPolicy(CreationPolicy.Shared)]
internal sealed class RemoveAnalyzeContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

22
ILSpy/App.xaml.cs

@ -42,6 +42,10 @@ using Microsoft.VisualStudio.Composition; @@ -42,6 +42,10 @@ using Microsoft.VisualStudio.Composition;
using TomsToolbox.Wpf.Styles;
using ICSharpCode.ILSpyX.TreeView;
using TomsToolbox.Composition;
using TomsToolbox.Wpf.Composition;
using System.ComponentModel.Composition.Hosting;
namespace ICSharpCode.ILSpy
{
/// <summary>
@ -52,8 +56,7 @@ namespace ICSharpCode.ILSpy @@ -52,8 +56,7 @@ namespace ICSharpCode.ILSpy
internal static CommandLineArguments CommandLineArguments;
internal static readonly IList<ExceptionData> StartupExceptions = new List<ExceptionData>();
public static ExportProvider ExportProvider { get; private set; }
public static IExportProviderFactory ExportProviderFactory { get; private set; }
public static IExportProvider ExportProvider { get; private set; }
internal class ExceptionData
{
@ -89,7 +92,12 @@ namespace ICSharpCode.ILSpy @@ -89,7 +92,12 @@ namespace ICSharpCode.ILSpy
}
TaskScheduler.UnobservedTaskException += DotNet40_UnobservedTaskException;
InitializeMef().GetAwaiter().GetResult();
Languages.Initialize(ExportProvider);
// Register the export provider so that it can be accessed from WPF/XAML components.
ExportProviderLocator.Register(ExportProvider);
// Add data templates registered via MEF.
Resources.MergedDictionaries.Add(DataTemplateManager.CreateDynamicDataTemplates(ExportProvider));
EventManager.RegisterClassHandler(typeof(Window),
Hyperlink.RequestNavigateEvent,
new RequestNavigateEventHandler(Window_RequestNavigate));
@ -170,8 +178,9 @@ namespace ICSharpCode.ILSpy @@ -170,8 +178,9 @@ namespace ICSharpCode.ILSpy
// If/When any part needs to import ICompositionService, this will be needed:
// catalog.WithCompositionService();
var config = CompositionConfiguration.Create(catalog);
ExportProviderFactory = config.CreateExportProviderFactory();
ExportProvider = ExportProviderFactory.CreateExportProvider();
var exportProviderFactory = config.CreateExportProviderFactory();
ExportProvider = new ExportProviderAdapter(exportProviderFactory.CreateExportProvider());
// This throws exceptions for composition failures. Alternatively, the configuration's CompositionErrors property
// could be used to log the errors directly. Used at the end so that it does not prevent the export provider setup.
config.ThrowOnErrors();
@ -192,7 +201,8 @@ namespace ICSharpCode.ILSpy @@ -192,7 +201,8 @@ namespace ICSharpCode.ILSpy
protected override void OnStartup(StartupEventArgs e)
{
var output = new StringBuilder();
if (ILSpy.MainWindow.FormatExceptions(StartupExceptions.ToArray(), output))
if (StartupExceptions.FormatExceptions(output))
{
MessageBox.Show(output.ToString(), "Sorry we crashed!");
Environment.Exit(1);

2
ILSpy/Commands/BrowseBackCommand.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.ComponentModel.Composition;
using System.Windows.Input;
using ICSharpCode.ILSpy.Properties;
@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.Properties; @@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = nameof(Resources.Back), ToolbarIcon = "Images/Back", ToolbarCategory = nameof(Resources.Navigation), ToolbarOrder = 0)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class BrowseBackCommand : CommandWrapper
{
public BrowseBackCommand()

2
ILSpy/Commands/BrowseForwardCommand.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.ComponentModel.Composition;
using System.Windows.Input;
using ICSharpCode.ILSpy.Properties;
@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.Properties; @@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = nameof(Resources.Forward), ToolbarIcon = "Images/Forward", ToolbarCategory = nameof(Resources.Navigation), ToolbarOrder = 1)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class BrowseForwardCommand : CommandWrapper
{
public BrowseForwardCommand()

3
ILSpy/Commands/CheckForUpdatesCommand.cs

@ -17,12 +17,15 @@ @@ -17,12 +17,15 @@
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel.Composition;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._Help), Header = nameof(Resources._CheckUpdates), MenuOrder = 5000)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class CheckForUpdatesCommand : SimpleCommand
{
public override bool CanExecute(object parameter)

2
ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs

@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
// 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.ComponentModel.Composition;
using System.Windows;
using ICSharpCode.ILSpy.Properties;
@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy
{
[ExportContextMenuEntry(Header = nameof(Resources.CopyName), Icon = "images/Copy", Order = 9999)]
[PartCreationPolicy(CreationPolicy.Shared)]
public class CopyFullyQualifiedNameContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

6
ILSpy/Commands/DecompileAllCommand.cs

@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
using System;
using System.Collections.Concurrent;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
@ -27,6 +28,7 @@ using System.Threading.Tasks; @@ -27,6 +28,7 @@ using System.Threading.Tasks;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using TomsToolbox.Essentials;
@ -34,6 +36,7 @@ using TomsToolbox.Essentials; @@ -34,6 +36,7 @@ using TomsToolbox.Essentials;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile), MenuCategory = nameof(Resources.Open), MenuOrder = 2.5)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class DecompileAllCommand : SimpleCommand
{
public override bool CanExecute(object parameter)
@ -86,12 +89,13 @@ namespace ICSharpCode.ILSpy @@ -86,12 +89,13 @@ namespace ICSharpCode.ILSpy
}
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile100x), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class Decompile100TimesCommand : SimpleCommand
{
public override void Execute(object parameter)
{
const int numRuns = 100;
var language = MainWindow.Instance.CurrentLanguage;
var language = SettingsService.Instance.SessionSettings.LanguageSettings.Language;
var nodes = MainWindow.Instance.SelectedNodes.ToArray();
var options = MainWindow.Instance.CreateDecompilationOptions();
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {

2
ILSpy/Commands/DecompileCommand.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.ComponentModel.Composition;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -25,6 +26,7 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -25,6 +26,7 @@ using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Commands
{
[ExportContextMenuEntry(Header = nameof(Resources.Decompile), Order = 10)]
[PartCreationPolicy(CreationPolicy.Shared)]
class DecompileCommand : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

2
ILSpy/Commands/DecompileInNewViewCommand.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows.Threading;
@ -30,6 +31,7 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -30,6 +31,7 @@ using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Commands
{
[ExportContextMenuEntry(Header = nameof(Resources.DecompileToNewPanel), InputGestureText = "MMB", Icon = "images/Search", Category = nameof(Resources.Analyze), Order = 90)]
[PartCreationPolicy(CreationPolicy.Shared)]
internal sealed class DecompileInNewViewCommand : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

2
ILSpy/Commands/DisassembleAllCommand.cs

@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
using System;
using System.Collections.Concurrent;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Threading.Tasks;
@ -30,6 +31,7 @@ using ICSharpCode.ILSpyX; @@ -30,6 +31,7 @@ using ICSharpCode.ILSpyX;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDisassemble), MenuCategory = nameof(Resources.Open), MenuOrder = 2.5)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class DisassembleAllCommand : SimpleCommand
{
public override bool CanExecute(object parameter)

3
ILSpy/Commands/ExitCommand.cs

@ -15,11 +15,14 @@ @@ -15,11 +15,14 @@
// 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.ComponentModel.Composition;
using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.E_xit), MenuOrder = 99999, MenuCategory = nameof(Resources.Exit))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class ExitCommand : SimpleCommand
{
public override void Execute(object parameter)

10
ILSpy/Commands/ExportCommandAttribute.cs

@ -99,21 +99,15 @@ namespace ICSharpCode.ILSpy @@ -99,21 +99,15 @@ namespace ICSharpCode.ILSpy
#endregion
#region Tool Panes
public interface IToolPaneMetadata
{
string ContentId { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ExportToolPaneAttribute : ExportAttribute, IToolPaneMetadata
[AttributeUsage(AttributeTargets.Class)]
public class ExportToolPaneAttribute : ExportAttribute
{
public ExportToolPaneAttribute()
: base("ToolPane", typeof(ViewModels.ToolPaneModel))
{
}
public string ContentId { get; set; }
}
#endregion
}

2
ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -34,6 +35,7 @@ using Microsoft.Win32; @@ -34,6 +35,7 @@ using Microsoft.Win32;
namespace ICSharpCode.ILSpy
{
[ExportContextMenuEntry(Header = nameof(Resources.ExtractPackageEntry), Category = nameof(Resources.Save), Icon = "Images/Save")]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class ExtractPackageEntryContextMenuEntry : IContextMenuEntry
{
public void Execute(TextViewContext context)

3
ILSpy/Commands/GeneratePdbContextMenuEntry.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -38,6 +39,7 @@ using Microsoft.Win32; @@ -38,6 +39,7 @@ using Microsoft.Win32;
namespace ICSharpCode.ILSpy
{
[ExportContextMenuEntry(Header = nameof(Resources.GeneratePortable))]
[PartCreationPolicy(CreationPolicy.Shared)]
class GeneratePdbContextMenuEntry : IContextMenuEntry
{
public void Execute(TextViewContext context)
@ -103,6 +105,7 @@ namespace ICSharpCode.ILSpy @@ -103,6 +105,7 @@ namespace ICSharpCode.ILSpy
}
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = nameof(Resources.Save))]
[PartCreationPolicy(CreationPolicy.Shared)]
class GeneratePdbMainMenuEntry : SimpleCommand
{
public override bool CanExecute(object parameter)

3
ILSpy/Commands/ManageAssemblyListsCommand.cs

@ -17,11 +17,14 @@ @@ -17,11 +17,14 @@
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel.Composition;
using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.ManageAssembly_Lists), MenuIcon = "Images/AssemblyList", MenuCategory = nameof(Resources.Open), MenuOrder = 1.7)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class ManageAssemblyListsCommand : SimpleCommand
{
public override void Execute(object parameter)

2
ILSpy/Commands/OpenCommand.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.ComponentModel.Composition;
using System.Windows.Input;
using ICSharpCode.ILSpy.Properties;
@ -24,6 +25,7 @@ namespace ICSharpCode.ILSpy @@ -24,6 +25,7 @@ namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = nameof(Resources.Open), ToolbarIcon = "Images/Open", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 0)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._Open), MenuIcon = "Images/Open", MenuCategory = nameof(Resources.Open), MenuOrder = 0)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class OpenCommand : CommandWrapper
{
public OpenCommand()

3
ILSpy/Commands/OpenFromGacCommand.cs

@ -16,12 +16,15 @@ @@ -16,12 +16,15 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel.Composition;
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.OpenFrom_GAC), MenuIcon = "Images/AssemblyListGAC", MenuCategory = nameof(Resources.Open), MenuOrder = 1)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class OpenFromGacCommand : SimpleCommand
{
public override bool CanExecute(object parameter)

3
ILSpy/Commands/Pdb2XmlCommand.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
#if DEBUG
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@ -34,6 +35,7 @@ using Microsoft.DiaSymReader.Tools; @@ -34,6 +35,7 @@ using Microsoft.DiaSymReader.Tools;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDumpPDBAsXML), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class Pdb2XmlCommand : SimpleCommand
{
public override bool CanExecute(object parameter)
@ -70,6 +72,7 @@ namespace ICSharpCode.ILSpy @@ -70,6 +72,7 @@ namespace ICSharpCode.ILSpy
}
[ExportContextMenuEntry(Header = nameof(Resources.DEBUGDumpPDBAsXML))]
[PartCreationPolicy(CreationPolicy.Shared)]
class Pdb2XmlCommandContextMenuEntry : IContextMenuEntry
{
public void Execute(TextViewContext context)

2
ILSpy/Commands/RefreshCommand.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.ComponentModel.Composition;
using System.Windows.Input;
using ICSharpCode.ILSpy.Properties;
@ -24,6 +25,7 @@ namespace ICSharpCode.ILSpy @@ -24,6 +25,7 @@ namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = nameof(Resources.RefreshCommand_ReloadAssemblies), ToolbarIcon = "Images/Refresh", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 2)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._Reload), MenuIcon = "Images/Refresh", MenuCategory = nameof(Resources.Open), MenuOrder = 2)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class RefreshCommand : CommandWrapper
{
public RefreshCommand()

3
ILSpy/Commands/RemoveAssembliesWithLoadErrors.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.ComponentModel.Composition;
using System.Linq;
using ICSharpCode.ILSpy.Properties;
@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.Properties; @@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._RemoveAssembliesWithLoadErrors), MenuCategory = nameof(Resources.Remove), MenuOrder = 2.6)]
[PartCreationPolicy(CreationPolicy.Shared)]
class RemoveAssembliesWithLoadErrors : SimpleCommand
{
public override bool CanExecute(object parameter)
@ -44,6 +46,7 @@ namespace ICSharpCode.ILSpy @@ -44,6 +46,7 @@ namespace ICSharpCode.ILSpy
}
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.ClearAssemblyList), MenuCategory = nameof(Resources.Remove), MenuOrder = 2.6)]
[PartCreationPolicy(CreationPolicy.Shared)]
class ClearAssemblyList : SimpleCommand
{
public override bool CanExecute(object parameter)

6
ILSpy/Commands/SaveCodeContextMenuEntry.cs

@ -30,10 +30,14 @@ using ICSharpCode.ILSpy.ViewModels; @@ -30,10 +30,14 @@ using ICSharpCode.ILSpy.ViewModels;
using Microsoft.Win32;
using ICSharpCode.ILSpyX.TreeView;
using System.ComponentModel.Composition;
using ICSharpCode.ILSpy.Util;
namespace ICSharpCode.ILSpy.TextView
{
[ExportContextMenuEntry(Header = nameof(Resources._SaveCode), Category = nameof(Resources.Save), Icon = "Images/Save")]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class SaveCodeContextMenuEntry : IContextMenuEntry
{
public void Execute(TextViewContext context)
@ -58,7 +62,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -58,7 +62,7 @@ namespace ICSharpCode.ILSpy.TextView
public static void Execute(IReadOnlyList<SharpTreeNode> selectedNodes)
{
var currentLanguage = MainWindow.Instance.CurrentLanguage;
var currentLanguage = SettingsService.Instance.SessionSettings.LanguageSettings.Language;
var tabPage = Docking.DockWorkspace.Instance.ActiveTabPage;
tabPage.ShowTextView(textView => {
if (selectedNodes.Count == 1 && selectedNodes[0] is ILSpyTreeNode singleSelection)

2
ILSpy/Commands/SaveCommand.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.ComponentModel.Composition;
using System.Windows.Input;
using ICSharpCode.ILSpy.Properties;
@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.Properties; @@ -23,6 +24,7 @@ using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._SaveCode), MenuIcon = "Images/Save", MenuCategory = nameof(Resources.Save), MenuOrder = 0)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class SaveCommand : CommandWrapper
{
public SaveCommand()

15
ILSpy/Commands/ScopeSearchToAssembly.cs

@ -18,22 +18,33 @@ @@ -18,22 +18,33 @@
#nullable enable
using System;
using System.ComponentModel.Composition;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy
{
[ExportContextMenuEntry(Header = nameof(Resources.ScopeSearchToThisAssembly), Category = nameof(Resources.Analyze), Order = 9999)]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ScopeSearchToAssembly : IContextMenuEntry
{
private readonly SearchPaneModel searchPane;
[ImportingConstructor]
public ScopeSearchToAssembly(SearchPaneModel searchPane)
{
this.searchPane = searchPane;
}
public void Execute(TextViewContext context)
{
// asmName cannot be null here, because Execute is only called if IsEnabled/IsVisible return true.
string asmName = GetAssembly(context)!;
string searchTerm = MainWindow.Instance.SearchPane.SearchTerm;
string searchTerm = searchPane.SearchTerm;
string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm);
bool replaced = false;
for (int i = 0; i < args.Length; i++)
@ -53,7 +64,7 @@ namespace ICSharpCode.ILSpy @@ -53,7 +64,7 @@ namespace ICSharpCode.ILSpy
{
searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args);
}
MainWindow.Instance.SearchPane.SearchTerm = searchTerm;
searchPane.SearchTerm = searchTerm;
}
public bool IsEnabled(TextViewContext context)

16
ILSpy/Commands/ScopeSearchToNamespace.cs

@ -16,21 +16,32 @@ @@ -16,21 +16,32 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel.Composition;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy
{
[ExportContextMenuEntry(Header = nameof(Resources.ScopeSearchToThisNamespace), Category = nameof(Resources.Analyze), Order = 9999)]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ScopeSearchToNamespace : IContextMenuEntry
{
private readonly SearchPaneModel searchPane;
[ImportingConstructor]
public ScopeSearchToNamespace(SearchPaneModel searchPane)
{
this.searchPane = searchPane;
}
public void Execute(TextViewContext context)
{
string ns = GetNamespace(context);
string searchTerm = MainWindow.Instance.SearchPane.SearchTerm;
string searchTerm = searchPane.SearchTerm;
string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm);
bool replaced = false;
for (int i = 0; i < args.Length; i++)
@ -50,7 +61,8 @@ namespace ICSharpCode.ILSpy @@ -50,7 +61,8 @@ namespace ICSharpCode.ILSpy
{
searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args);
}
MainWindow.Instance.SearchPane.SearchTerm = searchTerm;
searchPane.SearchTerm = searchTerm;
}
public bool IsEnabled(TextViewContext context)

3
ILSpy/Commands/SearchMsdnContextMenuEntry.cs

@ -23,9 +23,12 @@ using ICSharpCode.ILSpy.Properties; @@ -23,9 +23,12 @@ using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy
{
using System.ComponentModel.Composition;
using ICSharpCode.Decompiler.TypeSystem;
[ExportContextMenuEntry(Header = nameof(Resources.SearchMSDN), Icon = "images/SearchMsdn", Order = 9999)]
[PartCreationPolicy(CreationPolicy.Shared)]
internal sealed class SearchMsdnContextMenuEntry : IContextMenuEntry
{
private static string msdnAddress = "https://docs.microsoft.com/dotnet/api/{0}";

6
ILSpy/Commands/SelectPdbContextMenuEntry.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.ComponentModel.Composition;
using System.IO;
using System.Linq;
@ -27,6 +28,7 @@ using Microsoft.Win32; @@ -27,6 +28,7 @@ using Microsoft.Win32;
namespace ICSharpCode.ILSpy
{
[ExportContextMenuEntry(Header = nameof(Resources.SelectPDB))]
[PartCreationPolicy(CreationPolicy.Shared)]
class SelectPdbContextMenuEntry : IContextMenuEntry
{
public async void Execute(TextViewContext context)
@ -46,7 +48,9 @@ namespace ICSharpCode.ILSpy @@ -46,7 +48,9 @@ namespace ICSharpCode.ILSpy
await assembly.LoadDebugInfo(dlg.FileName);
}
MainWindow.Instance.SelectNode(MainWindow.Instance.FindNodeByPath(new[] { assembly.FileName }, true));
var node = (AssemblyTreeNode)MainWindow.Instance.FindNodeByPath(new[] { assembly.FileName }, true);
node.UpdateToolTip();
MainWindow.Instance.SelectNode(node);
MainWindow.Instance.RefreshDecompiledView();
}

6
ILSpy/Commands/SetThemeCommand.cs

@ -1,11 +1,13 @@ @@ -1,11 +1,13 @@
namespace ICSharpCode.ILSpy.Commands
using ICSharpCode.ILSpy.Util;
namespace ICSharpCode.ILSpy.Commands
{
public class SetThemeCommand : SimpleCommand
{
public override void Execute(object parameter)
{
if (parameter is string theme)
MainWindow.Instance.SessionSettings.Theme = theme;
SettingsService.Instance.SessionSettings.Theme = theme;
}
}
}

41
ILSpy/Commands/ShowCFGContextMenuEntry.cs

@ -1,14 +1,18 @@ @@ -1,14 +1,18 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows;
using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.ControlFlow;
using ICSharpCode.ILSpy.Util;
namespace ICSharpCode.ILSpy.Commands
{
#if DEBUG
[ExportContextMenuEntry(Header = "DEBUG -- Show CFG")]
[PartCreationPolicy(CreationPolicy.Shared)]
internal class ShowCFGContextMenuEntry : IContextMenuEntry
{
public void Execute(TextViewContext context)
@ -17,7 +21,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -17,7 +21,7 @@ namespace ICSharpCode.ILSpy.Commands
{
var container = (BlockContainer)context.Reference.Reference;
var cfg = new ControlFlowGraph(container);
ControlFlowNode.ExportGraph(cfg.cfg).Show();
ExportGraph(cfg.Nodes).Show();
}
catch (Exception ex)
{
@ -34,6 +38,41 @@ namespace ICSharpCode.ILSpy.Commands @@ -34,6 +38,41 @@ namespace ICSharpCode.ILSpy.Commands
{
return context.Reference?.Reference is BlockContainer;
}
internal static GraphVizGraph ExportGraph(IReadOnlyList<ControlFlowNode> nodes, Func<ControlFlowNode, string> labelFunc = null)
{
if (labelFunc == null)
{
labelFunc = node => {
var block = node.UserData as Block;
return block != null ? block.Label : node.UserData?.ToString();
};
}
GraphVizGraph g = new GraphVizGraph();
GraphVizNode[] n = new GraphVizNode[nodes.Count];
for (int i = 0; i < n.Length; i++)
{
n[i] = new GraphVizNode(nodes[i].UserIndex);
n[i].shape = "box";
n[i].label = labelFunc(nodes[i]);
g.AddNode(n[i]);
}
foreach (var source in nodes)
{
foreach (var target in source.Successors)
{
g.AddEdge(new GraphVizEdge(source.UserIndex, target.UserIndex));
}
if (source.ImmediateDominator != null)
{
g.AddEdge(
new GraphVizEdge(source.ImmediateDominator.UserIndex, source.UserIndex) {
color = "green"
});
}
}
return g;
}
}
#endif
}

3
ILSpy/Commands/SortAssemblyListCommand.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpyX;
@ -27,6 +28,7 @@ namespace ICSharpCode.ILSpy @@ -27,6 +28,7 @@ namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._View), Header = nameof(Resources.SortAssembly_listName), MenuIcon = "Images/Sort", MenuCategory = nameof(Resources.View))]
[ExportToolbarCommand(ToolTip = nameof(Resources.SortAssemblyListName), ToolbarIcon = "Images/Sort", ToolbarCategory = nameof(Resources.View))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class SortAssemblyListCommand : SimpleCommand, IComparer<LoadedAssembly>
{
public override void Execute(object parameter)
@ -43,6 +45,7 @@ namespace ICSharpCode.ILSpy @@ -43,6 +45,7 @@ namespace ICSharpCode.ILSpy
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._View), Header = nameof(Resources._CollapseTreeNodes), MenuIcon = "Images/CollapseAll", MenuCategory = nameof(Resources.View))]
[ExportToolbarCommand(ToolTip = nameof(Resources.CollapseTreeNodes), ToolbarIcon = "Images/CollapseAll", ToolbarCategory = nameof(Resources.View))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class CollapseAllCommand : SimpleCommand
{
public override void Execute(object parameter)

12
ILSpy/ContextMenuEntry.cs

@ -31,6 +31,8 @@ using ICSharpCode.ILSpyX.Search; @@ -31,6 +31,8 @@ using ICSharpCode.ILSpyX.Search;
using ICSharpCode.ILSpy.Controls.TreeView;
using ICSharpCode.ILSpyX.TreeView;
using TomsToolbox.Composition;
namespace ICSharpCode.ILSpy
{
public interface IContextMenuEntry
@ -205,7 +207,7 @@ namespace ICSharpCode.ILSpy @@ -205,7 +207,7 @@ namespace ICSharpCode.ILSpy
readonly DecompilerTextView textView;
readonly ListBox listBox;
readonly DataGrid dataGrid;
readonly Lazy<IContextMenuEntry, IContextMenuEntryMetadata>[] entries;
readonly IExport<IContextMenuEntry, IContextMenuEntryMetadata>[] entries;
private ContextMenuProvider()
{
@ -288,8 +290,8 @@ namespace ICSharpCode.ILSpy @@ -288,8 +290,8 @@ namespace ICSharpCode.ILSpy
bool ShowContextMenu(TextViewContext context, out ContextMenu menu)
{
menu = new ContextMenu();
var menuGroups = new Dictionary<string, Lazy<IContextMenuEntry, IContextMenuEntryMetadata>[]>();
Lazy<IContextMenuEntry, IContextMenuEntryMetadata>[] topLevelGroup = null;
var menuGroups = new Dictionary<string, IExport<IContextMenuEntry, IContextMenuEntryMetadata>[]>();
IExport<IContextMenuEntry, IContextMenuEntryMetadata>[] topLevelGroup = null;
foreach (var group in entries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.ParentMenuID))
{
if (group.Key == null)
@ -301,10 +303,10 @@ namespace ICSharpCode.ILSpy @@ -301,10 +303,10 @@ namespace ICSharpCode.ILSpy
menuGroups.Add(group.Key, group.ToArray());
}
}
BuildMenu(topLevelGroup ?? Array.Empty<Lazy<IContextMenuEntry, IContextMenuEntryMetadata>>(), menu.Items);
BuildMenu(topLevelGroup ?? Array.Empty<IExport<IContextMenuEntry, IContextMenuEntryMetadata>>(), menu.Items);
return menu.Items.Count > 0;
void BuildMenu(Lazy<IContextMenuEntry, IContextMenuEntryMetadata>[] menuGroup, ItemCollection parent)
void BuildMenu(IExport<IContextMenuEntry, IContextMenuEntryMetadata>[] menuGroup, ItemCollection parent)
{
foreach (var category in menuGroup.GroupBy(c => c.Metadata.Category))
{

44
ILSpy/Controls/BoolToVisibilityConverter.cs

@ -1,44 +0,0 @@ @@ -1,44 +0,0 @@
// Copyright (c) 2018 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace ICSharpCode.ILSpy.Controls
{
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(parameter is Visibility notVisible))
notVisible = Visibility.Collapsed;
if (!(value is bool b))
return notVisible;
return b ? Visibility.Visible : notVisible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is Visibility visibility))
return false;
return visibility == Visibility.Visible;
}
}
}

8
ILSpy/Controls/CultureSelectionConverter.cs

@ -19,10 +19,11 @@ @@ -19,10 +19,11 @@
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
namespace ICSharpCode.ILSpy.Controls
{
public class CultureSelectionConverter : IValueConverter
public class CultureSelectionConverter : MarkupExtension, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
@ -37,5 +38,10 @@ namespace ICSharpCode.ILSpy.Controls @@ -37,5 +38,10 @@ namespace ICSharpCode.ILSpy.Controls
return parameter;
return Binding.DoNothing;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
}

46
ILSpy/Controls/TreeView/Converters.cs

@ -1,46 +0,0 @@ @@ -1,46 +0,0 @@
// Copyright (c) 2020 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace ICSharpCode.ILSpy.Controls.TreeView
{
public class CollapsedWhenFalse : MarkupExtension, IValueConverter
{
public static CollapsedWhenFalse Instance = new CollapsedWhenFalse();
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Instance;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

12
ILSpy/Controls/TreeView/SharpTreeView.cs

@ -54,7 +54,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView @@ -54,7 +54,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView
RegisterCommands();
}
public static ResourceKey DefaultItemContainerStyleKey { get; private set; }
public static ResourceKey DefaultItemContainerStyleKey { get; }
public SharpTreeView()
{
@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView @@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView
}
public static readonly DependencyProperty RootProperty =
DependencyProperty.Register("Root", typeof(SharpTreeNode), typeof(SharpTreeView));
DependencyProperty.Register(nameof(Root), typeof(SharpTreeNode), typeof(SharpTreeView));
public SharpTreeNode Root {
get { return (SharpTreeNode)GetValue(RootProperty); }
@ -70,7 +70,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView @@ -70,7 +70,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView
}
public static readonly DependencyProperty ShowRootProperty =
DependencyProperty.Register("ShowRoot", typeof(bool), typeof(SharpTreeView),
DependencyProperty.Register(nameof(ShowRoot), typeof(bool), typeof(SharpTreeView),
new FrameworkPropertyMetadata(true));
public bool ShowRoot {
@ -79,7 +79,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView @@ -79,7 +79,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView
}
public static readonly DependencyProperty ShowRootExpanderProperty =
DependencyProperty.Register("ShowRootExpander", typeof(bool), typeof(SharpTreeView),
DependencyProperty.Register(nameof(ShowRootExpander), typeof(bool), typeof(SharpTreeView),
new FrameworkPropertyMetadata(false));
public bool ShowRootExpander {
@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView @@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView
}
public static readonly DependencyProperty AllowDropOrderProperty =
DependencyProperty.Register("AllowDropOrder", typeof(bool), typeof(SharpTreeView));
DependencyProperty.Register(nameof(AllowDropOrder), typeof(bool), typeof(SharpTreeView));
public bool AllowDropOrder {
get { return (bool)GetValue(AllowDropOrderProperty); }
@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView @@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView
}
public static readonly DependencyProperty ShowLinesProperty =
DependencyProperty.Register("ShowLines", typeof(bool), typeof(SharpTreeView),
DependencyProperty.Register(nameof(ShowLines), typeof(bool), typeof(SharpTreeView),
new FrameworkPropertyMetadata(true));
public bool ShowLines {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save