Browse Source

Merge branch 'master' of https://github.com/icsharpcode/ILSpy into pdbgen-enhancements

pull/1967/head
Siegfried Pammer 6 years ago
parent
commit
c95dc9efd7
  1. 20
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs
  2. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/ForLoopTests.xml
  3. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml
  4. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/LambdaCapturing.xml
  5. 10
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs
  6. 19
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  7. 1
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  8. 1
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  9. 64
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  10. 7
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs
  11. 21
      ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs
  12. 43
      ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs
  13. 12
      ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs
  14. 18
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs
  15. 5
      ICSharpCode.Decompiler/Output/IAmbience.cs
  16. 5
      ICSharpCode.Decompiler/TypeSystem/IProperty.cs
  17. 4
      ICSharpCode.Decompiler/TypeSystem/ISymbol.cs
  18. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
  19. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  20. 7
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs
  21. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedProperty.cs
  22. 8
      ILSpy.Package/Package-CI.appxmanifest
  23. 8
      ILSpy.Package/Package-Local.appxmanifest
  24. 8
      ILSpy.Package/Package.appxmanifest
  25. 2
      ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj
  26. 7
      ILSpy.ReadyToRun/ReadyToRunLanguage.cs
  27. 9
      ILSpy/Analyzers/AnalyzerTreeView.cs
  28. 2
      ILSpy/Commands/DecompileInNewViewCommand.cs
  29. 20
      ILSpy/Commands/ExportCommandAttribute.cs
  30. 2
      ILSpy/Commands/ShowDebugSteps.cs
  31. 6
      ILSpy/Commands/SortAssemblyListCommand.cs
  32. 93
      ILSpy/Docking/DockWorkspace.cs
  33. 2
      ILSpy/ILSpy.csproj
  34. 26
      ILSpy/IPane.cs
  35. 11
      ILSpy/Languages/CSharpLanguage.cs
  36. 2
      ILSpy/Languages/ILAstLanguage.cs
  37. 10
      ILSpy/Languages/Languages.cs
  38. 16
      ILSpy/LoadedAssembly.cs
  39. 5
      ILSpy/LoadedAssemblyExtensions.cs
  40. 19
      ILSpy/MainWindow.xaml
  41. 151
      ILSpy/MainWindow.xaml.cs
  42. 2
      ILSpy/Metadata/CorTables/EventTableTreeNode.cs
  43. 2
      ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
  44. 2
      ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
  45. 2
      ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
  46. 2
      ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
  47. 2
      ILSpy/Search/LiteralSearchStrategy.cs
  48. 2
      ILSpy/Search/MemberSearchStrategy.cs
  49. 2
      ILSpy/Search/MetadataTokenSearchStrategy.cs
  50. 2
      ILSpy/Search/NamespaceSearchStrategy.cs
  51. 10
      ILSpy/Search/SearchPane.cs
  52. 4
      ILSpy/TextView/DecompilerTextView.cs
  53. 2
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  54. 2
      ILSpy/TreeNodes/BaseTypesEntryNode.cs
  55. 5
      ILSpy/TreeNodes/EventTreeNode.cs
  56. 5
      ILSpy/TreeNodes/FieldTreeNode.cs
  57. 5
      ILSpy/TreeNodes/MethodTreeNode.cs
  58. 5
      ILSpy/TreeNodes/PropertyTreeNode.cs
  59. 5
      ILSpy/TreeNodes/TypeTreeNode.cs
  60. 7
      ILSpy/ViewModels/AnalyzerPaneModel.cs
  61. 6
      ILSpy/ViewModels/AssemblyListPaneModel.cs
  62. 7
      ILSpy/ViewModels/DebugStepsPaneModel.cs
  63. 32
      ILSpy/ViewModels/LegacyToolPaneModel.cs
  64. 7
      ILSpy/ViewModels/SearchPaneModel.cs
  65. 4
      ILSpy/ViewModels/ToolPaneModel.cs
  66. 14
      ILSpy/Views/DebugSteps.xaml.cs

20
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{
@ -18,6 +19,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -18,6 +19,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
InsideLoopOverArray2();
NotWhileDueToVariableInsideLoop();
NotDoWhileDueToVariableInsideLoop();
Issue1936();
}
static void TestCase1()
@ -210,5 +212,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -210,5 +212,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine(f());
}
}
public static void Issue1936()
{
IEnumerable<object> outerCapture = null;
for (int i = 0; i < 10; i++) {
int innerCapture = 0;
Action a = (delegate {
List<object> list = new List<object>();
Console.WriteLine("before inc: " + innerCapture);
++innerCapture;
Console.WriteLine("after inc: " + innerCapture);
Console.WriteLine("before assign: " + outerCapture);
outerCapture = outerCapture == null ? list : outerCapture.Concat(list);
Console.WriteLine("after assign: " + outerCapture);
});
a.Invoke();
}
}
}
}

2
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/ForLoopTests.xml

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
<file id="1" name="ICSharpCode\Decompiler\Tests\TestCases\PdbGen\ForLoopTests.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\ForLoopTests.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen
{

2
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
<file id="1" name="ICSharpCode\Decompiler\Tests\TestCases\PdbGen\HelloWorld.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\HelloWorld.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen
{

2
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/LambdaCapturing.xml

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
<file id="1" name="ICSharpCode\Decompiler\Tests\TestCases\PdbGen\LambdaCapturing.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\LambdaCapturing.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen
{

10
ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs

@ -62,6 +62,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -62,6 +62,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public struct NormalStruct
{
private readonly int dummy;
private int[] arr;
public int Property {
get {
@ -96,8 +97,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -96,8 +97,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public ref int RefProperty => ref arr[0];
public ref readonly int RefReadonlyProperty => ref arr[0];
public readonly ref int ReadonlyRefProperty => ref arr[0];
public readonly ref readonly int ReadonlyRefReadonlyProperty => ref arr[0];
#endif
public ref readonly int this[in int index] => ref arr[index];
public event EventHandler NormalEvent;
#if CS80
public readonly event EventHandler ReadOnlyEvent {
add {
}

19
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -401,12 +401,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -401,12 +401,13 @@ namespace ICSharpCode.Decompiler.CSharp
return new DecompilerTypeSystem(file, resolver);
}
static TypeSystemAstBuilder CreateAstBuilder(ITypeResolveContext decompilationContext)
static TypeSystemAstBuilder CreateAstBuilder(DecompilerSettings settings)
{
var typeSystemAstBuilder = new TypeSystemAstBuilder();
typeSystemAstBuilder.ShowAttributes = true;
typeSystemAstBuilder.AlwaysUseShortTypeNames = true;
typeSystemAstBuilder.AddResolveResultAnnotations = true;
typeSystemAstBuilder.UseNullableSpecifierForValueTypes = settings.LiftNullables;
return typeSystemAstBuilder;
}
@ -421,7 +422,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -421,7 +422,7 @@ namespace ICSharpCode.Decompiler.CSharp
void RunTransforms(AstNode rootNode, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
var context = new TransformContext(typeSystem, decompileRun, decompilationContext, typeSystemAstBuilder);
foreach (var transform in astTransforms) {
CancellationToken.ThrowIfCancellationRequested();
@ -466,13 +467,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -466,13 +467,13 @@ namespace ICSharpCode.Decompiler.CSharp
{
try {
foreach (var a in typeSystem.MainModule.GetAssemblyAttributes()) {
var astBuilder = CreateAstBuilder(decompilationContext);
var astBuilder = CreateAstBuilder(decompileRun.Settings);
var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a));
attrSection.AttributeTarget = "assembly";
syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole);
}
foreach (var a in typeSystem.MainModule.GetModuleAttributes()) {
var astBuilder = CreateAstBuilder(decompilationContext);
var astBuilder = CreateAstBuilder(decompileRun.Settings);
var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a));
attrSection.AttributeTarget = "module";
syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole);
@ -1076,7 +1077,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1076,7 +1077,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef);
try {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
var entityDecl = typeSystemAstBuilder.ConvertEntity(typeDef);
var typeDecl = entityDecl as TypeDeclaration;
if (typeDecl == null) {
@ -1239,7 +1240,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1239,7 +1240,7 @@ namespace ICSharpCode.Decompiler.CSharp
EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentMember == method);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
var methodDecl = typeSystemAstBuilder.ConvertEntity(method);
int lastDot = method.Name.LastIndexOf('.');
if (method.IsExplicitInterfaceImplementation && lastDot >= 0) {
@ -1412,7 +1413,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1412,7 +1413,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
Debug.Assert(decompilationContext.CurrentMember == field);
try {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum && field.IsConst) {
var enumDec = new EnumMemberDeclaration { Name = field.Name };
object constantValue = field.GetConstantValue();
@ -1483,7 +1484,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1483,7 +1484,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
Debug.Assert(decompilationContext.CurrentMember == property);
try {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
EntityDeclaration propertyDecl = typeSystemAstBuilder.ConvertEntity(property);
if (property.IsExplicitInterfaceImplementation && !property.IsIndexer) {
int lastDot = property.Name.LastIndexOf('.');
@ -1518,7 +1519,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1518,7 +1519,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
Debug.Assert(decompilationContext.CurrentMember == ev);
try {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
typeSystemAstBuilder.UseCustomEvents = ev.DeclaringTypeDefinition.Kind != TypeKind.Interface;
var eventDecl = typeSystemAstBuilder.ConvertEntity(ev);
int lastDot = ev.Name.LastIndexOf('.');

1
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -92,6 +92,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -92,6 +92,7 @@ namespace ICSharpCode.Decompiler.CSharp
this.astBuilder = new TypeSystemAstBuilder(resolver);
this.astBuilder.AlwaysUseShortTypeNames = true;
this.astBuilder.AddResolveResultAnnotations = true;
this.astBuilder.UseNullableSpecifierForValueTypes = settings.LiftNullables;
this.typeInference = new TypeInference(compilation) { Algorithm = TypeInferenceAlgorithm.Improved };
}

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

@ -195,6 +195,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -195,6 +195,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
astBuilder.ShowAccessibility = (ConversionFlags & ConversionFlags.ShowAccessibility) == ConversionFlags.ShowAccessibility;
astBuilder.AlwaysUseShortTypeNames = (ConversionFlags & ConversionFlags.UseFullyQualifiedTypeNames) != ConversionFlags.UseFullyQualifiedTypeNames;
astBuilder.ShowParameterNames = (ConversionFlags & ConversionFlags.ShowParameterNames) == ConversionFlags.ShowParameterNames;
astBuilder.UseNullableSpecifierForValueTypes = (ConversionFlags & ConversionFlags.UseNullableSpecifierForValueTypes) != 0;
return astBuilder;
}

64
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -64,7 +64,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -64,7 +64,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
#region Properties
void InitProperties()
{
this.AlwaysUseBuiltinTypeNames = true;
this.UseKeywordsForBuiltinTypes = true;
this.UseNullableSpecifierForValueTypes = true;
this.ShowAccessibility = true;
this.ShowModifiers = true;
this.ShowBaseTypes = true;
@ -78,82 +79,88 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -78,82 +79,88 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// <summary>
/// Specifies whether the ast builder should add annotations to type references.
/// The default value is <c>false</c>.
/// The default value is <see langword="false" />.
/// </summary>
public bool AddTypeReferenceAnnotations { get; set; }
/// <summary>
/// Specifies whether the ast builder should add ResolveResult annotations to AST nodes.
/// The default value is <c>false</c>.
/// The default value is <see langword="false" />.
/// </summary>
public bool AddResolveResultAnnotations { get; set; }
/// <summary>
/// Controls the accessibility modifiers are shown.
/// The default value is <c>true</c>.
/// The default value is <see langword="true" />.
/// </summary>
public bool ShowAccessibility { get; set; }
/// <summary>
/// Controls the non-accessibility modifiers are shown.
/// The default value is <c>true</c>.
/// The default value is <see langword="true" />.
/// </summary>
public bool ShowModifiers { get; set; }
/// <summary>
/// Controls whether base type references are shown.
/// The default value is <c>true</c>.
/// The default value is <see langword="true" />.
/// </summary>
public bool ShowBaseTypes { get; set; }
/// <summary>
/// Controls whether type parameter declarations are shown.
/// The default value is <c>true</c>.
/// The default value is <see langword="true" />.
/// </summary>
public bool ShowTypeParameters { get; set; }
/// <summary>
/// Controls whether type parameter names are shown for unbound types.
/// The default value is <c>false</c>.
/// The default value is <see langword="false" />.
/// </summary>
public bool ShowTypeParametersForUnboundTypes { get; set; }
/// <summary>
/// Controls whether constraints on type parameter declarations are shown.
/// Has no effect if ShowTypeParameters is false.
/// The default value is <c>true</c>.
/// The default value is <see langword="true" />.
/// </summary>
public bool ShowTypeParameterConstraints { get; set; }
/// <summary>
/// Controls whether the names of parameters are shown.
/// The default value is <c>true</c>.
/// The default value is <see langword="true" />.
/// </summary>
public bool ShowParameterNames { get; set; }
/// <summary>
/// Controls whether to show default values of optional parameters, and the values of constant fields.
/// The default value is <c>true</c>.
/// The default value is <see langword="true" />.
/// </summary>
public bool ShowConstantValues { get; set; }
/// <summary>
/// Controls whether to show attributes.
/// The default value is <c>false</c>.
/// The default value is <see langword="false" />.
/// </summary>
public bool ShowAttributes { get; set; }
/// <summary>
/// Controls whether to use fully-qualified type names or short type names.
/// The default value is <c>false</c>.
/// The default value is <see langword="false" />.
/// </summary>
public bool AlwaysUseShortTypeNames { get; set; }
/// <summary>
/// Controls whether to use fully-qualified type names or short type names.
/// The default value is <c>true</c>.
/// Controls whether to use keywords for builtin types.
/// The default value is <see langword="true" />.
/// </summary>
public bool AlwaysUseBuiltinTypeNames { get; set; }
public bool UseKeywordsForBuiltinTypes { get; set; }
/// <summary>
/// Controls whether to use <c>T?</c> or <c>Nullable&lt;T&gt;</c> for nullable value types.
/// The default value is <see langword="true" />.
/// </summary>
public bool UseNullableSpecifierForValueTypes { get; set; }
/// <summary>
/// Determines the name lookup mode for converting a type name.
@ -165,37 +172,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -165,37 +172,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// <summary>
/// Controls whether to generate a body that throws a <c>System.NotImplementedException</c>.
/// The default value is <c>false</c>.
/// The default value is <see langword="false" />.
/// </summary>
public bool GenerateBody { get; set; }
/// <summary>
/// Controls whether to generate custom events.
/// The default value is <c>false</c>.
/// The default value is <see langword="false" />.
/// </summary>
public bool UseCustomEvents { get; set; }
/// <summary>
/// Controls whether unbound type argument names are inserted in the ast or not.
/// The default value is <c>false</c>.
/// The default value is <see langword="false" />.
/// </summary>
public bool ConvertUnboundTypeArguments { get; set;}
/// <summary>
/// Controls whether aliases should be used inside the type name or not.
/// The default value is <c>true</c>.
/// The default value is <see langword="true" />.
/// </summary>
public bool UseAliases { get; set; }
/// <summary>
/// Controls whether constants like <c>int.MaxValue</c> are converted to a <see cref="MemberReferenceExpression"/> or <see cref="PrimitiveExpression" />.
/// The default value is <c>true</c>.
/// The default value is <see langword="true" />.
/// </summary>
public bool UseSpecialConstants { get; set; }
/// <summary>
/// Controls whether integral constants should be printed in hexadecimal format.
/// The default value is <c>false</c>.
/// The default value is <see langword="false" />.
/// </summary>
public bool PrintIntegralValuesAsHex { get; set; }
#endregion
@ -290,7 +297,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -290,7 +297,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
break;
case ParameterizedType pt:
if (AlwaysUseBuiltinTypeNames && pt.IsKnownType(KnownTypeCode.NullableOfT)) {
if (UseNullableSpecifierForValueTypes && pt.IsKnownType(KnownTypeCode.NullableOfT)) {
return ConvertType(pt.TypeArguments[0]).MakeNullableType();
}
astType = ConvertTypeHelper(pt.GenericType, pt.TypeArguments);
@ -313,7 +320,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -313,7 +320,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
Debug.Assert(typeDef != null || genericType.Kind == TypeKind.Unknown);
Debug.Assert(typeArguments.Count >= genericType.TypeParameterCount);
if (AlwaysUseBuiltinTypeNames && typeDef != null) {
if (UseKeywordsForBuiltinTypes && typeDef != null) {
string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode);
if (keyword != null) {
return new PrimitiveType(keyword);
@ -1567,6 +1574,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1567,6 +1574,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.AddAnnotation(new MemberResolveResult(null, property));
}
decl.ReturnType = ConvertType(property.ReturnType);
if (property.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) {
ct.HasReadOnlySpecifier = true;
}
decl.Name = property.Name;
decl.Getter = ConvertAccessor(property.Getter, property.Accessibility, false);
decl.Setter = ConvertAccessor(property.Setter, property.Accessibility, true);
@ -1594,6 +1604,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1594,6 +1604,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.AddAnnotation(new MemberResolveResult(null, indexer));
}
decl.ReturnType = ConvertType(indexer.ReturnType);
if (indexer.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) {
ct.HasReadOnlySpecifier = true;
}
foreach (IParameter p in indexer.Parameters) {
decl.Parameters.Add(ConvertParameter(p));
}
@ -1688,6 +1701,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1688,6 +1701,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.Modifiers = GetMemberModifiers(op);
decl.OperatorType = opType.Value;
decl.ReturnType = ConvertType(op.ReturnType);
if (op.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) {
ct.HasReadOnlySpecifier = true;
}
foreach (IParameter p in op.Parameters) {
decl.Parameters.Add(ConvertParameter(p));
}

7
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs

@ -116,12 +116,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -116,12 +116,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
readonly Stack<CSharpTypeResolveContext> context;
readonly bool ignoreUsingScope;
readonly DecompilerSettings settings;
TypeSystemAstBuilder astBuilder;
public FullyQualifyAmbiguousTypeNamesVisitor(TransformContext context, UsingScope usingScope)
{
this.ignoreUsingScope = !context.Settings.UsingDeclarations;
this.settings = context.Settings;
CSharpTypeResolveContext currentContext;
if (ignoreUsingScope) {
@ -139,7 +141,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -139,7 +141,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
this.astBuilder = CreateAstBuilder(currentContext);
}
static TypeSystemAstBuilder CreateAstBuilder(CSharpTypeResolveContext context, IL.ILFunction function = null)
TypeSystemAstBuilder CreateAstBuilder(CSharpTypeResolveContext context, IL.ILFunction function = null)
{
CSharpResolver resolver = new CSharpResolver(context);
if (function != null) {
@ -148,8 +150,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -148,8 +150,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
resolver = resolver.AddVariable(new DefaultVariable(v.Type, v.Name));
}
}
return new TypeSystemAstBuilder(resolver) {
UseNullableSpecifierForValueTypes = settings.LiftNullables,
AddResolveResultAnnotations = true,
UseAliases = true
};

21
ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs

@ -144,7 +144,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -144,7 +144,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
Name = Pattern.AnyString,
PrivateImplementationType = new AnyNodeOrNull(),
ReturnType = new AnyNode(),
Getter = new Accessor() { Body = new BlockStatement() { new ReturnStatement(new AnyNode("expression")) } }
Getter = new Accessor() {
Modifiers = Modifiers.Any,
Body = new BlockStatement() { new ReturnStatement(new AnyNode("expression")) }
}
};
static readonly IndexerDeclaration CalculatedGetterOnlyIndexerPattern = new IndexerDeclaration() {
@ -153,14 +156,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -153,14 +156,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
PrivateImplementationType = new AnyNodeOrNull(),
Parameters = { new Repeat(new AnyNode()) },
ReturnType = new AnyNode(),
Getter = new Accessor() { Body = new BlockStatement() { new ReturnStatement(new AnyNode("expression")) } }
Getter = new Accessor() {
Modifiers = Modifiers.Any,
Body = new BlockStatement() { new ReturnStatement(new AnyNode("expression")) }
}
};
/// <summary>
/// Modifiers that are emitted on accessors, but can be moved to the property declaration.
/// </summary>
const Modifiers movableModifiers = Modifiers.Readonly;
void SimplifyPropertyDeclaration(PropertyDeclaration propertyDeclaration)
{
var m = CalculatedGetterOnlyPropertyPattern.Match(propertyDeclaration);
if (!m.Success)
return;
if ((propertyDeclaration.Getter.Modifiers & ~movableModifiers) != 0)
return;
propertyDeclaration.Modifiers |= propertyDeclaration.Getter.Modifiers;
propertyDeclaration.ExpressionBody = m.Get<Expression>("expression").Single().Detach();
propertyDeclaration.Getter.Remove();
}
@ -170,6 +184,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -170,6 +184,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var m = CalculatedGetterOnlyIndexerPattern.Match(indexerDeclaration);
if (!m.Success)
return;
if ((indexerDeclaration.Getter.Modifiers & ~movableModifiers) != 0)
return;
indexerDeclaration.Modifiers |= indexerDeclaration.Getter.Modifiers;
indexerDeclaration.ExpressionBody = m.Get<Expression>("expression").Single().Detach();
indexerDeclaration.Getter.Remove();
}

43
ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs

@ -228,7 +228,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -228,7 +228,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
w.WriteElementString("WarningLevel", "4");
w.WriteElementString("AllowUnsafeBlocks", "True");
if (StrongNameKeyFile != null) {
w.WriteElementString("SignAssembly", "True");
w.WriteElementString("AssemblyOriginatorKeyFile", Path.GetFileName(StrongNameKeyFile));
@ -463,7 +463,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -463,7 +463,7 @@ namespace ICSharpCode.Decompiler.CSharp
} catch (EndOfStreamException) {
// if the .resources can't be decoded, just save them as-is
}
}
}
using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write)) {
entryStream.CopyTo(fs);
}
@ -512,7 +512,44 @@ namespace ICSharpCode.Decompiler.CSharp @@ -512,7 +512,44 @@ namespace ICSharpCode.Decompiler.CSharp
}
if (b.Length == 0)
b.Append('-');
return b.ToString();
string name = b.ToString();
if (IsReservedFileSystemName(name))
return name + "_";
else if (name == ".")
return "_";
else
return name;
}
static bool IsReservedFileSystemName(string name)
{
switch (name.ToUpperInvariant()) {
case "AUX":
case "COM1":
case "COM2":
case "COM3":
case "COM4":
case "COM5":
case "COM6":
case "COM7":
case "COM8":
case "COM9":
case "CON":
case "LPT1":
case "LPT2":
case "LPT3":
case "LPT4":
case "LPT5":
case "LPT6":
case "LPT7":
case "LPT8":
case "LPT9":
case "NUL":
case "PRN":
return true;
default:
return false;
}
}
public static string GetPlatformName(Metadata.PEFile module)

12
ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

@ -61,11 +61,15 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -61,11 +61,15 @@ namespace ICSharpCode.Decompiler.DebugInfo
var customMethodDebugInfo = new List<(MethodDefinitionHandle Parent, GuidHandle Guid, BlobHandle Blob)>();
var globalImportScope = metadata.AddImportScope(default, default);
foreach (var handle in reader.GetTopLevelTypeDefinitions()) {
var type = reader.GetTypeDefinition(handle);
string BuildFileNameFromTypeName(TypeDefinitionHandle handle)
{
var typeName = handle.GetFullTypeName(reader).TopLevelTypeName;
return Path.Combine(WholeProjectDecompiler.CleanUpFileName(typeName.Namespace), WholeProjectDecompiler.CleanUpFileName(typeName.Name) + ".cs");
}
foreach (var sourceFile in reader.GetTopLevelTypeDefinitions().GroupBy(BuildFileNameFromTypeName)) {
// Generate syntax tree
var syntaxTree = decompiler.DecompileTypes(new[] { handle });
var syntaxTree = decompiler.DecompileTypes(sourceFile);
if (!syntaxTree.HasChildren)
continue;
@ -83,7 +87,7 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -83,7 +87,7 @@ namespace ICSharpCode.Decompiler.DebugInfo
lock (metadata) {
var sourceBlob = WriteSourceToBlob(metadata, sourceText, out var sourceCheckSum);
var name = metadata.GetOrAddDocumentName(type.GetFullTypeName(reader).ReflectionName.Replace('.', Path.DirectorySeparatorChar) + ".cs");
var name = metadata.GetOrAddDocumentName(sourceFile.Key);
// Create Document(Handle)
var document = metadata.AddDocument(name,

18
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -64,7 +64,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -64,7 +64,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if ((context.Settings.AnonymousMethods || context.Settings.ExpressionTrees) && IsClosure(context, v, out ITypeDefinition closureType, out var inst)) {
if (!CanRemoveAllReferencesTo(context, v))
continue;
instructionsToRemove.Add(inst);
if (inst is StObj || inst is StLoc)
instructionsToRemove.Add(inst);
AddOrUpdateDisplayClass(f, v, closureType, inst, localFunctionClosureParameter: false);
continue;
}
@ -309,9 +310,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -309,9 +310,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
base.VisitStLoc(inst);
if (inst.Variable.Kind == VariableKind.Local && inst.Variable.IsSingleDefinition && inst.Variable.LoadCount == 0 && inst.Value is StLoc) {
context.Step($"Remove unused variable assignment {inst.Variable.Name}", inst);
inst.ReplaceWith(inst.Value);
if (inst.Parent is Block && inst.Variable.IsSingleDefinition) {
if (inst.Variable.Kind == VariableKind.Local && inst.Variable.LoadCount == 0 && inst.Value is StLoc) {
context.Step($"Remove unused variable assignment {inst.Variable.Name}", inst);
inst.ReplaceWith(inst.Value);
return;
}
if (inst.Value.MatchLdLoc(out var displayClassVariable) && displayClasses.TryGetValue(displayClassVariable, out var displayClass)) {
context.Step($"Found copy-assignment of display-class variable {displayClassVariable.Name}", inst);
displayClasses.Add(inst.Variable, displayClass);
instructionsToRemove.Add(inst);
return;
}
}
}

5
ICSharpCode.Decompiler/Output/IAmbience.cs

@ -92,12 +92,17 @@ namespace ICSharpCode.Decompiler.Output @@ -92,12 +92,17 @@ namespace ICSharpCode.Decompiler.Output
/// Show default values of parameters.
/// </summary>
ShowParameterDefaultValues = 0x4000,
/// <summary>
/// Use <c>T?</c> instead of <c>Nullable&lt;T&gt;</c>.
/// </summary>
UseNullableSpecifierForValueTypes = 0x8000,
StandardConversionFlags = ShowParameterNames |
ShowAccessibility |
ShowParameterList |
ShowParameterModifiers |
ShowParameterDefaultValues |
UseNullableSpecifierForValueTypes |
ShowReturnType |
ShowModifiers |
ShowTypeParameterList |

5
ICSharpCode.Decompiler/TypeSystem/IProperty.cs

@ -30,5 +30,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -30,5 +30,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
IMethod Setter { get; }
bool IsIndexer { get; }
/// <summary>
/// Gets whether the return type is 'ref readonly'.
/// </summary>
bool ReturnTypeIsRefReadOnly { get; }
}
}

4
ICSharpCode.Decompiler/TypeSystem/ISymbol.cs

@ -73,6 +73,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -73,6 +73,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Constraint on a type parameter.
/// </summary>
Constraint,
/// <summary>
/// Return type. Not actually an ISymbol implementation; but can appear as attribut target.
/// </summary>
ReturnType,
}
/// <summary>

4
ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs

@ -208,6 +208,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -208,6 +208,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
case SymbolKind.Method:
case SymbolKind.Accessor:
return (options & TypeSystemOptions.ReadOnlyMethods) != 0;
case SymbolKind.ReturnType:
case SymbolKind.Property:
case SymbolKind.Indexer:
return true; // "ref readonly" is currently always active
default:
return false;
}

2
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs

@ -400,7 +400,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -400,7 +400,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var retParam = metadata.GetParameter(parameters.First());
if (retParam.SequenceNumber == 0) {
b.AddMarshalInfo(retParam.GetMarshallingDescriptor());
b.Add(retParam.GetCustomAttributes(), symbolKind);
b.Add(retParam.GetCustomAttributes(), SymbolKind.ReturnType);
}
}
return b.Build();

7
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs

@ -113,6 +113,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -113,6 +113,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
public bool ReturnTypeIsRefReadOnly {
get {
var propertyDef = module.metadata.GetPropertyDefinition(propertyHandle);
return propertyDef.GetCustomAttributes().HasKnownAttribute(module.metadata, KnownAttribute.IsReadOnly);
}
}
private void DecodeSignature()
{
var propertyDef = module.metadata.GetPropertyDefinition(propertyHandle);

2
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedProperty.cs

@ -65,5 +65,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -65,5 +65,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool IsIndexer {
get { return propertyDefinition.IsIndexer; }
}
public bool ReturnTypeIsRefReadOnly => propertyDefinition.ReturnTypeIsRefReadOnly;
}
}

8
ILSpy.Package/Package-CI.appxmanifest

@ -37,7 +37,13 @@ @@ -37,7 +37,13 @@
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png"/>
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo" />
<uap:ShowOn Tile="wide310x150Logo" />
<uap:ShowOn Tile="square310x310Logo" />
</uap:ShowNameOnTiles>
</uap:DefaultTile>
<uap:SplashScreen Image="Images\SplashScreen.png" />
</uap:VisualElements>

8
ILSpy.Package/Package-Local.appxmanifest

@ -37,7 +37,13 @@ @@ -37,7 +37,13 @@
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png"/>
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo" />
<uap:ShowOn Tile="wide310x150Logo" />
<uap:ShowOn Tile="square310x310Logo" />
</uap:ShowNameOnTiles>
</uap:DefaultTile>
<uap:SplashScreen Image="Images\SplashScreen.png" />
</uap:VisualElements>

8
ILSpy.Package/Package.appxmanifest

@ -37,7 +37,13 @@ @@ -37,7 +37,13 @@
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png"/>
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo" />
<uap:ShowOn Tile="wide310x150Logo" />
<uap:ShowOn Tile="square310x310Logo" />
</uap:ShowNameOnTiles>
</uap:DefaultTile>
<uap:SplashScreen Image="Images\SplashScreen.png" />
</uap:VisualElements>

2
ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj

@ -57,7 +57,7 @@ @@ -57,7 +57,7 @@
<ItemGroup>
<PackageReference Include="Iced" Version="1.4.0" />
<PackageReference Include="ILCompiler.Reflection.ReadyToRun" Version="1.0.4-alpha" />
<PackageReference Include="ILCompiler.Reflection.ReadyToRun" Version="1.0.5-alpha" />
</ItemGroup>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />

7
ILSpy.ReadyToRun/ReadyToRunLanguage.cs

@ -175,6 +175,13 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -175,6 +175,13 @@ namespace ICSharpCode.ILSpy.ReadyToRun
LoadedAssembly loadedAssembly = this.loadedAssembly.LookupReferencedAssembly(new Decompiler.Metadata.AssemblyReference(metadataReader, assemblyReferenceHandle));
return loadedAssembly?.GetPEFileOrNull()?.Metadata;
}
public MetadataReader FindAssembly(string simpleName, string parentFile)
{
// This is called only for the composite R2R scenario,
// So it will never be called before the feature is released.
throw new NotSupportedException("Composite R2R format is not currently supported");
}
}
private class ReadyToRunReaderCacheEntry

9
ILSpy/Analyzers/AnalyzerTreeView.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.Analyzers
/// <summary>
/// Analyzer tree view.
/// </summary>
public class AnalyzerTreeView : SharpTreeView, IPane
public class AnalyzerTreeView : SharpTreeView
{
public AnalyzerTreeView()
{
@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.Analyzers
public void Show()
{
AnalyzerPaneModel.Instance.Show();
DockWorkspace.Instance.ShowToolPane(AnalyzerPaneModel.PaneContentId);
}
public void Show(AnalyzerTreeNode node)
@ -122,11 +122,6 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -122,11 +122,6 @@ namespace ICSharpCode.ILSpy.Analyzers
throw new ArgumentOutOfRangeException(nameof(entity), $"Entity {entity.GetType().FullName} is not supported.");
}
}
void IPane.Closed()
{
this.Root.Children.Clear();
}
sealed class AnalyzerRootNode : AnalyzerTreeNode
{

2
ILSpy/Commands/DecompileInNewViewCommand.cs

@ -49,7 +49,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -49,7 +49,7 @@ namespace ICSharpCode.ILSpy.Commands
IEnumerable<ILSpyTreeNode> GetNodes(TextViewContext context)
{
if (context.SelectedTreeNodes != null) {
if (context.TreeView != MainWindow.Instance.treeView) {
if (context.TreeView != MainWindow.Instance.AssemblyTreeView) {
return context.SelectedTreeNodes.OfType<IMemberTreeNode>().Select(FindTreeNode).Where(n => n != null);
} else {
return context.SelectedTreeNodes.OfType<ILSpyTreeNode>().Where(n => n != null);

20
ILSpy/Commands/ExportCommandAttribute.cs

@ -30,7 +30,6 @@ namespace ICSharpCode.ILSpy @@ -30,7 +30,6 @@ namespace ICSharpCode.ILSpy
string ToolbarCategory { get; }
object Tag { get; }
double ToolbarOrder { get; }
}
[MetadataAttribute]
@ -85,4 +84,23 @@ namespace ICSharpCode.ILSpy @@ -85,4 +84,23 @@ namespace ICSharpCode.ILSpy
public double MenuOrder { get; set; }
}
#endregion
#region Tool Panes
public interface IToolPaneMetadata
{
string ContentId { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ExportToolPaneAttribute : ExportAttribute, IToolPaneMetadata
{
public ExportToolPaneAttribute()
: base("ToolPane", typeof(ViewModels.ToolPaneModel))
{
}
public string ContentId { get; set; }
}
#endregion
}

2
ILSpy/Commands/ShowDebugSteps.cs

@ -11,7 +11,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -11,7 +11,7 @@ namespace ICSharpCode.ILSpy.Commands
{
public override void Execute(object parameter)
{
DebugStepsPaneModel.Instance.Show();
DockWorkspace.Instance.ShowToolPane(DebugStepsPaneModel.PaneContentId);
}
}
}

6
ILSpy/Commands/SortAssemblyListCommand.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy @@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy
{
public override void Execute(object parameter)
{
using (MainWindow.Instance.treeView.LockUpdates())
using (MainWindow.Instance.AssemblyTreeView.LockUpdates())
MainWindow.Instance.CurrentAssemblyList.Sort(this);
}
@ -45,8 +45,8 @@ namespace ICSharpCode.ILSpy @@ -45,8 +45,8 @@ namespace ICSharpCode.ILSpy
{
public override void Execute(object parameter)
{
using (MainWindow.Instance.treeView.LockUpdates())
CollapseChildren(MainWindow.Instance.treeView.Root);
using (MainWindow.Instance.AssemblyTreeView.LockUpdates())
CollapseChildren(MainWindow.Instance.AssemblyTreeView.Root);
void CollapseChildren(SharpTreeNode node)
{

93
ILSpy/Docking/DockWorkspace.cs

@ -22,6 +22,7 @@ using System.Collections.ObjectModel; @@ -22,6 +22,7 @@ using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
@ -34,7 +35,7 @@ using Xceed.Wpf.AvalonDock.Layout.Serialization; @@ -34,7 +35,7 @@ using Xceed.Wpf.AvalonDock.Layout.Serialization;
namespace ICSharpCode.ILSpy.Docking
{
public class DockWorkspace : INotifyPropertyChanged
public class DockWorkspace : INotifyPropertyChanged, ILayoutUpdateStrategy
{
private SessionSettings sessionSettings;
@ -58,21 +59,16 @@ namespace ICSharpCode.ILSpy.Docking @@ -58,21 +59,16 @@ namespace ICSharpCode.ILSpy.Docking
public PaneCollection<TabPageModel> TabPages { get; } = new PaneCollection<TabPageModel>();
private ToolPaneModel[] toolPanes;
public IEnumerable<ToolPaneModel> ToolPanes {
get {
if (toolPanes == null) {
toolPanes = new ToolPaneModel[] {
AssemblyListPaneModel.Instance,
SearchPaneModel.Instance,
AnalyzerPaneModel.Instance,
#if DEBUG
DebugStepsPaneModel.Instance,
#endif
};
}
return toolPanes;
public ObservableCollection<ToolPaneModel> ToolPanes { get; } = new ObservableCollection<ToolPaneModel>();
public bool ShowToolPane(string contentId)
{
var pane = ToolPanes.FirstOrDefault(p => p.ContentId == contentId);
if (pane != null) {
pane.Show();
return true;
}
return false;
}
public void Remove(PaneModel model)
@ -103,6 +99,7 @@ namespace ICSharpCode.ILSpy.Docking @@ -103,6 +99,7 @@ namespace ICSharpCode.ILSpy.Docking
public void InitializeLayout(Xceed.Wpf.AvalonDock.DockingManager manager)
{
manager.LayoutUpdateStrategy = this;
XmlLayoutSerializer serializer = new XmlLayoutSerializer(manager);
serializer.LayoutSerializationCallback += LayoutSerializationCallback;
try {
@ -116,25 +113,8 @@ namespace ICSharpCode.ILSpy.Docking @@ -116,25 +113,8 @@ namespace ICSharpCode.ILSpy.Docking
{
switch (e.Model) {
case LayoutAnchorable la:
switch (la.ContentId) {
case AssemblyListPaneModel.PaneContentId:
e.Content = AssemblyListPaneModel.Instance;
break;
case SearchPaneModel.PaneContentId:
e.Content = SearchPaneModel.Instance;
break;
case AnalyzerPaneModel.PaneContentId:
e.Content = AnalyzerPaneModel.Instance;
break;
#if DEBUG
case DebugStepsPaneModel.PaneContentId:
e.Content = DebugStepsPaneModel.Instance;
break;
#endif
default:
e.Cancel = true;
break;
}
e.Content = ToolPanes.FirstOrDefault(p => p.ContentId == la.ContentId);
e.Cancel = e.Content == null;
la.CanDockAsTabbedDocument = false;
if (!e.Cancel) {
e.Cancel = ((ToolPaneModel)e.Content).IsVisible;
@ -203,5 +183,50 @@ namespace ICSharpCode.ILSpy.Docking @@ -203,5 +183,50 @@ namespace ICSharpCode.ILSpy.Docking
InitializeLayout(MainWindow.Instance.DockManager);
MainWindow.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)MainWindow.Instance.RefreshDecompiledView);
}
static readonly PropertyInfo previousContainerProperty = typeof(LayoutContent).GetProperty("PreviousContainer", BindingFlags.NonPublic | BindingFlags.Instance);
public bool BeforeInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableToShow, ILayoutContainer destinationContainer)
{
if (!(anchorableToShow.Content is LegacyToolPaneModel legacyContent))
return false;
anchorableToShow.CanDockAsTabbedDocument = false;
LayoutAnchorablePane previousContainer;
switch (legacyContent.Location) {
case LegacyToolPaneLocation.Top:
previousContainer = GetContainer<SearchPaneModel>();
previousContainer.Children.Add(anchorableToShow);
return true;
case LegacyToolPaneLocation.Bottom:
previousContainer = GetContainer<AnalyzerPaneModel>();
previousContainer.Children.Add(anchorableToShow);
return true;
default:
return false;
}
LayoutAnchorablePane GetContainer<T>()
{
var anchorable = layout.Descendents().OfType<LayoutAnchorable>().FirstOrDefault(x => x.Content is T)
?? layout.Hidden.First(x => x.Content is T);
return (LayoutAnchorablePane)previousContainerProperty.GetValue(anchorable) ?? (LayoutAnchorablePane)anchorable.Parent;
}
}
public void AfterInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableShown)
{
anchorableShown.IsActive = true;
anchorableShown.IsSelected = true;
}
public bool BeforeInsertDocument(LayoutRoot layout, LayoutDocument anchorableToShow, ILayoutContainer destinationContainer)
{
return false;
}
public void AfterInsertDocument(LayoutRoot layout, LayoutDocument anchorableShown)
{
}
}
}

2
ILSpy/ILSpy.csproj

@ -208,6 +208,7 @@ @@ -208,6 +208,7 @@
<Compile Include="Metadata\MetadataProtocolHandler.cs" />
<Compile Include="Metadata\MetadataTableTreeNode.cs" />
<Compile Include="Metadata\DebugMetadataTreeNode.cs" />
<Compile Include="ViewModels\LegacyToolPaneModel.cs" />
<Compile Include="ViewModels\ManageAssemblyListsViewModel.cs" />
<Compile Include="ViewModels\ViewModelBase.cs" />
<Compile Include="Views\CreateListDialog.xaml.cs">
@ -248,7 +249,6 @@ @@ -248,7 +249,6 @@
<Compile Include="Images\AccessOverlayIcon.cs" />
<Compile Include="Images\MemberIcon.cs" />
<Compile Include="Images\TypeIcon.cs" />
<Compile Include="IPane.cs" />
<Compile Include="ISmartTextOutput.cs" />
<Compile Include="Images\Images.cs" />
<Compile Include="Languages\ILAstLanguage.cs" />

26
ILSpy/IPane.cs

@ -1,26 +0,0 @@ @@ -1,26 +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.
namespace ICSharpCode.ILSpy
{
public interface IPane
{
void Closed();
}
}

11
ILSpy/Languages/CSharpLanguage.cs

@ -457,6 +457,9 @@ namespace ICSharpCode.ILSpy @@ -457,6 +457,9 @@ namespace ICSharpCode.ILSpy
CSharpAmbience ambience = new CSharpAmbience();
// Do not forget to update CSharpAmbienceTests.ILSpyMainTreeViewTypeFlags, if this ever changes.
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.PlaceReturnTypeAfterParameterList;
if (new DecompilationOptions().DecompilerSettings.LiftNullables) {
ambience.ConversionFlags |= ConversionFlags.UseNullableSpecifierForValueTypes;
}
return ambience;
}
@ -635,7 +638,13 @@ namespace ICSharpCode.ILSpy @@ -635,7 +638,13 @@ namespace ICSharpCode.ILSpy
var output = new StringWriter();
var decoratedWriter = new TextWriterTokenWriter(output);
var writer = new CSharpHighlightingTokenWriter(TokenWriter.InsertRequiredSpaces(decoratedWriter), locatable: decoratedWriter);
new CSharpAmbience() { ConversionFlags = flags }.ConvertSymbol(entity, writer, new DecompilerSettings().CSharpFormattingOptions);
var settings = new DecompilationOptions().DecompilerSettings;
if (!settings.LiftNullables) {
flags &= ~ConversionFlags.UseNullableSpecifierForValueTypes;
}
new CSharpAmbience() {
ConversionFlags = flags,
}.ConvertSymbol(entity, writer, settings.CSharpFormattingOptions);
return new RichText(output.ToString(), writer.HighlightingModel);
}

2
ILSpy/Languages/ILAstLanguage.cs

@ -141,7 +141,7 @@ namespace ICSharpCode.ILSpy @@ -141,7 +141,7 @@ namespace ICSharpCode.ILSpy
}
}
(output as ISmartTextOutput)?.AddButton(Images.ViewCode, "Show Steps", delegate {
DebugStepsPaneModel.Instance.Show();
Docking.DockWorkspace.Instance.ShowToolPane(DebugStepsPaneModel.PaneContentId);
});
output.WriteLine();
il.WriteTo(output, DebugSteps.Options);

10
ILSpy/Languages/Languages.cs

@ -60,5 +60,15 @@ namespace ICSharpCode.ILSpy @@ -60,5 +60,15 @@ namespace ICSharpCode.ILSpy
{
return AllLanguages.FirstOrDefault(l => l.Name == name) ?? AllLanguages.First();
}
static ILLanguage ilLanguage;
public static ILLanguage ILLanguage {
get {
if (ilLanguage == null) {
ilLanguage = (ILLanguage)GetLanguage("IL");
}
return ilLanguage;
}
}
}
}

16
ILSpy/LoadedAssembly.cs

@ -115,6 +115,22 @@ namespace ICSharpCode.ILSpy @@ -115,6 +115,22 @@ namespace ICSharpCode.ILSpy
MinimalCorlib.Instance);
}
ICompilation typeSystemWithOptions;
TypeSystemOptions currentTypeSystemOptions;
public ICompilation GetTypeSystemOrNull(TypeSystemOptions options)
{
if (typeSystemWithOptions != null && options == currentTypeSystemOptions)
return typeSystemWithOptions;
var module = GetPEFileOrNull();
if (module == null)
return null;
currentTypeSystemOptions = options;
return typeSystemWithOptions = new SimpleCompilation(
module.WithOptions(options | TypeSystemOptions.Uncached | TypeSystemOptions.KeepModifiers),
MinimalCorlib.Instance);
}
public AssemblyList AssemblyList => assemblyList;
public string FileName => fileName;

5
ILSpy/LoadedAssemblyExtensions.cs

@ -45,6 +45,11 @@ namespace ICSharpCode.ILSpy @@ -45,6 +45,11 @@ namespace ICSharpCode.ILSpy
return GetLoadedAssembly(file).GetTypeSystemOrNull();
}
public static ICompilation GetTypeSystemWithCurrentOptionsOrNull(this PEFile file)
{
return GetLoadedAssembly(file).GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(new DecompilationOptions().DecompilerSettings));
}
public static LoadedAssembly GetLoadedAssembly(this PEFile file)
{
if (file == null)

19
ILSpy/MainWindow.xaml

@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
MinHeight="200"
UseLayoutRounding="True"
TextOptions.TextFormattingMode="Display"
FocusManager.FocusedElement="{Binding ElementName=treeView}"
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"
>
@ -24,7 +23,7 @@ @@ -24,7 +23,7 @@
<controls:BoolToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<docking:ActiveTabPageConverter x:Key="ActiveTabPageConverter"/>
<tv:SharpTreeView x:Key="TreeView"
<tv:SharpTreeView x:Key="AssemblyTreeView"
AutomationProperties.Name="Assemblies and Classes"
SelectionChanged="TreeView_SelectionChanged"
ShowRoot="False"
@ -33,7 +32,7 @@ @@ -33,7 +32,7 @@
BorderThickness="0,1,1,1" Visibility="Visible" />
<DataTemplate x:Key="AssemblyListPaneTemplate">
<ContentControl Content="{StaticResource TreeView}" />
<ContentControl Content="{StaticResource AssemblyTreeView}" />
</DataTemplate>
<local:DebugSteps x:Key="DebugSteps" />
@ -169,7 +168,7 @@ @@ -169,7 +168,7 @@
<avalondock:DockingManager x:Name="DockManager"
DataContext="{Binding Workspace}"
AnchorablesSource="{Binding ToolPanes}"
AnchorablesSource="{Binding ToolPanes}"
DocumentsSource="{Binding TabPages}"
ActiveContent="{Binding ActiveTabPage, Mode=TwoWay, Converter={StaticResource ActiveTabPageConverter}}"
AllowMixedOrientation="True">
@ -185,18 +184,6 @@ @@ -185,18 +184,6 @@
</DataTemplate>
</avalondock:DockingManager.DocumentHeaderTemplate>
<avalondock:DockingManager.LayoutItemTemplateSelector>
<docking:PaneTemplateSelector>
<docking:PaneTemplateSelector.Mappings>
<docking:TemplateMapping Type="{x:Type viewmodels:AssemblyListPaneModel}" Template="{StaticResource AssemblyListPaneTemplate}" />
<docking:TemplateMapping Type="{x:Type viewmodels:SearchPaneModel}" Template="{StaticResource SearchPaneTemplate}" />
<docking:TemplateMapping Type="{x:Type viewmodels:DebugStepsPaneModel}" Template="{StaticResource DebugStepsPaneTemplate}" />
<docking:TemplateMapping Type="{x:Type viewmodels:AnalyzerPaneModel}" Template="{StaticResource AnalyzerPaneTemplate}" />
<docking:TemplateMapping Type="{x:Type viewmodels:TabPageModel}" Template="{StaticResource DefaultContentTemplate}" />
</docking:PaneTemplateSelector.Mappings>
</docking:PaneTemplateSelector>
</avalondock:DockingManager.LayoutItemTemplateSelector>
<avalondock:DockingManager.LayoutItemContainerStyleSelector>
<docking:PaneStyleSelector>
<docking:PaneStyleSelector.ToolPaneStyle>

151
ILSpy/MainWindow.xaml.cs

@ -84,9 +84,9 @@ namespace ICSharpCode.ILSpy @@ -84,9 +84,9 @@ namespace ICSharpCode.ILSpy
internal AssemblyListManager AssemblyListManager { get; }
public SharpTreeView treeView {
public SharpTreeView AssemblyTreeView {
get {
return FindResource("TreeView") as SharpTreeView;
return FindResource("AssemblyTreeView") as SharpTreeView;
}
}
@ -120,13 +120,13 @@ namespace ICSharpCode.ILSpy @@ -120,13 +120,13 @@ namespace ICSharpCode.ILSpy
DockWorkspace.Instance.LoadSettings(sessionSettings);
InitializeComponent();
InitToolPanes();
DockWorkspace.Instance.InitializeLayout(DockManager);
sessionSettings.FilterSettings.PropertyChanged += filterSettings_PropertyChanged;
sessionSettings.PropertyChanged += SessionSettings_PropertyChanged;
InitMainMenu();
InitToolbar();
ContextMenuProvider.Add(treeView);
ContextMenuProvider.Add(AssemblyTreeView);
this.Loaded += MainWindow_Loaded;
}
@ -231,6 +231,48 @@ namespace ICSharpCode.ILSpy @@ -231,6 +231,48 @@ 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;
}
public void ShowInTopPane(string title, object content)
{
var model = DockWorkspace.Instance.ToolPanes.OfType<LegacyToolPaneModel>().FirstOrDefault(p => p.Content == content);
if (model == null) {
model = new LegacyToolPaneModel(title, content, LegacyToolPaneLocation.Top);
DockWorkspace.Instance.ToolPanes.Add(model);
}
model.Show();
}
public void ShowInBottomPane(string title, object content)
{
var model = DockWorkspace.Instance.ToolPanes.OfType<LegacyToolPaneModel>().FirstOrDefault(p => p.Content == content);
if (model == null) {
model = new LegacyToolPaneModel(title, content, LegacyToolPaneLocation.Bottom);
DockWorkspace.Instance.ToolPanes.Add(model);
}
model.Show();
}
#endregion
#region Message Hook
protected override void OnSourceInitialized(EventArgs e)
{
@ -337,7 +379,7 @@ namespace ICSharpCode.ILSpy @@ -337,7 +379,7 @@ namespace ICSharpCode.ILSpy
async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ILSpySettings spySettings, List<LoadedAssembly> relevantAssemblies)
{
var initialSelection = treeView.SelectedItem;
var initialSelection = AssemblyTreeView.SelectedItem;
if (navigateTo != null) {
bool found = false;
if (navigateTo.StartsWith("N:", StringComparison.Ordinal)) {
@ -351,7 +393,7 @@ namespace ICSharpCode.ILSpy @@ -351,7 +393,7 @@ namespace ICSharpCode.ILSpy
NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName);
if (nsNode != null) {
found = true;
if (treeView.SelectedItem == initialSelection) {
if (AssemblyTreeView.SelectedItem == initialSelection) {
SelectNode(nsNode);
}
break;
@ -366,12 +408,12 @@ namespace ICSharpCode.ILSpy @@ -366,12 +408,12 @@ namespace ICSharpCode.ILSpy
IEntity mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies));
if (mr != null && mr.ParentModule.PEFile != null) {
found = true;
if (treeView.SelectedItem == initialSelection) {
if (AssemblyTreeView.SelectedItem == initialSelection) {
JumpToReference(mr);
}
}
}
if (!found && treeView.SelectedItem == initialSelection) {
if (!found && AssemblyTreeView.SelectedItem == initialSelection) {
AvalonEditTextOutput output = new AvalonEditTextOutput();
output.Write(string.Format("Cannot find '{0}' in command line specified assemblies.", navigateTo));
DockWorkspace.Instance.ShowText(output);
@ -380,7 +422,7 @@ namespace ICSharpCode.ILSpy @@ -380,7 +422,7 @@ namespace ICSharpCode.ILSpy
// NavigateTo == null and an assembly was given on the command-line:
// Select the newly loaded assembly
AssemblyTreeNode asmNode = assemblyListTreeNode.FindAssemblyNode(relevantAssemblies[0]);
if (asmNode != null && treeView.SelectedItem == initialSelection) {
if (asmNode != null && AssemblyTreeView.SelectedItem == initialSelection) {
SelectNode(asmNode);
}
} else if (spySettings != null) {
@ -395,7 +437,7 @@ namespace ICSharpCode.ILSpy @@ -395,7 +437,7 @@ namespace ICSharpCode.ILSpy
}
node = FindNodeByPath(activeTreeViewPath, true);
}
if (treeView.SelectedItem == initialSelection) {
if (AssemblyTreeView.SelectedItem == initialSelection) {
if (node != null) {
SelectNode(node);
@ -598,6 +640,7 @@ namespace ICSharpCode.ILSpy @@ -598,6 +640,7 @@ namespace ICSharpCode.ILSpy
//Only load a new list when it is a different one
if (list.ListName != CurrentAssemblyList.ListName) {
ShowAssemblyList(list);
SelectNode(AssemblyTreeView.Root);
}
}
@ -611,7 +654,7 @@ namespace ICSharpCode.ILSpy @@ -611,7 +654,7 @@ namespace ICSharpCode.ILSpy
assemblyListTreeNode = new AssemblyListTreeNode(assemblyList);
assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone();
assemblyListTreeNode.Select = x => SelectNode(x, inNewTabPage: false);
treeView.Root = assemblyListTreeNode;
AssemblyTreeView.Root = assemblyListTreeNode;
if (assemblyList.ListName == AssemblyListManager.DefaultListName)
#if DEBUG
@ -662,6 +705,7 @@ namespace ICSharpCode.ILSpy @@ -662,6 +705,7 @@ namespace ICSharpCode.ILSpy
void filterSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
RefreshTreeView();
RefreshTreeViewFilter();
if (e.PropertyName == "Language" || e.PropertyName == "LanguageVersion") {
DecompileSelectedNodes(recordHistory: false);
@ -683,7 +727,17 @@ namespace ICSharpCode.ILSpy @@ -683,7 +727,17 @@ namespace ICSharpCode.ILSpy
#region Node Selection
public void SelectNode(SharpTreeNode obj, bool inNewTabPage = false)
public void SelectNode(SharpTreeNode obj)
{
SelectNode(obj, false);
}
public void SelectNode(SharpTreeNode obj, bool inNewTabPage)
{
SelectNode(obj, inNewTabPage, true);
}
public void SelectNode(SharpTreeNode obj, bool inNewTabPage, bool setFocus)
{
if (obj != null) {
if (!obj.AncestorsAndSelf().Any(node => node.IsHidden)) {
@ -694,12 +748,16 @@ namespace ICSharpCode.ILSpy @@ -694,12 +748,16 @@ namespace ICSharpCode.ILSpy
LanguageVersion = CurrentLanguageVersion
});
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
treeView.SelectedItem = null;
AssemblyTreeView.SelectedItem = null;
}
// Set both the selection and focus to ensure that keyboard navigation works as expected.
treeView.FocusNode(obj);
treeView.SelectedItem = obj;
if (setFocus) {
AssemblyTreeView.FocusNode(obj);
} else {
AssemblyTreeView.ScrollIntoView(obj);
}
AssemblyTreeView.SelectedItem = obj;
} else {
MessageBox.Show("Navigation failed because the target is hidden or a compiler-generated class.\n" +
"Please disable all filters that might hide the item (i.e. activate " +
@ -709,7 +767,17 @@ namespace ICSharpCode.ILSpy @@ -709,7 +767,17 @@ namespace ICSharpCode.ILSpy
}
}
public void SelectNodes(IEnumerable<SharpTreeNode> nodes, bool inNewTabPage = false)
public void SelectNodes(IEnumerable<SharpTreeNode> nodes)
{
SelectNodes(nodes, false);
}
public void SelectNodes(IEnumerable<SharpTreeNode> nodes, bool inNewTabPage)
{
SelectNodes(nodes, inNewTabPage, true);
}
public void SelectNodes(IEnumerable<SharpTreeNode> nodes, bool inNewTabPage, bool setFocus)
{
if (nodes.Any() && nodes.All(n => !n.AncestorsAndSelf().Any(a => a.IsHidden))) {
if (inNewTabPage) {
@ -721,8 +789,12 @@ namespace ICSharpCode.ILSpy @@ -721,8 +789,12 @@ namespace ICSharpCode.ILSpy
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
}
treeView.FocusNode(nodes.First());
treeView.SetSelectedNodes(nodes);
if (setFocus) {
AssemblyTreeView.FocusNode(nodes.First());
} else {
AssemblyTreeView.ScrollIntoView(nodes.First());
}
AssemblyTreeView.SetSelectedNodes(nodes);
}
}
@ -733,7 +805,7 @@ namespace ICSharpCode.ILSpy @@ -733,7 +805,7 @@ namespace ICSharpCode.ILSpy
{
if (path == null)
return null;
SharpTreeNode node = treeView.Root;
SharpTreeNode node = AssemblyTreeView.Root;
SharpTreeNode bestMatch = node;
foreach (var element in path) {
if (node == null)
@ -886,7 +958,7 @@ namespace ICSharpCode.ILSpy @@ -886,7 +958,7 @@ namespace ICSharpCode.ILSpy
throw new ArgumentNullException(nameof(fileNames));
if (focusNode)
treeView.UnselectAll();
AssemblyTreeView.UnselectAll();
LoadAssemblies(fileNames, focusNode: focusNode);
}
@ -912,7 +984,7 @@ namespace ICSharpCode.ILSpy @@ -912,7 +984,7 @@ namespace ICSharpCode.ILSpy
else {
var node = assemblyListTreeNode.FindAssemblyNode(nugetAsm);
if (node != null && focusNode) {
treeView.SelectedItems.Add(node);
AssemblyTreeView.SelectedItems.Add(node);
lastNode = node;
}
}
@ -930,7 +1002,7 @@ namespace ICSharpCode.ILSpy @@ -930,7 +1002,7 @@ namespace ICSharpCode.ILSpy
else {
var node = assemblyListTreeNode.FindAssemblyNode(asm);
if (node != null && focusNode) {
treeView.SelectedItems.Add(node);
AssemblyTreeView.SelectedItems.Add(node);
lastNode = node;
}
}
@ -939,17 +1011,22 @@ namespace ICSharpCode.ILSpy @@ -939,17 +1011,22 @@ namespace ICSharpCode.ILSpy
}
if (lastNode != null && focusNode)
treeView.FocusNode(lastNode);
AssemblyTreeView.FocusNode(lastNode);
}
}
void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
RefreshTreeView();
}
void RefreshTreeView()
{
try {
refreshInProgress = true;
var path = GetPathForNode(treeView.SelectedItem as SharpTreeNode);
var path = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
ShowAssemblyList(AssemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName));
SelectNode(FindNodeByPath(path, true));
SelectNode(FindNodeByPath(path, true), false, false);
} finally {
refreshInProgress = false;
}
@ -957,7 +1034,7 @@ namespace ICSharpCode.ILSpy @@ -957,7 +1034,7 @@ namespace ICSharpCode.ILSpy
void SearchCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
SearchPaneModel.Instance.Show();
DockWorkspace.Instance.ShowToolPane(SearchPaneModel.PaneContentId);
}
#endregion
@ -977,20 +1054,20 @@ namespace ICSharpCode.ILSpy @@ -977,20 +1054,20 @@ namespace ICSharpCode.ILSpy
if (ignoreDecompilationRequests)
return;
if (treeView.SelectedItems.Count == 0 && refreshInProgress)
if (AssemblyTreeView.SelectedItems.Count == 0 && refreshInProgress)
return;
if (recordHistory) {
var currentState = DockWorkspace.Instance.ActiveTabPage.GetState();
if (currentState != null)
history.UpdateCurrent(new NavigationState(currentState));
history.Record(new NavigationState(treeView.SelectedItems.OfType<SharpTreeNode>()));
history.Record(new NavigationState(AssemblyTreeView.SelectedItems.OfType<SharpTreeNode>()));
}
DockWorkspace.Instance.ActiveTabPage.SupportsLanguageSwitching = true;
if (treeView.SelectedItems.Count == 1) {
ILSpyTreeNode node = treeView.SelectedItem as ILSpyTreeNode;
if (AssemblyTreeView.SelectedItems.Count == 1) {
ILSpyTreeNode node = AssemblyTreeView.SelectedItem as ILSpyTreeNode;
if (node != null && node.View(DockWorkspace.Instance.ActiveTabPage))
return;
}
@ -1029,7 +1106,7 @@ namespace ICSharpCode.ILSpy @@ -1029,7 +1106,7 @@ namespace ICSharpCode.ILSpy
public IEnumerable<ILSpyTreeNode> SelectedNodes {
get {
return treeView.GetTopLevelSelection().OfType<ILSpyTreeNode>();
return AssemblyTreeView.GetTopLevelSelection().OfType<ILSpyTreeNode>();
}
}
#endregion
@ -1071,12 +1148,12 @@ namespace ICSharpCode.ILSpy @@ -1071,12 +1148,12 @@ namespace ICSharpCode.ILSpy
var newState = forward ? history.GoForward() : history.GoBack();
ignoreDecompilationRequests = true;
treeView.SelectedItems.Clear();
AssemblyTreeView.SelectedItems.Clear();
foreach (var node in newState.TreeNodes) {
treeView.SelectedItems.Add(node);
AssemblyTreeView.SelectedItems.Add(node);
}
if (newState.TreeNodes.Any())
treeView.FocusNode(newState.TreeNodes.First());
AssemblyTreeView.FocusNode(newState.TreeNodes.First());
ignoreDecompilationRequests = false;
DecompileSelectedNodes(newState.ViewState as DecompilerTextViewState, false);
}
@ -1136,8 +1213,8 @@ namespace ICSharpCode.ILSpy @@ -1136,8 +1213,8 @@ namespace ICSharpCode.ILSpy
{
base.OnClosing(e);
sessionSettings.ActiveAssemblyList = assemblyList.ListName;
sessionSettings.ActiveTreeViewPath = GetPathForNode(treeView.SelectedItem as SharpTreeNode);
sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(treeView.SelectedItem as SharpTreeNode);
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.Save();
@ -1161,7 +1238,7 @@ namespace ICSharpCode.ILSpy @@ -1161,7 +1238,7 @@ namespace ICSharpCode.ILSpy
public void UnselectAll()
{
treeView.UnselectAll();
AssemblyTreeView.UnselectAll();
}
public void SetStatus(string status, Brush foreground)

2
ILSpy/Metadata/CorTables/EventTableTreeNode.cs

@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy.Metadata
public string Name => metadata.GetString(eventDef.Name);
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
[StringFormat("X8")]
public int Type => MetadataTokens.GetToken(eventDef.Type);

2
ILSpy/Metadata/CorTables/FieldTableTreeNode.cs

@ -104,7 +104,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -104,7 +104,7 @@ namespace ICSharpCode.ILSpy.Metadata
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(fieldDef.Name):X} \"{Name}\"";
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
[StringFormat("X")]
public int Signature => MetadataTokens.GetHeapOffset(fieldDef.Signature);

2
ILSpy/Metadata/CorTables/MethodTableTreeNode.cs

@ -130,7 +130,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -130,7 +130,7 @@ namespace ICSharpCode.ILSpy.Metadata
}
}
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
public MethodDefEntry(PEFile module, MethodDefinitionHandle handle)
{

2
ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs

@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy.Metadata
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(propertyDef.Name):X} \"{Name}\"";
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
[StringFormat("X")]
public int Signature => MetadataTokens.GetHeapOffset(propertyDef.Signature);

2
ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs

@ -165,7 +165,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -165,7 +165,7 @@ namespace ICSharpCode.ILSpy.Metadata
}
}
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle);
public TypeDefEntry(PEFile module, TypeDefinitionHandle handle)
{

2
ILSpy/Search/LiteralSearchStrategy.cs

@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy.Search @@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy.Search
{
cancellationToken.ThrowIfCancellationRequested();
var metadata = module.Metadata;
var typeSystem = module.GetTypeSystemOrNull();
var typeSystem = module.GetTypeSystemWithCurrentOptionsOrNull();
if (typeSystem == null) return;
foreach (var handle in metadata.MethodDefinitions) {

2
ILSpy/Search/MemberSearchStrategy.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.Search @@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.Search
{
cancellationToken.ThrowIfCancellationRequested();
var metadata = module.Metadata;
var typeSystem = module.GetTypeSystemOrNull();
var typeSystem = module.GetTypeSystemWithCurrentOptionsOrNull();
if (typeSystem == null) return;
if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Type) {

2
ILSpy/Search/MetadataTokenSearchStrategy.cs

@ -26,7 +26,7 @@ namespace ICSharpCode.ILSpy.Search @@ -26,7 +26,7 @@ namespace ICSharpCode.ILSpy.Search
{
cancellationToken.ThrowIfCancellationRequested();
if (searchTermToken.IsNil) return;
var typeSystem = module.GetTypeSystemOrNull();
var typeSystem = module.GetTypeSystemWithCurrentOptionsOrNull();
if (typeSystem == null) return;
var metadataModule = (MetadataModule)typeSystem.MainModule;
int row = module.Metadata.GetRowNumber(searchTermToken);

2
ILSpy/Search/NamespaceSearchStrategy.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy.Search @@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy.Search
public override void Search(PEFile module, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var typeSystem = module.GetTypeSystemOrNull();
var typeSystem = module.GetTypeSystemWithCurrentOptionsOrNull();
if (typeSystem == null) return;
var root = ((MetadataModule)typeSystem.MainModule).RootNamespace;

10
ILSpy/Search/SearchPane.cs

@ -23,6 +23,7 @@ using System.Collections.ObjectModel; @@ -23,6 +23,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@ -40,7 +41,7 @@ namespace ICSharpCode.ILSpy @@ -40,7 +41,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Search pane
/// </summary>
public partial class SearchPane : UserControl, IPane
public partial class SearchPane : UserControl
{
const int MAX_RESULTS = 1000;
const int MAX_REFRESH_TIME_MS = 10; // More means quicker forward of data, less means better responsibility
@ -105,7 +106,7 @@ namespace ICSharpCode.ILSpy @@ -105,7 +106,7 @@ namespace ICSharpCode.ILSpy
public void Show()
{
if (!IsVisible) {
SearchPaneModel.Instance.IsVisible = true;
DockWorkspace.Instance.ToolPanes.Single(p => p.ContentId == SearchPaneModel.PaneContentId).IsVisible = true;
if (runSearchOnNextShow) {
runSearchOnNextShow = false;
StartSearch(this.SearchTerm);
@ -139,11 +140,6 @@ namespace ICSharpCode.ILSpy @@ -139,11 +140,6 @@ namespace ICSharpCode.ILSpy
MainWindow.Instance.SessionSettings.SelectedSearchMode = (SearchMode)searchModeComboBox.SelectedIndex;
StartSearch(this.SearchTerm);
}
void IPane.Closed()
{
this.SearchTerm = string.Empty;
}
void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{

4
ILSpy/TextView/DecompilerTextView.cs

@ -581,7 +581,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -581,7 +581,7 @@ namespace ICSharpCode.ILSpy.TextView
this.nextDecompilationRun = null;
}
if (nodes != null && string.IsNullOrEmpty(textOutput.Title))
textOutput.Title = string.Join(", ", nodes.Select(n => n.ToString()));
textOutput.Title = string.Join(", ", nodes.Select(n => n.Text));
ShowOutput(textOutput, highlighting);
decompiledNodes = nodes;
}
@ -772,7 +772,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -772,7 +772,7 @@ namespace ICSharpCode.ILSpy.TextView
{
var nodes = context.TreeNodes;
if (textOutput is ISmartTextOutput smartTextOutput) {
smartTextOutput.Title = string.Join(", ", nodes.Select(n => n.ToString()));
smartTextOutput.Title = string.Join(", ", nodes.Select(n => n.Text));
}
for (int i = 0; i < nodes.Length; i++) {
if (i > 0)

2
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -139,7 +139,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -139,7 +139,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
// if we crashed on loading, then we don't have any children
return;
}
typeSystem = LoadedAssembly.GetTypeSystemOrNull();
typeSystem = LoadedAssembly.GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(new DecompilationOptions().DecompilerSettings));
var assembly = (MetadataModule)typeSystem.MainModule;
var metadata = module.Metadata;
this.Children.Add(new Metadata.MetadataTreeNode(module, this));

2
ILSpy/TreeNodes/BaseTypesEntryNode.cs

@ -54,7 +54,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -54,7 +54,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
var t = typeSystem.MainModule.ResolveEntity(handle) as ITypeDefinition;
if (t != null) {
showExpander = t.DirectBaseTypes.Any();
var other = t.ParentModule.PEFile.GetTypeSystemOrNull();
var other = t.ParentModule.PEFile.GetTypeSystemWithCurrentOptionsOrNull();
Debug.Assert(other != null);
t = other.FindType(t.FullTypeName).GetDefinition();
} else {

5
ILSpy/TreeNodes/EventTreeNode.cs

@ -86,5 +86,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -86,5 +86,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
IEntity IMemberTreeNode.Member => EventDefinition;
public override string ToString()
{
return EventDefinition.Name;
}
}
}

5
ILSpy/TreeNodes/FieldTreeNode.cs

@ -87,5 +87,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -87,5 +87,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
IEntity IMemberTreeNode.Member => FieldDefinition;
public override string ToString()
{
return FieldDefinition.Name;
}
}
}

5
ILSpy/TreeNodes/MethodTreeNode.cs

@ -112,5 +112,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -112,5 +112,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
IEntity IMemberTreeNode.Member => MethodDefinition;
public override string ToString()
{
return Languages.ILLanguage.MethodToString(MethodDefinition, false, false, false);
}
}
}

5
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -93,5 +93,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -93,5 +93,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
IEntity IMemberTreeNode.Member => PropertyDefinition;
public override string ToString()
{
return Languages.ILLanguage.PropertyToString(PropertyDefinition, false, false, false);
}
}
}

5
ILSpy/TreeNodes/TypeTreeNode.cs

@ -154,5 +154,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -154,5 +154,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
IEntity IMemberTreeNode.Member => TypeDefinition;
public override string ToString()
{
return TypeDefinition.ReflectionName;
}
}
}

7
ILSpy/ViewModels/AnalyzerPaneModel.cs

@ -16,18 +16,21 @@ @@ -16,18 +16,21 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels
{
[ExportToolPane(ContentId = PaneContentId)]
public class AnalyzerPaneModel : ToolPaneModel
{
public const string PaneContentId = "analyzerPane";
public static AnalyzerPaneModel Instance { get; } = new AnalyzerPaneModel();
private AnalyzerPaneModel()
{
ContentId = PaneContentId;
Title = Properties.Resources.Analyze;
}
public override DataTemplate Template => (DataTemplate)MainWindow.Instance.FindResource("AnalyzerPaneTemplate");
}
}

6
ILSpy/ViewModels/AssemblyListPaneModel.cs

@ -16,21 +16,23 @@ @@ -16,21 +16,23 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Windows;
using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy.ViewModels
{
[ExportToolPane(ContentId = PaneContentId)]
public class AssemblyListPaneModel : ToolPaneModel
{
public const string PaneContentId = "assemblyListPane";
public static AssemblyListPaneModel Instance { get; } = new AssemblyListPaneModel();
private AssemblyListPaneModel()
{
Title = Resources.Assemblies;
ContentId = PaneContentId;
IsCloseable = false;
}
public override DataTemplate Template => (DataTemplate)MainWindow.Instance.FindResource("AssemblyListPaneTemplate");
}
}

7
ILSpy/ViewModels/DebugStepsPaneModel.cs

@ -16,18 +16,21 @@ @@ -16,18 +16,21 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels
{
[ExportToolPane(ContentId = PaneContentId)]
public class DebugStepsPaneModel : ToolPaneModel
{
public const string PaneContentId = "debugStepsPane";
public static DebugStepsPaneModel Instance { get; } = new DebugStepsPaneModel();
private DebugStepsPaneModel()
{
ContentId = PaneContentId;
Title = Properties.Resources.DebugSteps;
}
public override DataTemplate Template => (DataTemplate)MainWindow.Instance.FindResource("DebugStepsPaneTemplate");
}
}

32
ILSpy/ViewModels/LegacyToolPaneModel.cs

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels
{
internal enum LegacyToolPaneLocation
{
Top,
Bottom
}
internal class LegacyToolPaneModel : ToolPaneModel
{
public LegacyToolPaneModel(string title, object content, LegacyToolPaneLocation location)
{
this.Title = title;
this.Content = content;
this.IsCloseable = true;
this.Location = location;
}
public object Content { get; }
public override DataTemplate Template => throw new NotSupportedException();
public LegacyToolPaneLocation Location { get; }
}
}

7
ILSpy/ViewModels/SearchPaneModel.cs

@ -16,14 +16,15 @@ @@ -16,14 +16,15 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels
{
[ExportToolPane(ContentId = PaneContentId)]
public class SearchPaneModel : ToolPaneModel
{
public const string PaneContentId = "searchPane";
public static SearchPaneModel Instance { get; } = new SearchPaneModel();
private SearchPaneModel()
{
ContentId = PaneContentId;
@ -36,5 +37,7 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -36,5 +37,7 @@ namespace ICSharpCode.ILSpy.ViewModels
base.Show();
MainWindow.Instance.SearchPane.Show();
}
public override DataTemplate Template => (DataTemplate)MainWindow.Instance.FindResource("SearchPaneTemplate");
}
}

4
ILSpy/ViewModels/ToolPaneModel.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels
{
public abstract class ToolPaneModel : PaneModel
@ -25,5 +27,7 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -25,5 +27,7 @@ namespace ICSharpCode.ILSpy.ViewModels
this.IsActive = true;
this.IsVisible = true;
}
public abstract DataTemplate Template { get; }
}
}

14
ILSpy/Views/DebugSteps.xaml.cs

@ -9,7 +9,7 @@ using ICSharpCode.ILSpy.ViewModels; @@ -9,7 +9,7 @@ using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy
{
public partial class DebugSteps : UserControl, IPane
public partial class DebugSteps : UserControl
{
static readonly ILAstWritingOptions writingOptions = new ILAstWritingOptions {
UseFieldSugar = true,
@ -79,18 +79,6 @@ namespace ICSharpCode.ILSpy @@ -79,18 +79,6 @@ namespace ICSharpCode.ILSpy
#endif
}
void IPane.Closed()
{
#if DEBUG
MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged -= FilterSettings_PropertyChanged;
MainWindow.Instance.SelectionChanged -= SelectionChanged;
writingOptions.PropertyChanged -= WritingOptions_PropertyChanged;
if (language != null) {
language.StepperUpdated -= ILAstStepperUpdated;
}
#endif
}
private void ShowStateAfter_Click(object sender, RoutedEventArgs e)
{
Stepper.Node n = (Stepper.Node)tree.SelectedItem;

Loading…
Cancel
Save