Browse Source

Merge branch 'master' into pattern-matching

pull/2461/head
Siegfried Pammer 4 years ago committed by GitHub
parent
commit
6290e2f016
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 6
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  3. 33
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
  4. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/ForLoopTests.xml
  5. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml
  6. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/LambdaCapturing.xml
  7. 50
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CovariantReturns.cs
  8. 5
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InterfaceTests.cs
  9. 23
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  10. 2
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  11. 8
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  12. 95
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
  13. 138
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs
  14. 12
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  15. 2
      ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs
  16. 22
      ICSharpCode.Decompiler/DecompilerSettings.cs
  17. 16
      ICSharpCode.Decompiler/Disassembler/ILParser.cs
  18. 122
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  19. 5
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  20. 61
      ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs
  21. 15
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  22. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template
  23. 2
      ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs
  24. 2
      ICSharpCode.Decompiler/IL/ILReader.cs
  25. 2
      ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs
  26. 4
      ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs
  27. 2
      ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs
  28. 2
      ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs
  29. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
  30. 14
      ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs
  31. 4
      ICSharpCode.Decompiler/Util/CacheManager.cs
  32. 6
      ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs
  33. 16
      ILSpy.AddIn/Commands/OpenReferenceCommand.cs
  34. 10
      ILSpy.AddIn/ILSpy.AddIn.csproj
  35. 7
      ILSpy.AddIn/ILSpyAddIn.en-US.vsct
  36. 15
      ILSpy.AddIn/ILSpyAddIn.vsct
  37. 6
      ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct
  38. 6
      ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs
  39. 1
      ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
  40. 36
      ILSpy.BamlDecompiler/BamlDecompilationResult.cs
  41. 50
      ILSpy.BamlDecompiler/BamlDecompilerSettings.cs
  42. 144
      ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs
  43. 140
      ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
  44. 9
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  45. 6
      ILSpy.BamlDecompiler/XamlContext.cs
  46. 81
      ILSpy.BamlDecompiler/XamlDecompiler.cs
  47. 5
      ILSpy.Package/ILSpy.Package.wapproj
  48. 4
      ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj
  49. 2
      ILSpy.ReadyToRun/ReadyToRunDisassembler.cs
  50. 1
      ILSpy.Tests/ILSpy.Tests.csproj
  51. 44
      ILSpy.WithPackage.sln
  52. 3
      ILSpy/Analyzers/AnalyzerScope.cs
  53. 18
      ILSpy/Commands/ShowDebugSteps.cs
  54. 35
      ILSpy/Commands/ShowPane.cs
  55. 2
      ILSpy/FilterSettings.cs
  56. 11
      ILSpy/ILSpy.csproj
  57. 5
      ILSpy/Languages/CSharpILMixedLanguage.cs
  58. 1
      ILSpy/Languages/ILLanguage.cs
  59. 48
      ILSpy/LoadedAssembly.cs
  60. 2
      ILSpy/MainWindow.xaml
  61. 46
      ILSpy/MainWindow.xaml.cs
  62. 14
      ILSpy/Options/DisplaySettings.cs
  63. 32
      ILSpy/Options/DisplaySettingsPanel.xaml
  64. 2
      ILSpy/Options/DisplaySettingsPanel.xaml.cs
  65. 4
      ILSpy/Properties/AssemblyInfo.template.cs
  66. 80
      ILSpy/Properties/Resources.Designer.cs
  67. 32
      ILSpy/Properties/Resources.resx
  68. 6
      ILSpy/Properties/Resources.zh-Hans.resx
  69. 36
      ILSpy/Search/AbstractSearchStrategy.cs
  70. 2
      ILSpy/Search/SearchPane.cs
  71. 7
      ILSpy/SolutionWriter.cs
  72. 46
      ILSpy/TextView/DecompilerTextView.cs
  73. 4
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  74. 94
      ILSpy/app.manifest
  75. 4
      SharpTreeView/ICSharpCode.TreeView.csproj
  76. 28
      doc/third-party-notices.txt
  77. 10
      packages.props

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

@ -52,6 +52,7 @@ @@ -52,6 +52,7 @@
<PackageReference Include="Microsoft.DiaSymReader.Converter.Xml" Version="$(DSRConverterXmlVersion)" />
<PackageReference Include="NUnit3TestAdapter" Version="$(NUnitAdapterVersion)" />
<PackageReference Include="NUnit" Version="$(NUnitVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkVersion)" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="Mono.Cecil" Version="$(MonoCecilVersion)" />
<PackageReference Include="Microsoft.NETCore.ILAsm" Version="$(ILAsmVersion)" />
@ -108,6 +109,7 @@ @@ -108,6 +109,7 @@
<Compile Include="TestCases\Correctness\DynamicTests.cs" />
<Compile Include="TestCases\Correctness\StringConcat.cs" />
<Compile Include="TestCases\Pretty\PatternMatching.cs" />
<None Include="TestCases\Pretty\CovariantReturns.cs" />
<Compile Include="TestCases\VBPretty\VBPropertiesTest.cs" />
<None Include="TestCases\ILPretty\Issue2260SwitchString.cs" />
<None Include="TestCases\Pretty\Records.cs" />

6
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -579,6 +579,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -579,6 +579,12 @@ namespace ICSharpCode.Decompiler.Tests
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
[Test]
public void CovariantReturns([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
{
Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings);

33
ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs

@ -36,6 +36,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -36,6 +36,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Issue1747();
CallAmbiguousOutParam();
CallWithInParam();
Issue2444.M2();
}
#region ConstructorTest
@ -334,6 +335,38 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -334,6 +335,38 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
}
#endif
#endregion
#region #2444
public struct Issue2444
{
public class X { }
public class Y { }
public static implicit operator Issue2444(X x)
{
Console.WriteLine("#2444: op_Implicit(X)");
return new Issue2444();
}
public static implicit operator Issue2444(Y y)
{
Console.WriteLine("#2444: op_Implicit(Y)");
return new Issue2444();
}
public static void M1(Issue2444 z)
{
Console.WriteLine(string.Format("#2444: M1({0})", z));
}
public static void M2()
{
Console.WriteLine("#2444: before M1");
M1((X)null);
Console.WriteLine("#2444: after M1");
}
}
#endregion
}
class IndexerTests

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
{

50
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CovariantReturns.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
namespace ICSharpCode.Decompiler.Tests.TestCases.CovariantReturns
{
public abstract class Base
{
public abstract Base Instance { get; }
public abstract Base this[int index] { get; }
public virtual Base Build()
{
throw null;
}
protected abstract Base SetParent(object parent);
}
public class Derived : Base
{
public override Derived Instance { get; }
public override Derived this[int index] {
get {
throw null;
}
}
public override Derived Build()
{
throw null;
}
protected override Derived SetParent(object parent)
{
throw null;
}
}
public class UseSites
{
public Base Test(Base x)
{
return x.Build();
}
public Derived Test(Derived x)
{
return x.Build();
}
}
}

5
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InterfaceTests.cs

@ -32,6 +32,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -32,6 +32,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
void Method();
#if CS80
static IA()
{
}
void DefaultMethod()
{
Method();

23
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1453,9 +1453,24 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1453,9 +1453,24 @@ namespace ICSharpCode.Decompiler.CSharp
{
SetNewModifier(methodDecl);
}
if (IsCovariantReturnOverride(method))
{
RemoveAttribute(methodDecl, KnownAttribute.PreserveBaseOverrides);
methodDecl.Modifiers &= ~(Modifiers.New | Modifiers.Virtual);
methodDecl.Modifiers |= Modifiers.Override;
}
return methodDecl;
}
private bool IsCovariantReturnOverride(IEntity entity)
{
if (!settings.CovariantReturns)
return false;
if (!entity.HasAttribute(KnownAttribute.PreserveBaseOverrides))
return false;
return true;
}
internal static bool IsWindowsFormsInitializeComponentMethod(IMethod method)
{
return method.ReturnType.Kind == TypeKind.Void && method.Name == "InitializeComponent" && method.DeclaringTypeDefinition.GetNonInterfaceBaseTypes().Any(t => t.FullName == "System.Windows.Forms.Control");
@ -1768,7 +1783,15 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1768,7 +1783,15 @@ namespace ICSharpCode.Decompiler.CSharp
var accessorHandle = (MethodDefinitionHandle)(property.Getter ?? property.Setter).MetadataToken;
var accessor = metadata.GetMethodDefinition(accessorHandle);
if (!accessorHandle.GetMethodImplementations(metadata).Any() && accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot))
{
SetNewModifier(propertyDecl);
}
if (getterHasBody && IsCovariantReturnOverride(property.Getter))
{
RemoveAttribute(getter, KnownAttribute.PreserveBaseOverrides);
propertyDecl.Modifiers &= ~(Modifiers.New | Modifiers.Virtual);
propertyDecl.Modifiers |= Modifiers.Override;
}
return propertyDecl;
}
catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException))

2
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -1148,7 +1148,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1148,7 +1148,7 @@ namespace ICSharpCode.Decompiler.CSharp
var conversions = CSharpConversions.Get(expressionBuilder.compilation);
IType targetType = method.ReturnType;
var conv = conversions.ImplicitConversion(argument.Type, targetType);
if (!(conv.IsUserDefined && conv.Method.Equals(method)))
if (!(conv.IsUserDefined && conv.IsValid && conv.Method.Equals(method)))
{
// implicit conversion to targetType isn't directly possible, so first insert a cast to the argument type
argument = argument.ConvertTo(method.Parameters[0].Type, expressionBuilder);

8
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1618,7 +1618,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1618,7 +1618,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else
{
return compilation.FindType(stackType.ToKnownTypeCode(sign));
return compilation.FindType(stackType, sign);
}
}
@ -1644,7 +1644,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1644,7 +1644,7 @@ namespace ICSharpCode.Decompiler.CSharp
stackType = StackType.I8;
}
}
return compilation.FindType(stackType.ToKnownTypeCode(sign));
return compilation.FindType(stackType, sign);
}
/// <summary>
@ -3568,7 +3568,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3568,7 +3568,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if (!value.Type.Equals(SpecialType.NullType) && !fallback.Type.Equals(SpecialType.NullType) && !value.Type.Equals(fallback.Type))
{
targetType = compilation.FindType(inst.UnderlyingResultType.ToKnownTypeCode());
targetType = compilation.FindType(inst.UnderlyingResultType);
}
else
{
@ -3731,7 +3731,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3731,7 +3731,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else
{
resultType = compilation.FindType(inst.ResultType.ToKnownTypeCode());
resultType = compilation.FindType(inst.ResultType);
}
foreach (var section in inst.Sections)

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

@ -36,6 +36,8 @@ using ICSharpCode.Decompiler.Solution; @@ -36,6 +36,8 @@ using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using Microsoft.Win32;
using static ICSharpCode.Decompiler.Metadata.MetadataExtensions;
namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
@ -126,7 +128,6 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -126,7 +128,6 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
// per-run members
HashSet<string> directories = new HashSet<string>(Platform.FileNameComparer);
readonly IProjectFileWriter projectWriter;
public void DecompileProject(PEFile moduleDefinition, string targetDirectory, CancellationToken cancellationToken = default(CancellationToken))
@ -252,7 +253,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -252,7 +253,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
#region WriteResourceFilesInProject
protected virtual IEnumerable<(string itemType, string fileName)> WriteResourceFilesInProject(Metadata.PEFile module)
{
foreach (var r in module.Resources.Where(r => r.ResourceType == Metadata.ResourceType.Embedded))
foreach (var r in module.Resources.Where(r => r.ResourceType == ResourceType.Embedded))
{
Stream stream = r.TryOpenStream();
stream.Position = 0;
@ -268,7 +269,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -268,7 +269,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
foreach (var (name, value) in resourcesFile)
{
string fileName = Path.Combine(name.Split('/').Select(p => CleanUpFileName(p)).ToArray());
string fileName = CleanUpFileName(name)
.Replace('/', Path.DirectorySeparatorChar);
string dirName = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName))
{
@ -359,8 +361,15 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -359,8 +361,15 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
string GetFileNameForResource(string fullName)
{
string[] splitName = fullName.Split('.');
string fileName = CleanUpFileName(fullName);
// Clean up the name first and ensure the length does not exceed the maximum length
// supported by the OS.
fullName = CleanUpDirectoryName(fullName);
// The purpose of the below algorithm is to "maximize" the directory name and "minimize" the file name.
// That is, a full name of the form "Namespace1.Namespace2{...}.NamespaceN.ResourceName" is split such that
// the directory part Namespace1\Namespace2\... reuses as many existing directories as
// possible, and only the remaining name parts are used as prefix for the filename.
string[] splitName = fullName.Split(Path.DirectorySeparatorChar);
string fileName = string.Join(".", splitName);
string separator = Path.DirectorySeparatorChar.ToString();
for (int i = splitName.Length - 1; i > 0; i--)
{
@ -368,7 +377,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -368,7 +377,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
if (directories.Contains(ns))
{
string name = string.Join(".", splitName, i, splitName.Length - i);
fileName = Path.Combine(ns, CleanUpFileName(name));
fileName = Path.Combine(ns, name);
break;
}
}
@ -526,10 +535,50 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -526,10 +535,50 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
#endregion
static readonly Lazy<(bool longPathsEnabled, int maxPathLength, int maxSegmentLength)> longPathSupport =
new Lazy<(bool longPathsEnabled, int maxPathLength, int maxSegmentLength)>(GetLongPathSupport, isThreadSafe: true);
static (bool longPathsEnabled, int maxPathLength, int maxSegmentLength) GetLongPathSupport()
{
try
{
switch (Environment.OSVersion.Platform)
{
case PlatformID.MacOSX:
case PlatformID.Unix:
return (true, int.MaxValue, int.MaxValue);
case PlatformID.Win32NT:
const string key = @"SYSTEM\CurrentControlSet\Control\FileSystem";
var fileSystem = Registry.LocalMachine.OpenSubKey(key);
var value = (int?)fileSystem.GetValue("LongPathsEnabled");
if (value == 1)
{
return (true, int.MaxValue, 255);
}
return (false, 200, 30);
default:
return (false, 200, 30);
}
}
catch
{
return (false, 200, 30);
}
}
/// <summary>
/// Cleans up a node name for use as a file name.
/// </summary>
public static string CleanUpFileName(string text)
{
return CleanUpFileName(text, separateAtDots: false);
}
/// <summary>
/// Cleans up a node name for use as a file system name. If <paramref name="separateAtDots"/> is active,
/// dots are seen as segment separators. Each segment is limited to 255 characters.
/// </summary>
static string CleanUpFileName(string text, bool separateAtDots)
{
int pos = text.IndexOf(':');
if (pos > 0)
@ -540,16 +589,38 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -540,16 +589,38 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
text = text.Trim();
// Whitelist allowed characters, replace everything else:
StringBuilder b = new StringBuilder(text.Length);
int currentSegmentLength = 0;
var (supportsLongPaths, maxPathLength, maxSegmentLength) = longPathSupport.Value;
foreach (var c in text)
{
currentSegmentLength++;
if (char.IsLetterOrDigit(c) || c == '-' || c == '_')
b.Append(c);
{
// if the current segment exceeds 255 characters,
// skip until the end of the segment.
if (currentSegmentLength <= maxSegmentLength)
b.Append(c);
}
else if (c == '.' && b.Length > 0 && b[b.Length - 1] != '.')
b.Append('.'); // allow dot, but never two in a row
{
// if the current segment exceeds 255 characters,
// skip until the end of the segment.
if (separateAtDots || currentSegmentLength <= maxSegmentLength)
b.Append('.'); // allow dot, but never two in a row
// Reset length at end of segment.
if (separateAtDots)
currentSegmentLength = 0;
}
else
b.Append('-');
if (b.Length >= 200)
break; // limit to 200 chars
{
// if the current segment exceeds 255 characters,
// skip until the end of the segment.
if (currentSegmentLength <= maxSegmentLength)
b.Append('-');
}
if (b.Length >= maxPathLength && !supportsLongPaths)
break; // limit to 200 chars, if long paths are not supported.
}
if (b.Length == 0)
b.Append('-');
@ -567,7 +638,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -567,7 +638,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
/// </summary>
public static string CleanUpDirectoryName(string text)
{
return CleanUpFileName(text).Replace('.', Path.DirectorySeparatorChar);
return CleanUpFileName(text, separateAtDots: true).Replace('.', Path.DirectorySeparatorChar);
}
static bool IsReservedFileSystemName(string name)

138
ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.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.
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
@ -45,7 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -45,7 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
public static CSharpOperators Get(ICompilation compilation)
{
CacheManager cache = compilation.CacheManager;
CSharpOperators operators = (CSharpOperators)cache.GetShared(typeof(CSharpOperators));
CSharpOperators? operators = (CSharpOperators?)cache.GetShared(typeof(CSharpOperators));
if (operators == null)
{
operators = (CSharpOperators)cache.GetOrAddShared(typeof(CSharpOperators), new CSharpOperators(compilation));
@ -59,7 +61,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -59,7 +61,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
List<OperatorMethod> result = new List<OperatorMethod>(methods);
foreach (OperatorMethod method in methods)
{
OperatorMethod lifted = method.Lift(this);
OperatorMethod? lifted = method.Lift(this);
if (lifted != null)
result.Add(lifted);
}
@ -111,20 +113,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -111,20 +113,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return parameters; }
}
public IType ReturnType { get; internal set; }
public IType ReturnType { get; internal set; } = null!; // initialized by derived class ctor
public ICompilation Compilation {
get { return compilation; }
}
public virtual OperatorMethod Lift(CSharpOperators operators)
public virtual OperatorMethod? Lift(CSharpOperators operators)
{
return null;
}
public System.Reflection.Metadata.EntityHandle MetadataToken => default;
ITypeDefinition IEntity.DeclaringTypeDefinition {
ITypeDefinition? IEntity.DeclaringTypeDefinition {
get { return null; }
}
@ -226,7 +228,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -226,7 +228,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return b.ToString();
}
bool IMember.Equals(IMember obj, TypeVisitor typeNormalization)
bool IMember.Equals(IMember? obj, TypeVisitor? typeNormalization)
{
return this == obj;
}
@ -238,7 +240,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -238,7 +240,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
{
public virtual bool CanEvaluateAtCompileTime { get { return false; } }
public virtual object Invoke(CSharpResolver resolver, object input)
public virtual object? Invoke(CSharpResolver resolver, object? input)
{
throw new NotSupportedException();
}
@ -265,7 +267,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -265,7 +267,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return true; }
}
public override object Invoke(CSharpResolver resolver, object input)
public override object? Invoke(CSharpResolver resolver, object? input)
{
if (input == null)
return null;
@ -296,11 +298,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -296,11 +298,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
#region Unary operator definitions
// C# 4.0 spec: §7.7.1 Unary plus operator
OperatorMethod[] unaryPlusOperators;
OperatorMethod[]? unaryPlusOperators;
public OperatorMethod[] UnaryPlusOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref unaryPlusOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref unaryPlusOperators);
if (ops != null)
{
return ops;
@ -321,11 +323,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -321,11 +323,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
// C# 4.0 spec: §7.7.2 Unary minus operator
OperatorMethod[] uncheckedUnaryMinusOperators;
OperatorMethod[]? uncheckedUnaryMinusOperators;
public OperatorMethod[] UncheckedUnaryMinusOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref uncheckedUnaryMinusOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref uncheckedUnaryMinusOperators);
if (ops != null)
{
return ops;
@ -343,11 +345,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -343,11 +345,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] checkedUnaryMinusOperators;
OperatorMethod[]? checkedUnaryMinusOperators;
public OperatorMethod[] CheckedUnaryMinusOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref checkedUnaryMinusOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref checkedUnaryMinusOperators);
if (ops != null)
{
return ops;
@ -366,11 +368,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -366,11 +368,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
// C# 4.0 spec: §7.7.3 Logical negation operator
OperatorMethod[] logicalNegationOperators;
OperatorMethod[]? logicalNegationOperators;
public OperatorMethod[] LogicalNegationOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalNegationOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref logicalNegationOperators);
if (ops != null)
{
return ops;
@ -385,11 +387,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -385,11 +387,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
// C# 4.0 spec: §7.7.4 Bitwise complement operator
OperatorMethod[] bitwiseComplementOperators;
OperatorMethod[]? bitwiseComplementOperators;
public OperatorMethod[] BitwiseComplementOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseComplementOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref bitwiseComplementOperators);
if (ops != null)
{
return ops;
@ -411,7 +413,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -411,7 +413,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
internal class BinaryOperatorMethod : OperatorMethod
{
public virtual bool CanEvaluateAtCompileTime { get { return false; } }
public virtual object Invoke(CSharpResolver resolver, object lhs, object rhs)
public virtual object? Invoke(CSharpResolver resolver, object? lhs, object? rhs)
{
throw new NotSupportedException();
}
@ -444,7 +446,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -444,7 +446,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return true; }
}
public override object Invoke(CSharpResolver resolver, object lhs, object rhs)
public override object? Invoke(CSharpResolver resolver, object? lhs, object? rhs)
{
if (lhs == null || rhs == null)
return null;
@ -480,11 +482,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -480,11 +482,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
#region Arithmetic operators
// C# 4.0 spec: §7.8.1 Multiplication operator
OperatorMethod[] multiplicationOperators;
OperatorMethod[]? multiplicationOperators;
public OperatorMethod[] MultiplicationOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref multiplicationOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref multiplicationOperators);
if (ops != null)
{
return ops;
@ -505,11 +507,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -505,11 +507,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
// C# 4.0 spec: §7.8.2 Division operator
OperatorMethod[] divisionOperators;
OperatorMethod[]? divisionOperators;
public OperatorMethod[] DivisionOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref divisionOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref divisionOperators);
if (ops != null)
{
return ops;
@ -530,11 +532,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -530,11 +532,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
// C# 4.0 spec: §7.8.3 Remainder operator
OperatorMethod[] remainderOperators;
OperatorMethod[]? remainderOperators;
public OperatorMethod[] RemainderOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref remainderOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref remainderOperators);
if (ops != null)
{
return ops;
@ -555,11 +557,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -555,11 +557,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
// C# 4.0 spec: §7.8.3 Addition operator
OperatorMethod[] additionOperators;
OperatorMethod[]? additionOperators;
public OperatorMethod[] AdditionOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref additionOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref additionOperators);
if (ops != null)
{
return ops;
@ -600,18 +602,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -600,18 +602,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return canEvaluateAtCompileTime; }
}
public override object Invoke(CSharpResolver resolver, object lhs, object rhs)
public override object? Invoke(CSharpResolver? resolver, object? lhs, object? rhs)
{
return string.Concat(lhs, rhs);
}
}
// C# 4.0 spec: §7.8.4 Subtraction operator
OperatorMethod[] subtractionOperators;
OperatorMethod[]? subtractionOperators;
public OperatorMethod[] SubtractionOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref subtractionOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref subtractionOperators);
if (ops != null)
{
return ops;
@ -632,11 +634,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -632,11 +634,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
// C# 4.0 spec: §7.8.5 Shift operators
OperatorMethod[] shiftLeftOperators;
OperatorMethod[]? shiftLeftOperators;
public OperatorMethod[] ShiftLeftOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref shiftLeftOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref shiftLeftOperators);
if (ops != null)
{
return ops;
@ -653,11 +655,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -653,11 +655,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] shiftRightOperators;
OperatorMethod[]? shiftRightOperators;
public OperatorMethod[] ShiftRightOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref shiftRightOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref shiftRightOperators);
if (ops != null)
{
return ops;
@ -695,7 +697,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -695,7 +697,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return Type != TypeCode.Object; }
}
public override object Invoke(CSharpResolver resolver, object lhs, object rhs)
public override object Invoke(CSharpResolver resolver, object? lhs, object? rhs)
{
if (lhs == null && rhs == null)
return !Negate; // ==: true; !=: false
@ -719,7 +721,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -719,7 +721,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return equal ^ Negate;
}
public override OperatorMethod Lift(CSharpOperators operators)
public override OperatorMethod? Lift(CSharpOperators operators)
{
if (Type == TypeCode.Object || Type == TypeCode.String)
return null;
@ -746,7 +748,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -746,7 +748,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return baseMethod.CanEvaluateAtCompileTime; }
}
public override object Invoke(CSharpResolver resolver, object lhs, object rhs)
public override object Invoke(CSharpResolver resolver, object? lhs, object? rhs)
{
return baseMethod.Invoke(resolver, lhs, rhs);
}
@ -764,11 +766,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -764,11 +766,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
TypeCode.Boolean
};
OperatorMethod[] valueEqualityOperators;
OperatorMethod[]? valueEqualityOperators;
public OperatorMethod[] ValueEqualityOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref valueEqualityOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref valueEqualityOperators);
if (ops != null)
{
return ops;
@ -782,11 +784,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -782,11 +784,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] valueInequalityOperators;
OperatorMethod[]? valueInequalityOperators;
public OperatorMethod[] ValueInequalityOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref valueInequalityOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref valueInequalityOperators);
if (ops != null)
{
return ops;
@ -800,11 +802,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -800,11 +802,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] referenceEqualityOperators;
OperatorMethod[]? referenceEqualityOperators;
public OperatorMethod[] ReferenceEqualityOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref referenceEqualityOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref referenceEqualityOperators);
if (ops != null)
{
return ops;
@ -819,11 +821,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -819,11 +821,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] referenceInequalityOperators;
OperatorMethod[]? referenceInequalityOperators;
public OperatorMethod[] ReferenceInequalityOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref referenceInequalityOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref referenceInequalityOperators);
if (ops != null)
{
return ops;
@ -857,7 +859,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -857,7 +859,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return true; }
}
public override object Invoke(CSharpResolver resolver, object lhs, object rhs)
public override object? Invoke(CSharpResolver resolver, object? lhs, object? rhs)
{
if (lhs == null || rhs == null)
return null;
@ -873,11 +875,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -873,11 +875,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] lessThanOperators;
OperatorMethod[]? lessThanOperators;
public OperatorMethod[] LessThanOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref lessThanOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref lessThanOperators);
if (ops != null)
{
return ops;
@ -897,11 +899,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -897,11 +899,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] lessThanOrEqualOperators;
OperatorMethod[]? lessThanOrEqualOperators;
public OperatorMethod[] LessThanOrEqualOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref lessThanOrEqualOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref lessThanOrEqualOperators);
if (ops != null)
{
return ops;
@ -921,11 +923,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -921,11 +923,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] greaterThanOperators;
OperatorMethod[]? greaterThanOperators;
public OperatorMethod[] GreaterThanOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref greaterThanOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref greaterThanOperators);
if (ops != null)
{
return ops;
@ -945,11 +947,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -945,11 +947,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] greaterThanOrEqualOperators;
OperatorMethod[]? greaterThanOrEqualOperators;
public OperatorMethod[] GreaterThanOrEqualOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref greaterThanOrEqualOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref greaterThanOrEqualOperators);
if (ops != null)
{
return ops;
@ -971,11 +973,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -971,11 +973,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
#endregion
#region Bitwise operators
OperatorMethod[] logicalAndOperators;
OperatorMethod[]? logicalAndOperators;
public OperatorMethod[] LogicalAndOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalAndOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref logicalAndOperators);
if (ops != null)
{
return ops;
@ -990,11 +992,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -990,11 +992,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
OperatorMethod[] bitwiseAndOperators;
OperatorMethod[]? bitwiseAndOperators;
public OperatorMethod[] BitwiseAndOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseAndOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref bitwiseAndOperators);
if (ops != null)
{
return ops;
@ -1013,11 +1015,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -1013,11 +1015,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
OperatorMethod[] logicalOrOperators;
OperatorMethod[]? logicalOrOperators;
public OperatorMethod[] LogicalOrOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalOrOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref logicalOrOperators);
if (ops != null)
{
return ops;
@ -1031,11 +1033,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -1031,11 +1033,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
OperatorMethod[] bitwiseOrOperators;
OperatorMethod[]? bitwiseOrOperators;
public OperatorMethod[] BitwiseOrOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseOrOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref bitwiseOrOperators);
if (ops != null)
{
return ops;
@ -1057,11 +1059,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -1057,11 +1059,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
// we produce "true | null" = "null" when it should be true. However, this is irrelevant
// because bool? cannot be a compile-time type.
OperatorMethod[] bitwiseXorOperators;
OperatorMethod[]? bitwiseXorOperators;
public OperatorMethod[] BitwiseXorOperators {
get {
OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseXorOperators);
OperatorMethod[]? ops = LazyInit.VolatileRead(ref bitwiseXorOperators);
if (ops != null)
{
return ops;
@ -1081,7 +1083,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -1081,7 +1083,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
#endregion
#region User-defined operators
public static IMethod LiftUserDefinedOperator(IMethod m)
public static IMethod? LiftUserDefinedOperator(IMethod m)
{
if (IsComparisonOperator(m))
{
@ -1129,9 +1131,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -1129,9 +1131,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
public IReadOnlyList<IParameter> NonLiftedParameters => nonLiftedOperator.Parameters;
public IType NonLiftedReturnType => nonLiftedOperator.ReturnType;
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
LiftedUserDefinedOperator op = obj as LiftedUserDefinedOperator;
LiftedUserDefinedOperator? op = obj as LiftedUserDefinedOperator;
return op != null && this.nonLiftedOperator.Equals(op.nonLiftedOperator);
}

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

@ -2259,20 +2259,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2259,20 +2259,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
var declaringType = member.DeclaringType;
if (member.IsExplicitInterfaceImplementation)
return false;
if (declaringType != null && declaringType.Kind == TypeKind.Interface)
{
return member.Accessibility != Accessibility.Public;
}
switch (member.SymbolKind)
{
case SymbolKind.Constructor:
return !member.IsStatic;
case SymbolKind.Destructor:
return false;
case SymbolKind.Method:
return !((IMethod)member).IsLocalFunction;
default:
return true;
if (declaringType?.Kind == TypeKind.Interface)
{
return member.Accessibility != Accessibility.Public;
}
return member is not IMethod method || !method.IsLocalFunction;
}
}

2
ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.DebugInfo
string BuildFileNameFromTypeName(TypeDefinitionHandle handle)
{
var typeName = handle.GetFullTypeName(reader).TopLevelTypeName;
return Path.Combine(WholeProjectDecompiler.CleanUpFileName(typeName.Namespace), WholeProjectDecompiler.CleanUpFileName(typeName.Name) + ".cs");
return Path.Combine(WholeProjectDecompiler.CleanUpDirectoryName(typeName.Namespace), WholeProjectDecompiler.CleanUpFileName(typeName.Name) + ".cs");
}
foreach (var sourceFile in reader.GetTopLevelTypeDefinitions().GroupBy(BuildFileNameFromTypeName))

22
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -140,12 +140,14 @@ namespace ICSharpCode.Decompiler @@ -140,12 +140,14 @@ namespace ICSharpCode.Decompiler
recordClasses = false;
withExpressions = false;
usePrimaryConstructorSyntax = false;
covariantReturns = false;
}
}
public CSharp.LanguageVersion GetMinimumRequiredVersion()
{
if (nativeIntegers || initAccessors || functionPointers || forEachWithGetEnumeratorExtension || recordClasses)
if (nativeIntegers || initAccessors || functionPointers || forEachWithGetEnumeratorExtension
|| recordClasses || withExpressions || usePrimaryConstructorSyntax || covariantReturns)
return CSharp.LanguageVersion.Preview;
if (nullableReferenceTypes || readOnlyMethods || asyncEnumerator || asyncUsingAndForEachStatement
|| staticLocalFunctions || ranges || switchExpressions)
@ -194,6 +196,24 @@ namespace ICSharpCode.Decompiler @@ -194,6 +196,24 @@ namespace ICSharpCode.Decompiler
}
}
bool covariantReturns = true;
/// <summary>
/// Decompile C# 9 covariant return types.
/// </summary>
[Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.CovariantReturns")]
public bool CovariantReturns {
get { return covariantReturns; }
set {
if (covariantReturns != value)
{
covariantReturns = value;
OnPropertyChanged();
}
}
}
bool initAccessors = true;
/// <summary>

16
ICSharpCode.Decompiler/Disassembler/ILParser.cs

@ -107,5 +107,21 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -107,5 +107,21 @@ namespace ICSharpCode.Decompiler.Disassembler
{
return opCode == ILOpCode.Ret || opCode == ILOpCode.Endfilter || opCode == ILOpCode.Endfinally;
}
public static int GetHeaderSize(BlobReader bodyBlockReader)
{
byte header = bodyBlockReader.ReadByte();
if ((header & 3) == 3)
{
// fat
ushort largeHeader = (ushort)((bodyBlockReader.ReadByte() << 8) | header);
return (byte)(largeHeader >> 12) * 4;
}
else
{
// tiny
return 1;
}
}
}
}

122
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -58,6 +58,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -58,6 +58,11 @@ namespace ICSharpCode.Decompiler.Disassembler
/// </summary>
public bool ShowMetadataTokensInBase10 { get; set; }
/// <summary>
/// Show raw RVA offset and bytes before each instruction.
/// </summary>
public bool ShowRawRVAOffsetAndBytes { get; set; }
/// <summary>
/// Optional provider for sequence points.
/// </summary>
@ -90,15 +95,18 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -90,15 +95,18 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Method begins at RVA 0x{0:x4}", methodDefinition.RelativeVirtualAddress);
if (methodDefinition.RelativeVirtualAddress == 0)
{
output.WriteLine("// Code size {0} (0x{0:x})", 0);
output.WriteLine("// Header size: {0}", 0);
output.WriteLine("// Code size: {0} (0x{0:x})", 0);
output.WriteLine(".maxstack {0}", 0);
output.WriteLine();
return;
}
MethodBodyBlock body;
BlobReader bodyBlockReader;
try
{
body = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress);
bodyBlockReader = module.Reader.GetSectionData(methodDefinition.RelativeVirtualAddress).GetReader();
}
catch (BadImageFormatException ex)
{
@ -106,7 +114,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -106,7 +114,9 @@ namespace ICSharpCode.Decompiler.Disassembler
return;
}
var blob = body.GetILReader();
output.WriteLine("// Code size {0} (0x{0:x})", blob.Length);
int headerSize = ILParser.GetHeaderSize(bodyBlockReader);
output.WriteLine("// Header size: {0}", headerSize);
output.WriteLine("// Code size: {0} (0x{0:x})", blob.Length);
output.WriteLine(".maxstack {0}", body.MaxStack);
var entrypointHandle = MetadataTokens.MethodDefinitionHandle(module.Reader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress);
@ -123,14 +133,14 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -123,14 +133,14 @@ namespace ICSharpCode.Decompiler.Disassembler
blob.Reset();
HashSet<int> branchTargets = GetBranchTargets(blob);
blob.Reset();
WriteStructureBody(new ILStructure(module, handle, genericContext, body), branchTargets, ref blob);
WriteStructureBody(new ILStructure(module, handle, genericContext, body), branchTargets, ref blob, methodDefinition.RelativeVirtualAddress + headerSize);
}
else
{
while (blob.RemainingBytes > 0)
{
cancellationToken.ThrowIfCancellationRequested();
WriteInstruction(output, metadata, handle, ref blob);
WriteInstruction(output, metadata, handle, ref blob, methodDefinition.RelativeVirtualAddress);
}
WriteExceptionHandlers(module, handle, body);
}
@ -276,7 +286,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -276,7 +286,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Indent();
}
void WriteStructureBody(ILStructure s, HashSet<int> branchTargets, ref BlobReader body)
void WriteStructureBody(ILStructure s, HashSet<int> branchTargets, ref BlobReader body, int methodRva)
{
bool isFirstInstructionInStructure = true;
bool prevInstructionWasBranch = false;
@ -289,7 +299,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -289,7 +299,7 @@ namespace ICSharpCode.Decompiler.Disassembler
{
ILStructure child = s.Children[childIndex++];
WriteStructureHeader(child);
WriteStructureBody(child, branchTargets, ref body);
WriteStructureBody(child, branchTargets, ref body, methodRva);
WriteStructureFooter(child);
}
else
@ -300,7 +310,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -300,7 +310,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
var currentOpCode = ILParser.DecodeOpCode(ref body);
body.Offset = offset; // reset IL stream
WriteInstruction(output, metadata, s.MethodHandle, ref body);
WriteInstruction(output, metadata, s.MethodHandle, ref body, methodRva);
prevInstructionWasBranch = currentOpCode.IsBranch()
|| currentOpCode.IsReturn()
|| currentOpCode == ILOpCode.Throw
@ -333,7 +343,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -333,7 +343,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
protected virtual void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodDefinition, ref BlobReader blob)
protected virtual void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva)
{
int offset = blob.Offset;
if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count)
@ -358,10 +368,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -358,10 +368,11 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
ILOpCode opCode = ILParser.DecodeOpCode(ref blob);
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true);
output.Write(": ");
if (opCode.IsDefined())
{
WriteRVA(blob, offset + methodRva, opCode);
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true);
output.Write(": ");
WriteOpCode(opCode);
switch (opCode.GetOperandType())
{
@ -464,12 +475,40 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -464,12 +475,40 @@ namespace ICSharpCode.Decompiler.Disassembler
WriteMetadataToken(userString, metadataToken, spaceBefore: true);
break;
case OperandType.Switch:
var tmp = blob;
int[] targets = ILParser.DecodeSwitchTargets(ref blob);
output.Write(" (");
if (ShowRawRVAOffsetAndBytes)
{
output.WriteLine(" (");
}
else
{
output.Write(" (");
}
tmp.ReadInt32();
for (int i = 0; i < targets.Length; i++)
{
if (i > 0)
output.Write(", ");
{
if (ShowRawRVAOffsetAndBytes)
{
output.WriteLine(",");
}
else
{
output.Write(", ");
}
}
if (ShowRawRVAOffsetAndBytes)
{
output.Write("/* ");
output.Write($"{tmp.ReadByte():X2}{tmp.ReadByte():X2}{tmp.ReadByte():X2}{tmp.ReadByte():X2}");
output.Write(" */ ");
}
if (ShowRawRVAOffsetAndBytes)
{
output.Write(" ");
}
output.WriteLocalReference($"IL_{targets[i]:x4}", targets[i]);
}
output.Write(")");
@ -479,11 +518,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -479,11 +518,11 @@ namespace ICSharpCode.Decompiler.Disassembler
int index = blob.ReadUInt16();
if (opCode == ILOpCode.Ldloc || opCode == ILOpCode.Ldloca || opCode == ILOpCode.Stloc)
{
DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index);
DisassemblerHelpers.WriteVariableReference(output, metadata, methodHandle, index);
}
else
{
DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index);
DisassemblerHelpers.WriteParameterReference(output, metadata, methodHandle, index);
}
break;
case OperandType.ShortVariable:
@ -491,11 +530,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -491,11 +530,11 @@ namespace ICSharpCode.Decompiler.Disassembler
index = blob.ReadByte();
if (opCode == ILOpCode.Ldloc_s || opCode == ILOpCode.Ldloca_s || opCode == ILOpCode.Stloc_s)
{
DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index);
DisassemblerHelpers.WriteVariableReference(output, metadata, methodHandle, index);
}
else
{
DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index);
DisassemblerHelpers.WriteParameterReference(output, metadata, methodHandle, index);
}
break;
}
@ -505,8 +544,22 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -505,8 +544,22 @@ namespace ICSharpCode.Decompiler.Disassembler
ushort opCodeValue = (ushort)opCode;
if (opCodeValue > 0xFF)
{
if (ShowRawRVAOffsetAndBytes)
{
output.Write("/* ");
output.Write($"0x{offset + methodRva:X8} {(ushort)opCode >> 8:X2}");
output.Write(" */ ");
}
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true);
output.Write(": ");
// split 16-bit value into two emitbyte directives
output.WriteLine($".emitbyte 0x{(byte)(opCodeValue >> 8):x}");
if (ShowRawRVAOffsetAndBytes)
{
output.Write("/* ");
output.Write($"0x{offset + methodRva + 1:X8} {(ushort)opCode & 0xFF:X2}");
output.Write(" */ ");
}
// add label
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset + 1), offset + 1, isDefinition: true);
output.Write(": ");
@ -514,12 +567,49 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -514,12 +567,49 @@ namespace ICSharpCode.Decompiler.Disassembler
}
else
{
if (ShowRawRVAOffsetAndBytes)
{
output.Write("/* ");
output.Write($"0x{offset + methodRva:X8} {(ushort)opCode & 0xFF:X2}");
output.Write(" */ ");
}
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true);
output.Write(": ");
output.Write($".emitbyte 0x{(byte)opCodeValue:x}");
}
}
output.WriteLine();
}
void WriteRVA(BlobReader blob, int offset, ILOpCode opCode)
{
if (ShowRawRVAOffsetAndBytes)
{
output.Write("/* ");
var tmp = blob;
if (opCode == ILOpCode.Switch)
{
tmp.ReadInt32();
}
else
{
ILParser.SkipOperand(ref tmp, opCode);
}
output.Write($"0x{offset:X8} {(ushort)opCode:X2}");
int appendSpaces = (ushort)opCode > 0xFF ? 14 : 16;
while (blob.Offset < tmp.Offset)
{
output.Write($"{blob.ReadByte():X2}");
appendSpaces -= 2;
}
if (appendSpaces > 0)
{
output.Write(new string(' ', appendSpaces));
}
output.Write(" */ ");
}
}
private void WriteOpCode(ILOpCode opCode)
{
var opCodeInfo = new OpCodeInfo(opCode, opCode.GetDisplayName());

5
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -61,6 +61,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -61,6 +61,11 @@ namespace ICSharpCode.Decompiler.Disassembler
set => methodBodyDisassembler.ShowMetadataTokensInBase10 = value;
}
public bool ShowRawRVAOffsetAndBytes {
get => methodBodyDisassembler.ShowRawRVAOffsetAndBytes;
set => methodBodyDisassembler.ShowRawRVAOffsetAndBytes = value;
}
public IDebugInfoProvider DebugInfo {
get => methodBodyDisassembler.DebugInfo;
set => methodBodyDisassembler.DebugInfo = value;

61
ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.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.
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
@ -23,7 +25,6 @@ using System.Text; @@ -23,7 +25,6 @@ using System.Text;
using System.Threading;
using System.Xml.Linq;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
@ -35,15 +36,10 @@ namespace ICSharpCode.Decompiler.Documentation @@ -35,15 +36,10 @@ namespace ICSharpCode.Decompiler.Documentation
/// </summary>
public class XmlDocumentationElement
{
static XmlDocumentationElement Create(string documentationComment, IEntity declaringEntity)
{
return new XmlDocumentationElement(XElement.Parse(documentationComment), declaringEntity, null);
}
readonly XElement element;
readonly IEntity declaringEntity;
readonly Func<string, IEntity> crefResolver;
volatile string textContent;
readonly XElement? element;
readonly IEntity? declaringEntity;
readonly Func<string, IEntity?>? crefResolver;
volatile string? textContent;
/// <summary>
/// Inheritance level; used to prevent cyclic doc inheritance.
@ -53,7 +49,7 @@ namespace ICSharpCode.Decompiler.Documentation @@ -53,7 +49,7 @@ namespace ICSharpCode.Decompiler.Documentation
/// <summary>
/// Creates a new documentation element.
/// </summary>
public XmlDocumentationElement(XElement element, IEntity declaringEntity, Func<string, IEntity> crefResolver)
public XmlDocumentationElement(XElement element, IEntity? declaringEntity, Func<string, IEntity?>? crefResolver)
{
if (element == null)
throw new ArgumentNullException(nameof(element));
@ -65,7 +61,7 @@ namespace ICSharpCode.Decompiler.Documentation @@ -65,7 +61,7 @@ namespace ICSharpCode.Decompiler.Documentation
/// <summary>
/// Creates a new documentation element.
/// </summary>
public XmlDocumentationElement(string text, IEntity declaringEntity)
public XmlDocumentationElement(string text, IEntity? declaringEntity)
{
if (text == null)
throw new ArgumentNullException(nameof(text));
@ -77,26 +73,26 @@ namespace ICSharpCode.Decompiler.Documentation @@ -77,26 +73,26 @@ namespace ICSharpCode.Decompiler.Documentation
/// Gets the entity on which this documentation was originally declared.
/// May return null.
/// </summary>
public IEntity DeclaringEntity {
public IEntity? DeclaringEntity {
get { return declaringEntity; }
}
IEntity referencedEntity;
IEntity? referencedEntity;
volatile bool referencedEntityInitialized;
/// <summary>
/// Gets the entity referenced by the 'cref' attribute.
/// May return null.
/// </summary>
public IEntity ReferencedEntity {
public IEntity? ReferencedEntity {
get {
if (!referencedEntityInitialized)
{
string cref = GetAttribute("cref");
string? cref = GetAttribute("cref");
try
{
if (!string.IsNullOrEmpty(cref) && crefResolver != null)
referencedEntity = crefResolver(cref);
referencedEntity = crefResolver(cref!);
}
catch
{
@ -120,7 +116,7 @@ namespace ICSharpCode.Decompiler.Documentation @@ -120,7 +116,7 @@ namespace ICSharpCode.Decompiler.Documentation
/// <summary>
/// Gets the attribute value.
/// </summary>
public string GetAttribute(string name)
public string? GetAttribute(string? name)
{
return element?.Attribute(name)?.Value;
}
@ -148,7 +144,7 @@ namespace ICSharpCode.Decompiler.Documentation @@ -148,7 +144,7 @@ namespace ICSharpCode.Decompiler.Documentation
}
}
IList<XmlDocumentationElement> children;
IList<XmlDocumentationElement>? children;
/// <summary>
/// Gets the child elements.
@ -159,7 +155,7 @@ namespace ICSharpCode.Decompiler.Documentation @@ -159,7 +155,7 @@ namespace ICSharpCode.Decompiler.Documentation
return EmptyList<XmlDocumentationElement>.Instance;
return LazyInitializer.EnsureInitialized(
ref this.children,
() => CreateElements(element.Nodes(), declaringEntity, crefResolver, nestingLevel));
() => CreateElements(element.Nodes(), declaringEntity, crefResolver, nestingLevel))!;
}
}
@ -168,7 +164,7 @@ namespace ICSharpCode.Decompiler.Documentation @@ -168,7 +164,7 @@ namespace ICSharpCode.Decompiler.Documentation
"remarks", "returns", "threadsafety", "value"
};
static List<XmlDocumentationElement> CreateElements(IEnumerable<XObject> childObjects, IEntity declaringEntity, Func<string, IEntity> crefResolver, int nestingLevel)
static List<XmlDocumentationElement> CreateElements(IEnumerable<XObject?> childObjects, IEntity? declaringEntity, Func<string, IEntity?>? crefResolver, int nestingLevel)
{
List<XmlDocumentationElement> list = new List<XmlDocumentationElement>();
foreach (var child in childObjects)
@ -188,23 +184,24 @@ namespace ICSharpCode.Decompiler.Documentation @@ -188,23 +184,24 @@ namespace ICSharpCode.Decompiler.Documentation
{
if (nestingLevel < 5 && childElement.Name == "inheritdoc")
{
string cref = childElement.Attribute("cref").Value;
IEntity inheritedFrom = null;
string inheritedDocumentation = null;
if (cref != null)
string? cref = childElement.Attribute("cref")?.Value;
IEntity? inheritedFrom = null;
string? inheritedDocumentation = null;
if (cref != null && crefResolver != null)
{
inheritedFrom = crefResolver(cref);
if (inheritedFrom != null)
inheritedDocumentation = inheritedFrom.GetDocumentation();
inheritedDocumentation = "<doc>" + inheritedFrom.GetDocumentation() + "</doc>";
}
else
{
foreach (IMember baseMember in InheritanceHelper.GetBaseMembers((IMember)declaringEntity, includeImplementedInterfaces: true))
foreach (IMember baseMember in InheritanceHelper.GetBaseMembers((IMember?)declaringEntity, includeImplementedInterfaces: true))
{
inheritedDocumentation = baseMember.GetDocumentation();
if (inheritedDocumentation != null)
{
inheritedFrom = baseMember;
inheritedDocumentation = "<doc>" + inheritedDocumentation + "</doc>";
break;
}
}
@ -212,10 +209,10 @@ namespace ICSharpCode.Decompiler.Documentation @@ -212,10 +209,10 @@ namespace ICSharpCode.Decompiler.Documentation
if (inheritedDocumentation != null)
{
var doc = XDocument.Parse(inheritedDocumentation);
var doc = XDocument.Parse(inheritedDocumentation).Element("doc");
// XPath filter not yet implemented
if (childElement.Parent == null && childElement.Attribute("select").Value == null)
if (childElement.Parent?.Parent == null && childElement.Attribute("select")?.Value == null)
{
// Inheriting documentation at the root level
List<string> doNotInherit = new List<string>();
@ -225,7 +222,7 @@ namespace ICSharpCode.Decompiler.Documentation @@ -225,7 +222,7 @@ namespace ICSharpCode.Decompiler.Documentation
var inheritedChildren = doc.Nodes().Where(
inheritedObject => {
XElement inheritedElement = inheritedObject as XElement;
XElement? inheritedElement = inheritedObject as XElement;
return !(inheritedElement != null && doNotInherit.Contains(inheritedElement.Name.LocalName));
});
@ -244,14 +241,14 @@ namespace ICSharpCode.Decompiler.Documentation @@ -244,14 +241,14 @@ namespace ICSharpCode.Decompiler.Documentation
if (string.IsNullOrWhiteSpace(list[0].textContent))
list.RemoveAt(0);
else
list[0].textContent = list[0].textContent.TrimStart();
list[0].textContent = list[0].textContent!.TrimStart();
}
if (list.Count > 0 && list[list.Count - 1].IsTextNode)
{
if (string.IsNullOrWhiteSpace(list[list.Count - 1].textContent))
list.RemoveAt(list.Count - 1);
else
list[list.Count - 1].textContent = list[list.Count - 1].textContent.TrimEnd();
list[list.Count - 1].textContent = list[list.Count - 1].textContent!.TrimEnd();
}
return list;
}

15
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -19,26 +19,30 @@ @@ -19,26 +19,30 @@
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>ICSharpCode.Decompiler.snk</AssemblyOriginatorKeyFile>
<NoWarn>1701;1702;1591;1573</NoWarn>
<DebugType>embedded</DebugType>
<DebugSymbols>true</DebugSymbols>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
</PropertyGroup>
<!-- HACK: Disable package generation on Unix due to tooling issues. -->
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbolsInPackage>true</IncludeSymbolsInPackage>
<NuspecFile>ICSharpCode.Decompiler.nuspec</NuspecFile>
<NuspecProperties>Configuration=$(Configuration)</NuspecProperties>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>$(DefineConstants);STEP</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
<PropertyGroup>
@ -49,6 +53,7 @@ @@ -49,6 +53,7 @@
<Import Project="..\packages.props" />
<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template

@ -25,7 +25,6 @@ @@ -25,7 +25,6 @@
<files>
<file src="DecompilerNuGetPackageIcon.png" target="images\" />
<file src="bin\$Configuration$\netstandard2.0\ICSharpCode.Decompiler.dll" target="lib\netstandard2.0" />
<file src="bin\$Configuration$\netstandard2.0\ICSharpCode.Decompiler.pdb" target="lib\netstandard2.0" />
<file src="bin\$Configuration$\netstandard2.0\ICSharpCode.Decompiler.xml" target="lib\netstandard2.0" />
</files>
</package>

2
ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs

@ -157,7 +157,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -157,7 +157,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
{
identifierValueTargets.Add(value, otherBranch.TargetBlock);
block.Instructions.RemoveAt(statement.ChildIndex + 1);
statement.ReplaceWith(otherBranch);
statement.ReplaceWith(branchToTarget);
}
else
{

2
ICSharpCode.Decompiler/IL/ILReader.cs

@ -1170,7 +1170,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1170,7 +1170,7 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction Push(ILInstruction inst)
{
Debug.Assert(inst.ResultType != StackType.Void);
IType type = compilation.FindType(inst.ResultType.ToKnownTypeCode());
IType type = compilation.FindType(inst.ResultType);
var v = new ILVariable(VariableKind.StackSlot, type, inst.ResultType);
v.HasGeneratedName = true;
currentStack = currentStack.Push(v);

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

@ -148,7 +148,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -148,7 +148,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
for (int j = 0; j < uninlinedArgs.Length; j++)
{
var arg = copiedExpr.Children[j];
var type = context.TypeSystem.FindType(arg.ResultType.ToKnownTypeCode());
var type = context.TypeSystem.FindType(arg.ResultType);
uninlinedArgs[j] = new ILVariable(VariableKind.StackSlot, type, arg.ResultType) {
Name = "C_" + arg.StartILOffset,
HasGeneratedName = true,

4
ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
FlagsBeingMoved |= predecessor.Flags;
MoveActions.Add(delegate {
var type = context.TypeSystem.FindType(predecessor.ResultType.ToKnownTypeCode());
var type = context.TypeSystem.FindType(predecessor.ResultType);
var v = Function.RegisterVariable(VariableKind.StackSlot, type);
predecessor.ReplaceWith(new LdLoc(v));
return new StLoc(v, predecessor);
@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
// We've reached the target block, and extraction is possible all the way.
int insertIndex = inst.ChildIndex;
var type = context.TypeSystem.FindType(instToExtract.ResultType.ToKnownTypeCode());
var type = context.TypeSystem.FindType(instToExtract.ResultType);
// Move instToExtract itself:
var v = function.RegisterVariable(VariableKind.StackSlot, type);
instToExtract.ReplaceWith(new LdLoc(v));

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

@ -87,7 +87,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -87,7 +87,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
var call = (CallInstruction)arg.Parent;
Debug.Assert(context.Function == call.Ancestors.OfType<ILFunction>().First());
var type = context.TypeSystem.FindType(arg.ResultType.ToKnownTypeCode());
var type = context.TypeSystem.FindType(arg.ResultType);
var v = context.Function.RegisterVariable(VariableKind.NamedArgument, type);
context.Step($"Introduce named argument '{v.Name}'", arg);
if (!(call.Parent is Block namedArgBlock) || namedArgBlock.Kind != BlockKind.CallWithNamedArgs)

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

@ -712,7 +712,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -712,7 +712,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!MatchNullableCtor(trueInst, out var utype, out var exprToLift))
{
isNullCoalescingWithNonNullableFallback = true;
utype = context.TypeSystem.FindType(trueInst.ResultType.ToKnownTypeCode());
utype = context.TypeSystem.FindType(trueInst.ResultType);
exprToLift = trueInst;
if (nullableVars.Count == 1 && exprToLift.MatchLdLoc(nullableVars[0]))
{

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

@ -102,11 +102,12 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -102,11 +102,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
// C# 9 attributes:
NativeInteger,
PreserveBaseOverrides,
}
static class KnownAttributes
{
internal const int Count = (int)KnownAttribute.NativeInteger + 1;
internal const int Count = (int)KnownAttribute.PreserveBaseOverrides + 1;
static readonly TopLevelTypeName[] typeNames = new TopLevelTypeName[Count]{
default,
@ -167,6 +168,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -167,6 +168,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
new TopLevelTypeName("System.Security.Permissions", "PermissionSetAttribute"),
// C# 9 attributes:
new TopLevelTypeName("System.Runtime.CompilerServices", "NativeIntegerAttribute"),
new TopLevelTypeName("System.Runtime.CompilerServices", "PreserveBaseOverridesAttribute"),
};
public static ref readonly TopLevelTypeName GetTypeName(this KnownAttribute attr)

14
ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler.TypeSystem
@ -66,6 +67,19 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -66,6 +67,19 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
return type.ToTypeReference().Resolve(new SimpleTypeResolveContext(compilation));
}
public static IType FindType(this ICompilation compilation, StackType stackType, Sign sign = Sign.None)
{
switch (stackType)
{
case StackType.Unknown:
return SpecialType.UnknownType;
case StackType.Ref:
return new ByReferenceType(SpecialType.UnknownType);
default:
return compilation.FindType(stackType.ToKnownTypeCode(sign));
}
}
#endregion
#region Type.ToTypeReference()

4
ICSharpCode.Decompiler/Util/CacheManager.cs

@ -34,9 +34,9 @@ namespace ICSharpCode.Decompiler.Util @@ -34,9 +34,9 @@ namespace ICSharpCode.Decompiler.Util
// There used to be a thread-local dictionary here, but I removed it as it was causing memory
// leaks in some use cases.
public object GetShared(object key)
public object? GetShared(object key)
{
object value;
object? value;
sharedDict.TryGetValue(key, out value);
return value;
}

6
ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs

@ -8,6 +8,8 @@ using EnvDTE; @@ -8,6 +8,8 @@ using EnvDTE;
using Microsoft.VisualStudio.Shell;
using VSLangProj;
namespace ICSharpCode.ILSpy.AddIn.Commands
{
/// <summary>
@ -33,8 +35,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -33,8 +35,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
if (itemData is ProjectItem projectItem)
{
var properties = Utils.GetProperties(projectItem.Properties, "Type");
if ((properties[0] as string) == "Package")
var properties = Utils.GetProperties(projectItem.Properties, "Type", "ExtenderCATID");
if (((properties[0] as string) == "Package") || ((properties[1] as string) == PrjBrowseObjectCATID.prjCATIDCSharpReferenceBrowseObject))
{
return new NuGetReferenceForILSpy(projectItem);
}

16
ILSpy.AddIn/Commands/OpenReferenceCommand.cs

@ -68,14 +68,6 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -68,14 +68,6 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
return;
}
// Handle NuGet references
var nugetRefItem = NuGetReferenceForILSpy.Detect(itemObject);
if (nugetRefItem != null)
{
OpenAssembliesInILSpy(nugetRefItem.GetILSpyParameters());
return;
}
// Handle project references
var projectRefItem = ProjectReferenceForILSpy.Detect(itemObject);
if (projectRefItem != null)
@ -96,6 +88,14 @@ namespace ICSharpCode.ILSpy.AddIn.Commands @@ -96,6 +88,14 @@ namespace ICSharpCode.ILSpy.AddIn.Commands
OpenAssembliesInILSpy(projectRefItem.GetILSpyParameters());
return;
}
// Handle NuGet references
var nugetRefItem = NuGetReferenceForILSpy.Detect(itemObject);
if (nugetRefItem != null)
{
OpenAssembliesInILSpy(nugetRefItem.GetILSpyParameters());
return;
}
}
internal static void Register(ILSpyAddInPackage owner)

10
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.4.0" />
<PackageReference Include="Microsoft.VisualStudio.LanguageServices" Version="2.4.0" />
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="17.0.1619-preview1">
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="17.0.4201-preview4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
@ -165,6 +165,12 @@ @@ -165,6 +165,12 @@
<None Include="ILSpyAddIn.vsct">
<SubType>Designer</SubType>
</None>
<None Include="ILSpyAddIn.en-US.vsct">
<SubType>Designer</SubType>
</None>
<None Include="ILSpyAddIn.zh-Hans.vsct">
<SubType>Designer</SubType>
</None>
<Content Include="zh-Hans\extension.vsixlangpack">
<IncludeInVSIX>true</IncludeInVSIX>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@ -203,6 +209,8 @@ @@ -203,6 +209,8 @@
<PropertyGroup>
<UseCodebase>true</UseCodebase>
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
<RunAnalyzersDuringLiveAnalysis>true</RunAnalyzersDuringLiveAnalysis>
</PropertyGroup>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />

7
ILSpy.AddIn/ILSpyAddIn.en-US.vsct

@ -56,7 +56,7 @@ @@ -56,7 +56,7 @@
<ButtonText>Open in ILSpy</ButtonText>
</Strings>
</Button>
<Button guid="guidILSpyAddInCmdSet" id="cmdidOpenProjectOutputInILSpy" priority="0x0600" type="Button">
<Parent guid="guidILSpyAddInCmdSet" id="OpenILSpyProjGroup" />
<Icon guid="guidImages" id="bmpLogo" />
@ -84,11 +84,6 @@ @@ -84,11 +84,6 @@
<ButtonText>ILSpy</ButtonText>
</Strings>
</Button>
</Buttons>
</Commands>
</CommandTable>

15
ILSpy.AddIn/ILSpyAddIn.vsct

@ -64,6 +64,14 @@ @@ -64,6 +64,14 @@
<Bitmap guid="guidImages" href="Resources\Images.png" usedList="bmpLogo, bmpPic1, bmpPic2, bmpPicX, bmpPicArrows"/>
</Bitmaps>
</Commands>
<CommandPlacements>
<CommandPlacement guid="guidILSpyAddInCmdSet" id="OpenILSpyRefGroup" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PACKAGEREFERENCE"/>
</CommandPlacement>
<CommandPlacement guid="guidILSpyAddInCmdSet" id="OpenILSpyRefGroup" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PROJECTREFERENCE"/>
</CommandPlacement>
</CommandPlacements>
<Symbols>
<!-- This is the package guid. -->
<GuidSymbol name="guidILSpyAddInPkg" value="{a9120dbe-164a-4891-842f-fb7829273838}" />
@ -75,6 +83,8 @@ @@ -75,6 +83,8 @@
<IDSymbol name="OpenILSpyRefGroup" value="0x1020" />
<IDSymbol name="OpenILSpyProjGroup" value="0x1030" />
<IDSymbol name="OpenILSpyCodeItemGroup" value="0x1040" />
<IDSymbol name="OpenILSpyPackageRefGroup" value="0x1050" />
<IDSymbol name="OpenILSpyProjectRefGroup" value="0x1060" />
<IDSymbol name="cmdidOpenILSpy" value="0x0100" />
<IDSymbol name="cmdidOpenReferenceInILSpy" value="0x0200" />
<IDSymbol name="cmdidOpenProjectOutputInILSpy" value="0x0300" />
@ -89,6 +99,11 @@ @@ -89,6 +99,11 @@
<IDSymbol name="bmpPicArrows" value="5" />
<IDSymbol name="bmpPicStrikethrough" value="6" />
</GuidSymbol>
<GuidSymbol name="guidReferenceContext" value="{D309F791-903F-11D0-9EFC-00A0C911004F}">
<IDSymbol name="IDM_VS_CTXT_PACKAGEREFERENCE" value="0x04A3"/>
<IDSymbol name="IDM_VS_CTXT_PROJECTREFERENCE" value="0x04A7"/>
</GuidSymbol>
</Symbols>
</CommandTable>

6
ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct

@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
group; your package should define its own command set in order to avoid collisions
with command ids defined by other packages. -->
<!--Buttons section. -->
<!--This section defines the elements the user can interact with, like a menu command or a button
or combo box in a toolbar. -->
@ -84,9 +84,9 @@ @@ -84,9 +84,9 @@
<ButtonText>ILSpy</ButtonText>
</Strings>
</Button>
</Buttons>
</Commands>
</CommandTable>

6
ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs

@ -168,7 +168,11 @@ namespace ILSpy.BamlDecompiler.Tests @@ -168,7 +168,11 @@ namespace ILSpy.BamlDecompiler.Tests
var res = module.Resources.First();
Stream bamlStream = LoadBaml(res, name + ".baml");
Assert.IsNotNull(bamlStream);
XDocument document = BamlResourceEntryNode.LoadIntoDocument(module, resolver, bamlStream, CancellationToken.None);
BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(module, resolver);
var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings());
XDocument document = decompiler.Decompile(bamlStream).Xaml;
XamlIsEqual(File.ReadAllText(sourcePath), document.ToString());
}

1
ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -40,6 +40,7 @@ @@ -40,6 +40,7 @@
<Import Project="..\packages.props" />
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkVersion)" />
<PackageReference Include="NUnit" Version="$(NUnitVersion)" />
</ItemGroup>

36
ILSpy.BamlDecompiler/BamlDecompilationResult.cs

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
// Copyright (c) 2021 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.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace ILSpy.BamlDecompiler
{
public class BamlDecompilationResult
{
public XDocument Xaml { get; }
public List<string> AssemblyReferences { get; }
public BamlDecompilationResult(XDocument xaml, IEnumerable<string> assemblyReferences)
{
this.Xaml = xaml;
this.AssemblyReferences = assemblyReferences.ToList();
}
}
}

50
ILSpy.BamlDecompiler/BamlDecompilerSettings.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// Copyright (c) 2021 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.ComponentModel;
using System.Runtime.CompilerServices;
namespace ILSpy.BamlDecompiler
{
public class BamlDecompilerSettings : INotifyPropertyChanged
{
bool throwOnAssemblyResolveErrors = true;
[Browsable(false)]
public bool ThrowOnAssemblyResolveErrors {
get { return throwOnAssemblyResolveErrors; }
set {
if (throwOnAssemblyResolveErrors != value)
{
throwOnAssemblyResolveErrors = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

144
ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
// Copyright (c) 2021 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.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
namespace ILSpy.BamlDecompiler
{
class BamlDecompilerTypeSystem : SimpleCompilation, IDecompilerTypeSystem
{
string[] defaultBamlReferences = new[] {
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"PresentationUI, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
};
public BamlDecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver)
{
if (mainModule == null)
throw new ArgumentNullException(nameof(mainModule));
if (assemblyResolver == null)
throw new ArgumentNullException(nameof(assemblyResolver));
// Load referenced assemblies and type-forwarder references.
// This is necessary to make .NET Core/PCL binaries work better.
var referencedAssemblies = new List<PEFile>();
var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference)>();
var mainMetadata = mainModule.Metadata;
foreach (var h in mainMetadata.GetModuleReferences())
{
var moduleRef = mainMetadata.GetModuleReference(h);
var moduleName = mainMetadata.GetString(moduleRef.Name);
foreach (var fileHandle in mainMetadata.AssemblyFiles)
{
var file = mainMetadata.GetAssemblyFile(fileHandle);
if (mainMetadata.StringComparer.Equals(file.Name, moduleName) && file.ContainsMetadata)
{
assemblyReferenceQueue.Enqueue((false, mainModule, moduleName));
break;
}
}
}
foreach (var refs in mainModule.AssemblyReferences)
{
assemblyReferenceQueue.Enqueue((true, mainModule, refs));
}
foreach (var bamlReference in defaultBamlReferences)
{
assemblyReferenceQueue.Enqueue((true, mainModule, AssemblyNameReference.Parse(bamlReference)));
}
var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) =>
reference.IsAssembly ? "A:" + ((IAssemblyReference)reference.Reference).FullName :
"M:" + reference.Reference);
var processedAssemblyReferences = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer);
while (assemblyReferenceQueue.Count > 0)
{
var asmRef = assemblyReferenceQueue.Dequeue();
if (!processedAssemblyReferences.Add(asmRef))
continue;
PEFile asm;
if (asmRef.IsAssembly)
{
asm = assemblyResolver.Resolve((IAssemblyReference)asmRef.Reference);
}
else
{
asm = assemblyResolver.ResolveModule(asmRef.MainModule, (string)asmRef.Reference);
}
if (asm != null)
{
referencedAssemblies.Add(asm);
var metadata = asm.Metadata;
foreach (var h in metadata.ExportedTypes)
{
var exportedType = metadata.GetExportedType(h);
switch (exportedType.Implementation.Kind)
{
case HandleKind.AssemblyReference:
assemblyReferenceQueue.Enqueue((true, asm, new ICSharpCode.Decompiler.Metadata.AssemblyReference(asm, (AssemblyReferenceHandle)exportedType.Implementation)));
break;
case HandleKind.AssemblyFile:
var file = metadata.GetAssemblyFile((AssemblyFileHandle)exportedType.Implementation);
assemblyReferenceQueue.Enqueue((false, asm, metadata.GetString(file.Name)));
break;
}
}
}
}
var mainModuleWithOptions = mainModule.WithOptions(TypeSystemOptions.Default);
var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(TypeSystemOptions.Default));
// Primitive types are necessary to avoid assertions in ILReader.
// Fallback to MinimalCorlib to provide the primitive types.
if (!HasType(KnownTypeCode.Void) || !HasType(KnownTypeCode.Int32))
{
Init(mainModule.WithOptions(TypeSystemOptions.Default), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.Instance }));
}
else
{
Init(mainModuleWithOptions, referencedAssembliesWithOptions);
}
this.MainModule = (MetadataModule)base.MainModule;
bool HasType(KnownTypeCode code)
{
TopLevelTypeName name = KnownTypeReference.Get(code).TypeName;
if (!mainModule.GetTypeDefinition(name).IsNil)
return true;
foreach (var file in referencedAssemblies)
{
if (!file.GetTypeDefinition(name).IsNil)
return true;
}
return false;
}
}
public new MetadataModule MainModule { get; }
}
}

140
ILSpy.BamlDecompiler/BamlResourceEntryNode.cs

@ -17,27 +17,17 @@ @@ -17,27 +17,17 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
using ILSpy.BamlDecompiler.Baml;
using SRM = System.Reflection.Metadata;
namespace ILSpy.BamlDecompiler
{
public sealed class BamlResourceEntryNode : ResourceEntryNode
@ -75,131 +65,11 @@ namespace ILSpy.BamlDecompiler @@ -75,131 +65,11 @@ namespace ILSpy.BamlDecompiler
{
var asm = this.Ancestors().OfType<AssemblyTreeNode>().First().LoadedAssembly;
using var data = OpenStream();
XDocument xamlDocument = LoadIntoDocument(asm.GetPEFileOrNull(), asm.GetAssemblyResolver(), data, cancellationToken);
output.Write(xamlDocument.ToString());
}
internal static XDocument LoadIntoDocument(PEFile module, IAssemblyResolver assemblyResolver,
Stream stream, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var document = BamlReader.ReadDocument(stream, cancellationToken);
var xaml = new XamlDecompiler().Decompile(new BamlDecompilerTypeSystem(module, assemblyResolver), document, cancellationToken, new BamlDecompilerOptions(), null);
return xaml;
}
class BamlDecompilerTypeSystem : SimpleCompilation, IDecompilerTypeSystem
{
string[] defaultBamlReferences = new[] {
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"PresentationUI, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
};
public BamlDecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver)
{
if (mainModule == null)
throw new ArgumentNullException(nameof(mainModule));
if (assemblyResolver == null)
throw new ArgumentNullException(nameof(assemblyResolver));
// Load referenced assemblies and type-forwarder references.
// This is necessary to make .NET Core/PCL binaries work better.
var referencedAssemblies = new List<PEFile>();
var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference)>();
var mainMetadata = mainModule.Metadata;
foreach (var h in mainMetadata.GetModuleReferences())
{
var moduleRef = mainMetadata.GetModuleReference(h);
var moduleName = mainMetadata.GetString(moduleRef.Name);
foreach (var fileHandle in mainMetadata.AssemblyFiles)
{
var file = mainMetadata.GetAssemblyFile(fileHandle);
if (mainMetadata.StringComparer.Equals(file.Name, moduleName) && file.ContainsMetadata)
{
assemblyReferenceQueue.Enqueue((false, mainModule, moduleName));
break;
}
}
}
foreach (var refs in mainModule.AssemblyReferences)
{
assemblyReferenceQueue.Enqueue((true, mainModule, refs));
}
foreach (var bamlReference in defaultBamlReferences)
{
assemblyReferenceQueue.Enqueue((true, mainModule, AssemblyNameReference.Parse(bamlReference)));
}
var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) =>
reference.IsAssembly ? "A:" + ((IAssemblyReference)reference.Reference).FullName :
"M:" + reference.Reference);
var processedAssemblyReferences = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer);
while (assemblyReferenceQueue.Count > 0)
{
var asmRef = assemblyReferenceQueue.Dequeue();
if (!processedAssemblyReferences.Add(asmRef))
continue;
PEFile asm;
if (asmRef.IsAssembly)
{
asm = assemblyResolver.Resolve((IAssemblyReference)asmRef.Reference);
}
else
{
asm = assemblyResolver.ResolveModule(asmRef.MainModule, (string)asmRef.Reference);
}
if (asm != null)
{
referencedAssemblies.Add(asm);
var metadata = asm.Metadata;
foreach (var h in metadata.ExportedTypes)
{
var exportedType = metadata.GetExportedType(h);
switch (exportedType.Implementation.Kind)
{
case SRM.HandleKind.AssemblyReference:
assemblyReferenceQueue.Enqueue((true, asm, new AssemblyReference(asm, (SRM.AssemblyReferenceHandle)exportedType.Implementation)));
break;
case SRM.HandleKind.AssemblyFile:
var file = metadata.GetAssemblyFile((SRM.AssemblyFileHandle)exportedType.Implementation);
assemblyReferenceQueue.Enqueue((false, asm, metadata.GetString(file.Name)));
break;
}
}
}
}
var mainModuleWithOptions = mainModule.WithOptions(TypeSystemOptions.Default);
var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(TypeSystemOptions.Default));
// Primitive types are necessary to avoid assertions in ILReader.
// Fallback to MinimalCorlib to provide the primitive types.
if (!HasType(KnownTypeCode.Void) || !HasType(KnownTypeCode.Int32))
{
Init(mainModule.WithOptions(TypeSystemOptions.Default), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.Instance }));
}
else
{
Init(mainModuleWithOptions, referencedAssembliesWithOptions);
}
this.MainModule = (MetadataModule)base.MainModule;
bool HasType(KnownTypeCode code)
{
TopLevelTypeName name = KnownTypeReference.Get(code).TypeName;
if (mainModule.GetTypeDefinition(name) != null)
return true;
foreach (var file in referencedAssemblies)
{
if (file.GetTypeDefinition(name) != null)
return true;
}
return false;
}
}
public new MetadataModule MainModule { get; }
BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(asm.GetPEFileOrNull(), asm.GetAssemblyResolver());
var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings());
decompiler.CancellationToken = cancellationToken;
var result = decompiler.Decompile(data);
output.Write(result.Xaml.ToString());
}
}
}

9
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -46,9 +46,14 @@ namespace ILSpy.BamlDecompiler @@ -46,9 +46,14 @@ namespace ILSpy.BamlDecompiler
public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options)
{
var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetPEFileOrNull(), assembly.GetAssemblyResolver(), stream, options.CancellationToken);
BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(assembly.GetPEFileOrNull(), assembly.GetAssemblyResolver());
var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings() {
ThrowOnAssemblyResolveErrors = options.DecompilerSettings.ThrowOnAssemblyResolveErrors
});
decompiler.CancellationToken = options.CancellationToken;
fileName = Path.ChangeExtension(fileName, ".xaml");
document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName));
var result = decompiler.Decompile(stream);
result.Xaml.Save(Path.Combine(options.SaveAsProjectDirectory, fileName));
return fileName;
}
}

6
ILSpy.BamlDecompiler/XamlContext.cs

@ -48,7 +48,7 @@ namespace ILSpy.BamlDecompiler @@ -48,7 +48,7 @@ namespace ILSpy.BamlDecompiler
public IDecompilerTypeSystem TypeSystem { get; }
public CancellationToken CancellationToken { get; private set; }
public BamlDecompilerOptions BamlDecompilerOptions { get; private set; }
public BamlDecompilerSettings Settings { get; private set; }
public BamlContext Baml { get; private set; }
public BamlNode RootNode { get; private set; }
@ -56,11 +56,11 @@ namespace ILSpy.BamlDecompiler @@ -56,11 +56,11 @@ namespace ILSpy.BamlDecompiler
public XmlnsDictionary XmlNs { get; }
public static XamlContext Construct(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token, BamlDecompilerOptions bamlDecompilerOptions)
public static XamlContext Construct(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token, BamlDecompilerSettings bamlDecompilerOptions)
{
var ctx = new XamlContext(typeSystem);
ctx.CancellationToken = token;
ctx.BamlDecompilerOptions = bamlDecompilerOptions ?? new BamlDecompilerOptions();
ctx.Settings = bamlDecompilerOptions ?? new BamlDecompilerSettings();
ctx.Baml = BamlContext.ConstructContext(typeSystem, document, token);
ctx.RootNode = BamlNode.Parse(document, token);

81
ILSpy.BamlDecompiler/XamlDecompiler.cs

@ -20,11 +20,15 @@ @@ -20,11 +20,15 @@
THE SOFTWARE.
*/
using System.Collections.Generic;
using System;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Threading;
using System.Xml.Linq;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ILSpy.BamlDecompiler.Baml;
@ -32,7 +36,7 @@ using ILSpy.BamlDecompiler.Rewrite; @@ -32,7 +36,7 @@ using ILSpy.BamlDecompiler.Rewrite;
namespace ILSpy.BamlDecompiler
{
internal class XamlDecompiler
public class XamlDecompiler
{
static readonly IRewritePass[] rewritePasses = new IRewritePass[] {
new XClassRewritePass(),
@ -42,9 +46,66 @@ namespace ILSpy.BamlDecompiler @@ -42,9 +46,66 @@ namespace ILSpy.BamlDecompiler
new DocumentRewritePass(),
};
public XDocument Decompile(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token, BamlDecompilerOptions bamlDecompilerOptions, List<string> assemblyReferences)
private BamlDecompilerTypeSystem typeSystem;
private BamlDecompilerSettings settings;
private MetadataModule module;
public BamlDecompilerSettings Settings {
get { return settings; }
set { settings = value; }
}
public CancellationToken CancellationToken { get; set; }
public XamlDecompiler(string fileName, BamlDecompilerSettings settings)
: this(CreateTypeSystemFromFile(fileName, settings), settings)
{
}
public XamlDecompiler(string fileName, IAssemblyResolver assemblyResolver, BamlDecompilerSettings settings)
: this(LoadPEFile(fileName, settings), assemblyResolver, settings)
{
}
public XamlDecompiler(PEFile module, IAssemblyResolver assemblyResolver, BamlDecompilerSettings settings)
: this(new BamlDecompilerTypeSystem(module, assemblyResolver), settings)
{
}
internal XamlDecompiler(BamlDecompilerTypeSystem typeSystem, BamlDecompilerSettings settings)
{
var ctx = XamlContext.Construct(typeSystem, document, token, bamlDecompilerOptions);
this.typeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem));
this.settings = settings;
this.module = typeSystem.MainModule;
if (module.TypeSystemOptions.HasFlag(TypeSystemOptions.Uncached))
throw new ArgumentException("Cannot use an uncached type system in the decompiler.");
}
static PEFile LoadPEFile(string fileName, BamlDecompilerSettings settings)
{
return new PEFile(
fileName,
new FileStream(fileName, FileMode.Open, FileAccess.Read),
streamOptions: PEStreamOptions.PrefetchEntireImage,
metadataOptions: MetadataReaderOptions.None
);
}
static BamlDecompilerTypeSystem CreateTypeSystemFromFile(string fileName, BamlDecompilerSettings settings)
{
var file = LoadPEFile(fileName, settings);
var resolver = new UniversalAssemblyResolver(fileName, settings.ThrowOnAssemblyResolveErrors,
file.DetectTargetFrameworkId(), file.DetectRuntimePack(),
PEStreamOptions.PrefetchMetadata,
MetadataReaderOptions.None);
return new BamlDecompilerTypeSystem(file, resolver);
}
public BamlDecompilationResult Decompile(Stream stream)
{
var ct = CancellationToken;
var document = BamlReader.ReadDocument(stream, ct);
var ctx = XamlContext.Construct(typeSystem, document, ct, settings);
var handler = HandlerMap.LookupHandler(ctx.RootNode.Type);
var elem = handler.Translate(ctx, ctx.RootNode, null);
@ -54,18 +115,12 @@ namespace ILSpy.BamlDecompiler @@ -54,18 +115,12 @@ namespace ILSpy.BamlDecompiler
foreach (var pass in rewritePasses)
{
token.ThrowIfCancellationRequested();
ct.ThrowIfCancellationRequested();
pass.Run(ctx, xaml);
}
if (assemblyReferences != null)
assemblyReferences.AddRange(ctx.Baml.AssemblyIdMap.Select(a => a.Value.AssemblyFullName));
return xaml;
var assemblyReferences = ctx.Baml.AssemblyIdMap.Select(a => a.Value.AssemblyFullName);
return new BamlDecompilationResult(xaml, assemblyReferences);
}
}
public class BamlDecompilerOptions
{
}
}

5
ILSpy.Package/ILSpy.Package.wapproj

@ -75,5 +75,10 @@ @@ -75,5 +75,10 @@
<ItemGroup>
<ProjectReference Include="..\ILSpy\ILSpy.csproj" SkipGetTargetFrameworkProperties="true" />
</ItemGroup>
<ItemGroup>
<Content Include="..\ILSpy\bin\$(Configuration)\net472\\**\*.*" Link="ILSpy\%(RecursiveDir)%(Filename)%(Extension)">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
</Project>

4
ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj

@ -38,8 +38,8 @@ @@ -38,8 +38,8 @@
<Import Project="../packages.props" />
<ItemGroup>
<PackageReference Include="Iced" Version="1.8.0" />
<PackageReference Include="ILCompiler.Reflection.ReadyToRun.Experimental" Version="6.0.0-preview.5.21224.4" />
<PackageReference Include="Iced" Version="1.13.0" />
<PackageReference Include="ILCompiler.Reflection.ReadyToRun.Experimental" Version="6.0.0-rc.2.21424.11" />
<!-- ILCompiler.Reflection.ReadyToRun has dependencies on System.Reflection.Metadata and
System.Runtime.CompilerServices.Unsafe. Because the AddIn compiles into ILSpy's output
directory, we're at risk of overwriting our dependencies with different versions.

2
ILSpy.ReadyToRun/ReadyToRunDisassembler.cs

@ -243,7 +243,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -243,7 +243,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
{
// This could happen if the compiler is generating bogus variable info mapping record that covers 0 instructions
// See https://github.com/dotnet/runtime/issues/47202
Debug.Assert(false);
// Debug.Assert(false);
continue;
}
switch (varLoc.VariableLocation.VarLocType)

1
ILSpy.Tests/ILSpy.Tests.csproj

@ -52,6 +52,7 @@ @@ -52,6 +52,7 @@
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(RoslynVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="$(RoslynVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkVersion)" />
<PackageReference Include="NUnit3TestAdapter" Version="$(NUnitAdapterVersion)" />
<PackageReference Include="NUnit" Version="$(NUnitVersion)" />
<PackageReference Include="Moq" Version="$(MoqVersion)" />

44
ILSpy.WithPackage.sln

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.202
# Visual Studio Version 17
VisualStudioVersion = 17.0.31612.314
MinimumVisualStudioVersion = 15.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E72-4000-B5AD-3A7B485A0896}"
ProjectSection(SolutionItems) = preProject
@ -34,6 +34,10 @@ EndProject @@ -34,6 +34,10 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.ReadyToRun", "ILSpy.ReadyToRun\ILSpy.ReadyToRun.csproj", "{4A9EDD49-EE62-4417-9140-EF82E39214E4}"
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "ILSpy.Package", "ILSpy.Package\ILSpy.Package.wapproj", "{BAB51A23-9C15-42CC-8465-EB732BF9A932}"
ProjectSection(ProjectDependencies) = postProject
{4A9EDD49-EE62-4417-9140-EF82E39214E4} = {4A9EDD49-EE62-4417-9140-EF82E39214E4}
{A6BAD2BA-76BA-461C-8B6D-418607591247} = {A6BAD2BA-76BA-461C-8B6D-418607591247}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -129,18 +133,6 @@ Global @@ -129,18 +133,6 @@ Global
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|x64.Build.0 = Release|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|x86.ActiveCfg = Release|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|x86.Build.0 = Release|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|x64.ActiveCfg = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|x64.Build.0 = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|x86.ActiveCfg = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|x86.Build.0 = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|Any CPU.Build.0 = Release|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|x64.ActiveCfg = Release|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|x64.Build.0 = Release|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|x86.ActiveCfg = Release|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|x86.Build.0 = Release|Any CPU
{B85A155A-9DD6-43BC-A624-2D8EC773D71F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B85A155A-9DD6-43BC-A624-2D8EC773D71F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B85A155A-9DD6-43BC-A624-2D8EC773D71F}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -165,6 +157,18 @@ Global @@ -165,6 +157,18 @@ Global
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|x64.Build.0 = Release|Any CPU
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|x86.ActiveCfg = Release|Any CPU
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|x86.Build.0 = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|x64.ActiveCfg = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|x64.Build.0 = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|x86.ActiveCfg = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|x86.Build.0 = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|Any CPU.Build.0 = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|x64.ActiveCfg = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|x64.Build.0 = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|x86.ActiveCfg = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|x86.Build.0 = Release|Any CPU
{BAB51A23-9C15-42CC-8465-EB732BF9A932}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BAB51A23-9C15-42CC-8465-EB732BF9A932}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BAB51A23-9C15-42CC-8465-EB732BF9A932}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@ -183,18 +187,6 @@ Global @@ -183,18 +187,6 @@ Global
{BAB51A23-9C15-42CC-8465-EB732BF9A932}.Release|x86.ActiveCfg = Release|x86
{BAB51A23-9C15-42CC-8465-EB732BF9A932}.Release|x86.Build.0 = Release|x86
{BAB51A23-9C15-42CC-8465-EB732BF9A932}.Release|x86.Deploy.0 = Release|x86
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|x64.ActiveCfg = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|x64.Build.0 = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|x86.ActiveCfg = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Debug|x86.Build.0 = Debug|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|Any CPU.Build.0 = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|x64.ActiveCfg = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|x64.Build.0 = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|x86.ActiveCfg = Release|Any CPU
{4A9EDD49-EE62-4417-9140-EF82E39214E4}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

3
ILSpy/Analyzers/AnalyzerScope.cs

@ -77,7 +77,8 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -77,7 +77,8 @@ namespace ICSharpCode.ILSpy.Analyzers
public IEnumerable<PEFile> GetAllModules()
{
return AssemblyList.GetAllAssemblies().GetAwaiter().GetResult()
.Select(asm => asm.GetPEFileOrNull());
.Select(asm => asm.GetPEFileOrNull())
.Where(x => x != null);
}
public IEnumerable<ITypeDefinition> GetTypesInScope(CancellationToken ct)

18
ILSpy/Commands/ShowDebugSteps.cs

@ -1,18 +0,0 @@ @@ -1,18 +0,0 @@
#if DEBUG
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Commands
{
[ExportMainMenuCommand(Menu = nameof(Resources._View), Header = nameof(Resources._ShowDebugSteps), MenuOrder = 5000)]
class ShowDebugSteps : SimpleCommand
{
public override void Execute(object parameter)
{
DockWorkspace.Instance.ShowToolPane(DebugStepsPaneModel.PaneContentId);
}
}
}
#endif

35
ILSpy/Commands/ShowPane.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Commands
{
[ExportMainMenuCommand(Menu = nameof(Resources._Window), Header = nameof(Resources._Assemblies), MenuCategory = "pane", MenuOrder = 5000)]
class ShowAssemblies : SimpleCommand
{
public override void Execute(object parameter)
{
DockWorkspace.Instance.ShowToolPane(AssemblyListPaneModel.PaneContentId);
}
}
[ExportMainMenuCommand(Menu = nameof(Resources._Window), Header = nameof(Resources._Analyzer), MenuCategory = "pane", MenuOrder = 5000)]
class ShowAnalyzer : SimpleCommand
{
public override void Execute(object parameter)
{
DockWorkspace.Instance.ShowToolPane(AnalyzerPaneModel.PaneContentId);
}
}
#if DEBUG
[ExportMainMenuCommand(Menu = nameof(Resources._Window), Header = nameof(Resources._ShowDebugSteps), MenuCategory = "pane", MenuOrder = 5000)]
class ShowDebugSteps : SimpleCommand
{
public override void Execute(object parameter)
{
DockWorkspace.Instance.ShowToolPane(DebugStepsPaneModel.PaneContentId);
}
}
#endif
}

2
ILSpy/FilterSettings.cs

@ -73,7 +73,7 @@ namespace ICSharpCode.ILSpy @@ -73,7 +73,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Gets whether a node with the specified text is matched by the current search term.
/// </summary>
public bool SearchTermMatches(string text)
public virtual bool SearchTermMatches(string text)
{
if (string.IsNullOrEmpty(searchTerm))
return true;

11
ILSpy/ILSpy.csproj

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<ApplicationIcon>Images\ILSpy-Large.ico</ApplicationIcon>
<ApplicationManifest>app.manifest</ApplicationManifest>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk</AssemblyOriginatorKeyFile>
@ -45,15 +46,17 @@ @@ -45,15 +46,17 @@
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemCompilerServicesUnsafeVersion)" />
<PackageReference Include="Dirkster.AvalonDock.Themes.VS2013" Version="4.50.1" />
<PackageReference Include="Dirkster.AvalonDock.Themes.VS2013" Version="4.51.1" />
<PackageReference Include="Microsoft.VisualStudio.Composition" Version="16.9.6-alpha" />
<PackageReference Include="System.Composition" Version="$(SystemCompositionVersion)" />
<PackageReference Include="Mono.Cecil" Version="$(MonoCecilVersion)" />
<PackageReference Include="OSVersionHelper" Version="1.1.24" />
<PackageReference Include="DataGridExtensions" Version="2.5.0" />
<PackageReference Include="DataGridExtensions" Version="2.5.6" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.31" />
<PackageReference Include="TomsToolbox.Wpf.Styles" Version="2.5.5" />
<PackageReference Include="TomsToolbox.Wpf.Styles" Version="$(WpfStylesToolboxVersion)" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="K4os.Compression.LZ4" Version="1.2.6" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
</ItemGroup>
<ItemGroup>
@ -132,6 +135,6 @@ @@ -132,6 +135,6 @@
<Target Name="ApplyStackExtension" AfterTargets="PostBuildEvent">
<Exec Condition="'$(VCToolsVersion)'!=''" Command="&quot;$(VCBasePath)Tools\MSVC\$(VCToolsVersion)\bin\Hostx64\x64\editbin.exe&quot; /stack:16777216 &quot;$(TargetPath)&quot;&#xD;&#xA;EXIT 0" />
<Exec Command="&quot;$(TargetFrameworkSDKToolsDirectory)sn.exe&quot; -R &quot;$(TargetPath)&quot; &quot;$(SolutionDir)\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk&quot;" />
<Exec Command="&quot;$(TargetFrameworkSDKToolsDirectory)sn.exe&quot; -R &quot;$(TargetPath)&quot; &quot;$(AssemblyOriginatorKeyFile)&quot;" />
</Target>
</Project>

5
ILSpy/Languages/CSharpILMixedLanguage.cs

@ -56,6 +56,7 @@ namespace ICSharpCode.ILSpy @@ -56,6 +56,7 @@ namespace ICSharpCode.ILSpy
options.CancellationToken) {
ShowMetadataTokens = Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens,
ShowMetadataTokensInBase10 = Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10,
ShowRawRVAOffsetAndBytes = Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowRawOffsetsAndBytesBeforeInstruction,
ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions
};
}
@ -109,7 +110,7 @@ namespace ICSharpCode.ILSpy @@ -109,7 +110,7 @@ namespace ICSharpCode.ILSpy
}
}
protected override void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodDefinition, ref BlobReader blob)
protected override void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva)
{
int index = sequencePoints.BinarySearch(blob.Offset, seq => seq.Offset);
if (index >= 0)
@ -143,7 +144,7 @@ namespace ICSharpCode.ILSpy @@ -143,7 +144,7 @@ namespace ICSharpCode.ILSpy
highlightingOutput?.EndSpan();
}
}
base.WriteInstruction(output, metadata, methodDefinition, ref blob);
base.WriteInstruction(output, metadata, methodHandle, ref blob, methodRva);
}
HighlightingColor gray = new HighlightingColor { Foreground = new SimpleHighlightingBrush(Colors.DarkGray) };

1
ILSpy/Languages/ILLanguage.cs

@ -61,6 +61,7 @@ namespace ICSharpCode.ILSpy @@ -61,6 +61,7 @@ namespace ICSharpCode.ILSpy
ShowSequencePoints = options.DecompilerSettings.ShowDebugInfo,
ShowMetadataTokens = Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens,
ShowMetadataTokensInBase10 = Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10,
ShowRawRVAOffsetAndBytes = Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowRawOffsetsAndBytesBeforeInstruction,
ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions
};
}

48
ILSpy/LoadedAssembly.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -35,6 +36,8 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -35,6 +36,8 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.Options;
using K4os.Compression.LZ4;
#nullable enable
namespace ICSharpCode.ILSpy
@ -323,6 +326,15 @@ namespace ICSharpCode.ILSpy @@ -323,6 +326,15 @@ namespace ICSharpCode.ILSpy
{
loadAssemblyException = ex;
}
// Maybe its a compressed Xamarin/Mono assembly, see https://github.com/xamarin/xamarin-android/pull/4686
try
{
return LoadCompressedAssembly(fileName);
}
catch (InvalidDataException)
{
// Not a compressed module, try other options below
}
// If it's not a .NET module, maybe it's a single-file bundle
var bundle = LoadedPackage.FromBundle(fileName);
if (bundle != null)
@ -365,6 +377,42 @@ namespace ICSharpCode.ILSpy @@ -365,6 +377,42 @@ namespace ICSharpCode.ILSpy
return new LoadResult(module);
}
LoadResult LoadCompressedAssembly(string fileName)
{
const uint CompressedDataMagic = 0x5A4C4158; // Magic used for Xamarin compressed module header ('XALZ', little-endian)
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (var fileReader = new BinaryReader(fileStream))
{
// Read compressed file header
var magic = fileReader.ReadUInt32();
if (magic != CompressedDataMagic)
throw new InvalidDataException($"Xamarin compressed module header magic {magic} does not match expected {CompressedDataMagic}");
_ = fileReader.ReadUInt32(); // skip index into descriptor table, unused
int uncompressedLength = (int)fileReader.ReadUInt32();
int compressedLength = (int)fileStream.Length; // Ensure we read all of compressed data
ArrayPool<byte> pool = ArrayPool<byte>.Shared;
var src = pool.Rent(compressedLength);
var dst = pool.Rent(uncompressedLength);
try
{
// fileReader stream position is now at compressed module data
fileStream.Read(src, 0, compressedLength);
// Decompress
LZ4Codec.Decode(src, 0, compressedLength, dst, 0, uncompressedLength);
// Load module from decompressed data buffer
using (var uncompressedStream = new MemoryStream(dst, writable: false))
{
return LoadAssembly(uncompressedStream, PEStreamOptions.PrefetchEntireImage);
}
}
finally
{
pool.Return(dst);
pool.Return(src);
}
}
}
IDebugInfoProvider? LoadDebugInfo(PEFile module)
{
if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols)

2
ILSpy/MainWindow.xaml

@ -107,7 +107,7 @@ @@ -107,7 +107,7 @@
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.FilterSettings.ApiVisPublicAndInternal}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.FilterSettings.ApiVisAll}" />
<Separator/>
<MenuItem Header="{x:Static properties:Resources.Language}">
<MenuItem Header="{x:Static properties:Resources.UILanguage}">
<MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={StaticResource cultureSelectionConverter}, ConverterParameter={x:Null}}" />
<MenuItem Header="English" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={StaticResource cultureSelectionConverter}, ConverterParameter=en-US}" />
<MenuItem Header="中文" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={StaticResource cultureSelectionConverter}, ConverterParameter=zh-Hans}" />

46
ILSpy/MainWindow.xaml.cs

@ -371,6 +371,29 @@ namespace ICSharpCode.ILSpy @@ -371,6 +371,29 @@ namespace ICSharpCode.ILSpy
}
#endregion
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (!e.Handled && e.KeyboardDevice.Modifiers == ModifierKeys.Alt && e.Key == Key.System)
{
switch (e.SystemKey)
{
case Key.A:
assemblyListComboBox.Focus();
e.Handled = true;
break;
case Key.L:
languageComboBox.Focus();
e.Handled = true;
break;
case Key.E: // Alt+V was already taken by _View menu
languageVersionComboBox.Focus();
e.Handled = true;
break;
}
}
}
public AssemblyList CurrentAssemblyList {
get { return assemblyList; }
}
@ -379,24 +402,8 @@ namespace ICSharpCode.ILSpy @@ -379,24 +402,8 @@ namespace ICSharpCode.ILSpy
List<LoadedAssembly> commandLineLoadedAssemblies = new List<LoadedAssembly>();
List<string> nugetPackagesToLoad = new List<string>();
bool HandleCommandLineArguments(CommandLineArguments args)
{
int i = 0;
while (i < args.AssembliesToLoad.Count)
{
var asm = args.AssembliesToLoad[i];
if (Path.GetExtension(asm) == ".nupkg")
{
nugetPackagesToLoad.Add(asm);
args.AssembliesToLoad.RemoveAt(i);
}
else
{
i++;
}
}
LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, focusNode: false);
if (args.Language != null)
sessionSettings.FilterSettings.Language = Languages.GetLanguage(args.Language);
@ -409,13 +416,6 @@ namespace ICSharpCode.ILSpy @@ -409,13 +416,6 @@ namespace ICSharpCode.ILSpy
/// </summary>
void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, ILSpySettings spySettings = null)
{
if (nugetPackagesToLoad.Count > 0)
{
var relevantPackages = nugetPackagesToLoad.ToArray();
nugetPackagesToLoad.Clear();
// Show the nuget package open dialog after the command line/window message was processed.
Dispatcher.BeginInvoke(new Action(() => LoadAssemblies(relevantPackages, commandLineLoadedAssemblies, focusNode: false)), DispatcherPriority.Normal);
}
var relevantAssemblies = commandLineLoadedAssemblies.ToList();
commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore
NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies);

14
ILSpy/Options/DisplaySettings.cs

@ -286,6 +286,19 @@ namespace ICSharpCode.ILSpy.Options @@ -286,6 +286,19 @@ namespace ICSharpCode.ILSpy.Options
}
}
private bool showRawOffsetsAndBytesBeforeInstruction;
public bool ShowRawOffsetsAndBytesBeforeInstruction {
get { return showRawOffsetsAndBytesBeforeInstruction; }
set {
if (showRawOffsetsAndBytesBeforeInstruction != value)
{
showRawOffsetsAndBytesBeforeInstruction = value;
OnPropertyChanged();
}
}
}
public void CopyValues(DisplaySettings s)
{
this.SelectedFont = s.selectedFont;
@ -305,6 +318,7 @@ namespace ICSharpCode.ILSpy.Options @@ -305,6 +318,7 @@ namespace ICSharpCode.ILSpy.Options
this.HighlightMatchingBraces = s.highlightMatchingBraces;
this.HighlightCurrentLine = s.highlightCurrentLine;
this.HideEmptyMetadataTables = s.hideEmptyMetadataTables;
this.ShowRawOffsetsAndBytesBeforeInstruction = s.showRawOffsetsAndBytesBeforeInstruction;
this.StyleWindowTitleBar = s.styleWindowTitleBar;
}
}

32
ILSpy/Options/DisplaySettingsPanel.xaml

@ -11,12 +11,7 @@ @@ -11,12 +11,7 @@
<local:FontSizeConverter x:Key="fontSizeConv" />
</UserControl.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical">
<GroupBox Header="{x:Static properties:Resources.Font}">
<Grid>
<Grid.ColumnDefinitions>
@ -64,7 +59,7 @@ @@ -64,7 +59,7 @@
</Border>
</Grid>
</GroupBox>
<GroupBox Header="{x:Static properties:Resources.Indentation}" Grid.Row="1">
<GroupBox Header="{x:Static properties:Resources.Indentation}">
<StackPanel Margin="3">
<CheckBox IsChecked="{Binding IndentationUseTabs}" Content="{x:Static properties:Resources.UseTabsInsteadOfSpaces}"></CheckBox>
<StackPanel Orientation="Horizontal">
@ -77,23 +72,32 @@ @@ -77,23 +72,32 @@
</StackPanel>
</StackPanel>
</GroupBox>
<GroupBox Header="{x:Static properties:Resources.OtherOptions}" Grid.Row="2">
<GroupBox Header="{x:Static properties:Resources.DecompilationViewOptions}">
<StackPanel Margin="3">
<CheckBox IsChecked="{Binding ShowLineNumbers}" Content="{x:Static properties:Resources.ShowLineNumbers}"></CheckBox>
<CheckBox IsChecked="{Binding ShowMetadataTokens}" Content="{x:Static properties:Resources.ShowMetadataTokens}"></CheckBox>
<CheckBox IsChecked="{Binding ShowMetadataTokensInBase10}" Content="{x:Static properties:Resources.ShowMetadataTokensInBase10}"></CheckBox>
<CheckBox IsChecked="{Binding HideEmptyMetadataTables}" Content="{x:Static properties:Resources.HideEmptyMetadataTables}"></CheckBox>
<CheckBox IsChecked="{Binding ShowDebugInfo}" Content="{x:Static properties:Resources.ShowInfoFromDebugSymbolsAvailable}"></CheckBox>
<CheckBox IsChecked="{Binding EnableWordWrap}" Content="{x:Static properties:Resources.EnableWordWrap}"></CheckBox>
<CheckBox IsChecked="{Binding FoldBraces}" Content="{x:Static properties:Resources.EnableFoldingBlocksBraces}"></CheckBox>
<CheckBox IsChecked="{Binding HighlightMatchingBraces}" Content="{x:Static properties:Resources.HighlightMatchingBraces}"></CheckBox>
<CheckBox IsChecked="{Binding HighlightCurrentLine}" Content="{x:Static properties:Resources.HighlightCurrentLine}"></CheckBox>
<CheckBox IsChecked="{Binding SortResults}" Content="{x:Static properties:Resources.SortResultsFitness}"></CheckBox>
<CheckBox IsChecked="{Binding ExpandMemberDefinitions}" Content="{x:Static properties:Resources.ExpandMemberDefinitionsAfterDecompilation}"></CheckBox>
<CheckBox IsChecked="{Binding ExpandUsingDeclarations}" Content="{x:Static properties:Resources.ExpandUsingDeclarationsAfterDecompilation}"></CheckBox>
<CheckBox IsChecked="{Binding ShowDebugInfo}" Content="{x:Static properties:Resources.ShowInfoFromDebugSymbolsAvailable}"></CheckBox>
<CheckBox IsChecked="{Binding ShowRawOffsetsAndBytesBeforeInstruction}" Content="{x:Static properties:Resources.ShowRawOffsetsAndBytesBeforeInstruction}"></CheckBox>
</StackPanel>
</GroupBox>
<GroupBox Header="{x:Static properties:Resources.TreeViewOptions}">
<StackPanel Margin="3">
<CheckBox IsChecked="{Binding ShowMetadataTokens}" Content="{x:Static properties:Resources.ShowMetadataTokens}"></CheckBox>
<CheckBox IsChecked="{Binding ShowMetadataTokensInBase10}" Content="{x:Static properties:Resources.ShowMetadataTokensInBase10}"></CheckBox>
<CheckBox IsChecked="{Binding HideEmptyMetadataTables}" Content="{x:Static properties:Resources.HideEmptyMetadataTables}"></CheckBox>
</StackPanel>
</GroupBox>
<GroupBox Header="{x:Static properties:Resources.OtherOptions}">
<StackPanel Margin="3">
<CheckBox IsChecked="{Binding SortResults}" Content="{x:Static properties:Resources.SortResultsFitness}"></CheckBox>
<CheckBox IsChecked="{Binding StyleWindowTitleBar}" Content="{x:Static properties:Resources.StyleTheWindowTitleBar}"></CheckBox>
</StackPanel>
</GroupBox>
</Grid>
</StackPanel>
</ScrollViewer>
</UserControl>

2
ILSpy/Options/DisplaySettingsPanel.xaml.cs

@ -123,6 +123,7 @@ namespace ICSharpCode.ILSpy.Options @@ -123,6 +123,7 @@ namespace ICSharpCode.ILSpy.Options
s.HighlightMatchingBraces = (bool?)e.Attribute("HighlightMatchingBraces") ?? true;
s.HighlightCurrentLine = (bool?)e.Attribute("HighlightCurrentLine") ?? false;
s.HideEmptyMetadataTables = (bool?)e.Attribute("HideEmptyMetadataTables") ?? true;
s.ShowRawOffsetsAndBytesBeforeInstruction = (bool?)e.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false;
s.StyleWindowTitleBar = (bool?)e.Attribute("StyleWindowTitleBar") ?? false;
return s;
@ -150,6 +151,7 @@ namespace ICSharpCode.ILSpy.Options @@ -150,6 +151,7 @@ namespace ICSharpCode.ILSpy.Options
section.SetAttributeValue("HighlightMatchingBraces", s.HighlightMatchingBraces);
section.SetAttributeValue("HighlightCurrentLine", s.HighlightCurrentLine);
section.SetAttributeValue("HideEmptyMetadataTables", s.HideEmptyMetadataTables);
section.SetAttributeValue("ShowRawOffsetsAndBytesBeforeInstruction", s.ShowRawOffsetsAndBytesBeforeInstruction);
section.SetAttributeValue("StyleWindowTitleBar", s.StyleWindowTitleBar);
XElement existingElement = root.Element("DisplaySettings");

4
ILSpy/Properties/AssemblyInfo.template.cs

@ -37,10 +37,10 @@ using System.Runtime.InteropServices; @@ -37,10 +37,10 @@ using System.Runtime.InteropServices;
internal static class RevisionClass
{
public const string Major = "7";
public const string Minor = "1";
public const string Minor = "2";
public const string Build = "0";
public const string Revision = "$INSERTREVISION$";
public const string VersionName = null;
public const string VersionName = "preview1";
public const string FullVersion = Major + "." + Minor + "." + Build + ".$INSERTREVISION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$";
}

80
ILSpy/Properties/Resources.Designer.cs generated

@ -78,6 +78,24 @@ namespace ICSharpCode.ILSpy.Properties { @@ -78,6 +78,24 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Analy_zer.
/// </summary>
public static string _Analyzer {
get {
return ResourceManager.GetString("_Analyzer", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Assemblies.
/// </summary>
public static string _Assemblies {
get {
return ResourceManager.GetString("_Assemblies", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Check for Updates.
/// </summary>
@ -621,6 +639,15 @@ namespace ICSharpCode.ILSpy.Properties { @@ -621,6 +639,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Decompilation view options.
/// </summary>
public static string DecompilationViewOptions {
get {
return ResourceManager.GetString("DecompilationViewOptions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompilation was cancelled..
/// </summary>
@ -1694,15 +1721,6 @@ namespace ICSharpCode.ILSpy.Properties { @@ -1694,15 +1721,6 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Language.
/// </summary>
public static string Language {
get {
return ResourceManager.GetString("Language", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Are you sure that you want to delete the selected assembly list?.
/// </summary>
@ -1992,6 +2010,17 @@ namespace ICSharpCode.ILSpy.Properties { @@ -1992,6 +2010,17 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Failed to decompile the assemblies {0} because the namespace directory structure is nested too deep.
///
///If you are using Windows 10.0.14393 (Windows 10 version 1607) or later, you can enable &quot;Long path support&quot; by creating a REG_DWORD registry key named &quot;LongPathsEnabled&quot; with value 0x1 at &quot;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem&quot; (see https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation for more information)..
/// </summary>
public static string ProjectExportPathTooLong {
get {
return ResourceManager.GetString("ProjectExportPathTooLong", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies..
/// </summary>
@ -2220,7 +2249,7 @@ namespace ICSharpCode.ILSpy.Properties { @@ -2220,7 +2249,7 @@ namespace ICSharpCode.ILSpy.Properties {
}
/// <summary>
/// Looks up a localized string similar to Select a list of assemblies.
/// Looks up a localized string similar to Select a list of assemblies (Alt+A).
/// </summary>
public static string SelectAssemblyListDropdownTooltip {
get {
@ -2229,7 +2258,7 @@ namespace ICSharpCode.ILSpy.Properties { @@ -2229,7 +2258,7 @@ namespace ICSharpCode.ILSpy.Properties {
}
/// <summary>
/// Looks up a localized string similar to Select language to decompile to.
/// Looks up a localized string similar to Select language to decompile to (Alt+L).
/// </summary>
public static string SelectLanguageDropdownTooltip {
get {
@ -2256,7 +2285,7 @@ namespace ICSharpCode.ILSpy.Properties { @@ -2256,7 +2285,7 @@ namespace ICSharpCode.ILSpy.Properties {
}
/// <summary>
/// Looks up a localized string similar to Select version of language to output.
/// Looks up a localized string similar to Select version of language to output (Alt+E).
/// </summary>
public static string SelectVersionDropdownTooltip {
get {
@ -2408,6 +2437,15 @@ namespace ICSharpCode.ILSpy.Properties { @@ -2408,6 +2437,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Show raw offsets and bytes before each instruction.
/// </summary>
public static string ShowRawOffsetsAndBytesBeforeInstruction {
get {
return ResourceManager.GetString("ShowRawOffsetsAndBytesBeforeInstruction", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show state after this step.
/// </summary>
@ -2516,6 +2554,15 @@ namespace ICSharpCode.ILSpy.Properties { @@ -2516,6 +2554,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Tree view options.
/// </summary>
public static string TreeViewOptions {
get {
return ResourceManager.GetString("TreeViewOptions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type.
/// </summary>
@ -2525,6 +2572,15 @@ namespace ICSharpCode.ILSpy.Properties { @@ -2525,6 +2572,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to UI Language.
/// </summary>
public static string UILanguage {
get {
return ResourceManager.GetString("UILanguage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to System.
/// </summary>

32
ILSpy/Properties/Resources.resx

@ -234,6 +234,9 @@ Are you sure you want to continue?</value> @@ -234,6 +234,9 @@ Are you sure you want to continue?</value>
<data name="DecompilationCompleteInF1Seconds" xml:space="preserve">
<value>Decompilation complete in {0:F1} seconds.</value>
</data>
<data name="DecompilationViewOptions" xml:space="preserve">
<value>Decompilation view options</value>
</data>
<data name="DecompilationWasCancelled" xml:space="preserve">
<value>Decompilation was cancelled.</value>
</data>
@ -591,9 +594,6 @@ Are you sure you want to continue?</value> @@ -591,9 +594,6 @@ Are you sure you want to continue?</value>
<data name="InsertUsingDeclarations" xml:space="preserve">
<value>Insert using declarations</value>
</data>
<data name="Language" xml:space="preserve">
<value>Language</value>
</data>
<data name="ListDeleteConfirmation" xml:space="preserve">
<value>Are you sure that you want to delete the selected assembly list?</value>
</data>
@ -691,6 +691,11 @@ Please disable all filters that might hide the item (i.e. activate "View &gt; Sh @@ -691,6 +691,11 @@ Please disable all filters that might hide the item (i.e. activate "View &gt; Sh
<data name="ProjectExportFormatSDKHint" xml:space="preserve">
<value>A SDK-style project was generated. Learn more at https://docs.microsoft.com/en-us/nuget/resources/check-project-format.</value>
</data>
<data name="ProjectExportPathTooLong" xml:space="preserve">
<value>Failed to decompile the assemblies {0} because the namespace directory structure is nested too deep.
If you are using Windows 10.0.14393 (Windows 10 version 1607) or later, you can enable "Long path support" by creating a REG_DWORD registry key named "LongPathsEnabled" with value 0x1 at "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem" (see https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation for more information).</value>
</data>
<data name="PropertyManuallyMissingReferencesListLoadedAssemblies" xml:space="preserve">
<value>for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies.</value>
</data>
@ -769,10 +774,10 @@ Do you want to continue?</value> @@ -769,10 +774,10 @@ Do you want to continue?</value>
<value>Select assemblies to open:</value>
</data>
<data name="SelectAssemblyListDropdownTooltip" xml:space="preserve">
<value>Select a list of assemblies</value>
<value>Select a list of assemblies (Alt+A)</value>
</data>
<data name="SelectLanguageDropdownTooltip" xml:space="preserve">
<value>Select language to decompile to</value>
<value>Select language to decompile to (Alt+L)</value>
</data>
<data name="SelectList" xml:space="preserve">
<value>Select a list:</value>
@ -781,7 +786,7 @@ Do you want to continue?</value> @@ -781,7 +786,7 @@ Do you want to continue?</value>
<value>Select PDB...</value>
</data>
<data name="SelectVersionDropdownTooltip" xml:space="preserve">
<value>Select version of language to output</value>
<value>Select version of language to output (Alt+E)</value>
</data>
<data name="SettingsChangeRestartRequired" xml:space="preserve">
<value>You must restart ILSpy for the change to take effect.</value>
@ -822,6 +827,9 @@ Do you want to continue?</value> @@ -822,6 +827,9 @@ Do you want to continue?</value>
<data name="ShowPublicOnlyTypesMembers" xml:space="preserve">
<value>Show only public types and members</value>
</data>
<data name="ShowRawOffsetsAndBytesBeforeInstruction" xml:space="preserve">
<value>Show raw offsets and bytes before each instruction</value>
</data>
<data name="ShowStateAfterThisStep" xml:space="preserve">
<value>Show state after this step</value>
</data>
@ -867,9 +875,15 @@ Do you want to continue?</value> @@ -867,9 +875,15 @@ Do you want to continue?</value>
<data name="ToggleFolding" xml:space="preserve">
<value>Toggle All Folding</value>
</data>
<data name="TreeViewOptions" xml:space="preserve">
<value>Tree view options</value>
</data>
<data name="Type" xml:space="preserve">
<value>Type</value>
</data>
<data name="UILanguage" xml:space="preserve">
<value>UI Language</value>
</data>
<data name="UILanguage_System" xml:space="preserve">
<value>System</value>
</data>
@ -933,6 +947,12 @@ Do you want to continue?</value> @@ -933,6 +947,12 @@ Do you want to continue?</value>
<data name="_AddMainList" xml:space="preserve">
<value>_Add To Main List</value>
</data>
<data name="_Analyzer" xml:space="preserve">
<value>Analy_zer</value>
</data>
<data name="_Assemblies" xml:space="preserve">
<value>_Assemblies</value>
</data>
<data name="_CheckUpdates" xml:space="preserve">
<value>_Check for Updates</value>
</data>

6
ILSpy/Properties/Resources.zh-Hans.resx

@ -585,9 +585,6 @@ @@ -585,9 +585,6 @@
<data name="InsertUsingDeclarations" xml:space="preserve">
<value>插入使用声明</value>
</data>
<data name="Language" xml:space="preserve">
<value>语言</value>
</data>
<data name="ListDeleteConfirmation" xml:space="preserve">
<value>是否删除选中的程序集列表?</value>
</data>
@ -858,6 +855,9 @@ @@ -858,6 +855,9 @@
<data name="Type" xml:space="preserve">
<value>类型</value>
</data>
<data name="UILanguage" xml:space="preserve">
<value>语言</value>
</data>
<data name="UILanguage_System" xml:space="preserve">
<value>系统</value>
</data>

36
ILSpy/Search/AbstractSearchStrategy.cs

@ -25,14 +25,10 @@ namespace ICSharpCode.ILSpy.Search @@ -25,14 +25,10 @@ namespace ICSharpCode.ILSpy.Search
if (terms.Length == 1 && terms[0].Length > 2)
{
string search = terms[0];
if (search.StartsWith("/", StringComparison.Ordinal) && search.Length > 4)
if (TryParseRegex(search, out regex))
{
var regexString = search.Substring(1, search.Length - 1);
fullNameSearch = search.Contains("\\.");
omitGenerics = !search.Contains("<");
if (regexString.EndsWith("/", StringComparison.Ordinal))
regexString = regexString.Substring(0, regexString.Length - 1);
regex = SafeNewRegex(regexString);
}
else
{
@ -129,15 +125,35 @@ namespace ICSharpCode.ILSpy.Search @@ -129,15 +125,35 @@ namespace ICSharpCode.ILSpy.Search
resultQueue.TryAdd(result);
}
Regex SafeNewRegex(string unsafePattern)
bool TryParseRegex(string input, out Regex pattern)
{
try
pattern = null;
if (!input.StartsWith("/", StringComparison.Ordinal))
{
return new Regex(unsafePattern, RegexOptions.Compiled);
return false;
}
input = input.Substring(1);
if (input.EndsWith("/", StringComparison.Ordinal))
{
input = input.Remove(input.Length - 1);
}
catch (ArgumentException)
if (string.IsNullOrWhiteSpace(input))
{
return null;
return false;
}
pattern = SafeNewRegex(input);
return pattern != null;
static Regex SafeNewRegex(string unsafePattern)
{
try
{
return new Regex(unsafePattern, RegexOptions.Compiled);
}
catch (ArgumentException)
{
return null;
}
}
}
}

2
ILSpy/Search/SearchPane.cs

@ -397,7 +397,7 @@ namespace ICSharpCode.ILSpy @@ -397,7 +397,7 @@ namespace ICSharpCode.ILSpy
}
}
[ExportMainMenuCommand(Menu = nameof(Properties.Resources._View), Header = nameof(Properties.Resources.Search), MenuIcon = "Images/Search", MenuCategory = nameof(Properties.Resources.View), MenuOrder = 100)]
[ExportMainMenuCommand(Menu = nameof(Properties.Resources._Window), Header = nameof(Properties.Resources.Search), MenuIcon = "Images/Search", MenuCategory = "pane", MenuOrder = 100)]
[ExportToolbarCommand(ToolTip = nameof(Properties.Resources.SearchCtrlShiftFOrCtrlE), ToolbarIcon = "Images/Search", ToolbarCategory = nameof(Properties.Resources.View), ToolbarOrder = 100)]
sealed class ShowSearchCommand : CommandWrapper
{

7
ILSpy/SolutionWriter.cs

@ -229,6 +229,13 @@ namespace ICSharpCode.ILSpy @@ -229,6 +229,13 @@ namespace ICSharpCode.ILSpy
statusOutput.Add("-------------");
statusOutput.Add($"Failed to decompile the assembly '{loadedAssembly.FileName}':{Environment.NewLine}{e.Message}");
}
catch (PathTooLongException e)
{
statusOutput.Add("-------------");
statusOutput.Add(string.Format(Properties.Resources.ProjectExportPathTooLong, loadedAssembly.FileName)
+ Environment.NewLine + Environment.NewLine
+ e.ToString());
}
catch (Exception e) when (!(e is OperationCanceledException))
{
statusOutput.Add("-------------");

46
ILSpy/TextView/DecompilerTextView.cs

@ -1079,26 +1079,40 @@ namespace ICSharpCode.ILSpy.TextView @@ -1079,26 +1079,40 @@ namespace ICSharpCode.ILSpy.TextView
{
bool originalProjectFormatSetting = context.Options.DecompilerSettings.UseSdkStyleProjectFormat;
context.Options.EscapeInvalidIdentifiers = true;
AvalonEditTextOutput output = new AvalonEditTextOutput {
EnableHyperlinks = true,
Title = string.Join(", ", context.TreeNodes.Select(n => n.Text))
};
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
using (StreamWriter w = new StreamWriter(fileName))
try
{
try
using (StreamWriter w = new StreamWriter(fileName))
{
DecompileNodes(context, new PlainTextOutput(w));
}
catch (OperationCanceledException)
{
w.WriteLine();
w.WriteLine(Properties.Resources.DecompilationWasCancelled);
throw;
try
{
DecompileNodes(context, new PlainTextOutput(w));
}
catch (OperationCanceledException)
{
w.WriteLine();
w.WriteLine(Properties.Resources.DecompilationWasCancelled);
throw;
}
catch (PathTooLongException pathTooLong) when (context.Options.SaveAsProjectDirectory != null)
{
output.WriteLine(Properties.Resources.ProjectExportPathTooLong, string.Join(", ", context.TreeNodes.Select(n => n.Text)));
output.WriteLine();
output.WriteLine(pathTooLong.ToString());
tcs.SetResult(output);
return;
}
}
}
stopwatch.Stop();
AvalonEditTextOutput output = new AvalonEditTextOutput {
EnableHyperlinks = true,
Title = string.Join(", ", context.TreeNodes.Select(n => n.Text))
};
finally
{
stopwatch.Stop();
}
output.WriteLine(Properties.Resources.DecompilationCompleteInF1Seconds, stopwatch.Elapsed.TotalSeconds);
if (context.Options.SaveAsProjectDirectory != null)
@ -1106,9 +1120,13 @@ namespace ICSharpCode.ILSpy.TextView @@ -1106,9 +1120,13 @@ namespace ICSharpCode.ILSpy.TextView
output.WriteLine();
bool useSdkStyleProjectFormat = context.Options.DecompilerSettings.UseSdkStyleProjectFormat;
if (useSdkStyleProjectFormat)
{
output.WriteLine(Properties.Resources.ProjectExportFormatSDKHint);
}
else
{
output.WriteLine(Properties.Resources.ProjectExportFormatNonSDKHint);
}
output.WriteLine(Properties.Resources.ProjectExportFormatChangeSettingHint);
if (originalProjectFormatSetting != useSdkStyleProjectFormat)
{

4
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -342,11 +342,11 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -342,11 +342,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
HandleException(badImage, "This file does not contain a managed assembly.");
}
catch (FileNotFoundException fileNotFound)
catch (FileNotFoundException fileNotFound) when (options.SaveAsProjectDirectory == null)
{
HandleException(fileNotFound, "The file was not found.");
}
catch (DirectoryNotFoundException dirNotFound)
catch (DirectoryNotFoundException dirNotFound) when (options.SaveAsProjectDirectory == null)
{
HandleException(dirNotFound, "The directory was not found.");
}

94
ILSpy/app.manifest

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
@ -16,62 +16,62 @@ @@ -16,62 +16,62 @@
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
is designed to work with. Uncomment the appropriate elements and Windows will
automatically selected the most compatible environment. -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- Enable per-monitor DPI awareness: https://github.com/Microsoft/WPF-Samples/tree/master/PerMonitorDPI -->
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True</dpiAware>
<!-- Enable long path support: https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/ -->
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- Enable per-monitor DPI awareness: https://github.com/Microsoft/WPF-Samples/tree/master/PerMonitorDPI -->
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True</dpiAware>
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
<!-- Enable long path support: https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/ -->
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">True</longPathAware>
</windowsSettings>
</application>
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</dependentAssembly>
</dependency>
</assembly>

4
SharpTreeView/ICSharpCode.TreeView.csproj

@ -23,8 +23,10 @@ @@ -23,8 +23,10 @@
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<Import Project="..\packages.props" />
<ItemGroup>
<PackageReference Include="TomsToolbox.Wpf.Styles" Version="2.5.5" />
<PackageReference Include="TomsToolbox.Wpf.Styles" Version="$(WpfStylesToolboxVersion)" />
</ItemGroup>
</Project>

28
doc/third-party-notices.txt

@ -415,6 +415,34 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE @@ -415,6 +415,34 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
License Notice for K4os.Compression.LZ4 (part of ILSpy)
---------------------------
https://github.com/MiloszKrajewski/K4os.Compression.LZ4/blob/master/LICENSE
MIT License
Copyright (c) 2017 Milosz Krajewski
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.
License Notice for LightJson (part of ICSharpCode.Decompiler)
---------------------------

10
packages.props

@ -11,11 +11,13 @@ @@ -11,11 +11,13 @@
<SystemCompositionVersion>5.0.1</SystemCompositionVersion>
<ILAsmVersion>5.0.0</ILAsmVersion> <!-- Microsoft.NETCore.ILAsm -->
<RoslynVersion>3.11.0-1.final</RoslynVersion> <!-- Microsoft.CodeAnalysis.* -->
<MonoCecilVersion>0.11.3</MonoCecilVersion>
<MonoCecilVersion>0.11.4</MonoCecilVersion>
<AvalonEditVersion>6.1.1</AvalonEditVersion>
<NUnitVersion>3.12.0</NUnitVersion>
<NUnitAdapterVersion>3.13.0</NUnitAdapterVersion>
<MoqVersion>4.14.1</MoqVersion>
<WpfStylesToolboxVersion>2.6.1</WpfStylesToolboxVersion>
<NUnitVersion>3.13.2</NUnitVersion>
<NUnitAdapterVersion>4.0.0</NUnitAdapterVersion>
<MicrosoftNETTestSdkVersion>16.11.0</MicrosoftNETTestSdkVersion>
<MoqVersion>4.16.1</MoqVersion>
<DiffLibVersion>2017.7.26.1241</DiffLibVersion>
<DSRConverterXmlVersion>1.1.0-beta2-20115-01</DSRConverterXmlVersion>
</PropertyGroup>

Loading…
Cancel
Save