diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs index cd307a66f..6b1d10e83 100644 --- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs +++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs @@ -3,16 +3,10 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; -using System.Reflection.PortableExecutable; -using System.Text; -using System.Threading.Tasks; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; -using ICSharpCode.Decompiler.Util; using static ICSharpCode.Decompiler.Metadata.ILOpCodeExtensions; @@ -20,24 +14,39 @@ namespace ICSharpCode.Decompiler.CSharp { class RequiredNamespaceCollector { + static readonly Decompiler.TypeSystem.GenericContext genericContext = default; + + readonly HashSet namespaces; + + public RequiredNamespaceCollector(HashSet namespaces) + { + this.namespaces = namespaces; + } + public static void CollectNamespaces(MetadataModule module, HashSet namespaces) { + var collector = new RequiredNamespaceCollector(namespaces); foreach (var type in module.TypeDefinitions) { - CollectNamespaces(type, module, namespaces); + collector.CollectNamespaces(type, module, (CodeMappingInfo)null); } - CollectAttributeNamespaces(module, namespaces); + collector.HandleAttributes(module.GetAssemblyAttributes()); + collector.HandleAttributes(module.GetModuleAttributes()); } public static void CollectAttributeNamespaces(MetadataModule module, HashSet namespaces) { - HandleAttributes(module.GetAssemblyAttributes(), namespaces); - HandleAttributes(module.GetModuleAttributes(), namespaces); + var collector = new RequiredNamespaceCollector(namespaces); + collector.HandleAttributes(module.GetAssemblyAttributes()); + collector.HandleAttributes(module.GetModuleAttributes()); } - static readonly Decompiler.TypeSystem.GenericContext genericContext = default; + public static void CollectNamespaces(IEntity entity, MetadataModule module, HashSet namespaces) + { + var collector = new RequiredNamespaceCollector(namespaces); + collector.CollectNamespaces(entity, module); + } - public static void CollectNamespaces(IEntity entity, MetadataModule module, - HashSet namespaces, CodeMappingInfo mappingInfo = null) + void CollectNamespaces(IEntity entity, MetadataModule module, CodeMappingInfo mappingInfo = null) { if (entity == null || entity.MetadataToken.IsNil) return; @@ -46,53 +55,53 @@ namespace ICSharpCode.Decompiler.CSharp if (mappingInfo == null) mappingInfo = CSharpDecompiler.GetCodeMappingInfo(entity.ParentModule.PEFile, entity.MetadataToken); namespaces.Add(td.Namespace); - HandleAttributes(td.GetAttributes(), namespaces); - HandleTypeParameters(td.TypeParameters, namespaces); + HandleAttributes(td.GetAttributes()); + HandleTypeParameters(td.TypeParameters); foreach (var baseType in td.DirectBaseTypes) { - CollectNamespacesForTypeReference(baseType, namespaces); + CollectNamespacesForTypeReference(baseType); } foreach (var nestedType in td.NestedTypes) { - CollectNamespaces(nestedType, module, namespaces, mappingInfo); + CollectNamespaces(nestedType, module, mappingInfo); } foreach (var field in td.Fields) { - CollectNamespaces(field, module, namespaces, mappingInfo); + CollectNamespaces(field, module, mappingInfo); } foreach (var property in td.Properties) { - CollectNamespaces(property, module, namespaces, mappingInfo); + CollectNamespaces(property, module, mappingInfo); } foreach (var @event in td.Events) { - CollectNamespaces(@event, module, namespaces, mappingInfo); + CollectNamespaces(@event, module, mappingInfo); } foreach (var method in td.Methods) { - CollectNamespaces(method, module, namespaces, mappingInfo); + CollectNamespaces(method, module, mappingInfo); } break; case IField field: - HandleAttributes(field.GetAttributes(), namespaces); - CollectNamespacesForTypeReference(field.ReturnType, namespaces); + HandleAttributes(field.GetAttributes()); + CollectNamespacesForTypeReference(field.ReturnType); break; case IMethod method: - HandleAttributes(method.GetAttributes(), namespaces); - HandleAttributes(method.GetReturnTypeAttributes(), namespaces); - CollectNamespacesForTypeReference(method.ReturnType, namespaces); + HandleAttributes(method.GetAttributes()); + HandleAttributes(method.GetReturnTypeAttributes()); + CollectNamespacesForTypeReference(method.ReturnType); foreach (var param in method.Parameters) { - HandleAttributes(param.GetAttributes(), namespaces); - CollectNamespacesForTypeReference(param.Type, namespaces); + HandleAttributes(param.GetAttributes()); + CollectNamespacesForTypeReference(param.Type); } - HandleTypeParameters(method.TypeParameters, namespaces); + HandleTypeParameters(method.TypeParameters); if (!method.MetadataToken.IsNil) { if (mappingInfo == null) mappingInfo = CSharpDecompiler.GetCodeMappingInfo(entity.ParentModule.PEFile, entity.MetadataToken); var reader = module.PEFile.Reader; var parts = mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken).ToList(); foreach (var part in parts) { - HandleOverrides(part.GetMethodImplementations(module.metadata), module, namespaces); + HandleOverrides(part.GetMethodImplementations(module.metadata), module); var methodDef = module.metadata.GetMethodDefinition(part); if (method.HasBody) { MethodBodyBlock body; @@ -101,49 +110,49 @@ namespace ICSharpCode.Decompiler.CSharp } catch (BadImageFormatException) { continue; } - CollectNamespacesFromMethodBody(body, module, namespaces); + CollectNamespacesFromMethodBody(body, module); } } } break; case IProperty property: - HandleAttributes(property.GetAttributes(), namespaces); - CollectNamespaces(property.Getter, module, namespaces); - CollectNamespaces(property.Setter, module, namespaces); + HandleAttributes(property.GetAttributes()); + CollectNamespaces(property.Getter, module); + CollectNamespaces(property.Setter, module); break; case IEvent @event: - HandleAttributes(@event.GetAttributes(), namespaces); - CollectNamespaces(@event.AddAccessor, module, namespaces); - CollectNamespaces(@event.RemoveAccessor, module, namespaces); + HandleAttributes(@event.GetAttributes()); + CollectNamespaces(@event.AddAccessor, module); + CollectNamespaces(@event.RemoveAccessor, module); break; } } - static void HandleOverrides(ImmutableArray immutableArray, MetadataModule module, HashSet namespaces) + void HandleOverrides(ImmutableArray immutableArray, MetadataModule module) { foreach (var h in immutableArray) { var methodImpl = module.metadata.GetMethodImplementation(h); - CollectNamespacesForTypeReference(module.ResolveType(methodImpl.Type, genericContext), namespaces); - CollectNamespacesForMemberReference(module.ResolveMethod(methodImpl.MethodBody, genericContext), module, namespaces); - CollectNamespacesForMemberReference(module.ResolveMethod(methodImpl.MethodDeclaration, genericContext), module, namespaces); + CollectNamespacesForTypeReference(module.ResolveType(methodImpl.Type, genericContext)); + CollectNamespacesForMemberReference(module.ResolveMethod(methodImpl.MethodBody, genericContext)); + CollectNamespacesForMemberReference(module.ResolveMethod(methodImpl.MethodDeclaration, genericContext)); } } - static void CollectNamespacesForTypeReference(IType type, HashSet namespaces) + void CollectNamespacesForTypeReference(IType type) { switch (type) { case ParameterizedType parameterizedType: namespaces.Add(parameterizedType.Namespace); - CollectNamespacesForTypeReference(parameterizedType.GenericType, namespaces); + CollectNamespacesForTypeReference(parameterizedType.GenericType); foreach (var arg in parameterizedType.TypeArguments) - CollectNamespacesForTypeReference(arg, namespaces); + CollectNamespacesForTypeReference(arg); break; case TypeWithElementType typeWithElementType: - CollectNamespacesForTypeReference(typeWithElementType.ElementType, namespaces); + CollectNamespacesForTypeReference(typeWithElementType.ElementType); break; case TupleType tupleType: foreach (var elementType in tupleType.ElementTypes) { - CollectNamespacesForTypeReference(elementType, namespaces); + CollectNamespacesForTypeReference(elementType); } break; default: @@ -161,43 +170,43 @@ namespace ICSharpCode.Decompiler.CSharp CollectNamespaces(module.ResolveEntity(entity, genericContext), module, namespaces); } - public static void HandleAttributes(IEnumerable attributes, HashSet namespaces) + void HandleAttributes(IEnumerable attributes) { foreach (var attr in attributes) { namespaces.Add(attr.AttributeType.Namespace); foreach (var arg in attr.FixedArguments) { - HandleAttributeValue(arg.Type, arg.Value, namespaces); + HandleAttributeValue(arg.Type, arg.Value); } foreach (var arg in attr.NamedArguments) { - HandleAttributeValue(arg.Type, arg.Value, namespaces); + HandleAttributeValue(arg.Type, arg.Value); } } } - static void HandleAttributeValue(IType type, object value, HashSet namespaces) + void HandleAttributeValue(IType type, object value) { - CollectNamespacesForTypeReference(type, namespaces); + CollectNamespacesForTypeReference(type); if (value is IType typeofType) - CollectNamespacesForTypeReference(typeofType, namespaces); + CollectNamespacesForTypeReference(typeofType); if (value is ImmutableArray> arr) { foreach (var element in arr) { - HandleAttributeValue(element.Type, element.Value, namespaces); + HandleAttributeValue(element.Type, element.Value); } } } - static void HandleTypeParameters(IEnumerable typeParameters, HashSet namespaces) + void HandleTypeParameters(IEnumerable typeParameters) { foreach (var typeParam in typeParameters) { - HandleAttributes(typeParam.GetAttributes(), namespaces); + HandleAttributes(typeParam.GetAttributes()); foreach (var constraint in typeParam.DirectBaseTypes) { - CollectNamespacesForTypeReference(constraint, namespaces); + CollectNamespacesForTypeReference(constraint); } } } - static void CollectNamespacesFromMethodBody(MethodBodyBlock method, MetadataModule module, HashSet namespaces) + void CollectNamespacesFromMethodBody(MethodBodyBlock method, MetadataModule module) { var metadata = module.metadata; var instructions = method.GetILReader(); @@ -211,7 +220,7 @@ namespace ICSharpCode.Decompiler.CSharp localSignature = ImmutableArray.Empty; } foreach (var type in localSignature) - CollectNamespacesForTypeReference(type, namespaces); + CollectNamespacesForTypeReference(type); } foreach (var region in method.ExceptionRegions) { @@ -223,7 +232,7 @@ namespace ICSharpCode.Decompiler.CSharp } catch (BadImageFormatException) { continue; } - CollectNamespacesForTypeReference(ty, namespaces); + CollectNamespacesForTypeReference(ty); } while (instructions.RemainingBytes > 0) { @@ -234,11 +243,11 @@ namespace ICSharpCode.Decompiler.CSharp return; } switch (opCode.GetOperandType()) { - case Metadata.OperandType.Field: - case Metadata.OperandType.Method: - case Metadata.OperandType.Sig: - case Metadata.OperandType.Tok: - case Metadata.OperandType.Type: + case OperandType.Field: + case OperandType.Method: + case OperandType.Sig: + case OperandType.Tok: + case OperandType.Type: var handle = MetadataTokenHelpers.EntityHandleOrNil(instructions.ReadInt32()); if (handle.IsNil) break; @@ -252,7 +261,7 @@ namespace ICSharpCode.Decompiler.CSharp } catch (BadImageFormatException) { break; } - CollectNamespacesForTypeReference(type, namespaces); + CollectNamespacesForTypeReference(type); break; case HandleKind.FieldDefinition: case HandleKind.MethodDefinition: @@ -264,7 +273,7 @@ namespace ICSharpCode.Decompiler.CSharp } catch (BadImageFormatException) { break; } - CollectNamespacesForMemberReference(member, module, namespaces); + CollectNamespacesForMemberReference(member); break; case HandleKind.StandaloneSignature: StandaloneSignature sig; @@ -280,9 +289,9 @@ namespace ICSharpCode.Decompiler.CSharp } catch (BadImageFormatException) { break; } - CollectNamespacesForTypeReference(methodSig.ReturnType, namespaces); + CollectNamespacesForTypeReference(methodSig.ReturnType); foreach (var paramType in methodSig.ParameterTypes) { - CollectNamespacesForTypeReference(paramType, namespaces); + CollectNamespacesForTypeReference(paramType); } } break; @@ -299,20 +308,20 @@ namespace ICSharpCode.Decompiler.CSharp } } - static void CollectNamespacesForMemberReference(IMember member, MetadataModule module, HashSet namespaces) + void CollectNamespacesForMemberReference(IMember member) { switch (member) { case IField field: - CollectNamespacesForTypeReference(field.DeclaringType, namespaces); - CollectNamespacesForTypeReference(field.ReturnType, namespaces); + CollectNamespacesForTypeReference(field.DeclaringType); + CollectNamespacesForTypeReference(field.ReturnType); break; case IMethod method: - CollectNamespacesForTypeReference(method.DeclaringType, namespaces); - CollectNamespacesForTypeReference(method.ReturnType, namespaces); + CollectNamespacesForTypeReference(method.DeclaringType); + CollectNamespacesForTypeReference(method.ReturnType); foreach (var param in method.Parameters) - CollectNamespacesForTypeReference(param.Type, namespaces); + CollectNamespacesForTypeReference(param.Type); foreach (var arg in method.TypeArguments) - CollectNamespacesForTypeReference(arg, namespaces); + CollectNamespacesForTypeReference(arg); break; } }