Browse Source

Merge branch 'master' of https://github.com/icsharpcode/ILSpy into fix-1981

pull/2005/head
Siegfried Pammer 5 years ago
parent
commit
68bac527d1
  1. 7
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 2
      ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs
  3. 2
      ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs
  4. 37
      ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
  5. 5
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  6. 12
      ILSpy.AddIn/ILSpy.AddIn.csproj
  7. 8
      ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs
  8. 22
      ILSpy.BamlDecompiler/Xaml/XamlUtils.cs
  9. 186
      ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs
  10. 2
      ILSpy.Tests/ILSpy.Tests.csproj
  11. 2
      ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs
  12. 59
      ILSpy/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs
  13. 2
      ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs
  14. 2
      ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs
  15. 6
      ILSpy/Commands/SearchMsdnContextMenuEntry.cs
  16. 9
      ILSpy/ILSpy.csproj
  17. 75
      ILSpy/MainWindow.xaml.cs
  18. 17
      ILSpy/Properties/Resources.Designer.cs
  19. 14
      ILSpy/Properties/Resources.resx
  20. 2
      ILSpy/Properties/Resources.zh-Hans.resx

7
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -616,6 +616,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -616,6 +616,7 @@ namespace ICSharpCode.Decompiler.CSharp
while (blob.RemainingBytes > 0) {
var code = blob.DecodeOpCode();
switch (code) {
case ILOpCode.Newobj:
case ILOpCode.Stfld:
// async and yield fsms:
var token = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32());
@ -623,14 +624,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -623,14 +624,16 @@ namespace ICSharpCode.Decompiler.CSharp
continue;
TypeDefinitionHandle fsmTypeDef;
switch (token.Kind) {
case HandleKind.MethodDefinition:
var fsmMethod = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)token);
fsmTypeDef = fsmMethod.GetDeclaringType();
break;
case HandleKind.FieldDefinition:
var fsmField = module.Metadata.GetFieldDefinition((FieldDefinitionHandle)token);
fsmTypeDef = fsmField.GetDeclaringType();
break;
case HandleKind.MemberReference:
var memberRef = module.Metadata.GetMemberReference((MemberReferenceHandle)token);
if (memberRef.GetKind() != MemberReferenceKind.Field)
continue;
fsmTypeDef = ExtractDeclaringType(memberRef);
break;
default:

2
ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs

@ -416,7 +416,6 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -416,7 +416,6 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
return "\\u" + ((int)ch).ToString("x4");
default:
switch (char.GetUnicodeCategory(ch)) {
case UnicodeCategory.ModifierLetter:
case UnicodeCategory.NonSpacingMark:
case UnicodeCategory.SpacingCombiningMark:
case UnicodeCategory.EnclosingMark:
@ -503,7 +502,6 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -503,7 +502,6 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
return true;
}
switch (char.GetUnicodeCategory(identifier, index)) {
case UnicodeCategory.ModifierLetter:
case UnicodeCategory.NonSpacingMark:
case UnicodeCategory.SpacingCombiningMark:
case UnicodeCategory.EnclosingMark:

2
ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs

@ -59,7 +59,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -59,7 +59,7 @@ namespace ICSharpCode.Decompiler.Disassembler
return unchecked(982451629 * Code.GetHashCode() + 982451653 * Name.GetHashCode());
}
public string Link => "http://msdn.microsoft.com/library/system.reflection.emit.opcodes." + EncodedName.ToLowerInvariant() + ".aspx";
public string Link => "https://docs.microsoft.com/dotnet/api/system.reflection.emit.opcodes." + EncodedName.ToLowerInvariant();
public string EncodedName {
get {
if (encodedName != null)

37
ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs

@ -83,24 +83,35 @@ namespace ICSharpCode.Decompiler.Metadata @@ -83,24 +83,35 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
packageBasePaths.Add(basePath);
var depsJsonFileName = Path.Combine(basePath, $"{assemblyName}.deps.json");
if (!File.Exists(depsJsonFileName)) {
if (File.Exists(depsJsonFileName)) {
packages = LoadPackageInfos(depsJsonFileName, targetFrameworkIdString).ToArray();
foreach (var path in LookupPaths) {
foreach (var p in packages) {
foreach (var item in p.RuntimeComponents) {
var itemPath = Path.GetDirectoryName(item);
var fullPath = Path.Combine(path, p.Name, p.Version, itemPath).ToLowerInvariant();
if (Directory.Exists(fullPath))
packageBasePaths.Add(fullPath);
}
}
}
} else {
loadInfo?.AddMessage(assemblyName, MessageKind.Warning, $"{assemblyName}.deps.json could not be found!");
return;
}
}
packages = LoadPackageInfos(depsJsonFileName, targetFrameworkIdString).ToArray();
public void AddSearchDirectory(string path)
{
this.packageBasePaths.Add(path);
}
foreach (var path in LookupPaths) {
foreach (var p in packages) {
foreach (var item in p.RuntimeComponents) {
var itemPath = Path.GetDirectoryName(item);
var fullPath = Path.Combine(path, p.Name, p.Version, itemPath).ToLowerInvariant();
if (Directory.Exists(fullPath))
packageBasePaths.Add(fullPath);
}
}
}
public void RemoveSearchDirectory(string path)
{
this.packageBasePaths.Remove(path);
}
public string TryResolveDotNetCore(IAssemblyReference name)

5
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -71,11 +71,13 @@ namespace ICSharpCode.Decompiler.Metadata @@ -71,11 +71,13 @@ namespace ICSharpCode.Decompiler.Metadata
public void AddSearchDirectory(string directory)
{
directories.Add(directory);
dotNetCorePathFinder?.AddSearchDirectory(directory);
}
public void RemoveSearchDirectory(string directory)
{
directories.Remove(directory);
dotNetCorePathFinder?.RemoveSearchDirectory(directory);
}
public string[] GetSearchDirectories()
@ -185,6 +187,9 @@ namespace ICSharpCode.Decompiler.Metadata @@ -185,6 +187,9 @@ namespace ICSharpCode.Decompiler.Metadata
goto default;
if (dotNetCorePathFinder == null) {
dotNetCorePathFinder = new DotNetCorePathFinder(mainAssemblyFileName, targetFramework, targetFrameworkIdentifier, targetFrameworkVersion);
foreach (var directory in directories) {
dotNetCorePathFinder.AddSearchDirectory(directory);
}
}
file = dotNetCorePathFinder.TryResolveDotNetCore(name);
if (file != null)

12
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -117,14 +117,12 @@ @@ -117,14 +117,12 @@
<AdditionalDependencies Include="$(ILSpyBuildPath)Mono.Cecil.Pdb.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)ILSpy.BamlDecompiler.Plugin.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)Microsoft.DiaSymReader*.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)OSVersionHelper.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)OSVersionHelper.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)Xceed.Wpf.AvalonDock.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)DataGridExtensions.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)Iced.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)ILCompiler.Reflection.ReadyToRun.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)ILSpy.ReadyToRun.Plugin.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)Microsoft.NET.HostModel.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)Ookii.Dialogs.Wpf.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)DataGridExtensions.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)Iced.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)ILCompiler.Reflection.ReadyToRun.dll" />
<AdditionalDependencies Include="$(ILSpyBuildPath)ILSpy.ReadyToRun.Plugin.dll" />
</ItemGroup>
<ItemGroup>

8
ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs

@ -27,6 +27,8 @@ using ICSharpCode.Decompiler.IL.Transforms; @@ -27,6 +27,8 @@ using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using ILSpy.BamlDecompiler.Xaml;
namespace ILSpy.BamlDecompiler.Rewrite
{
internal class ConnectionIdRewritePass : IRewritePass
@ -111,7 +113,8 @@ namespace ILSpy.BamlDecompiler.Rewrite @@ -111,7 +113,8 @@ namespace ILSpy.BamlDecompiler.Rewrite
}
} else {
foreach (var ifInst in function.Descendants.OfType<IfInstruction>()) {
var comp = ifInst.Condition as Comp;
if (!(ifInst.Condition is Comp comp))
continue;
if (comp.Kind != ComparisonKind.Inequality && comp.Kind != ComparisonKind.Equality)
continue;
if (!comp.Right.MatchLdcI4(out int id))
@ -128,7 +131,7 @@ namespace ILSpy.BamlDecompiler.Rewrite @@ -128,7 +131,7 @@ namespace ILSpy.BamlDecompiler.Rewrite
var events = new List<EventRegistration>();
switch (inst) {
case Block b:
case Block _:
foreach (var node in ((Block)inst).Instructions) {
FindEvents(node, events);
}
@ -197,6 +200,7 @@ namespace ILSpy.BamlDecompiler.Rewrite @@ -197,6 +200,7 @@ namespace ILSpy.BamlDecompiler.Rewrite
if (ldftn.OpCode != OpCode.LdFtn && ldftn.OpCode != OpCode.LdVirtFtn)
return false;
handlerName = ((IInstructionWithMethodOperand)ldftn).Method.Name;
handlerName = XamlUtils.EscapeName(handlerName);
return true;
}

22
ILSpy.BamlDecompiler/Xaml/XamlUtils.cs

@ -73,5 +73,27 @@ namespace ILSpy.BamlDecompiler.Xaml { @@ -73,5 +73,27 @@ namespace ILSpy.BamlDecompiler.Xaml {
// (11700684 * 0.000001) != (11700684 / 1000000.0) => 11.700683999999999 != 11.700684
return reader.ReadInt32() / 1000000.0;
}
/// <summary>
/// Escape characters that cannot be used in XML.
/// </summary>
public static StringBuilder EscapeName(StringBuilder sb, string name)
{
foreach (char ch in name) {
if (char.IsWhiteSpace(ch) || char.IsControl(ch) || char.IsSurrogate(ch))
sb.AppendFormat("\\u{0:x4}", (int)ch);
else
sb.Append(ch);
}
return sb;
}
/// <summary>
/// Escape characters that cannot be displayed in the UI.
/// </summary>
public static string EscapeName(string name)
{
return EscapeName(new StringBuilder(name.Length), name).ToString();
}
}
}

186
ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs

@ -0,0 +1,186 @@ @@ -0,0 +1,186 @@
// Copyright (c) 2020 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.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.Analyzers.Builtin;
using Moq;
using NUnit.Framework;
namespace ICSharpCode.ILSpy.Tests.Analyzers
{
[TestFixture, Parallelizable(ParallelScope.All)]
public class MemberImplementsInterfaceAnalyzerTests
{
static readonly SymbolKind[] ValidSymbolKinds = { SymbolKind.Event, SymbolKind.Indexer, SymbolKind.Method, SymbolKind.Property };
static readonly SymbolKind[] InvalidSymbolKinds =
Enum.GetValues(typeof(SymbolKind)).Cast<SymbolKind>().Except(ValidSymbolKinds).ToArray();
static readonly TypeKind[] ValidTypeKinds = { TypeKind.Class, TypeKind.Struct };
static readonly TypeKind[] InvalidTypeKinds = Enum.GetValues(typeof(TypeKind)).Cast<TypeKind>().Except(ValidTypeKinds).ToArray();
private ICompilation testAssembly;
[OneTimeSetUp]
public void Setup()
{
string fileName = GetType().Assembly.Location;
using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {
var module = new PEFile(fileName, stream, PEStreamOptions.PrefetchEntireImage, MetadataReaderOptions.None);
testAssembly = new SimpleCompilation(module.WithOptions(TypeSystemOptions.Default), MinimalCorlib.Instance);
}
}
[Test]
public void VerifyDoesNotShowForNoSymbol()
{
// Arrange
var analyzer = new MemberImplementsInterfaceAnalyzer();
// Act
var shouldShow = analyzer.Show(symbol: null);
// Assert
Assert.IsFalse(shouldShow, $"The analyzer will be unexpectedly shown for no symbol");
}
[Test]
[TestCaseSource(nameof(InvalidSymbolKinds))]
public void VerifyDoesNotShowForNonMembers(SymbolKind symbolKind)
{
// Arrange
var symbolMock = new Mock<ISymbol>();
symbolMock.Setup(s => s.SymbolKind).Returns(symbolKind);
var analyzer = new MemberImplementsInterfaceAnalyzer();
// Act
var shouldShow = analyzer.Show(symbolMock.Object);
// Assert
Assert.IsFalse(shouldShow, $"The analyzer will be unexpectedly shown for symbol '{symbolKind}'");
}
[Test]
[TestCaseSource(nameof(ValidSymbolKinds))]
public void VerifyDoesNotShowForStaticMembers(SymbolKind symbolKind)
{
// Arrange
var memberMock = SetupMemberMock(symbolKind, TypeKind.Unknown, isStatic: true);
var analyzer = new MemberImplementsInterfaceAnalyzer();
// Act
var shouldShow = analyzer.Show(memberMock.Object);
// Assert
Assert.IsFalse(shouldShow, $"The analyzer will be unexpectedly shown for static symbol '{symbolKind}'");
}
[Test]
[Pairwise]
public void VerifyDoesNotShowForUnsupportedTypes(
[ValueSource(nameof(ValidSymbolKinds))] SymbolKind symbolKind,
[ValueSource(nameof(InvalidTypeKinds))] TypeKind typeKind)
{
// Arrange
var memberMock = SetupMemberMock(symbolKind, typeKind, isStatic: true);
var analyzer = new MemberImplementsInterfaceAnalyzer();
// Act
var shouldShow = analyzer.Show(memberMock.Object);
// Assert
Assert.IsFalse(shouldShow, $"The analyzer will be unexpectedly shown for symbol '{symbolKind}' and '{typeKind}'");
}
[Test]
[Pairwise]
public void VerifyShowsForSupportedTypes(
[ValueSource(nameof(ValidSymbolKinds))] SymbolKind symbolKind,
[ValueSource(nameof(ValidTypeKinds))] TypeKind typeKind)
{
// Arrange
var memberMock = SetupMemberMock(symbolKind, typeKind, isStatic: false);
var analyzer = new MemberImplementsInterfaceAnalyzer();
// Act
var shouldShow = analyzer.Show(memberMock.Object);
// Assert
Assert.IsTrue(shouldShow, $"The analyzer will not be shown for symbol '{symbolKind}' and '{typeKind}'");
}
[Test]
public void VerifyReturnsOnlyInterfaceMembers()
{
// Arrange
var symbol = SetupSymbolForAnalysis(typeof(TestClass), nameof(TestClass.TestMethod));
var analyzer = new MemberImplementsInterfaceAnalyzer();
// Act
var results = analyzer.Analyze(symbol, new AnalyzerContext());
// Assert
Assert.IsNotNull(results);
Assert.AreEqual(1, results.Count());
var result = results.FirstOrDefault() as IMethod;
Assert.IsNotNull(result);
Assert.IsNotNull(result.DeclaringTypeDefinition);
Assert.AreEqual(TypeKind.Interface, result.DeclaringTypeDefinition.Kind);
Assert.AreEqual(nameof(ITestInterface), result.DeclaringTypeDefinition.Name);
}
private ISymbol SetupSymbolForAnalysis(Type type, string methodName)
{
var typeDefinition = testAssembly.FindType(type).GetDefinition();
return typeDefinition.Methods.First(m => m.Name == methodName);
}
private static Mock<IMember> SetupMemberMock(SymbolKind symbolKind, TypeKind typeKind, bool isStatic)
{
var memberMock = new Mock<IMember>();
memberMock.Setup(m => m.SymbolKind).Returns(symbolKind);
memberMock.Setup(m => m.DeclaringTypeDefinition.Kind).Returns(typeKind);
memberMock.Setup(m => m.IsStatic).Returns(isStatic);
return memberMock;
}
private interface ITestInterface
{
void TestMethod();
}
private class BaseClass
{
public virtual void TestMethod() => throw new NotImplementedException();
}
private class TestClass : BaseClass, ITestInterface
{
public override void TestMethod() => throw new NotImplementedException();
}
}
}

2
ILSpy.Tests/ILSpy.Tests.csproj

@ -37,6 +37,7 @@ @@ -37,6 +37,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="Analyzers\MemberImplementsInterfaceAnalyzerTests.cs" />
<Compile Include="Analyzers\MethodUsesAnalyzerTests.cs" />
<Compile Include="Analyzers\TestCases\MainAssembly.cs" />
<Compile Include="Analyzers\TypeUsedByAnalyzerTests.cs" />
@ -50,6 +51,7 @@ @@ -50,6 +51,7 @@
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
<PackageReference Include="NUnit" Version="3.11.0" />
<PackageReference Include="Moq" Version="4.14.1" />
</ItemGroup>
<ItemGroup>

2
ILSpy/Analyzers/Builtin/EventImplementsInterfaceAnalyzer.cs → ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
/// Shows events that implement an interface event.
/// </summary>
[ExportAnalyzer(Header = "Implemented By", Order = 10)]
class EventImplementsInterfaceAnalyzer : IAnalyzer
class EventImplementedByAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{

59
ILSpy/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
// Copyright (c) 2018 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
{
/// <summary>
/// Shows members from all corresponding interfaces the selected member implements.
/// </summary>
[ExportAnalyzer(Header = "Implements", Order = 40)]
class MemberImplementsInterfaceAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is IMember);
var member = (IMember)analyzedSymbol;
Debug.Assert(!member.IsStatic);
var baseMembers = InheritanceHelper.GetBaseMembers(member, includeImplementedInterfaces: true);
return baseMembers.Where(m => m.DeclaringTypeDefinition.Kind == TypeKind.Interface);
}
public bool Show(ISymbol symbol)
{
switch (symbol?.SymbolKind) {
case SymbolKind.Event:
case SymbolKind.Indexer:
case SymbolKind.Method:
case SymbolKind.Property:
var member = (IMember)symbol;
var type = member.DeclaringTypeDefinition;
return !member.IsStatic && (type.Kind == TypeKind.Class || type.Kind == TypeKind.Struct);
default:
return false;
}
}
}
}

2
ILSpy/Analyzers/Builtin/MethodImplementsInterfaceAnalyzer.cs → ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
/// Shows methods that implement an interface method.
/// </summary>
[ExportAnalyzer(Header = "Implemented By", Order = 40)]
class MethodImplementsInterfaceAnalyzer : IAnalyzer
class MethodImplementedByAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{

2
ILSpy/Analyzers/Builtin/PropertyImplementsInterfaceAnalyzer.cs → ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
/// Shows properties that implement an interface property.
/// </summary>
[ExportAnalyzer(Header = "Implemented By", Order = 10)]
class PropertyImplementsInterfaceAnalyzer : IAnalyzer
class PropertyImplementedByAnalyzer : IAnalyzer
{
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{

6
ILSpy/Commands/SearchMsdnContextMenuEntry.cs

@ -26,7 +26,7 @@ namespace ICSharpCode.ILSpy @@ -26,7 +26,7 @@ namespace ICSharpCode.ILSpy
[ExportContextMenuEntry(Header = nameof(Resources.SearchMSDN), Icon = "images/SearchMsdn", Order = 9999)]
internal sealed class SearchMsdnContextMenuEntry : IContextMenuEntry
{
private static string msdnAddress = "http://msdn.microsoft.com/{1}/library/{0}";
private static string msdnAddress = "https://docs.microsoft.com/dotnet/api/{0}";
public bool IsVisible(TextViewContext context)
{
@ -100,7 +100,7 @@ namespace ICSharpCode.ILSpy @@ -100,7 +100,7 @@ namespace ICSharpCode.ILSpy
var namespaceNode = node as NamespaceTreeNode;
if (namespaceNode != null)
address = string.Format(msdnAddress, namespaceNode.Name, Thread.CurrentThread.CurrentUICulture.Name);
address = string.Format(msdnAddress, namespaceNode.Name);
if (node is IMemberTreeNode memberNode) {
var member = memberNode.Member;
@ -111,7 +111,7 @@ namespace ICSharpCode.ILSpy @@ -111,7 +111,7 @@ namespace ICSharpCode.ILSpy
else
memberName = string.Format("{0}.{1}", member.DeclaringType.FullName, member.Name);
address = string.Format(msdnAddress, memberName, Thread.CurrentThread.CurrentUICulture.Name);
address = string.Format(msdnAddress, memberName);
}
address = address.ToLower();

9
ILSpy/ILSpy.csproj

@ -56,8 +56,6 @@ @@ -56,8 +56,6 @@
<PackageReference Include="Mono.Cecil" Version="0.10.3" />
<PackageReference Include="OSVersionHelper" Version="1.0.11" />
<PackageReference Include="DataGridExtensions" Version="2.1.1" />
<PackageReference Include="Microsoft.NET.HostModel" Version="3.1.4" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
@ -79,14 +77,15 @@ @@ -79,14 +77,15 @@
<Compile Include="Analyzers\AnalyzerContext.cs" />
<Compile Include="Analyzers\AnalyzerScope.cs" />
<Compile Include="Analyzers\Builtin\AttributeAppliedToAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\EventImplementsInterfaceAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\EventImplementedByAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\EventOverriddenByAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\MethodImplementsInterfaceAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\MethodImplementedByAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\MemberImplementsInterfaceAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\MethodOverriddenByAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\MethodVirtualUsedByAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\MethodUsedByAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\MethodUsesAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\PropertyImplementsInterfaceAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\PropertyImplementedByAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\PropertyOverriddenByAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\TypeExposedByAnalyzer.cs" />
<Compile Include="Analyzers\Builtin\TypeInstantiatedByAnalyzer.cs" />

75
ILSpy/MainWindow.xaml.cs

@ -35,7 +35,6 @@ using System.Windows.Media; @@ -35,7 +35,6 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.Metadata;
@ -47,13 +46,7 @@ using ICSharpCode.ILSpy.TextView; @@ -47,13 +46,7 @@ using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.TreeView;
using Microsoft.NET.HostModel.AppHost;
using Microsoft.NET.HostModel.Bundle;
using Microsoft.Win32;
using Ookii.Dialogs.Wpf;
using OSVersionHelper;
using Xceed.Wpf.AvalonDock.Layout.Serialization;
@ -1012,55 +1005,15 @@ namespace ICSharpCode.ILSpy @@ -1012,55 +1005,15 @@ namespace ICSharpCode.ILSpy
}
break;
default:
if (IsAppBundle(file, out var headerOffset)) {
if (MessageBox.Show(this, Properties.Resources.OpenSelfContainedExecutableMessage, "ILSpy", MessageBoxButton.YesNo) == MessageBoxResult.No)
break;
var dialog = new VistaFolderBrowserDialog();
if (dialog.ShowDialog() != true)
break;
DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
var output = new AvalonEditTextOutput { Title = "Extracting " + file };
Stopwatch w = Stopwatch.StartNew();
output.WriteLine($"Extracting {file} to {dialog.SelectedPath}...");
var extractor = new Extractor(file, dialog.SelectedPath);
extractor.ExtractFiles();
output.WriteLine($"Done in {w.Elapsed}.");
return output;
}, ct)).Then(output => {
DockWorkspace.Instance.ShowText(output);
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd";
dlg.Multiselect = true;
dlg.InitialDirectory = dialog.SelectedPath;
if (dlg.ShowDialog() == true) {
foreach (var item in dlg.FileNames) {
var asm = assemblyList.OpenAssembly(item);
if (asm != null) {
if (loadedAssemblies != null)
loadedAssemblies.Add(asm);
else {
var node = assemblyListTreeNode.FindAssemblyNode(asm);
if (node != null && focusNode) {
AssemblyTreeView.SelectedItems.Add(node);
lastNode = node;
}
}
}
}
}
}).HandleExceptions();
} else {
var asm = assemblyList.OpenAssembly(file);
if (asm != null) {
if (loadedAssemblies != null)
loadedAssemblies.Add(asm);
else {
var node = assemblyListTreeNode.FindAssemblyNode(asm);
if (node != null && focusNode) {
AssemblyTreeView.SelectedItems.Add(node);
lastNode = node;
}
var asm = assemblyList.OpenAssembly(file);
if (asm != null) {
if (loadedAssemblies != null)
loadedAssemblies.Add(asm);
else {
var node = assemblyListTreeNode.FindAssemblyNode(asm);
if (node != null && focusNode) {
AssemblyTreeView.SelectedItems.Add(node);
lastNode = node;
}
}
}
@ -1070,16 +1023,6 @@ namespace ICSharpCode.ILSpy @@ -1070,16 +1023,6 @@ namespace ICSharpCode.ILSpy
if (lastNode != null && focusNode)
AssemblyTreeView.FocusNode(lastNode);
}
bool IsAppBundle(string filename, out long bundleHeaderOffset)
{
try {
return HostWriter.IsBundle(filename, out bundleHeaderOffset);
} catch (Exception) {
bundleHeaderOffset = -1;
return false;
}
}
}
void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e)

17
ILSpy/Properties/Resources.Designer.cs generated

@ -1623,21 +1623,6 @@ namespace ICSharpCode.ILSpy.Properties { @@ -1623,21 +1623,6 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to You are trying to open a single-file executable (app bundle). In order to work with this type of program, ILSpy will
///
///(i) show you a dialog to select a folder to extract the bundle to
///(ii) extract the assemblies (might take a few seconds)
///(iii) show you a dialog to select one or more of those extracted assemblies to decompile
///
///Do you want to proceed?.
/// </summary>
public static string OpenSelfContainedExecutableMessage {
get {
return ResourceManager.GetString("OpenSelfContainedExecutableMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Options.
/// </summary>
@ -1866,7 +1851,7 @@ namespace ICSharpCode.ILSpy.Properties { @@ -1866,7 +1851,7 @@ namespace ICSharpCode.ILSpy.Properties {
}
/// <summary>
/// Looks up a localized string similar to Search MSDN....
/// Looks up a localized string similar to Search Microsoft Docs....
/// </summary>
public static string SearchMSDN {
get {

14
ILSpy/Properties/Resources.resx

@ -721,7 +721,7 @@ @@ -721,7 +721,7 @@
<value>Apply Windows Runtime projections on loaded assemblies</value>
</data>
<data name="SearchMSDN" xml:space="preserve">
<value>Search MSDN...</value>
<value>Search Microsoft Docs...</value>
</data>
<data name="CannotAnalyzeMissingRef" xml:space="preserve">
<value>Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again.</value>
@ -867,18 +867,6 @@ Do you want to continue?</value> @@ -867,18 +867,6 @@ Do you want to continue?</value>
<data name="CultureLabel" xml:space="preserve">
<value>Culture</value>
</data>
<data name="DecompilerSettings.AggressiveScalarReplacementOfAggregates" xml:space="preserve">
<value>Aggressively perform Scalar Replacement Of Aggregates (SROA)</value>
</data>
<data name="OpenSelfContainedExecutableMessage" xml:space="preserve">
<value>You are trying to open a single-file executable (app bundle). In order to work with this type of program, ILSpy will
(i) show you a dialog to select a folder to extract the bundle to
(ii) extract the assemblies (might take a few seconds)
(iii) show you a dialog to select one or more of those extracted assemblies to decompile
Do you want to proceed?</value>
</data>
<data name="NewTab" xml:space="preserve">
<value>New Tab</value>
</data>

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

@ -727,7 +727,7 @@ @@ -727,7 +727,7 @@
<value>在已加载的程序集上应用 Windows 运行时投影</value>
</data>
<data name="SearchMSDN" xml:space="preserve">
<value>搜索MSDN...</value>
<value>搜索Microsoft Docs...</value>
</data>
<data name="About" xml:space="preserve">
<value>关于</value>

Loading…
Cancel
Save