From 7e69247f3f5de3e70235b4cb253c9229c3e65192 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer <siegfriedpammer@gmail.com> Date: Fri, 29 Mar 2024 12:30:17 +0100 Subject: [PATCH] Add nullability annotations --- .../Analyzers/AnalyzerContext.cs | 78 +++++++++---------- .../Analyzers/AnalyzerHelpers.cs | 4 +- ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs | 20 ++--- .../Builtin/EventImplementedByAnalyzer.cs | 7 +- .../Builtin/EventOverriddenByAnalyzer.cs | 7 +- .../Analyzers/Builtin/FieldAccessAnalyzer.cs | 10 ++- .../MemberImplementsInterfaceAnalyzer.cs | 2 +- .../Builtin/MethodImplementedByAnalyzer.cs | 10 +-- .../Builtin/MethodOverriddenByAnalyzer.cs | 7 +- .../Analyzers/Builtin/MethodUsedByAnalyzer.cs | 16 ++-- .../Analyzers/Builtin/MethodUsesAnalyzer.cs | 6 +- .../Builtin/MethodVirtualUsedByAnalyzer.cs | 19 +++-- .../Builtin/PropertyImplementedByAnalyzer.cs | 7 +- .../Builtin/PropertyOverriddenByAnalyzer.cs | 10 +-- .../Builtin/TypeExposedByAnalyzer.cs | 7 +- .../Builtin/TypeExtensionMethodsAnalyzer.cs | 6 +- .../Builtin/TypeInstantiatedByAnalyzer.cs | 11 ++- .../Analyzers/Builtin/TypeUsedByAnalyzer.cs | 6 +- .../Analyzers/ExportAnalyzerAttribute.cs | 2 +- ICSharpCode.ILSpyX/Search/SearchResult.cs | 16 ++-- .../MemberImplementsInterfaceAnalyzerTests.cs | 2 +- ILSpy/Search/SearchPane.cs | 9 ++- 22 files changed, 137 insertions(+), 125 deletions(-) diff --git a/ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs b/ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs index cfb324a879..09112056f4 100644 --- a/ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs +++ b/ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs @@ -32,51 +32,51 @@ namespace ICSharpCode.ILSpyX.Analyzers /// </summary> public class AnalyzerContext { - public AssemblyList AssemblyList { get; internal set; } + 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; internal set; } + /// <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 ILanguage Language { get; internal set; } + /// <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; } +/// <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 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); - } +public AnalyzerScope GetScopeOf(IEntity entity) +{ + return new AnalyzerScope(AssemblyList, entity); +} - readonly ConcurrentDictionary<MetadataFile, DecompilerTypeSystem> typeSystemCache = new(); +readonly ConcurrentDictionary<MetadataFile, DecompilerTypeSystem> typeSystemCache = new(); - public DecompilerTypeSystem GetOrCreateTypeSystem(MetadataFile module) - { - return typeSystemCache.GetOrAdd(module, m => new DecompilerTypeSystem(m, m.GetAssemblyResolver())); - } +public DecompilerTypeSystem GetOrCreateTypeSystem(MetadataFile module) +{ + return typeSystemCache.GetOrAdd(module, m => new DecompilerTypeSystem(m, m.GetAssemblyResolver())); +} } } diff --git a/ICSharpCode.ILSpyX/Analyzers/AnalyzerHelpers.cs b/ICSharpCode.ILSpyX/Analyzers/AnalyzerHelpers.cs index ca51e7d31b..4c5217ef6a 100644 --- a/ICSharpCode.ILSpyX/Analyzers/AnalyzerHelpers.cs +++ b/ICSharpCode.ILSpyX/Analyzers/AnalyzerHelpers.cs @@ -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) @@ -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) diff --git a/ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs b/ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs index b9b8e10f98..8f01faf0f7 100644 --- a/ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs +++ b/ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs @@ -24,7 +24,6 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; -using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpyX.Analyzers { @@ -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) @@ -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. @@ -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) { @@ -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; @@ -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) diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs index 94988b50b3..e928f531a5 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs @@ -17,7 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; @@ -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; } } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs index ec45c5bb7a..5db8f0841b 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs @@ -17,7 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; @@ -44,11 +43,13 @@ 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) @@ -56,7 +57,7 @@ IEnumerable<IEntity> AnalyzeType(IEvent analyzedEntity, ITypeDefinition type) 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; } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs index 0065e13f5c..ba829b0fc2 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs @@ -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) @@ -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)) @@ -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; @@ -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; @@ -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; } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs index 3f77265ac8..a25d48d86c 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs @@ -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) diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs index e0d0768025..89da791ed6 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs @@ -16,13 +16,9 @@ // 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; @@ -47,17 +43,19 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont 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; } } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs index 5c6e4bd10a..ab9c4fe71f 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs @@ -17,7 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; @@ -46,11 +45,13 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont 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 @@ IEnumerable<IEntity> AnalyzeType(IMethod analyzedEntity, ITypeDefinition type) 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; } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs index da5f747d35..702d77a7d9 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs @@ -18,12 +18,10 @@ 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; @@ -46,9 +44,11 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont 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 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont 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 @@ bool IsUsedInMethod(IMethod analyzedEntity, IMethod analyzedBaseMethod, IMethod 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 @@ static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, IMethod analy } } - IMember m; + IMember? m; try { m = (mainModule.ResolveEntity(member, genericContext) as IMember)?.MemberDefinition; @@ -192,7 +194,7 @@ static bool IsSupportedOpCode(ILOpCode opCode) static bool IsSameMember(IMember analyzedMethod, IMember m) { return m.MetadataToken == analyzedMethod.MetadataToken - && m.ParentModule.MetadataFile == analyzedMethod.ParentModule.MetadataFile; + && m.ParentModule?.MetadataFile == analyzedMethod.ParentModule!.MetadataFile; } } } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs index 6bfe94ea8b..2b361ec000 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs @@ -38,7 +38,7 @@ class MethodUsesAnalyzer : IAnalyzer 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 @@ IEnumerable<IEntity> ScanMethod(MethodDefinitionHandle handle, DecompilerTypeSys case HandleKind.TypeDefinition: case HandleKind.TypeReference: case HandleKind.TypeSpecification: - IType ty; + IType? ty; try { ty = module.ResolveType(member, genericContext); @@ -110,7 +110,7 @@ IEnumerable<IEntity> ScanMethod(MethodDefinitionHandle handle, DecompilerTypeSys case HandleKind.MethodSpecification: case HandleKind.MemberReference: case HandleKind.FieldDefinition: - IEntity m; + IEntity? m; try { m = module.ResolveEntity(member, genericContext); diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs index 0d74e068ea..a24787a880 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs @@ -41,9 +41,16 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont { 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 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont 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 @@ bool IsUsedInMethod(IMethod analyzedEntity, IMethod method, AnalyzerContext cont 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 @@ static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlo 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; } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs index 0b4e7affd6..4188822f40 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs @@ -17,7 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; @@ -44,17 +43,19 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont 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; } } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs index 7652252170..1eb0d4a004 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs @@ -16,13 +16,9 @@ // 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; @@ -47,11 +43,13 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont 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 @@ IEnumerable<IEntity> AnalyzeType(IProperty analyzedEntity, ITypeDefinition type) 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; } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs index 6174e2d8c3..3f4fd59b21 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs @@ -16,13 +16,8 @@ // 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.ILSpyX.Analyzers.Builtin @@ -52,7 +47,7 @@ IEnumerable<IEntity> ScanType(ITypeDefinition analyzedType, ITypeDefinition type { 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)) diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs index 11f1d7bd67..b557110212 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs @@ -17,7 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using ICSharpCode.Decompiler.TypeSystem; @@ -48,6 +47,9 @@ IEnumerable<IEntity> ScanType(ITypeDefinition analyzedType, ITypeDefinition type if (!type.HasExtensionMethods) yield break; + if (analyzedType.ParentModule?.MetadataFile == null) + yield break; + foreach (IMethod method in type.Methods) { if (!method.IsExtensionMethod) @@ -56,7 +58,7 @@ IEnumerable<IEntity> ScanType(ITypeDefinition analyzedType, ITypeDefinition type var firstParamType = method.Parameters[0].Type.GetDefinition(); if (firstParamType != null && firstParamType.MetadataToken == analyzedType.MetadataToken && - firstParamType.ParentModule.MetadataFile == analyzedType.ParentModule.MetadataFile) + firstParamType.ParentModule?.MetadataFile == analyzedType.ParentModule.MetadataFile) yield return method; } } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs index 4f5c82e5ea..603f3e5b0f 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs @@ -18,12 +18,9 @@ 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; @@ -46,6 +43,8 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont 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 @@ bool IsUsedInMethod(ITypeDefinition analyzedEntity, IMethod method, CodeMappingI 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 @@ bool ScanMethodBody(ITypeDefinition analyzedEntity, IMethod method, MethodBodyBl continue; if (ctor.DeclaringTypeDefinition?.MetadataToken == analyzedEntity.MetadataToken - && ctor.ParentModule.MetadataFile == analyzedEntity.ParentModule.MetadataFile) + && ctor.ParentModule?.MetadataFile == analyzedEntity.ParentModule!.MetadataFile) return true; } diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs index cfbe5d665e..e4a10801f2 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs @@ -107,7 +107,7 @@ static IEnumerable<ISymbol> AnalyzeModule(ITypeDefinition analyzedType, Analyzer 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 @@ private static bool AnalyzeCustomAttributeValue(CustomAttributeValue<TokenSearch } return false; - bool CheckAttributeValue(object value) + bool CheckAttributeValue(object? value) { if (value is TokenSearchResult typeofType) { @@ -408,7 +408,7 @@ public TypeDefinitionUsedVisitor(ITypeDefinition definition, bool topLevelOnly) 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); } diff --git a/ICSharpCode.ILSpyX/Analyzers/ExportAnalyzerAttribute.cs b/ICSharpCode.ILSpyX/Analyzers/ExportAnalyzerAttribute.cs index e4da690f15..fbd4b3a724 100644 --- a/ICSharpCode.ILSpyX/Analyzers/ExportAnalyzerAttribute.cs +++ b/ICSharpCode.ILSpyX/Analyzers/ExportAnalyzerAttribute.cs @@ -28,7 +28,7 @@ public class ExportAnalyzerAttribute : ExportAttribute, IAnalyzerMetadata public ExportAnalyzerAttribute() : base("Analyzer", typeof(IAnalyzer)) { } - public string Header { get; set; } + public required string Header { get; init; } public int Order { get; set; } } diff --git a/ICSharpCode.ILSpyX/Search/SearchResult.cs b/ICSharpCode.ILSpyX/Search/SearchResult.cs index 98e8560109..38b618a2dc 100644 --- a/ICSharpCode.ILSpyX/Search/SearchResult.cs +++ b/ICSharpCode.ILSpyX/Search/SearchResult.cs @@ -42,18 +42,14 @@ public class SearchResult 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() { diff --git a/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs b/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs index d27b985ee2..1149418e86 100644 --- a/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs @@ -145,7 +145,7 @@ public void VerifyReturnsOnlyInterfaceMembers() 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); diff --git a/ILSpy/Search/SearchPane.cs b/ILSpy/Search/SearchPane.cs index 995c9303e8..0eb3fe8d05 100644 --- a/ILSpy/Search/SearchPane.cs +++ b/ILSpy/Search/SearchPane.cs @@ -218,7 +218,14 @@ void UpdateResults(object sender, EventArgs e) 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(); } }