Browse Source

Merge pull request #3186 from icsharpcode/take2

Move non-UI analyzer code to ILSpyX
pull/3191/head
Christoph Wille 2 years ago committed by GitHub
parent
commit
fd0acb039f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      Directory.Packages.props
  2. 3
      ICSharpCode.ILSpyX/Abstractions/ILanguage.cs
  3. 82
      ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs
  4. 6
      ICSharpCode.ILSpyX/Analyzers/AnalyzerHelpers.cs
  5. 22
      ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs
  6. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs
  7. 9
      ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs
  8. 9
      ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs
  9. 12
      ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs
  10. 2
      ICSharpCode.ILSpyX/Analyzers/Builtin/FindTypeInAttributeDecoder.cs
  11. 4
      ICSharpCode.ILSpyX/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs
  12. 12
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs
  13. 9
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs
  14. 18
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs
  15. 8
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs
  16. 21
      ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs
  17. 9
      ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs
  18. 12
      ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs
  19. 9
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs
  20. 66
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs
  21. 13
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs
  22. 8
      ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs
  23. 4
      ICSharpCode.ILSpyX/Analyzers/ExportAnalyzerAttribute.cs
  24. 2
      ICSharpCode.ILSpyX/Analyzers/IAnalyzer.cs
  25. 1
      ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj
  26. 16
      ICSharpCode.ILSpyX/Search/SearchResult.cs
  27. 2
      ILSpy.Tests/Analyzers/AnalyzerScopeTests.cs
  28. 6
      ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs
  29. 4
      ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs
  30. 4
      ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs
  31. 82
      ILSpy/Analyzers/AnalyzerContext.cs
  32. 1
      ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
  33. 46
      ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs
  34. 1
      ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
  35. 1
      ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
  36. 1
      ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
  37. 1
      ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs
  38. 1
      ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
  39. 1
      ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
  40. 7
      ILSpy/App.xaml.cs
  41. 9
      ILSpy/Search/SearchPane.cs

1
Directory.Packages.props

@ -35,6 +35,7 @@ @@ -35,6 +35,7 @@
<PackageVersion Include="NuGet.Protocol" Version="6.9.1" />
<PackageVersion Include="PowerShellStandard.Library" Version="5.1.1" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.ComponentModel.Composition" Version="8.0.0" />
<PackageVersion Include="System.Composition" Version="8.0.0" />
<PackageVersion Include="System.Memory" Version="4.5.5" />
<PackageVersion Include="System.Reflection.Metadata" Version="8.0.0" />

3
ICSharpCode.ILSpyX/Abstractions/ILanguage.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
@ -24,6 +26,7 @@ namespace ICSharpCode.ILSpyX.Abstractions @@ -24,6 +26,7 @@ namespace ICSharpCode.ILSpyX.Abstractions
public interface ILanguage
{
bool ShowMember(IEntity member);
CodeMappingInfo GetCodeMappingInfo(MetadataFile module, EntityHandle member);
string GetEntityName(MetadataFile module, System.Reflection.Metadata.EntityHandle handle, bool fullName, bool omitGenerics);
string GetTooltip(IEntity entity);

82
ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
// Copyright (c) 2018 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.Reflection.Metadata;
using System.Threading;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX.Abstractions;
namespace ICSharpCode.ILSpyX.Analyzers
{
/// <summary>
/// Provides additional context for analyzers.
/// </summary>
public class AnalyzerContext
{
public required AssemblyList AssemblyList { get; init; }
/// <summary>
/// CancellationToken. Currently Analyzers do not support cancellation from the UI, but it should be checked nonetheless.
/// </summary>
public CancellationToken CancellationToken { get; init; }
/// <summary>
/// Currently used language.
/// </summary>
public required ILanguage Language { get; init; }
/// <summary>
/// Allows the analyzer to control whether the tree nodes will be sorted.
/// Must be set within <see cref="IAnalyzer.Analyze(ISymbol, AnalyzerContext)"/>
/// before the results are enumerated.
/// </summary>
public bool SortResults { get; set; }
public MethodBodyBlock? GetMethodBody(IMethod method)
{
if (!method.HasBody || method.MetadataToken.IsNil || method.ParentModule?.MetadataFile == null)
return null;
var module = method.ParentModule.MetadataFile;
var md = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
try
{
return module.GetMethodBody(md.RelativeVirtualAddress);
}
catch (BadImageFormatException)
{
return null;
}
}
public AnalyzerScope GetScopeOf(IEntity entity)
{
return new AnalyzerScope(AssemblyList, entity);
}
readonly ConcurrentDictionary<MetadataFile, DecompilerTypeSystem> typeSystemCache = new();
public DecompilerTypeSystem GetOrCreateTypeSystem(MetadataFile module)
{
return typeSystemCache.GetOrAdd(module, m => new DecompilerTypeSystem(m, m.GetAssemblyResolver()));
}
}
}

6
ILSpy/Analyzers/AnalyzerHelpers.cs → ICSharpCode.ILSpyX/Analyzers/AnalyzerHelpers.cs

@ -21,7 +21,7 @@ using System.Reflection.Metadata; @@ -21,7 +21,7 @@ using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers
namespace ICSharpCode.ILSpyX.Analyzers
{
internal static class AnalyzerHelpers
{
@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.Analyzers
{
case HandleKind.MethodDefinition:
return member == analyzedMethod.MetadataToken
&& module == analyzedMethod.ParentModule.MetadataFile;
&& module == analyzedMethod.ParentModule?.MetadataFile;
case HandleKind.MemberReference:
var mr = metadata.GetMemberReference((MemberReferenceHandle)member);
if (mr.GetKind() != MemberReferenceKind.Method)
@ -48,7 +48,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -48,7 +48,7 @@ namespace ICSharpCode.ILSpy.Analyzers
}
}
public static ISymbol GetParentEntity(DecompilerTypeSystem ts, CustomAttribute customAttribute)
public static ISymbol? GetParentEntity(DecompilerTypeSystem ts, CustomAttribute customAttribute)
{
var metadata = ts.MainModule.MetadataFile.Metadata;
switch (customAttribute.Parent.Kind)

22
ILSpy/Analyzers/AnalyzerScope.cs → ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs

@ -24,9 +24,8 @@ using System.Threading; @@ -24,9 +24,8 @@ using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpyX;
namespace ICSharpCode.ILSpy.Analyzers
namespace ICSharpCode.ILSpyX.Analyzers
{
using ICSharpCode.Decompiler.TypeSystem;
@ -61,19 +60,19 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -61,19 +60,19 @@ namespace ICSharpCode.ILSpy.Analyzers
public IEnumerable<MetadataFile> GetModulesInScope(CancellationToken ct)
{
if (IsLocal)
return new[] { TypeScope.ParentModule.MetadataFile };
return new[] { TypeScope.ParentModule!.MetadataFile! };
if (effectiveAccessibility.LessThanOrEqual(Accessibility.Internal))
return GetModuleAndAnyFriends(TypeScope, ct);
return GetReferencingModules(TypeScope.ParentModule.MetadataFile, ct);
return GetReferencingModules(TypeScope.ParentModule!.MetadataFile!, ct);
}
public IEnumerable<MetadataFile> GetAllModules()
{
return assemblyListSnapshot.GetAllAssembliesAsync().GetAwaiter().GetResult()
.Select(asm => asm.GetMetadataFileOrNull())
.Where(x => x != null);
.Where(x => x != null)!;
}
public DecompilerTypeSystem ConstructTypeSystem(MetadataFile module)
@ -113,7 +112,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -113,7 +112,7 @@ namespace ICSharpCode.ILSpy.Analyzers
else
{
accessibility = input.Accessibility;
typeScope = input.DeclaringTypeDefinition;
typeScope = input.DeclaringTypeDefinition!;
}
// Once we reach a private entity, we leave the loop with typeScope set to the class that
// contains the private entity = the scope that needs to be searched.
@ -123,7 +122,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -123,7 +122,7 @@ namespace ICSharpCode.ILSpy.Analyzers
{
accessibility = accessibility.Intersect(typeScope.Accessibility);
prevTypeScope = typeScope;
typeScope = prevTypeScope.DeclaringTypeDefinition;
typeScope = prevTypeScope.DeclaringTypeDefinition!;
}
if (typeScope == null)
{
@ -181,7 +180,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -181,7 +180,7 @@ namespace ICSharpCode.ILSpy.Analyzers
IEnumerable<MetadataFile> GetModuleAndAnyFriends(ITypeDefinition typeScope, CancellationToken ct)
{
var self = typeScope.ParentModule.MetadataFile;
var self = typeScope.ParentModule!.MetadataFile!;
yield return self;
@ -191,9 +190,10 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -191,9 +190,10 @@ namespace ICSharpCode.ILSpy.Analyzers
var friendAssemblies = new HashSet<string>();
foreach (var attribute in attributes)
{
string assemblyName = attribute.DecodeValue(typeProvider).FixedArguments[0].Value as string;
assemblyName = assemblyName.Split(',')[0]; // strip off any public key info
friendAssemblies.Add(assemblyName);
string? assemblyName = attribute.DecodeValue(typeProvider).FixedArguments[0].Value as string;
assemblyName = assemblyName?.Split(',')[0]; // strip off any public key info
if (assemblyName != null)
friendAssemblies.Add(assemblyName);
}
if (friendAssemblies.Count > 0)

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

@ -26,7 +26,7 @@ using ICSharpCode.Decompiler.Metadata; @@ -26,7 +26,7 @@ using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
[ExportAnalyzer(Header = "Applied To", Order = 10)]
class AttributeAppliedToAnalyzer : IAnalyzer

9
ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs

@ -17,13 +17,12 @@ @@ -17,13 +17,12 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows events that implement an interface event.
@ -44,17 +43,19 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -44,17 +43,19 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
IEnumerable<IEntity> AnalyzeType(IEvent analyzedEntity, ITypeDefinition type)
{
if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null)
yield break;
var token = analyzedEntity.MetadataToken;
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile;
var allTypes = type.GetAllBaseTypeDefinitions();
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module))
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module))
yield break;
foreach (var @event in type.Events)
{
var baseMembers = InheritanceHelper.GetBaseMembers(@event, true);
if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.MetadataFile == module))
if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule?.MetadataFile == module))
yield return @event;
}
}

9
ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs

@ -17,13 +17,12 @@ @@ -17,13 +17,12 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows events that override an event.
@ -44,11 +43,13 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -44,11 +43,13 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
IEnumerable<IEntity> AnalyzeType(IEvent analyzedEntity, ITypeDefinition type)
{
if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null)
yield break;
var token = analyzedEntity.MetadataToken;
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile;
var allTypes = type.GetAllBaseTypeDefinitions();
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module))
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module))
yield break;
foreach (var @event in type.Events)
@ -56,7 +57,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -56,7 +57,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
if (!@event.IsOverride)
continue;
var baseMembers = InheritanceHelper.GetBaseMembers(@event, false);
if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.MetadataFile == module))
if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule?.MetadataFile == module))
{
yield return @event;
}

12
ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs

@ -29,7 +29,7 @@ using ICSharpCode.Decompiler.TypeSystem; @@ -29,7 +29,7 @@ using ICSharpCode.Decompiler.TypeSystem;
using ILOpCode = System.Reflection.Metadata.ILOpCode;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Finds methods where this field is read.
@ -74,6 +74,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -74,6 +74,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
var scope = context.GetScopeOf((IEntity)analyzedSymbol);
foreach (var type in scope.GetTypesInScope(context.CancellationToken))
{
if (type.ParentModule?.MetadataFile == null)
continue;
var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.MetadataFile, type.MetadataToken);
var methods = type.GetMembers(m => m is IMethod, Options).OfType<IMethod>();
foreach (var method in methods)
@ -119,7 +121,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -119,7 +121,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
bool IsUsedInMethod(IField analyzedField, IMethod method, CodeMappingInfo mappingInfo, AnalyzerContext context)
{
if (method.MetadataToken.IsNil)
if (method.MetadataToken.IsNil || method.ParentModule?.MetadataFile == null)
return false;
var module = method.ParentModule.MetadataFile;
foreach (var part in mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken))
@ -144,7 +146,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -144,7 +146,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
bool ScanMethodBody(IField analyzedField, IMethod method, MethodBodyBlock methodBody)
{
if (methodBody == null)
if (methodBody == null || method.ParentModule?.MetadataFile == null)
return false;
var mainModule = (MetadataModule)method.ParentModule;
@ -170,7 +172,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -170,7 +172,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
EntityHandle fieldHandle = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32());
if (!fieldHandle.Kind.IsMemberKind())
continue;
IField field;
IField? field;
try
{
field = mainModule.ResolveEntity(fieldHandle, genericContext) as IField;
@ -183,7 +185,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -183,7 +185,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
continue;
if (field.MetadataToken == analyzedField.MetadataToken
&& field.ParentModule.MetadataFile == analyzedField.ParentModule.MetadataFile)
&& field.ParentModule?.MetadataFile == analyzedField.ParentModule!.MetadataFile)
return true;
}

2
ILSpy/Analyzers/Builtin/FindTypeInAttributeDecoder.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/FindTypeInAttributeDecoder.cs

@ -25,7 +25,7 @@ using ICSharpCode.Decompiler; @@ -25,7 +25,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
public enum TokenSearchResult : byte
{

4
ILSpy/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs

@ -22,7 +22,7 @@ using System.Linq; @@ -22,7 +22,7 @@ using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows members from all corresponding interfaces the selected member implements.
@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
Debug.Assert(!member.IsStatic);
var baseMembers = InheritanceHelper.GetBaseMembers(member, includeImplementedInterfaces: true);
return baseMembers.Where(m => m.DeclaringTypeDefinition.Kind == TypeKind.Interface);
return baseMembers.Where(m => m.DeclaringTypeDefinition?.Kind == TypeKind.Interface);
}
public bool Show(ISymbol symbol)

12
ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs

@ -16,17 +16,13 @@ @@ -16,17 +16,13 @@
// 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.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows methods that implement an interface method.
@ -47,17 +43,19 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -47,17 +43,19 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
IEnumerable<IEntity> AnalyzeType(IMethod analyzedEntity, ITypeDefinition type)
{
if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null)
yield break;
var token = analyzedEntity.MetadataToken;
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile;
var allTypes = type.GetAllBaseTypeDefinitions();
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module))
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module))
yield break;
foreach (var method in type.Methods)
{
var baseMembers = InheritanceHelper.GetBaseMembers(method, true);
if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.MetadataFile == module))
if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule?.MetadataFile == module))
yield return method;
}
}

9
ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs

@ -17,13 +17,12 @@ @@ -17,13 +17,12 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows methods that override a method.
@ -46,11 +45,13 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -46,11 +45,13 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
IEnumerable<IEntity> AnalyzeType(IMethod analyzedEntity, ITypeDefinition type)
{
if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null)
yield break;
var token = analyzedEntity.MetadataToken;
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile;
var allTypes = type.GetAllBaseTypeDefinitions();
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module))
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module))
yield break;
foreach (var method in type.Methods)
@ -58,7 +59,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -58,7 +59,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
if (!method.IsOverride)
continue;
var baseMembers = InheritanceHelper.GetBaseMembers(method, false);
if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.MetadataFile == module))
if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule?.MetadataFile == module))
{
yield return method;
}

18
ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs

@ -18,17 +18,15 @@ @@ -18,17 +18,15 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows entities that are used by a method.
@ -46,9 +44,11 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -46,9 +44,11 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
var analyzedMethod = (IMethod)analyzedSymbol;
var analyzedBaseMethod = (IMethod)InheritanceHelper.GetBaseMember(analyzedMethod);
if (analyzedMethod.ParentModule?.MetadataFile == null)
yield break;
var mapping = context.Language
.GetCodeMappingInfo(analyzedMethod.ParentModule.MetadataFile,
analyzedMethod.DeclaringTypeDefinition.MetadataToken);
analyzedMethod.DeclaringTypeDefinition!.MetadataToken);
var parentMethod = mapping.GetParentMethod((MethodDefinitionHandle)analyzedMethod.MetadataToken);
if (parentMethod != analyzedMethod.MetadataToken)
@ -57,6 +57,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -57,6 +57,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
var scope = context.GetScopeOf(analyzedMethod);
foreach (var type in scope.GetTypesInScope(context.CancellationToken))
{
if (type.ParentModule?.MetadataFile == null)
continue;
var parentModule = (MetadataModule)type.ParentModule;
mapping = null;
var methods = type.GetMembers(m => m is IMethod, Options).OfType<IMethod>();
@ -110,9 +112,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -110,9 +112,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
return ScanMethodBody(analyzedEntity, method, analyzedBaseMethod, context.GetMethodBody(method));
}
static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, IMethod analyzedBaseMethod, MethodBodyBlock methodBody)
static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, IMethod analyzedBaseMethod, MethodBodyBlock? methodBody)
{
if (methodBody == null)
if (methodBody == null || method.ParentModule?.MetadataFile == null)
return false;
var mainModule = (MetadataModule)method.ParentModule;
@ -145,7 +147,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -145,7 +147,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
}
}
IMember m;
IMember? m;
try
{
m = (mainModule.ResolveEntity(member, genericContext) as IMember)?.MemberDefinition;
@ -192,7 +194,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -192,7 +194,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
static bool IsSameMember(IMember analyzedMethod, IMember m)
{
return m.MetadataToken == analyzedMethod.MetadataToken
&& m.ParentModule.MetadataFile == analyzedMethod.ParentModule.MetadataFile;
&& m.ParentModule?.MetadataFile == analyzedMethod.ParentModule!.MetadataFile;
}
}
}

8
ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs

@ -26,7 +26,7 @@ using ICSharpCode.Decompiler.Disassembler; @@ -26,7 +26,7 @@ using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows entities that are used by a method.
@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
public IEnumerable<ISymbol> Analyze(ISymbol symbol, AnalyzerContext context)
{
if (symbol is IMethod method && method.ParentModule.MetadataFile is MetadataFile corFile)
if (symbol is IMethod method && method.ParentModule?.MetadataFile is MetadataFile corFile)
{
var typeSystem = context.GetOrCreateTypeSystem(corFile);
return context.Language.GetCodeMappingInfo(corFile, method.MetadataToken)
@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
case HandleKind.TypeDefinition:
case HandleKind.TypeReference:
case HandleKind.TypeSpecification:
IType ty;
IType? ty;
try
{
ty = module.ResolveType(member, genericContext);
@ -110,7 +110,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -110,7 +110,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
case HandleKind.MethodSpecification:
case HandleKind.MemberReference:
case HandleKind.FieldDefinition:
IEntity m;
IEntity? m;
try
{
m = module.ResolveEntity(member, genericContext);

21
ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs

@ -25,7 +25,7 @@ using ICSharpCode.Decompiler.Disassembler; @@ -25,7 +25,7 @@ using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows entities that are used by a method.
@ -41,9 +41,16 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -41,9 +41,16 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
{
Debug.Assert(analyzedSymbol is IMethod);
var analyzedMethod = (IMethod)analyzedSymbol;
if (analyzedMethod.ParentModule?.MetadataFile == null)
yield break;
if (analyzedMethod.DeclaringTypeDefinition?.MetadataToken.IsNil != true)
yield break;
var mapping = context.Language
.GetCodeMappingInfo(analyzedMethod.ParentModule.MetadataFile,
analyzedMethod.DeclaringTypeDefinition.MetadataToken);
analyzedMethod.DeclaringTypeDefinition?.MetadataToken ?? default);
var parentMethod = mapping.GetParentMethod((MethodDefinitionHandle)analyzedMethod.MetadataToken);
if (parentMethod != analyzedMethod.MetadataToken)
@ -52,7 +59,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -52,7 +59,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
var scope = context.GetScopeOf(analyzedMethod);
foreach (var type in scope.GetTypesInScope(context.CancellationToken))
{
var parentModule = (MetadataModule)type.ParentModule;
var parentModule = (MetadataModule?)type.ParentModule;
if (parentModule?.MetadataFile == null)
continue;
mapping = context.Language.GetCodeMappingInfo(parentModule.MetadataFile, type.MetadataToken);
var methods = type.GetMembers(m => m is IMethod, Options).OfType<IMethod>();
foreach (var method in methods)
@ -105,9 +114,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -105,9 +114,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
return ScanMethodBody(analyzedEntity, method, context.GetMethodBody(method));
}
static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlock methodBody)
static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlock? methodBody)
{
if (methodBody == null)
if (methodBody == null || method.ParentModule?.MetadataFile == null)
return false;
var mainModule = (MetadataModule)method.ParentModule;
var blob = methodBody.GetILReader();
@ -131,7 +140,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -131,7 +140,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
case HandleKind.MethodSpecification:
case HandleKind.MemberReference:
var m = (mainModule.ResolveEntity(member, genericContext) as IMember)?.MemberDefinition;
if (m != null && m.MetadataToken == analyzedMethod.MetadataToken && m.ParentModule.MetadataFile == analyzedMethod.ParentModule.MetadataFile)
if (m != null && m.MetadataToken == analyzedMethod.MetadataToken && m.ParentModule?.MetadataFile == analyzedMethod.ParentModule!.MetadataFile)
{
return true;
}

9
ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs

@ -17,13 +17,12 @@ @@ -17,13 +17,12 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows properties that implement an interface property.
@ -44,17 +43,19 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -44,17 +43,19 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
IEnumerable<IEntity> AnalyzeType(IProperty analyzedEntity, ITypeDefinition type)
{
if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null)
yield break;
var token = analyzedEntity.MetadataToken;
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile;
var allTypes = type.GetAllBaseTypeDefinitions();
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module))
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module))
yield break;
foreach (var property in type.Properties)
{
var baseMembers = InheritanceHelper.GetBaseMembers(property, true);
if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.MetadataFile == module))
if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule?.MetadataFile == module))
yield return property;
}
}

12
ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs

@ -16,17 +16,13 @@ @@ -16,17 +16,13 @@
// 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.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows properties that override a property.
@ -47,11 +43,13 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -47,11 +43,13 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
IEnumerable<IEntity> AnalyzeType(IProperty analyzedEntity, ITypeDefinition type)
{
if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null)
yield break;
var token = analyzedEntity.MetadataToken;
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile;
var allTypes = type.GetAllBaseTypeDefinitions();
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module))
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module))
yield break;
foreach (var property in type.Properties)
@ -59,7 +57,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -59,7 +57,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
if (!property.IsOverride)
continue;
var baseMembers = InheritanceHelper.GetBaseMembers(property, false);
if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.MetadataFile == module))
if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule?.MetadataFile == module))
{
yield return property;
}

9
ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs

@ -16,16 +16,11 @@ @@ -16,16 +16,11 @@
// 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.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
using ICSharpCode.Decompiler.TypeSystem;
@ -52,7 +47,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -52,7 +47,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
{
if (analyzedType.Kind == TypeKind.Enum
&& type.MetadataToken == analyzedType.MetadataToken
&& type.ParentModule.MetadataFile == analyzedType.ParentModule.MetadataFile)
&& type.ParentModule?.MetadataFile == analyzedType.ParentModule?.MetadataFile)
yield break;
if (!context.Language.ShowMember(type))

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

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
// 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 ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Finds all extension methods defined for a type.
/// </summary>
[ExportAnalyzer(Header = "Extension Methods", Order = 50)]
class TypeExtensionMethodsAnalyzer : IAnalyzer
{
public bool Show(ISymbol symbol) => symbol is ITypeDefinition entity && !entity.IsStatic;
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is ITypeDefinition);
var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol);
foreach (var type in scope.GetTypesInScope(context.CancellationToken))
{
foreach (var result in ScanType((ITypeDefinition)analyzedSymbol, type, context))
yield return result;
}
}
IEnumerable<IEntity> ScanType(ITypeDefinition analyzedType, ITypeDefinition type, AnalyzerContext context)
{
if (!type.HasExtensionMethods)
yield break;
if (analyzedType.ParentModule?.MetadataFile == null)
yield break;
foreach (IMethod method in type.Methods)
{
if (!method.IsExtensionMethod)
continue;
var firstParamType = method.Parameters[0].Type.GetDefinition();
if (firstParamType != null &&
firstParamType.MetadataToken == analyzedType.MetadataToken &&
firstParamType.ParentModule?.MetadataFile == analyzedType.ParentModule.MetadataFile)
yield return method;
}
}
}
}

13
ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs

@ -18,19 +18,16 @@ @@ -18,19 +18,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows methods that instantiate a type.
@ -46,6 +43,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -46,6 +43,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol);
foreach (var type in scope.GetTypesInScope(context.CancellationToken))
{
if (type.ParentModule?.MetadataFile == null)
continue;
var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.MetadataFile, type.MetadataToken);
var methods = type.GetMembers(m => m is IMethod, Options).OfType<IMethod>();
foreach (var method in methods)
@ -94,9 +93,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -94,9 +93,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
return ScanMethodBody(analyzedEntity, method, context.GetMethodBody(method));
}
bool ScanMethodBody(ITypeDefinition analyzedEntity, IMethod method, MethodBodyBlock methodBody)
bool ScanMethodBody(ITypeDefinition analyzedEntity, IMethod method, MethodBodyBlock? methodBody)
{
if (methodBody == null)
if (methodBody == null || method.ParentModule?.MetadataFile == null)
return false;
var blob = methodBody.GetILReader();
var module = (MetadataModule)method.ParentModule;
@ -134,7 +133,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -134,7 +133,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
continue;
if (ctor.DeclaringTypeDefinition?.MetadataToken == analyzedEntity.MetadataToken
&& ctor.ParentModule.MetadataFile == analyzedEntity.ParentModule.MetadataFile)
&& ctor.ParentModule?.MetadataFile == analyzedEntity.ParentModule!.MetadataFile)
return true;
}

8
ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs

@ -28,7 +28,7 @@ using ICSharpCode.Decompiler.Disassembler; @@ -28,7 +28,7 @@ using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Shows entities that use a type.
@ -107,7 +107,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -107,7 +107,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
if (found || ScanMethodBody(analyzedType, module, md, decoder))
{
var method = typeSystem.MainModule.GetDefinition(h);
yield return method?.AccessorOwner ?? method;
yield return method.AccessorOwner ?? method;
}
}
@ -221,7 +221,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -221,7 +221,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
}
return false;
bool CheckAttributeValue(object value)
bool CheckAttributeValue(object? value)
{
if (value is TokenSearchResult typeofType)
{
@ -408,7 +408,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -408,7 +408,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
public override IType VisitTypeDefinition(ITypeDefinition type)
{
Found |= TypeDefinition.MetadataToken == type.MetadataToken
&& TypeDefinition.ParentModule.MetadataFile == type.ParentModule.MetadataFile;
&& TypeDefinition.ParentModule!.MetadataFile == type.ParentModule?.MetadataFile;
return base.VisitTypeDefinition(type);
}

4
ILSpy/Analyzers/ExportAnalyzerAttribute.cs → ICSharpCode.ILSpyX/Analyzers/ExportAnalyzerAttribute.cs

@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
using System;
using System.ComponentModel.Composition;
namespace ICSharpCode.ILSpy.Analyzers
namespace ICSharpCode.ILSpyX.Analyzers
{
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.Analyzers
public ExportAnalyzerAttribute() : base("Analyzer", typeof(IAnalyzer))
{ }
public string Header { get; set; }
public required string Header { get; init; }
public int Order { get; set; }
}

2
ILSpy/Analyzers/IAnalyzer.cs → ICSharpCode.ILSpyX/Analyzers/IAnalyzer.cs

@ -20,7 +20,7 @@ using System.Collections.Generic; @@ -20,7 +20,7 @@ using System.Collections.Generic;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers
namespace ICSharpCode.ILSpyX.Analyzers
{
/// <summary>
/// Base interface for all analyzers. You can register an analyzer for any <see cref="ISymbol"/> by implementing

1
ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj

@ -62,6 +62,7 @@ @@ -62,6 +62,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.ComponentModel.Composition" />
<PackageReference Include="System.Reflection.Metadata" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" />
<PackageReference Include="System.Composition" />

16
ICSharpCode.ILSpyX/Search/SearchResult.cs

@ -42,18 +42,14 @@ namespace ICSharpCode.ILSpyX.Search @@ -42,18 +42,14 @@ namespace ICSharpCode.ILSpyX.Search
public float Fitness { get; set; }
#nullable disable
public string Name { get; set; }
public string Location { get; set; }
public string Assembly { get; set; }
#nullable enable
public required string Name { get; set; }
public required string Location { get; set; }
public required string Assembly { get; set; }
public object? ToolTip { get; set; }
#nullable disable
public object Image { get; set; }
public object LocationImage { get; set; }
public required object Image { get; set; }
public required object LocationImage { get; set; }
public object AssemblyImage { get; set; }
#nullable enable
public required object AssemblyImage { get; set; }
public override string ToString()
{

2
ILSpy.Tests/Analyzers/AnalyzerScopeTests.cs

@ -23,7 +23,7 @@ using ICSharpCode.Decompiler; @@ -23,7 +23,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpyX.Analyzers;
using NUnit.Framework;

6
ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs

@ -25,8 +25,8 @@ using System.Reflection.PortableExecutable; @@ -25,8 +25,8 @@ 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 ICSharpCode.ILSpyX.Analyzers;
using ICSharpCode.ILSpyX.Analyzers.Builtin;
using NSubstitute;
@ -145,7 +145,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers @@ -145,7 +145,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers
var analyzer = new MemberImplementsInterfaceAnalyzer();
// Act
var results = analyzer.Analyze(symbol, new AnalyzerContext());
var results = analyzer.Analyze(symbol, new AnalyzerContext() { AssemblyList = new ILSpyX.AssemblyList(), Language = new CSharpLanguage() });
// Assert
Assert.That(results, Is.Not.Null);

4
ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs

@ -6,9 +6,9 @@ using System.Threading.Tasks; @@ -6,9 +6,9 @@ using System.Threading.Tasks;
using System.Windows;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.Analyzers.Builtin;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Analyzers;
using ICSharpCode.ILSpyX.Analyzers.Builtin;
using NUnit.Framework;

4
ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs

@ -19,9 +19,9 @@ @@ -19,9 +19,9 @@
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.Analyzers.Builtin;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Analyzers;
using ICSharpCode.ILSpyX.Analyzers.Builtin;
using NUnit.Framework;

82
ILSpy/Analyzers/AnalyzerContext.cs

@ -1,82 +0,0 @@ @@ -1,82 +0,0 @@
// Copyright (c) 2018 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.Reflection.Metadata;
using System.Threading;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX;
namespace ICSharpCode.ILSpy.Analyzers
{
/// <summary>
/// Provides additional context for analyzers.
/// </summary>
public class AnalyzerContext
{
public AssemblyList AssemblyList { get; internal set; }
/// <summary>
/// CancellationToken. Currently Analyzers do not support cancellation from the UI, but it should be checked nonetheless.
/// </summary>
public CancellationToken CancellationToken { get; internal set; }
/// <summary>
/// Currently used language.
/// </summary>
public Language Language { get; internal set; }
/// <summary>
/// Allows the analyzer to control whether the tree nodes will be sorted.
/// Must be set within <see cref="IAnalyzer.Analyze(ISymbol, AnalyzerContext)"/>
/// before the results are enumerated.
/// </summary>
public bool SortResults { get; set; }
public MethodBodyBlock GetMethodBody(IMethod method)
{
if (!method.HasBody || method.MetadataToken.IsNil)
return null;
var module = method.ParentModule.MetadataFile;
var md = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
try
{
return module.GetMethodBody(md.RelativeVirtualAddress);
}
catch (BadImageFormatException)
{
return null;
}
}
public AnalyzerScope GetScopeOf(IEntity entity)
{
return new AnalyzerScope(AssemblyList, entity);
}
readonly ConcurrentDictionary<MetadataFile, DecompilerTypeSystem> typeSystemCache = new();
public DecompilerTypeSystem GetOrCreateTypeSystem(MetadataFile module)
{
return typeSystemCache.GetOrAdd(module, m => new DecompilerTypeSystem(m, m.GetAssemblyResolver()));
}
}
}

1
ILSpy/Analyzers/AnalyzerSearchTreeNode.cs

@ -25,6 +25,7 @@ using ICSharpCode.Decompiler.TypeSystem; @@ -25,6 +25,7 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Analyzers.TreeNodes;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Analyzers;
namespace ICSharpCode.ILSpy.Analyzers
{

46
ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs

@ -1,46 +0,0 @@ @@ -1,46 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers.Builtin
{
/// <summary>
/// Finds all extension methods defined for a type.
/// </summary>
[ExportAnalyzer(Header = "Extension Methods", Order = 50)]
class TypeExtensionMethodsAnalyzer : IAnalyzer
{
public bool Show(ISymbol symbol) => symbol is ITypeDefinition entity && !entity.IsStatic;
public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext context)
{
Debug.Assert(analyzedSymbol is ITypeDefinition);
var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol);
foreach (var type in scope.GetTypesInScope(context.CancellationToken))
{
foreach (var result in ScanType((ITypeDefinition)analyzedSymbol, type, context))
yield return result;
}
}
IEnumerable<IEntity> ScanType(ITypeDefinition analyzedType, ITypeDefinition type, AnalyzerContext context)
{
if (!type.HasExtensionMethods)
yield break;
foreach (IMethod method in type.Methods)
{
if (!method.IsExtensionMethod)
continue;
var firstParamType = method.Parameters[0].Type.GetDefinition();
if (firstParamType != null &&
firstParamType.MetadataToken == analyzedType.MetadataToken &&
firstParamType.ParentModule.MetadataFile == analyzedType.ParentModule.MetadataFile)
yield return method;
}
}
}
}

1
ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs

@ -24,6 +24,7 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -24,6 +24,7 @@ using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
{
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX.Analyzers;
internal sealed class AnalyzedEventTreeNode : AnalyzerEntityTreeNode
{

1
ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs

@ -21,6 +21,7 @@ using System.Linq; @@ -21,6 +21,7 @@ using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpyX.Analyzers;
namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
{

1
ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs

@ -21,6 +21,7 @@ using System.Linq; @@ -21,6 +21,7 @@ using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpyX.Analyzers;
namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
{

1
ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs

@ -21,6 +21,7 @@ using System.Linq; @@ -21,6 +21,7 @@ using System.Linq;
using System.Windows;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX.Analyzers;
namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
{

1
ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs

@ -21,6 +21,7 @@ using System.Linq; @@ -21,6 +21,7 @@ using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpyX.Analyzers;
namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
{

1
ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs

@ -21,6 +21,7 @@ using System.Linq; @@ -21,6 +21,7 @@ using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpyX.Analyzers;
namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
{

7
ILSpy/App.xaml.cs

@ -31,6 +31,7 @@ using System.Windows.Navigation; @@ -31,6 +31,7 @@ using System.Windows.Navigation;
using System.Windows.Threading;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpyX.Analyzers;
using ICSharpCode.ILSpyX.Settings;
using Microsoft.VisualStudio.Composition;
@ -131,9 +132,13 @@ namespace ICSharpCode.ILSpy @@ -131,9 +132,13 @@ namespace ICSharpCode.ILSpy
}
}
}
// Add the built-in parts
// Add the built-in parts: First, from ILSpyX
var xParts = await discovery.CreatePartsAsync(typeof(IAnalyzer).Assembly);
catalog = catalog.AddParts(xParts);
// Then from ILSpy itself
var createdParts = await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly());
catalog = catalog.AddParts(createdParts);
// If/When the project switches to .NET Standard/Core, this will be needed to allow metadata interfaces (as opposed
// to metadata classes). When running on .NET Framework, it's automatic.
// catalog.WithDesktopSupport();

9
ILSpy/Search/SearchPane.cs

@ -218,7 +218,14 @@ namespace ICSharpCode.ILSpy.Search @@ -218,7 +218,14 @@ namespace ICSharpCode.ILSpy.Search
if (resultsAdded > 0 && Results.Count == MAX_RESULTS)
{
Results.Add(new SearchResult { Name = Properties.Resources.SearchAbortedMoreThan1000ResultsFound });
Results.Add(new SearchResult {
Name = Properties.Resources.SearchAbortedMoreThan1000ResultsFound,
Location = null!,
Assembly = null!,
Image = null!,
LocationImage = null!,
AssemblyImage = null!,
});
currentSearch.Cancel();
}
}

Loading…
Cancel
Save