Browse Source

Merge pull request #3257 from tom-englert/dev/WpfRefactoring

WPF Refactoring #1: Add abstraction layer for MEF
pull/3266/head
Siegfried Pammer 9 months ago committed by GitHub
parent
commit
58bd49938b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 52
      .editorconfig
  2. 4
      BuildTools/format.bat
  3. 7
      Directory.Packages.props
  4. 3
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.ruleset
  5. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs
  6. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs
  7. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs
  8. 3
      ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs
  9. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs
  10. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs
  11. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs
  12. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs
  13. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs
  14. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs
  15. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs
  16. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs
  17. 7
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs
  18. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs
  19. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs
  20. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs
  21. 2
      ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs
  22. 2
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  23. 1
      ILSpy.ReadyToRun/ReadyToRunLanguage.cs
  24. 2
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
  25. 6
      ILSpy.sln
  26. 2
      ILSpy/AboutPage.cs
  27. 65
      ILSpy/Analyzers/AnalyzeCommand.cs
  28. 42
      ILSpy/Analyzers/AnalyzerRootNode.cs
  29. 24
      ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
  30. 29
      ILSpy/Analyzers/AnalyzerTreeNode.cs
  31. 178
      ILSpy/Analyzers/AnalyzerTreeView.cs
  32. 23
      ILSpy/Analyzers/AnalyzerTreeView.xaml
  33. 42
      ILSpy/Analyzers/AnalyzerTreeView.xaml.cs
  34. 130
      ILSpy/Analyzers/AnalyzerTreeViewModel.cs
  35. 2
      ILSpy/Analyzers/CopyAnalysisResultsContextMenuEntry.cs
  36. 2
      ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs
  37. 19
      ILSpy/App.xaml.cs
  38. 2
      ILSpy/Commands/BrowseBackCommand.cs
  39. 2
      ILSpy/Commands/BrowseForwardCommand.cs
  40. 3
      ILSpy/Commands/CheckForUpdatesCommand.cs
  41. 2
      ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs
  42. 6
      ILSpy/Commands/DecompileAllCommand.cs
  43. 2
      ILSpy/Commands/DecompileCommand.cs
  44. 2
      ILSpy/Commands/DecompileInNewViewCommand.cs
  45. 2
      ILSpy/Commands/DisassembleAllCommand.cs
  46. 3
      ILSpy/Commands/ExitCommand.cs
  47. 10
      ILSpy/Commands/ExportCommandAttribute.cs
  48. 2
      ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs
  49. 3
      ILSpy/Commands/GeneratePdbContextMenuEntry.cs
  50. 3
      ILSpy/Commands/ManageAssemblyListsCommand.cs
  51. 2
      ILSpy/Commands/OpenCommand.cs
  52. 3
      ILSpy/Commands/OpenFromGacCommand.cs
  53. 3
      ILSpy/Commands/Pdb2XmlCommand.cs
  54. 2
      ILSpy/Commands/RefreshCommand.cs
  55. 3
      ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
  56. 6
      ILSpy/Commands/SaveCodeContextMenuEntry.cs
  57. 2
      ILSpy/Commands/SaveCommand.cs
  58. 2
      ILSpy/Commands/ScopeSearchToAssembly.cs
  59. 2
      ILSpy/Commands/ScopeSearchToNamespace.cs
  60. 3
      ILSpy/Commands/SearchMsdnContextMenuEntry.cs
  61. 2
      ILSpy/Commands/SelectPdbContextMenuEntry.cs
  62. 6
      ILSpy/Commands/SetThemeCommand.cs
  63. 2
      ILSpy/Commands/ShowCFGContextMenuEntry.cs
  64. 3
      ILSpy/Commands/SortAssemblyListCommand.cs
  65. 12
      ILSpy/ContextMenuEntry.cs
  66. 44
      ILSpy/Controls/BoolToVisibilityConverter.cs
  67. 12
      ILSpy/Controls/TreeView/SharpTreeView.cs
  68. 3
      ILSpy/Docking/CloseAllDocumentsCommand.cs
  69. 74
      ILSpy/Docking/DockWorkspace.cs
  70. 8
      ILSpy/Docking/PaneCollection.cs
  71. 18
      ILSpy/Docking/TabPageGuardConverter.cs
  72. 85
      ILSpy/ExportProviderAdapter.cs
  73. 6
      ILSpy/ILSpy.csproj
  74. 62
      ILSpy/LanguageSettings.cs
  75. 1
      ILSpy/Languages/CSharpILMixedLanguage.cs
  76. 1
      ILSpy/Languages/CSharpLanguage.cs
  77. 1
      ILSpy/Languages/ILLanguage.cs
  78. 24
      ILSpy/Languages/Languages.cs
  79. 61
      ILSpy/MainWindow.xaml
  80. 151
      ILSpy/MainWindow.xaml.cs
  81. 3
      ILSpy/Metadata/GoToTokenCommand.cs
  82. 1
      ILSpy/Metadata/MetadataProtocolHandler.cs
  83. 2
      ILSpy/Options/DecompilerSettingsPanel.xaml.cs
  84. 9
      ILSpy/Options/DisplaySettingsPanel.xaml.cs
  85. 2
      ILSpy/Options/MiscSettingsPanel.xaml.cs
  86. 11
      ILSpy/Options/OptionsDialog.xaml.cs
  87. 22
      ILSpy/Search/SearchPane.cs
  88. 18
      ILSpy/SessionSettings.cs
  89. 7
      ILSpy/TextView/DecompilerTextView.cs
  90. 4
      ILSpy/TextView/EditorCommands.cs
  91. 3
      ILSpy/TextView/FoldingCommands.cs
  92. 9
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  93. 2
      ILSpy/TreeNodes/DerivedTypesEntryNode.cs
  94. 2
      ILSpy/TreeNodes/EventTreeNode.cs
  95. 2
      ILSpy/TreeNodes/FieldTreeNode.cs
  96. 53
      ILSpy/TreeNodes/ILSpyTreeNode.cs
  97. 2
      ILSpy/TreeNodes/MethodTreeNode.cs
  98. 2
      ILSpy/TreeNodes/NamespaceTreeNode.cs
  99. 2
      ILSpy/TreeNodes/PropertyTreeNode.cs
  100. 2
      ILSpy/TreeNodes/ResourceListTreeNode.cs
  101. Some files were not shown because too many files have changed in this diff Show More

52
.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,53 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false @@ -119,3 +119,53 @@ 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
dotnet_naming_rule.constants_rule.severity = warning
dotnet_naming_rule.constants_rule.style = upper_camel_case_style
dotnet_naming_rule.constants_rule.symbols = constants_symbols
dotnet_naming_rule.private_constants_rule.severity = warning
dotnet_naming_rule.private_constants_rule.style = upper_camel_case_style
dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols
dotnet_naming_rule.private_instance_fields_rule.severity = warning
dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_style
dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols
dotnet_naming_rule.private_static_fields_rule.severity = warning
dotnet_naming_rule.private_static_fields_rule.style = lower_camel_case_style
dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols
dotnet_naming_rule.private_static_readonly_rule.severity = warning
dotnet_naming_rule.private_static_readonly_rule.style = upper_camel_case_style
dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols
dotnet_naming_rule.public_static_fields_rule.severity = warning
dotnet_naming_rule.public_static_fields_rule.style = lower_camel_case_style
dotnet_naming_rule.public_static_fields_rule.symbols = public_static_fields_symbols
dotnet_naming_rule.static_readonly_rule.severity = warning
dotnet_naming_rule.static_readonly_rule.style = upper_camel_case_style
dotnet_naming_rule.static_readonly_rule.symbols = static_readonly_symbols
dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case
dotnet_naming_symbols.constants_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
dotnet_naming_symbols.constants_symbols.applicable_kinds = field
dotnet_naming_symbols.constants_symbols.required_modifiers = const
dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private
dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field
dotnet_naming_symbols.private_constants_symbols.required_modifiers = const
dotnet_naming_symbols.private_instance_fields_symbols.applicable_accessibilities = private
dotnet_naming_symbols.private_instance_fields_symbols.applicable_kinds = field
dotnet_naming_symbols.private_static_fields_symbols.applicable_accessibilities = private
dotnet_naming_symbols.private_static_fields_symbols.applicable_kinds = field
dotnet_naming_symbols.private_static_fields_symbols.required_modifiers = static
dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private
dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field
dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = readonly,static
dotnet_naming_symbols.public_static_fields_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
dotnet_naming_symbols.public_static_fields_symbols.applicable_kinds = field
dotnet_naming_symbols.public_static_fields_symbols.required_modifiers = static
dotnet_naming_symbols.static_readonly_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
dotnet_naming_symbols.static_readonly_symbols.applicable_kinds = field
dotnet_naming_symbols.static_readonly_symbols.required_modifiers = readonly,static
# 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>

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>

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)

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";

1
ILSpy.ReadyToRun/ReadyToRunLanguage.cs

@ -95,6 +95,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -95,6 +95,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>();

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)

19
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();

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()

2
ILSpy/Commands/ScopeSearchToAssembly.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
#nullable enable
using System;
using System.ComponentModel.Composition;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AppEnv;
@ -27,6 +28,7 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -27,6 +28,7 @@ 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
{
public void Execute(TextViewContext context)

2
ILSpy/Commands/ScopeSearchToNamespace.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel.Composition;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AppEnv;
@ -25,6 +26,7 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -25,6 +26,7 @@ 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
{
public void Execute(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}";

2
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)

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;
}
}
}

2
ILSpy/Commands/ShowCFGContextMenuEntry.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows;
using ICSharpCode.Decompiler.FlowAnalysis;
@ -11,6 +12,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -11,6 +12,7 @@ namespace ICSharpCode.ILSpy.Commands
{
#if DEBUG
[ExportContextMenuEntry(Header = "DEBUG -- Show CFG")]
[PartCreationPolicy(CreationPolicy.Shared)]
internal class ShowCFGContextMenuEntry : IContextMenuEntry
{
public void Execute(TextViewContext context)

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;
}
}
}

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 {

3
ILSpy/Docking/CloseAllDocumentsCommand.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -9,6 +10,7 @@ using ICSharpCode.ILSpy.Properties; @@ -9,6 +10,7 @@ using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy.Docking
{
[ExportMainMenuCommand(Header = nameof(Resources.Window_CloseAllDocuments), ParentMenuID = nameof(Resources._Window))]
[PartCreationPolicy(CreationPolicy.Shared)]
class CloseAllDocumentsCommand : SimpleCommand
{
public override void Execute(object parameter)
@ -18,6 +20,7 @@ namespace ICSharpCode.ILSpy.Docking @@ -18,6 +20,7 @@ namespace ICSharpCode.ILSpy.Docking
}
[ExportMainMenuCommand(Header = nameof(Resources.Window_ResetLayout), ParentMenuID = nameof(Resources._Window))]
[PartCreationPolicy(CreationPolicy.Shared)]
class ResetLayoutCommand : SimpleCommand
{
public override void Execute(object parameter)

74
ILSpy/Docking/DockWorkspace.cs

@ -35,27 +35,28 @@ using AvalonDock.Layout; @@ -35,27 +35,28 @@ using AvalonDock.Layout;
using AvalonDock.Layout.Serialization;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels;
using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy.Docking
{
public class DockWorkspace : INotifyPropertyChanged, ILayoutUpdateStrategy
public class DockWorkspace : ObservableObject, ILayoutUpdateStrategy
{
private SessionSettings sessionSettings;
public event PropertyChangedEventHandler PropertyChanged;
private static SessionSettings SessionSettings => SettingsService.Instance.SessionSettings;
public static DockWorkspace Instance { get; private set; }
public static readonly DockWorkspace Instance = new();
internal DockWorkspace(MainWindow parent)
private DockWorkspace()
{
Instance = this;
this.TabPages.CollectionChanged += Documents_CollectionChanged;
parent.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged;
MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => CurrentAssemblyList_Changed(sender, e);
}
private void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e)
private void CurrentAssemblyList_Changed(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems == null)
{
@ -88,6 +89,11 @@ namespace ICSharpCode.ILSpy.Docking @@ -88,6 +89,11 @@ namespace ICSharpCode.ILSpy.Docking
private void Documents_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var collection = (PaneCollection<TabPageModel>)sender;
if (e.Action == NotifyCollectionChangedAction.Add)
{
ActiveTabPage = e.NewItems?[0] as TabPageModel;
}
bool canClose = collection.Count > 1;
foreach (var item in collection)
{
@ -118,31 +124,31 @@ namespace ICSharpCode.ILSpy.Docking @@ -118,31 +124,31 @@ namespace ICSharpCode.ILSpy.Docking
tool.IsVisible = false;
}
private TabPageModel _activeTabPage = null;
private TabPageModel activeTabPage = null;
public TabPageModel ActiveTabPage {
get {
return _activeTabPage;
return activeTabPage;
}
set {
if (_activeTabPage != value)
if (!SetProperty(ref activeTabPage, value))
{
_activeTabPage = value;
var state = value.GetState();
if (state != null)
return;
}
var state = value.GetState();
if (state != null)
{
if (state.DecompiledNodes != null)
{
if (state.DecompiledNodes != null)
{
MainWindow.Instance.SelectNodes(state.DecompiledNodes,
inNewTabPage: false, setFocus: true, changingActiveTab: true);
}
else
{
MainWindow.Instance.NavigateTo(new RequestNavigateEventArgs(state.ViewedUri, null));
}
MainWindow.Instance.SelectNodes(state.DecompiledNodes,
inNewTabPage: false, setFocus: true, changingActiveTab: true);
}
else
{
MainWindow.Instance.NavigateTo(new(state.ViewedUri, null));
}
RaisePropertyChanged(nameof(ActiveTabPage));
}
MessageBus.Send(this, new DockWorkspaceActiveTabPageChangedEventArgs());
}
}
@ -153,7 +159,7 @@ namespace ICSharpCode.ILSpy.Docking @@ -153,7 +159,7 @@ namespace ICSharpCode.ILSpy.Docking
serializer.LayoutSerializationCallback += LayoutSerializationCallback;
try
{
sessionSettings.DockLayout.Deserialize(serializer);
SessionSettings.DockLayout.Deserialize(serializer);
}
finally
{
@ -181,11 +187,6 @@ namespace ICSharpCode.ILSpy.Docking @@ -181,11 +187,6 @@ namespace ICSharpCode.ILSpy.Docking
}
}
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void ShowText(AvalonEditTextOutput textOutput)
{
ActiveTabPage.ShowTextView(textView => textView.ShowText(textOutput));
@ -201,11 +202,6 @@ namespace ICSharpCode.ILSpy.Docking @@ -201,11 +202,6 @@ namespace ICSharpCode.ILSpy.Docking
ActiveTabPage.ShowTextView(textView => textView.ShowNodes(output, nodes, highlighting));
}
internal void LoadSettings(SessionSettings sessionSettings)
{
this.sessionSettings = sessionSettings;
}
internal void CloseAllTabs()
{
foreach (var doc in TabPages.ToArray())
@ -222,7 +218,7 @@ namespace ICSharpCode.ILSpy.Docking @@ -222,7 +218,7 @@ namespace ICSharpCode.ILSpy.Docking
pane.IsVisible = false;
}
CloseAllTabs();
sessionSettings.DockLayout.Reset();
SessionSettings.DockLayout.Reset();
InitializeLayout(MainWindow.Instance.DockManager);
MainWindow.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)MainWindow.Instance.RefreshDecompiledView);
}
@ -243,7 +239,7 @@ namespace ICSharpCode.ILSpy.Docking @@ -243,7 +239,7 @@ namespace ICSharpCode.ILSpy.Docking
previousContainer.Children.Add(anchorableToShow);
return true;
case LegacyToolPaneLocation.Bottom:
previousContainer = GetContainer<AnalyzerPaneModel>();
previousContainer = GetContainer<AnalyzerTreeViewModel>();
previousContainer.Children.Add(anchorableToShow);
return true;
default:

8
ILSpy/Docking/PaneCollection.cs

@ -20,15 +20,13 @@ using System.Collections; @@ -20,15 +20,13 @@ using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Docking
{
public class PaneCollection<T> : INotifyCollectionChanged, ICollection<T>
where T : PaneModel
where T : PaneModel, new()
{
private ObservableCollection<T> observableCollection = new ObservableCollection<T>();
@ -39,8 +37,10 @@ namespace ICSharpCode.ILSpy.Docking @@ -39,8 +37,10 @@ namespace ICSharpCode.ILSpy.Docking
observableCollection.CollectionChanged += (sender, e) => CollectionChanged?.Invoke(this, e);
}
public void Add(T item)
public void Add(T item = null)
{
item ??= new T();
observableCollection.Add(item);
item.IsVisible = true;

18
ILSpy/Docking/ActiveTabPageConverter.cs → ILSpy/Docking/TabPageGuardConverter.cs

@ -21,24 +21,20 @@ using System.Windows.Data; @@ -21,24 +21,20 @@ using System.Windows.Data;
using ICSharpCode.ILSpy.ViewModels;
using TomsToolbox.Wpf.Converters;
namespace ICSharpCode.ILSpy.Docking
{
public class ActiveTabPageConverter : IValueConverter
public class TabPageGuardConverter : ValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
protected override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is TabPageModel)
return value;
return Binding.DoNothing;
return value is TabPageModel ? value : Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
protected override object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is TabPageModel)
return value;
return Binding.DoNothing;
return value is TabPageModel ? value : Binding.DoNothing;
}
}
}

85
ILSpy/ExportProviderAdapter.cs

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.VisualStudio.Composition;
using TomsToolbox.Composition;
using TomsToolbox.Essentials;
namespace ICSharpCode.ILSpy;
#nullable enable
/// <summary>
/// Adapter for Microsoft.VisualStudio.Composition.<see cref="ExportProvider"/> to <see cref="IExportProvider"/>.
/// </summary>
public sealed class ExportProviderAdapter : IExportProvider
{
private static readonly Type DefaultMetadataType = typeof(Dictionary<string, object>);
private readonly ExportProvider _exportProvider;
/// <summary>
/// Initializes a new instance of the <see cref="ExportProviderAdapter"/> class.
/// </summary>
/// <param name="exportProvider">The export provider.</param>
public ExportProviderAdapter(ExportProvider exportProvider)
{
_exportProvider = exportProvider;
}
event EventHandler<EventArgs>? IExportProvider.ExportsChanged { add { } remove { } }
T IExportProvider.GetExportedValue<T>(string? contractName) where T : class
{
return _exportProvider.GetExportedValue<T>(contractName) ?? throw new InvalidOperationException($"No export found for type {typeof(T).FullName} with contract '{contractName}'");
}
T? IExportProvider.GetExportedValueOrDefault<T>(string? contractName) where T : class
{
return _exportProvider.GetExportedValues<T>(contractName).SingleOrDefault();
}
bool IExportProvider.TryGetExportedValue<T>(string? contractName, [NotNullWhen(true)] out T? value) where T : class
{
value = _exportProvider.GetExportedValues<T>(contractName).SingleOrDefault();
return !Equals(value, default(T));
}
IEnumerable<T> IExportProvider.GetExportedValues<T>(string? contractName) where T : class
{
return _exportProvider.GetExportedValues<T>(contractName);
}
IEnumerable<object> IExportProvider.GetExportedValues(Type contractType, string? contractName)
{
return _exportProvider
.GetExports(contractType, DefaultMetadataType, contractName)
.Select(item => item.Value)
.ExceptNullItems();
}
IEnumerable<IExport<object>> IExportProvider.GetExports(Type contractType, string? contractName)
{
return _exportProvider
.GetExports(contractType, DefaultMetadataType, contractName)
.Select(item => new ExportAdapter<object>(() => item.Value, new MetadataAdapter((IDictionary<string, object?>)item.Metadata)));
}
IEnumerable<IExport<T>> IExportProvider.GetExports<T>(string? contractName) where T : class
{
return _exportProvider
.GetExports(typeof(T), DefaultMetadataType, contractName)
.Select(item => new ExportAdapter<T>(() => (T?)item.Value, new MetadataAdapter((IDictionary<string, object?>)item.Metadata)));
}
IEnumerable<IExport<T, TMetadataView>> IExportProvider.GetExports<T, TMetadataView>(string? contractName) where T : class where TMetadataView : class
{
return _exportProvider
.GetExports<T, TMetadataView>(contractName)
.Select(item => new ExportAdapter<T, TMetadataView>(() => item.Value, item.Metadata));
}
}

6
ILSpy/ILSpy.csproj

@ -50,6 +50,8 @@ @@ -50,6 +50,8 @@
<PackageReference Include="DataGridExtensions" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" />
<PackageReference Include="NaturalSort.Extension" />
<PackageReference Include="TomsToolbox.Wpf.Composition" />
<PackageReference Include="TomsToolbox.Wpf.Composition.Mef" />
<PackageReference Include="TomsToolbox.Wpf.Styles" />
</ItemGroup>
@ -90,8 +92,8 @@ @@ -90,8 +92,8 @@
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<PackageReference Include="Microsoft.DiaSymReader.Converter.Xml" />
<PackageReference Include="Microsoft.DiaSymReader" />
<PackageReference Include="Microsoft.DiaSymReader.Native" />
<PackageReference Include="Microsoft.DiaSymReader" />
<PackageReference Include="Microsoft.DiaSymReader.Native" />
</ItemGroup>
<PropertyGroup>

62
ILSpy/FilterSettings.cs → ILSpy/LanguageSettings.cs

@ -23,6 +23,7 @@ using System.Linq; @@ -23,6 +23,7 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
namespace ICSharpCode.ILSpy
@ -30,12 +31,7 @@ namespace ICSharpCode.ILSpy @@ -30,12 +31,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Represents the filters applied to the tree view.
/// </summary>
/// <remarks>
/// This class is mutable; but the ILSpyTreeNode filtering assumes that filter settings are immutable.
/// Thus, the main window will use one mutable instance (for data-binding), and will assign a new
/// clone to the ILSpyTreeNodes whenever the main mutable instance changes.
/// </remarks>
public class FilterSettings : INotifyPropertyChanged
public class LanguageSettings : INotifyPropertyChanged
{
/// <summary>
/// This dictionary is necessary to remember language versions across language changes. For example,
@ -44,13 +40,12 @@ namespace ICSharpCode.ILSpy @@ -44,13 +40,12 @@ namespace ICSharpCode.ILSpy
/// </summary>
private readonly Dictionary<Language, LanguageVersion> languageVersionHistory = new Dictionary<Language, LanguageVersion>();
public FilterSettings(XElement element)
public LanguageSettings(XElement element)
{
this.ShowApiLevel = (ApiVisibility?)(int?)element.Element("ShowAPILevel") ?? ApiVisibility.PublicAndInternal;
this.Language = Languages.GetLanguage((string)element.Element("Language"));
this.LanguageVersion = Language.LanguageVersions.FirstOrDefault(v => v.Version == (string)element.Element("LanguageVersion"));
if (this.LanguageVersion == default(LanguageVersion))
this.LanguageVersion = language.LanguageVersions.LastOrDefault();
this.Language = Languages.GetLanguage((string)element.Element("Language")) ?? Languages.AllLanguages.First();
this.LanguageVersion = Language.LanguageVersions.FirstOrDefault(v => v.Version == (string)element.Element("LanguageVersion"))
?? Language.LanguageVersions.LastOrDefault();
}
public XElement SaveAsXml()
@ -63,33 +58,6 @@ namespace ICSharpCode.ILSpy @@ -63,33 +58,6 @@ namespace ICSharpCode.ILSpy
);
}
string searchTerm;
/// <summary>
/// Gets/Sets the search term.
/// Only tree nodes containing the search term will be shown.
/// </summary>
public string SearchTerm {
get { return searchTerm; }
set {
if (searchTerm != value)
{
searchTerm = value;
OnPropertyChanged(nameof(SearchTerm));
}
}
}
/// <summary>
/// Gets whether a node with the specified text is matched by the current search term.
/// </summary>
public virtual bool SearchTermMatches(string text)
{
if (string.IsNullOrEmpty(searchTerm))
return true;
return text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0;
}
ApiVisibility showApiLevel;
/// <summary>
@ -211,15 +179,23 @@ namespace ICSharpCode.ILSpy @@ -211,15 +179,23 @@ namespace ICSharpCode.ILSpy
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
var args = new PropertyChangedEventArgs(propertyName);
PropertyChanged(this, args);
MessageBus.Send(this, new LanguageSettingsChangedEventArgs(args));
}
}
public FilterSettings Clone()
// This class has been initially called FilterSettings, but then has been Hijacked to store language settings as well.
// While the filter settings were some sort of local, the language settings are global. This is a bit of a mess.
// There has been a lot of workarounds cloning the FilterSettings to pass them down to the tree nodes, without messing up the global language settings.
// Finally, this filtering was not used at all, so this SearchTerm is just a placeholder to make the filtering code compile, in case someone wants to reactivate filtering in the future.
public string SearchTerm => string.Empty;
public bool SearchTermMatches(string value)
{
FilterSettings f = (FilterSettings)MemberwiseClone();
f.PropertyChanged = null;
return f;
return true;
}
}
}

1
ILSpy/Languages/CSharpILMixedLanguage.cs

@ -42,6 +42,7 @@ namespace ICSharpCode.ILSpy @@ -42,6 +42,7 @@ namespace ICSharpCode.ILSpy
using SequencePoint = ICSharpCode.Decompiler.DebugInfo.SequencePoint;
[Export(typeof(Language))]
[PartCreationPolicy(CreationPolicy.Shared)]
class CSharpILMixedLanguage : ILLanguage
{
public override string Name => "IL with C#";

1
ILSpy/Languages/CSharpLanguage.cs

@ -53,6 +53,7 @@ namespace ICSharpCode.ILSpy @@ -53,6 +53,7 @@ namespace ICSharpCode.ILSpy
/// please directly use the CSharpDecompiler class.
/// </summary>
[Export(typeof(Language))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class CSharpLanguage : Language
{
string name = "C#";

1
ILSpy/Languages/ILLanguage.cs

@ -42,6 +42,7 @@ namespace ICSharpCode.ILSpy @@ -42,6 +42,7 @@ namespace ICSharpCode.ILSpy
/// flat IL (detectControlStructure=false) and structured IL (detectControlStructure=true).
/// </remarks>
[Export(typeof(Language))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ILLanguage : Language
{
protected bool detectControlStructure = true;

24
ILSpy/Languages/Languages.cs

@ -16,39 +16,31 @@ @@ -16,39 +16,31 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.VisualStudio.Composition;
using TomsToolbox.Composition;
namespace ICSharpCode.ILSpy
{
public static class Languages
{
// Start with a dummy list with an IL entry so that crashes
// in Initialize() (e.g. due to invalid plugins) don't lead to
// confusing follow-up errors in GetLanguage().
private static ReadOnlyCollection<Language> allLanguages = new ReadOnlyCollection<Language>(
new Language[] { new ILLanguage() });
/// <summary>
/// A list of all languages.
/// </summary>
public static ReadOnlyCollection<Language> AllLanguages {
get { return allLanguages; }
}
public static ReadOnlyCollection<Language> AllLanguages { get; } = Initialize(App.ExportProvider);
internal static void Initialize(ExportProvider ep)
static ReadOnlyCollection<Language> Initialize(IExportProvider ep)
{
List<Language> languages = new List<Language>();
languages.AddRange(ep.GetExportedValues<Language>());
languages.Sort((a, b) => a.Name.CompareTo(b.Name));
var languages = ep.GetExportedValues<Language>().ToList();
languages.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
#if DEBUG
languages.AddRange(ILAstLanguage.GetDebugLanguages());
languages.AddRange(CSharpLanguage.GetDebugLanguages());
#endif
allLanguages = languages.AsReadOnly();
return languages.AsReadOnly();
}
/// <summary>

61
ILSpy/MainWindow.xaml

@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
<Window
x:Class="ICSharpCode.ILSpy.MainWindow"
x:ClassModifier="public"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tv="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView"
xmlns:local="clr-namespace:ICSharpCode.ILSpy"
xmlns:search="clr-namespace:ICSharpCode.ILSpy.Search"
@ -19,16 +19,13 @@ @@ -19,16 +19,13 @@
TextOptions.TextFormattingMode="Display"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="500" d:DesignWidth="500"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:styles="urn:TomsToolbox.Wpf.Styles"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
xmlns:toms="urn:TomsToolbox"
xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}"
>
<Window.Resources>
<controls:BoolToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<docking:ActiveTabPageConverter x:Key="ActiveTabPageConverter"/>
<tv:SharpTreeView x:Key="AssemblyTreeView"
AutomationProperties.Name="Assemblies and Classes"
SelectionChanged="TreeView_SelectionChanged"
@ -38,7 +35,6 @@ @@ -38,7 +35,6 @@
BorderThickness="0" Visibility="Visible">
<tv:SharpTreeView.ItemContainerStyle>
<Style TargetType="tv:SharpTreeViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type tv:SharpTreeViewItem}">
@ -69,35 +65,22 @@ @@ -69,35 +65,22 @@
</tv:SharpTreeView.ItemContainerStyle>
</tv:SharpTreeView>
<DataTemplate x:Key="AssemblyListPaneTemplate">
<DataTemplate DataType="{x:Type viewModels:AssemblyListPaneModel}">
<ContentControl Content="{StaticResource AssemblyTreeView}" />
</DataTemplate>
<local:DebugSteps x:Key="DebugSteps" />
<DataTemplate x:Key="DebugStepsPaneTemplate">
<ContentControl Content="{StaticResource DebugSteps}" />
</DataTemplate>
<search:SearchPane x:Key="SearchPane" />
<DataTemplate x:Key="SearchPaneTemplate">
<ContentControl Content="{StaticResource SearchPane}" />
</DataTemplate>
<analyzers:AnalyzerTreeView x:Key="AnalyzerTreeView" />
<DataTemplate x:Key="AnalyzerPaneTemplate">
<ContentControl Content="{StaticResource AnalyzerTreeView}" />
<DataTemplate DataType="{x:Type viewModels:TabPageModel}">
<ContentPresenter Content="{Binding Content}" />
</DataTemplate>
<DataTemplate x:Key="DefaultContentTemplate">
<DataTemplate DataType="{x:Type viewModels:LegacyToolPaneModel}">
<ContentPresenter Content="{Binding Content}" />
</DataTemplate>
<controls:CultureSelectionConverter x:Key="cultureSelectionConverter" />
</Window.Resources>
<b:Interaction.Behaviors>
<themes:WindowStyleManagerBehavior />
</b:Interaction.Behaviors>
@ -125,21 +108,24 @@ @@ -125,21 +108,24 @@
Command="Search"
Executed="SearchCommandExecuted" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Key="R" Modifiers="Control" Command="{x:Static local:ILSpyCommands.Analyze}" />
</Window.InputBindings>
<Window.TaskbarItemInfo>
<TaskbarItemInfo />
</Window.TaskbarItemInfo>
<DockPanel>
<!-- Main menu -->
<Menu DockPanel.Dock="Top" Name="mainMenu" Height="23" KeyboardNavigation.TabNavigation="None">
<MenuItem Header="{x:Static properties:Resources._File}" Tag="_File" />
<!-- contents of file menu are added using MEF -->
<MenuItem Header="{x:Static properties:Resources._View}" Tag="_View">
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisPublicOnly}" />
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisPublicAndInternal}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True" IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisAll}" />
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" />
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" />
<Separator/>
<MenuItem Header="{x:Static properties:Resources.Theme}" ItemsSource="{x:Static themes:ThemeManager.AllThemes}">
<MenuItem.ItemContainerStyle>
@ -203,26 +189,27 @@ @@ -203,26 +189,27 @@
<Image Width="16" Height="16" Source="{controls:XamlResource Images/AssemblyList}" Style="{StaticResource DarkModeAwareImageStyle}"/>
</Button>
<Separator />
<CheckBox IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisPublicOnly}" ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPublicOnly}" Style="{StaticResource DarkModeAwareImageStyle}"/>
</CheckBox>
<CheckBox IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisPublicAndInternal}" ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPrivateInternal}" Style="{StaticResource DarkModeAwareImageStyle}"/>
</CheckBox>
<CheckBox IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisAll}" ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowAll}" Style="{StaticResource DarkModeAwareImageStyle}"/>
</CheckBox>
<Separator />
<ComboBox Name="languageComboBox" DisplayMemberPath="Name" Width="100" MaxDropDownHeight="Auto"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{x:Static local:Languages.AllLanguages}" ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}"
SelectedItem="{Binding Workspace.ActiveTabPage.FilterSettings.Language}"/>
SelectedItem="{Binding SessionSettings.LanguageSettings.Language}"/>
<ComboBox Name="languageVersionComboBox" DisplayMemberPath="DisplayName" Width="120" MaxDropDownHeight="Auto" ToolTip="{x:Static properties:Resources.SelectVersionDropdownTooltip}"
Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={StaticResource BooleanToVisibilityConverter}}"
Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={toms:BooleanToVisibilityConverter}}"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Workspace.ActiveTabPage.FilterSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/>
SelectedItem="{Binding SessionSettings.LanguageSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/>
</ToolBar>
<!-- Update panel -->
<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1" Name="updatePanel" Visibility="Collapsed">
<DockPanel KeyboardNavigation.TabNavigation="Contained">
<Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button>
@ -247,7 +234,7 @@ @@ -247,7 +234,7 @@
DataContext="{Binding Workspace}"
AnchorablesSource="{Binding ToolPanes}"
DocumentsSource="{Binding TabPages}"
ActiveContent="{Binding ActiveTabPage, Mode=TwoWay, Converter={StaticResource ActiveTabPageConverter}}"
ActiveContent="{Binding ActiveTabPage, Mode=TwoWay, Converter={docking:TabPageGuardConverter}}"
AllowMixedOrientation="True">
<avalondock:DockingManager.DocumentHeaderTemplate>
@ -266,7 +253,7 @@ @@ -266,7 +253,7 @@
<docking:PaneStyleSelector.ToolPaneStyle>
<Style TargetType="{x:Type avalondock:LayoutAnchorableItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
<Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter={x:Static Visibility.Hidden}}"/>
<Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={toms:BooleanToVisibilityConverter VisibilityWhenBooleanIsFalse=Hidden}}"/>
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
<Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/>
<Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/>
@ -279,7 +266,7 @@ @@ -279,7 +266,7 @@
<docking:PaneStyleSelector.TabPageStyle>
<Style TargetType="{x:Type avalondock:LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
<Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter={x:Static Visibility.Hidden}}"/>
<Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={toms:BooleanToVisibilityConverter VisibilityWhenBooleanIsFalse=Hidden}}"/>
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
<Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/>
<Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/>

151
ILSpy/MainWindow.xaml.cs

@ -31,7 +31,6 @@ using System.Windows; @@ -31,7 +31,6 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Windows.Threading;
@ -43,7 +42,6 @@ using ICSharpCode.Decompiler.Documentation; @@ -43,7 +42,6 @@ using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Commands;
using ICSharpCode.ILSpy.Docking;
@ -58,10 +56,14 @@ using ICSharpCode.ILSpyX; @@ -58,10 +56,14 @@ using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.FileLoaders;
using ICSharpCode.ILSpyX.Settings;
using ICSharpCode.ILSpy.Controls.TreeView;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.Extensions;
using Microsoft.Win32;
using ICSharpCode.ILSpyX.TreeView;
using TomsToolbox.Composition;
namespace ICSharpCode.ILSpy
{
/// <summary>
@ -71,9 +73,7 @@ namespace ICSharpCode.ILSpy @@ -71,9 +73,7 @@ namespace ICSharpCode.ILSpy
{
bool refreshInProgress, changingActiveTab;
readonly NavigationHistory<NavigationState> history = new NavigationHistory<NavigationState>();
ILSpySettings spySettingsForMainWindow_Loaded;
SessionSettings sessionSettings;
FilterSettings filterSettings;
AssemblyList assemblyList;
AssemblyListTreeNode assemblyListTreeNode;
@ -83,10 +83,6 @@ namespace ICSharpCode.ILSpy @@ -83,10 +83,6 @@ namespace ICSharpCode.ILSpy
get { return instance; }
}
public SessionSettings SessionSettings {
get { return sessionSettings; }
}
internal AssemblyListManager AssemblyListManager { get; }
public SharpTreeView AssemblyTreeView {
@ -95,15 +91,9 @@ namespace ICSharpCode.ILSpy @@ -95,15 +91,9 @@ namespace ICSharpCode.ILSpy
}
}
public AnalyzerTreeView AnalyzerTreeView {
get {
return !IsLoaded ? null : FindResource("AnalyzerTreeView") as AnalyzerTreeView;
}
}
public SearchPane SearchPane {
get {
return FindResource("SearchPane") as SearchPane;
return App.ExportProvider.GetExportedValue<SearchPane>();
}
}
@ -120,9 +110,10 @@ namespace ICSharpCode.ILSpy @@ -120,9 +110,10 @@ namespace ICSharpCode.ILSpy
public MainWindow()
{
instance = this;
var spySettings = ILSpySettings.Load();
this.spySettingsForMainWindow_Loaded = spySettings;
this.sessionSettings = new SessionSettings(spySettings);
var spySettings = SettingsService.Instance.SpySettings;
var sessionSettings = SettingsService.Instance.SessionSettings;
this.CurrentDecompilerSettings = DecompilerSettingsPanel.LoadDecompilerSettings(spySettings);
this.CurrentDisplaySettings = DisplaySettingsPanel.LoadDisplaySettings(spySettings);
this.AssemblyListManager = new AssemblyListManager(spySettings) {
@ -134,7 +125,7 @@ namespace ICSharpCode.ILSpy @@ -134,7 +125,7 @@ namespace ICSharpCode.ILSpy
this.Icon = Images.ILSpyIcon;
this.DataContext = new MainWindowViewModel {
Workspace = new DockWorkspace(this),
Workspace = DockWorkspace.Instance,
SessionSettings = sessionSettings,
AssemblyListManager = AssemblyListManager
};
@ -144,14 +135,14 @@ namespace ICSharpCode.ILSpy @@ -144,14 +135,14 @@ namespace ICSharpCode.ILSpy
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(sessionSettings.CurrentCulture);
}
DockWorkspace.Instance.LoadSettings(sessionSettings);
InitializeComponent();
InitToolPanes();
DockWorkspace.Instance.InitializeLayout(DockManager);
sessionSettings.PropertyChanged += SessionSettings_PropertyChanged;
filterSettings = sessionSettings.FilterSettings;
filterSettings.PropertyChanged += filterSettings_PropertyChanged;
DockWorkspace.Instance.PropertyChanged += DockWorkspace_PropertyChanged;
MessageBus<SessionSettingsChangedEventArgs>.Subscribers += (sender, e) => SessionSettings_PropertyChanged(sender, e);
MessageBus<LanguageSettingsChangedEventArgs>.Subscribers += (sender, e) => filterSettings_PropertyChanged(sender, e);
MessageBus<DockWorkspaceActiveTabPageChangedEventArgs>.Subscribers += DockWorkspace_ActiveTabPageChanged;
InitMainMenu();
InitWindowMenu();
InitToolbar();
@ -161,30 +152,24 @@ namespace ICSharpCode.ILSpy @@ -161,30 +152,24 @@ namespace ICSharpCode.ILSpy
this.Loaded += MainWindow_Loaded;
}
private void DockWorkspace_PropertyChanged(object sender, PropertyChangedEventArgs e)
private void DockWorkspace_ActiveTabPageChanged(object sender, EventArgs e)
{
switch (e.PropertyName)
{
case nameof(DockWorkspace.Instance.ActiveTabPage):
DockWorkspace dock = DockWorkspace.Instance;
filterSettings.PropertyChanged -= filterSettings_PropertyChanged;
filterSettings = dock.ActiveTabPage.FilterSettings;
filterSettings.PropertyChanged += filterSettings_PropertyChanged;
DockWorkspace dock = DockWorkspace.Instance;
var windowMenuItem = mainMenu.Items.OfType<MenuItem>().First(m => (string)m.Tag == nameof(Properties.Resources._Window));
foreach (MenuItem menuItem in windowMenuItem.Items.OfType<MenuItem>())
{
if (menuItem.IsCheckable && menuItem.Tag is TabPageModel)
{
menuItem.IsChecked = menuItem.Tag == dock.ActiveTabPage;
}
}
break;
var windowMenuItem = mainMenu.Items.OfType<MenuItem>().First(m => (string)m.Tag == nameof(Properties.Resources._Window));
foreach (MenuItem menuItem in windowMenuItem.Items.OfType<MenuItem>())
{
if (menuItem.IsCheckable && menuItem.Tag is TabPageModel)
{
menuItem.IsChecked = menuItem.Tag == dock.ActiveTabPage;
}
}
}
private void SessionSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
var sessionSettings = SettingsService.Instance.SessionSettings;
switch (e.PropertyName)
{
case nameof(SessionSettings.ActiveAssemblyList):
@ -245,7 +230,7 @@ namespace ICSharpCode.ILSpy @@ -245,7 +230,7 @@ namespace ICSharpCode.ILSpy
}
Button MakeToolbarItem(Lazy<ICommand, IToolbarCommandMetadata> command)
Button MakeToolbarItem(IExport<ICommand, IToolbarCommandMetadata> command)
{
return new Button {
Style = ThemeManager.Current.CreateToolBarButtonStyle(),
@ -363,25 +348,12 @@ namespace ICSharpCode.ILSpy @@ -363,25 +348,12 @@ namespace ICSharpCode.ILSpy
#endregion
#region Tool Pane extensibility
private void InitToolPanes()
{
var toolPanes = App.ExportProvider.GetExports<ToolPaneModel, IToolPaneMetadata>("ToolPane");
var templateSelector = new PaneTemplateSelector();
templateSelector.Mappings.Add(new TemplateMapping {
Type = typeof(TabPageModel),
Template = (DataTemplate)FindResource("DefaultContentTemplate")
});
templateSelector.Mappings.Add(new TemplateMapping {
Type = typeof(LegacyToolPaneModel),
Template = (DataTemplate)FindResource("DefaultContentTemplate")
});
foreach (var toolPane in toolPanes)
{
ToolPaneModel model = toolPane.Value;
templateSelector.Mappings.Add(new TemplateMapping { Type = model.GetType(), Template = model.Template });
DockWorkspace.Instance.ToolPanes.Add(model);
}
DockManager.LayoutItemTemplateSelector = templateSelector;
var toolPanes = App.ExportProvider.GetExportedValues<ToolPaneModel>("ToolPane").OrderBy(item => item.Title);
DockWorkspace.Instance.ToolPanes.AddRange(toolPanes);
}
private void InitWindowMenu()
@ -602,6 +574,8 @@ namespace ICSharpCode.ILSpy @@ -602,6 +574,8 @@ namespace ICSharpCode.ILSpy
base.OnSourceInitialized(e);
PresentationSource source = PresentationSource.FromVisual(this);
var sessionSettings = SettingsService.Instance.SessionSettings;
// Validate and Set Window Bounds
Rect bounds = Rect.Transform(sessionSettings.WindowBounds, source.CompositionTarget.TransformToDevice);
var boundsRect = new System.Drawing.Rectangle((int)bounds.Left, (int)bounds.Top, (int)bounds.Width, (int)bounds.Height);
@ -649,8 +623,6 @@ namespace ICSharpCode.ILSpy @@ -649,8 +623,6 @@ namespace ICSharpCode.ILSpy
get { return assemblyList; }
}
public event NotifyCollectionChangedEventHandler CurrentAssemblyListChanged;
List<LoadedAssembly> commandLineLoadedAssemblies = new List<LoadedAssembly>();
internal async Task HandleSingleInstanceCommandLineArguments(string[] args)
@ -672,7 +644,7 @@ namespace ICSharpCode.ILSpy @@ -672,7 +644,7 @@ namespace ICSharpCode.ILSpy
{
LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, focusNode: false);
if (args.Language != null)
filterSettings.Language = Languages.GetLanguage(args.Language);
SettingsService.Instance.SessionSettings.LanguageSettings.Language = Languages.GetLanguage(args.Language);
return true;
}
@ -682,6 +654,8 @@ namespace ICSharpCode.ILSpy @@ -682,6 +654,8 @@ namespace ICSharpCode.ILSpy
/// </summary>
void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, ILSpySettings spySettings = null)
{
var sessionSettings = SettingsService.Instance.SessionSettings;
var relevantAssemblies = commandLineLoadedAssemblies.ToList();
commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore
NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies);
@ -856,15 +830,12 @@ namespace ICSharpCode.ILSpy @@ -856,15 +830,12 @@ namespace ICSharpCode.ILSpy
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
DockWorkspace.Instance.TabPages.Add(new TabPageModel() {
FilterSettings = filterSettings.Clone()
});
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.First();
DockWorkspace.Instance.TabPages.Add();
ILSpySettings spySettings = this.spySettingsForMainWindow_Loaded;
this.spySettingsForMainWindow_Loaded = null;
var loadPreviousAssemblies = Options.MiscSettingsPanel.CurrentMiscSettings.LoadPreviousAssemblies;
var sessionSettings = SettingsService.Instance.SessionSettings;
if (loadPreviousAssemblies)
{
// Load AssemblyList only in Loaded event so that WPF is initialized before we start the CPU-heavy stuff.
@ -894,7 +865,7 @@ namespace ICSharpCode.ILSpy @@ -894,7 +865,7 @@ namespace ICSharpCode.ILSpy
this.assemblyList.Open(sessionSettings.ActiveAutoLoadedAssembly, true);
}
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => OpenAssemblies(spySettings)));
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => OpenAssemblies(SettingsService.Instance.SpySettings)));
}
void OpenAssemblies(ILSpySettings spySettings)
@ -1024,7 +995,6 @@ namespace ICSharpCode.ILSpy @@ -1024,7 +995,6 @@ namespace ICSharpCode.ILSpy
assemblyList.CollectionChanged += assemblyList_Assemblies_CollectionChanged;
assemblyListTreeNode = new AssemblyListTreeNode(assemblyList);
assemblyListTreeNode.FilterSettings = filterSettings.Clone();
assemblyListTreeNode.Select = x => SelectNode(x, inNewTabPage: false);
AssemblyTreeView.Root = assemblyListTreeNode;
@ -1055,7 +1025,8 @@ namespace ICSharpCode.ILSpy @@ -1055,7 +1025,8 @@ namespace ICSharpCode.ILSpy
nd => nd.AncestorsAndSelf().OfType<AssemblyTreeNode>().Any(
a => oldAssemblies.Contains(a.LoadedAssembly))));
}
CurrentAssemblyListChanged?.Invoke(this, e);
MessageBus.Send(this, new CurrentAssemblyListChangedEventArgs(e));
}
void LoadInitialAssemblies()
@ -1087,13 +1058,7 @@ namespace ICSharpCode.ILSpy @@ -1087,13 +1058,7 @@ namespace ICSharpCode.ILSpy
public void RefreshTreeViewFilter()
{
// filterSettings is mutable; but the ILSpyTreeNode filtering assumes that filter settings are immutable.
// Thus, the main window will use one mutable instance (for data-binding), and assign a new clone to the ILSpyTreeNodes whenever the main
// mutable instance changes.
FilterSettings filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings.Clone();
if (assemblyListTreeNode != null)
assemblyListTreeNode.FilterSettings = filterSettings;
SearchPane.UpdateFilter(filterSettings);
SearchPane.UpdateFilter();
}
internal AssemblyListTreeNode AssemblyListTreeNode {
@ -1120,11 +1085,7 @@ namespace ICSharpCode.ILSpy @@ -1120,11 +1085,7 @@ namespace ICSharpCode.ILSpy
{
if (inNewTabPage)
{
DockWorkspace.Instance.TabPages.Add(
new TabPageModel() {
FilterSettings = filterSettings.Clone()
});
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
DockWorkspace.Instance.TabPages.Add();
AssemblyTreeView.SelectedItem = null;
}
@ -1166,11 +1127,7 @@ namespace ICSharpCode.ILSpy @@ -1166,11 +1127,7 @@ namespace ICSharpCode.ILSpy
{
if (inNewTabPage)
{
DockWorkspace.Instance.TabPages.Add(
new TabPageModel() {
FilterSettings = filterSettings.Clone()
});
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
DockWorkspace.Instance.TabPages.Add();
}
// Ensure nodes exist
@ -1542,10 +1499,9 @@ namespace ICSharpCode.ILSpy @@ -1542,10 +1499,9 @@ namespace ICSharpCode.ILSpy
}
}
public Language CurrentLanguage => DockWorkspace.Instance.ActiveTabPage.FilterSettings.Language;
public LanguageVersion CurrentLanguageVersion => DockWorkspace.Instance.ActiveTabPage.FilterSettings.LanguageVersion;
public Language CurrentLanguage => SettingsService.Instance.SessionSettings.LanguageSettings.Language;
public bool SupportsLanguageSwitching => DockWorkspace.Instance.ActiveTabPage.SupportsLanguageSwitching;
public LanguageVersion CurrentLanguageVersion => SettingsService.Instance.SessionSettings.LanguageSettings.LanguageVersion;
public event SelectionChangedEventHandler SelectionChanged;
@ -1615,11 +1571,7 @@ namespace ICSharpCode.ILSpy @@ -1615,11 +1571,7 @@ namespace ICSharpCode.ILSpy
{
if (inNewTabPage)
{
DockWorkspace.Instance.TabPages.Add(
new TabPageModel() {
FilterSettings = filterSettings.Clone()
});
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
DockWorkspace.Instance.TabPages.Add();
}
if (e.Uri.Host == "aboutpage")
@ -1671,18 +1623,19 @@ namespace ICSharpCode.ILSpy @@ -1671,18 +1623,19 @@ namespace ICSharpCode.ILSpy
base.OnStateChanged(e);
// store window state in settings only if it's not minimized
if (this.WindowState != System.Windows.WindowState.Minimized)
sessionSettings.WindowState = this.WindowState;
SettingsService.Instance.SessionSettings.WindowState = this.WindowState;
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
var sessionSettings = SettingsService.Instance.SessionSettings;
sessionSettings.ActiveAssemblyList = assemblyList.ListName;
sessionSettings.ActiveTreeViewPath = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
sessionSettings.WindowBounds = this.RestoreBounds;
sessionSettings.DockLayout.Serialize(new XmlLayoutSerializer(DockManager));
sessionSettings.FilterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings.Clone();
sessionSettings.Save();
}

3
ILSpy/Metadata/GoToTokenCommand.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
@ -31,6 +32,7 @@ using ICSharpCode.ILSpy.Properties; @@ -31,6 +32,7 @@ using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy.Commands
{
[ExportContextMenuEntry(Header = nameof(Resources.GoToToken), Order = 10)]
[PartCreationPolicy(CreationPolicy.Shared)]
class GoToTokenCommand : IContextMenuEntry
{
public void Execute(TextViewContext context)
@ -68,6 +70,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -68,6 +70,7 @@ namespace ICSharpCode.ILSpy.Commands
}
[ExportContextMenuEntry(Header = nameof(Resources.Copy), Order = 10)]
[PartCreationPolicy(CreationPolicy.Shared)]
class CopyCommand : IContextMenuEntry
{
public void Execute(TextViewContext context)

1
ILSpy/Metadata/MetadataProtocolHandler.cs

@ -26,6 +26,7 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -26,6 +26,7 @@ using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Metadata
{
[Export(typeof(IProtocolHandler))]
[PartCreationPolicy(CreationPolicy.Shared)]
class MetadataProtocolHandler : IProtocolHandler
{
public ILSpyTreeNode Resolve(string protocol, MetadataFile module, Handle handle, out bool newTabPage)

2
ILSpy/Options/DecompilerSettingsPanel.xaml.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.Xml.Linq;
using ICSharpCode.ILSpyX.Settings;
@ -26,6 +27,7 @@ namespace ICSharpCode.ILSpy.Options @@ -26,6 +27,7 @@ namespace ICSharpCode.ILSpy.Options
/// Interaction logic for DecompilerSettingsPanel.xaml
/// </summary>
[ExportOptionPage(Title = nameof(Properties.Resources.Decompiler), Order = 10)]
[PartCreationPolicy(CreationPolicy.NonShared)]
internal partial class DecompilerSettingsPanel : IOptionPage
{
public DecompilerSettingsPanel()

9
ILSpy/Options/DisplaySettingsPanel.xaml.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
@ -26,6 +27,7 @@ using System.Windows.Media; @@ -26,6 +27,7 @@ using System.Windows.Media;
using System.Windows.Threading;
using System.Xml.Linq;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.Options
@ -34,6 +36,7 @@ namespace ICSharpCode.ILSpy.Options @@ -34,6 +36,7 @@ namespace ICSharpCode.ILSpy.Options
/// Interaction logic for DisplaySettingsPanel.xaml
/// </summary>
[ExportOptionPage(Title = nameof(Properties.Resources.Display), Order = 20)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class DisplaySettingsPanel : UserControl, IOptionPage
{
public DisplaySettingsPanel()
@ -121,7 +124,7 @@ namespace ICSharpCode.ILSpy.Options @@ -121,7 +124,7 @@ namespace ICSharpCode.ILSpy.Options
s.ShowRawOffsetsAndBytesBeforeInstruction = (bool?)e.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false;
s.StyleWindowTitleBar = (bool?)e.Attribute("StyleWindowTitleBar") ?? false;
s.Theme = MainWindow.Instance.SessionSettings.Theme;
s.Theme = SettingsService.Instance.SessionSettings.Theme;
return s;
}
@ -152,8 +155,8 @@ namespace ICSharpCode.ILSpy.Options @@ -152,8 +155,8 @@ namespace ICSharpCode.ILSpy.Options
section.SetAttributeValue("ShowRawOffsetsAndBytesBeforeInstruction", s.ShowRawOffsetsAndBytesBeforeInstruction);
section.SetAttributeValue("StyleWindowTitleBar", s.StyleWindowTitleBar);
MainWindow.Instance.SessionSettings.Theme = s.Theme;
var sessionSettings = MainWindow.Instance.SessionSettings.ToXml();
SettingsService.Instance.SessionSettings.Theme = s.Theme;
var sessionSettings = SettingsService.Instance.SessionSettings.ToXml();
MainWindow.Instance.CurrentDisplaySettings.CopyValues(s);

2
ILSpy/Options/MiscSettingsPanel.xaml.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.Controls;
using System.Xml.Linq;
@ -27,6 +28,7 @@ namespace ICSharpCode.ILSpy.Options @@ -27,6 +28,7 @@ namespace ICSharpCode.ILSpy.Options
/// Interaction logic for MiscSettingsPanel.xaml
/// </summary>
[ExportOptionPage(Title = nameof(Properties.Resources.Misc), Order = 30)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class MiscSettingsPanel : UserControl, IOptionPage
{
public MiscSettingsPanel()

11
ILSpy/Options/OptionsDialog.xaml.cs

@ -28,6 +28,8 @@ using System.Xml.Linq; @@ -28,6 +28,8 @@ using System.Xml.Linq;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpyX.Settings;
using TomsToolbox.Composition;
namespace ICSharpCode.ILSpy.Options
{
public class TabItemViewModel
@ -47,16 +49,12 @@ namespace ICSharpCode.ILSpy.Options @@ -47,16 +49,12 @@ namespace ICSharpCode.ILSpy.Options
/// </summary>
public partial class OptionsDialog : Window
{
readonly Lazy<UIElement, IOptionsMetadata>[] optionPages;
readonly IExport<UIElement, IOptionsMetadata>[] optionPages;
public OptionsDialog()
{
InitializeComponent();
// These used to have [ImportMany(..., RequiredCreationPolicy = CreationPolicy.NonShared)], so they use their own
// ExportProvider instance.
// FIXME: Ideally, the export provider should be disposed when it's no longer needed.
var ep = App.ExportProviderFactory.CreateExportProvider();
var ep = App.ExportProvider;
this.optionPages = ep.GetExports<UIElement, IOptionsMetadata>("OptionPages").ToArray();
ILSpySettings settings = ILSpySettings.Load();
foreach (var optionPage in optionPages.OrderBy(p => p.Metadata.Order))
@ -123,6 +121,7 @@ namespace ICSharpCode.ILSpy.Options @@ -123,6 +121,7 @@ namespace ICSharpCode.ILSpy.Options
}
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._View), Header = nameof(Resources._Options), MenuCategory = nameof(Resources.Options), MenuOrder = 999)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class ShowOptionsCommand : SimpleCommand
{
public override void Execute(object parameter)

22
ILSpy/Search/SearchPane.cs

@ -21,6 +21,7 @@ using System.Collections.Concurrent; @@ -21,6 +21,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
@ -34,16 +35,22 @@ using System.Windows.Threading; @@ -34,16 +35,22 @@ using System.Windows.Threading;
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Extensions;
using ICSharpCode.ILSpyX.Search;
using TomsToolbox.Wpf.Composition.Mef;
namespace ICSharpCode.ILSpy.Search
{
/// <summary>
/// Search pane
/// </summary>
[DataTemplate(typeof(SearchPaneModel))]
[PartCreationPolicy(CreationPolicy.Shared)]
[Export]
public partial class SearchPane : UserControl
{
const int MAX_RESULTS = 1000;
@ -51,7 +58,6 @@ namespace ICSharpCode.ILSpy.Search @@ -51,7 +58,6 @@ namespace ICSharpCode.ILSpy.Search
RunningSearch currentSearch;
bool runSearchOnNextShow;
IComparer<SearchResult> resultsComparer;
FilterSettings filterSettings;
public static readonly DependencyProperty ResultsProperty =
DependencyProperty.Register("Results", typeof(ObservableCollection<SearchResult>), typeof(SearchPane),
@ -77,12 +83,11 @@ namespace ICSharpCode.ILSpy.Search @@ -77,12 +83,11 @@ namespace ICSharpCode.ILSpy.Search
searchModeComboBox.Items.Add(new { Image = Images.Namespace, Name = "Namespace" });
ContextMenuProvider.Add(listBox);
MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged;
filterSettings = MainWindow.Instance.SessionSettings.FilterSettings;
MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => MainWindow_Instance_CurrentAssemblyListChanged(sender, e);
CompositionTarget.Rendering += UpdateResults;
// This starts empty search right away, so do at the end (we're still in ctor)
searchModeComboBox.SelectedIndex = (int)MainWindow.Instance.SessionSettings.SelectedSearchMode;
searchModeComboBox.SelectedIndex = (int)SettingsService.Instance.SessionSettings.SelectedSearchMode;
}
void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e)
@ -98,10 +103,8 @@ namespace ICSharpCode.ILSpy.Search @@ -98,10 +103,8 @@ namespace ICSharpCode.ILSpy.Search
}
}
internal void UpdateFilter(FilterSettings settings)
internal void UpdateFilter()
{
this.filterSettings = settings;
if (IsVisible)
{
StartSearch(this.SearchTerm);
@ -149,7 +152,7 @@ namespace ICSharpCode.ILSpy.Search @@ -149,7 +152,7 @@ namespace ICSharpCode.ILSpy.Search
void SearchModeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MainWindow.Instance.SessionSettings.SelectedSearchMode = (SearchMode)searchModeComboBox.SelectedIndex;
SettingsService.Instance.SessionSettings.SelectedSearchMode = (SearchMode)searchModeComboBox.SelectedIndex;
StartSearch(this.SearchTerm);
}
@ -252,7 +255,7 @@ namespace ICSharpCode.ILSpy.Search @@ -252,7 +255,7 @@ namespace ICSharpCode.ILSpy.Search
searchProgressBar.IsIndeterminate = true;
startedSearch = new RunningSearch(await mainWindow.CurrentAssemblyList.GetAllAssemblies(), searchTerm,
(SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage,
filterSettings.ShowApiLevel);
SettingsService.Instance.SessionSettings.LanguageSettings.ShowApiLevel);
currentSearch = startedSearch;
await startedSearch.Run();
@ -531,6 +534,7 @@ namespace ICSharpCode.ILSpy.Search @@ -531,6 +534,7 @@ namespace ICSharpCode.ILSpy.Search
}
[ExportToolbarCommand(ToolTip = nameof(Properties.Resources.SearchCtrlShiftFOrCtrlE), ToolbarIcon = "Images/Search", ToolbarCategory = nameof(Properties.Resources.View), ToolbarOrder = 100)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class ShowSearchCommand : CommandWrapper
{
public ShowSearchCommand()

18
ILSpy/SessionSettings.cs

@ -28,6 +28,7 @@ using System.Xml.Linq; @@ -28,6 +28,7 @@ using System.Xml.Linq;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Themes;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.Search;
using ICSharpCode.ILSpyX.Settings;
@ -47,7 +48,7 @@ namespace ICSharpCode.ILSpy @@ -47,7 +48,7 @@ namespace ICSharpCode.ILSpy
if (filterSettings == null)
filterSettings = new XElement("FilterSettings");
this.FilterSettings = new FilterSettings(filterSettings);
this.LanguageSettings = new LanguageSettings(filterSettings);
this.ActiveAssemblyList = (string)doc.Element("ActiveAssemblyList");
@ -72,10 +73,15 @@ namespace ICSharpCode.ILSpy @@ -72,10 +73,15 @@ namespace ICSharpCode.ILSpy
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
var args = new PropertyChangedEventArgs(propertyName);
PropertyChanged?.Invoke(this, args);
MessageBus.Send(this, new SessionSettingsChangedEventArgs(args));
}
public FilterSettings FilterSettings { get; internal set; }
public LanguageSettings LanguageSettings { get; }
public SearchMode SelectedSearchMode { get; set; }
public string Theme {
@ -113,16 +119,16 @@ namespace ICSharpCode.ILSpy @@ -113,16 +119,16 @@ namespace ICSharpCode.ILSpy
}
}
public WindowState WindowState = WindowState.Normal;
public WindowState WindowState;
public Rect WindowBounds;
internal static Rect DefaultWindowBounds = new Rect(10, 10, 750, 550);
public DockLayoutSettings DockLayout { get; private set; }
public DockLayoutSettings DockLayout { get; }
public XElement ToXml()
{
XElement doc = new XElement("SessionSettings");
doc.Add(this.FilterSettings.SaveAsXml());
doc.Add(this.LanguageSettings.SaveAsXml());
if (this.ActiveAssemblyList != null)
{
doc.Add(new XElement("ActiveAssemblyList", this.ActiveAssemblyList));

7
ILSpy/TextView/DecompilerTextView.cs

@ -56,6 +56,7 @@ using ICSharpCode.ILSpy.AvalonEdit; @@ -56,6 +56,7 @@ using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.Themes;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX;
@ -392,7 +393,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -392,7 +393,7 @@ namespace ICSharpCode.ILSpy.TextView
if (segment.Reference is ICSharpCode.Decompiler.Disassembler.OpCodeInfo code)
{
XmlDocumentationProvider docProvider = XmlDocLoader.MscorlibDocumentation;
DocumentationUIBuilder renderer = new DocumentationUIBuilder(new CSharpAmbience(), MainWindow.Instance.CurrentLanguage.SyntaxHighlighting);
DocumentationUIBuilder renderer = new DocumentationUIBuilder(new CSharpAmbience(), SettingsService.Instance.SessionSettings.LanguageSettings.Language.SyntaxHighlighting);
renderer.AddSignatureBlock($"{code.Name} (0x{code.Code:x})");
if (docProvider != null)
{
@ -442,7 +443,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -442,7 +443,7 @@ namespace ICSharpCode.ILSpy.TextView
static FlowDocument? CreateTooltipForEntity(IEntity resolved)
{
Language currentLanguage = MainWindow.Instance.CurrentLanguage;
Language currentLanguage = SettingsService.Instance.SessionSettings.LanguageSettings.Language;
DocumentationUIBuilder renderer = new DocumentationUIBuilder(new CSharpAmbience(), currentLanguage.SyntaxHighlighting);
RichText richText = currentLanguage.GetRichTextTooltip(resolved);
if (richText == null)
@ -533,7 +534,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -533,7 +534,7 @@ namespace ICSharpCode.ILSpy.TextView
{
if (MainWindow.Instance.CurrentDisplaySettings.HighlightMatchingBraces)
{
var result = MainWindow.Instance.CurrentLanguage.BracketSearcher.SearchBracket(textEditor.Document, textEditor.CaretOffset);
var result = SettingsService.Instance.SessionSettings.LanguageSettings.Language.BracketSearcher.SearchBracket(textEditor.Document, textEditor.CaretOffset);
bracketHighlightRenderer.SetHighlight(result);
}
else

4
ILSpy/TextView/EditorCommands.cs

@ -16,11 +16,14 @@ @@ -16,11 +16,14 @@
// 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.TextView
{
[ExportContextMenuEntry(Header = nameof(Resources.Copy), Category = nameof(Resources.Editor))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class CopyContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -40,6 +43,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -40,6 +43,7 @@ namespace ICSharpCode.ILSpy.TextView
}
[ExportContextMenuEntry(Header = nameof(Resources.Select), Category = nameof(Resources.Editor))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class SelectAllContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

3
ILSpy/TextView/FoldingCommands.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.AvalonEdit;
@ -25,6 +26,7 @@ using ICSharpCode.ILSpy.Properties; @@ -25,6 +26,7 @@ using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy.TextView
{
[ExportContextMenuEntryAttribute(Header = nameof(Resources.ToggleFolding), Category = nameof(Resources.Folding))]
[PartCreationPolicy(CreationPolicy.Shared)]
internal sealed class ToggleAllContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -61,6 +63,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -61,6 +63,7 @@ namespace ICSharpCode.ILSpy.TextView
}
[ExportContextMenuEntryAttribute(Header = nameof(Resources._ToggleFolding), Category = nameof(Resources.Folding))]
[PartCreationPolicy(CreationPolicy.Shared)]
internal sealed class ToggleContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

9
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@ -448,7 +449,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -448,7 +449,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return dataObject;
}
public override FilterResult Filter(FilterSettings settings)
public override FilterResult Filter(LanguageSettings settings)
{
if (settings.SearchTermMatches(LoadedAssembly.ShortName))
return FilterResult.Match;
@ -577,6 +578,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -577,6 +578,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
[ExportContextMenuEntry(Header = nameof(Resources._Remove), Icon = "images/Delete")]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class RemoveAssembly : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -603,6 +605,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -603,6 +605,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
[ExportContextMenuEntry(Header = nameof(Resources._Reload), Icon = "images/Refresh")]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class ReloadAssembly : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -637,6 +640,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -637,6 +640,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
[ExportContextMenuEntry(Header = nameof(Resources._LoadDependencies), Category = nameof(Resources.Dependencies))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class LoadDependencies : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -676,6 +680,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -676,6 +680,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
[ExportContextMenuEntry(Header = nameof(Resources._AddMainList), Category = nameof(Resources.Dependencies))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class AddToMainList : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -710,6 +715,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -710,6 +715,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
[ExportContextMenuEntry(Header = nameof(Resources._OpenContainingFolder), Category = nameof(Resources.Shell))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class OpenContainingFolder : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -762,6 +768,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -762,6 +768,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
[ExportContextMenuEntry(Header = nameof(Resources._OpenCommandLineHere), Category = nameof(Resources.Shell))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class OpenCmdHere : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

2
ILSpy/TreeNodes/DerivedTypesEntryNode.cs

@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override object Icon => TypeTreeNode.GetIcon(type);
public override FilterResult Filter(FilterSettings settings)
public override FilterResult Filter(LanguageSettings settings)
{
if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI)
return FilterResult.Hidden;

2
ILSpy/TreeNodes/EventTreeNode.cs

@ -68,7 +68,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -68,7 +68,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return Images.GetIcon(MemberIcon.Event, MethodTreeNode.GetOverlayIcon(@event.Accessibility), @event.IsStatic);
}
public override FilterResult Filter(FilterSettings settings)
public override FilterResult Filter(LanguageSettings settings)
{
if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI)
return FilterResult.Hidden;

2
ILSpy/TreeNodes/FieldTreeNode.cs

@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return Images.GetIcon(MemberIcon.Field, MethodTreeNode.GetOverlayIcon(field.Accessibility), field.IsStatic);
}
public override FilterResult Filter(FilterSettings settings)
public override FilterResult Filter(LanguageSettings settings)
{
if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI)
return FilterResult.Hidden;

53
ILSpy/TreeNodes/ILSpyTreeNode.cs

@ -27,6 +27,7 @@ using System.Windows.Threading; @@ -27,6 +27,7 @@ using System.Windows.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.Abstractions;
using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions;
using ICSharpCode.ILSpyX.TreeView;
@ -38,25 +39,18 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -38,25 +39,18 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
public abstract class ILSpyTreeNode : SharpTreeNode, ITreeNode
{
FilterSettings filterSettings;
bool childrenNeedFiltering;
public FilterSettings FilterSettings {
get { return filterSettings; }
set {
if (filterSettings != value)
{
filterSettings = value;
OnFilterSettingsChanged();
}
}
public ILSpyTreeNode()
{
MessageBus<LanguageSettingsChangedEventArgs>.Subscribers += LanguageSettings_Changed;
}
public Language Language {
get { return filterSettings != null ? filterSettings.Language : Languages.AllLanguages[0]; }
}
LanguageSettings LanguageSettings => SettingsService.Instance.SessionSettings.LanguageSettings;
public Language Language => LanguageSettings.Language;
public virtual FilterResult Filter(FilterSettings settings)
public virtual FilterResult Filter(LanguageSettings settings)
{
if (string.IsNullOrEmpty(settings.SearchTerm))
return FilterResult.Match;
@ -92,7 +86,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -92,7 +86,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return false;
}
internal protected override void OnChildrenChanged(NotifyCollectionChangedEventArgs e)
protected internal override void OnChildrenChanged(NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
@ -111,27 +105,21 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -111,27 +105,21 @@ namespace ICSharpCode.ILSpy.TreeNodes
void ApplyFilterToChild(ILSpyTreeNode child)
{
FilterResult r;
if (this.FilterSettings == null)
r = FilterResult.Match;
else
r = child.Filter(this.FilterSettings);
FilterResult r = child.Filter(this.LanguageSettings);
switch (r)
{
case FilterResult.Hidden:
child.IsHidden = true;
break;
case FilterResult.Match:
child.FilterSettings = StripSearchTerm(this.FilterSettings);
child.IsHidden = false;
break;
case FilterResult.Recurse:
child.FilterSettings = this.FilterSettings;
child.EnsureChildrenFiltered();
child.IsHidden = child.Children.All(c => c.IsHidden);
break;
case FilterResult.MatchAndRecurse:
child.FilterSettings = StripSearchTerm(this.FilterSettings);
child.EnsureChildrenFiltered();
child.IsHidden = child.Children.All(c => c.IsHidden);
break;
@ -140,19 +128,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -140,19 +128,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
static FilterSettings StripSearchTerm(FilterSettings filterSettings)
{
if (filterSettings == null)
return null;
if (!string.IsNullOrEmpty(filterSettings.SearchTerm))
{
filterSettings = filterSettings.Clone();
filterSettings.SearchTerm = null;
}
return filterSettings;
}
protected virtual void OnFilterSettingsChanged()
protected virtual void LanguageSettings_Changed(object sender, EventArgs e)
{
RaisePropertyChanged(nameof(Text));
if (IsVisible)
@ -166,11 +142,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -166,11 +142,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
/*protected override void OnIsVisibleChanged()
{
base.OnIsVisibleChanged();
EnsureChildrenFiltered();
}*/
internal void EnsureChildrenFiltered()
{

2
ILSpy/TreeNodes/MethodTreeNode.cs

@ -99,7 +99,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -99,7 +99,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
language.DecompileMethod(MethodDefinition, output, options);
}
public override FilterResult Filter(FilterSettings settings)
public override FilterResult Filter(LanguageSettings settings)
{
if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI)
return FilterResult.Hidden;

2
ILSpy/TreeNodes/NamespaceTreeNode.cs

@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.isPublicAPI = value;
}
public override FilterResult Filter(FilterSettings settings)
public override FilterResult Filter(LanguageSettings settings)
{
if (settings.SearchTermMatches(name))
return FilterResult.MatchAndRecurse;

2
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -71,7 +71,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -71,7 +71,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
MethodTreeNode.GetOverlayIcon(property.Accessibility), property.IsStatic);
}
public override FilterResult Filter(FilterSettings settings)
public override FilterResult Filter(LanguageSettings settings)
{
if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI)
return FilterResult.Hidden;

2
ILSpy/TreeNodes/ResourceListTreeNode.cs

@ -51,7 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -51,7 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.Children.Add(ResourceTreeNode.Create(r));
}
public override FilterResult Filter(FilterSettings settings)
public override FilterResult Filter(LanguageSettings settings)
{
if (string.IsNullOrEmpty(settings.SearchTerm))
return FilterResult.MatchAndRecurse;

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

Loading…
Cancel
Save