Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move non-UI analyzer code to ILSpyX #3186

Merged
merged 2 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
3 changes: 3 additions & 0 deletions ICSharpCode.ILSpyX/Abstractions/ILanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);

Expand Down
82 changes: 82 additions & 0 deletions ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs
Original file line number Diff line number Diff line change
@@ -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()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;

namespace ICSharpCode.ILSpy.Analyzers
namespace ICSharpCode.ILSpyX.Analyzers
{
internal static class AnalyzerHelpers
{
Expand All @@ -34,7 +34,7 @@ public static bool IsPossibleReferenceTo(EntityHandle member, MetadataFile modul
{
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)
Expand All @@ -48,7 +48,7 @@ public static bool IsPossibleReferenceTo(EntityHandle member, MetadataFile modul
}
}

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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@
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;

Expand Down Expand Up @@ -61,19 +60,19 @@ public AnalyzerScope(AssemblyList assemblyList, IEntity entity)
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)
Expand Down Expand Up @@ -113,7 +112,7 @@ static void DetermineEffectiveAccessibility(IEntity input, out ITypeDefinition t
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.
Expand All @@ -123,7 +122,7 @@ static void DetermineEffectiveAccessibility(IEntity input, out ITypeDefinition t
{
accessibility = accessibility.Intersect(typeScope.Accessibility);
prevTypeScope = typeScope;
typeScope = prevTypeScope.DeclaringTypeDefinition;
typeScope = prevTypeScope.DeclaringTypeDefinition!;
}
if (typeScope == null)
{
Expand Down Expand Up @@ -181,7 +180,7 @@ IEnumerable<MetadataFile> GetReferencingModules(MetadataFile self, CancellationT

IEnumerable<MetadataFile> GetModuleAndAnyFriends(ITypeDefinition typeScope, CancellationToken ct)
{
var self = typeScope.ParentModule.MetadataFile;
var self = typeScope.ParentModule!.MetadataFile!;

yield return self;

Expand All @@ -191,9 +190,10 @@ IEnumerable<MetadataFile> GetModuleAndAnyFriends(ITypeDefinition typeScope, Canc
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -44,17 +43,19 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont

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;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -44,19 +43,21 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont

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)
{
if ([email protected])
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

using ILOpCode = System.Reflection.Metadata.ILOpCode;

namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
/// <summary>
/// Finds methods where this field is read.
Expand Down Expand Up @@ -74,6 +74,8 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont
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)
Expand Down Expand Up @@ -119,7 +121,7 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont

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))
Expand All @@ -144,7 +146,7 @@ bool IsUsedInMethod(IField analyzedField, IMethod method, CodeMappingInfo mappin

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;
Expand All @@ -170,7 +172,7 @@ bool ScanMethodBody(IField analyzedField, IMethod method, MethodBodyBlock method
EntityHandle fieldHandle = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32());
if (!fieldHandle.Kind.IsMemberKind())
continue;
IField field;
IField? field;
try
{
field = mainModule.ResolveEntity(fieldHandle, genericContext) as IField;
Expand All @@ -183,7 +185,7 @@ bool ScanMethodBody(IField analyzedField, IMethod method, MethodBodyBlock method
continue;

if (field.MetadataToken == analyzedField.MetadataToken
&& field.ParentModule.MetadataFile == analyzedField.ParentModule.MetadataFile)
&& field.ParentModule?.MetadataFile == analyzedField.ParentModule!.MetadataFile)
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;

namespace ICSharpCode.ILSpy.Analyzers.Builtin
namespace ICSharpCode.ILSpyX.Analyzers.Builtin
{
public enum TokenSearchResult : byte
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

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.
Expand All @@ -38,7 +38,7 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont
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)
Expand Down
Loading
Loading