| File: Linker.Steps\SubStepsDispatcher.cs | Web Access |
| Project: src\runtime\src\tools\illink\src\linker\Mono.Linker.csproj (illink) |
// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; using System.Diagnostics; using Mono.Cecil; using Mono.Collections.Generic; namespace Mono.Linker.Steps { struct CategorizedSubSteps { public List<ISubStep> on_assemblies; public List<ISubStep> on_types; public List<ISubStep> on_fields; public List<ISubStep> on_methods; public List<ISubStep> on_properties; public List<ISubStep> on_events; } // // Generic steps dispatcher is intended to by used by custom ILLink step which // consist of multiple steps. It simplifies their implementation as well as the // way how to hook them into the pipeline of existing steps. // public abstract class SubStepsDispatcher : IStep { readonly List<ISubStep> substeps; CategorizedSubSteps? categorized; CategorizedSubSteps Categorized { get { Debug.Assert(categorized.HasValue); return categorized.Value; } } protected SubStepsDispatcher() { substeps = new List<ISubStep>(); } protected SubStepsDispatcher(IEnumerable<ISubStep> subSteps) { substeps = new List<ISubStep>(subSteps); } public void Add(ISubStep substep) { substeps.Add(substep); } public virtual void Process(LinkContext context) { InitializeSubSteps(context); BrowseAssemblies(context.GetAssemblies()); } static bool HasSubSteps(List<ISubStep> substeps) => substeps?.Count > 0; void BrowseAssemblies(IEnumerable<AssemblyDefinition> assemblies) { foreach (var assembly in assemblies) { CategorizeSubSteps(assembly); if (HasSubSteps(Categorized.on_assemblies)) DispatchAssembly(assembly); if (!ShouldDispatchTypes()) continue; BrowseTypes(assembly.MainModule.Types); } } bool ShouldDispatchTypes() { return HasSubSteps(Categorized.on_types) || HasSubSteps(Categorized.on_fields) || HasSubSteps(Categorized.on_methods) || HasSubSteps(Categorized.on_properties) || HasSubSteps(Categorized.on_events); } void BrowseTypes(Collection<TypeDefinition> types) { foreach (TypeDefinition type in types) { DispatchType(type); if (type.HasFields && HasSubSteps(Categorized.on_fields)) { foreach (FieldDefinition field in type.Fields) DispatchField(field); } if (type.HasMethods && HasSubSteps(Categorized.on_methods)) { foreach (MethodDefinition method in type.Methods) DispatchMethod(method); } if (type.HasProperties && HasSubSteps(Categorized.on_properties)) { foreach (PropertyDefinition property in type.Properties) DispatchProperty(property); } if (type.HasEvents && HasSubSteps(Categorized.on_events)) { foreach (EventDefinition @event in type.Events) DispatchEvent(@event); } if (type.HasNestedTypes) BrowseTypes(type.NestedTypes); } } void DispatchAssembly(AssemblyDefinition assembly) { foreach (var substep in Categorized.on_assemblies) { substep.ProcessAssembly(assembly); } } void DispatchType(TypeDefinition type) { foreach (var substep in Categorized.on_types) { substep.ProcessType(type); } } void DispatchField(FieldDefinition field) { foreach (var substep in Categorized.on_fields) { substep.ProcessField(field); } } void DispatchMethod(MethodDefinition method) { foreach (var substep in Categorized.on_methods) { substep.ProcessMethod(method); } } void DispatchProperty(PropertyDefinition property) { foreach (var substep in Categorized.on_properties) { substep.ProcessProperty(property); } } void DispatchEvent(EventDefinition @event) { foreach (var substep in Categorized.on_events) { substep.ProcessEvent(@event); } } void InitializeSubSteps(LinkContext context) { foreach (var substep in substeps) substep.Initialize(context); } void CategorizeSubSteps(AssemblyDefinition assembly) { categorized = new CategorizedSubSteps { on_assemblies = new List<ISubStep>(), on_types = new List<ISubStep>(), on_fields = new List<ISubStep>(), on_methods = new List<ISubStep>(), on_properties = new List<ISubStep>(), on_events = new List<ISubStep>() }; foreach (var substep in substeps) CategorizeSubStep(substep, assembly); } void CategorizeSubStep(ISubStep substep, AssemblyDefinition assembly) { if (!substep.IsActiveFor(assembly)) return; CategorizeTarget(substep, SubStepTargets.Assembly, Categorized.on_assemblies); CategorizeTarget(substep, SubStepTargets.Type, Categorized.on_types); CategorizeTarget(substep, SubStepTargets.Field, Categorized.on_fields); CategorizeTarget(substep, SubStepTargets.Method, Categorized.on_methods); CategorizeTarget(substep, SubStepTargets.Property, Categorized.on_properties); CategorizeTarget(substep, SubStepTargets.Event, Categorized.on_events); } static void CategorizeTarget(ISubStep substep, SubStepTargets target, List<ISubStep> list) { if (!Targets(substep, target)) return; list.Add(substep); } static bool Targets(ISubStep substep, SubStepTargets target) => (substep.Targets & target) == target; } }