Xamarin Public Jenkins (auto-signing) 6bdd276d05 Imported Upstream version 5.0.0.42
Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
2017-04-10 11:41:01 +00:00

289 lines
6.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using Mono.Linker;
using Mono.Linker.Steps;
using Mono.Cecil;
namespace Mono.Tuner {
[Flags]
public enum SubStepTargets {
None = 0,
Assembly = 1,
Type = 2,
Field = 4,
Method = 8,
Property = 16,
Event = 32,
}
public interface ISubStep {
SubStepTargets Targets { get; }
void Initialize (LinkContext context);
bool IsActiveFor (AssemblyDefinition assembly);
void ProcessAssembly (AssemblyDefinition assembly);
void ProcessType (TypeDefinition type);
void ProcessField (FieldDefinition field);
void ProcessMethod (MethodDefinition method);
void ProcessProperty (PropertyDefinition property);
void ProcessEvent (EventDefinition @event);
}
public abstract class BaseSubStep : ISubStep {
protected LinkContext context;
public AnnotationStore Annotations {
get { return context.Annotations; }
}
public abstract SubStepTargets Targets { get; }
public virtual void Initialize (LinkContext context)
{
this.context = context;
}
public virtual bool IsActiveFor (AssemblyDefinition assembly)
{
return true;
}
public virtual void ProcessAssembly (AssemblyDefinition assembly)
{
}
public virtual void ProcessType (TypeDefinition type)
{
}
public virtual void ProcessField (FieldDefinition field)
{
}
public virtual void ProcessMethod (MethodDefinition method)
{
}
public virtual void ProcessProperty (PropertyDefinition property)
{
}
public virtual void ProcessEvent (EventDefinition @event)
{
}
}
public class SubStepDispatcher : IStep, IEnumerable<ISubStep> {
List<ISubStep> substeps = new List<ISubStep> ();
List<ISubStep> on_assemblies;
List<ISubStep> on_types;
List<ISubStep> on_fields;
List<ISubStep> on_methods;
List<ISubStep> on_properties;
List<ISubStep> on_events;
public void Add (ISubStep substep)
{
substeps.Add (substep);
}
public void Process (LinkContext context)
{
InitializeSubSteps (context);
BrowseAssemblies (context.GetAssemblies ());
}
static bool HasSubSteps (List<ISubStep> substeps)
{
return substeps != null && substeps.Count > 0;
}
void BrowseAssemblies (IEnumerable<AssemblyDefinition> assemblies)
{
foreach (var assembly in assemblies) {
CategorizeSubSteps (assembly);
if (HasSubSteps (on_assemblies))
DispatchAssembly (assembly);
if (!ShouldDispatchTypes ())
continue;
BrowseTypes (assembly.MainModule.Types);
}
}
bool ShouldDispatchTypes ()
{
return HasSubSteps (on_types)
|| HasSubSteps (on_fields)
|| HasSubSteps (on_methods)
|| HasSubSteps (on_properties)
|| HasSubSteps (on_events);
}
void BrowseTypes (ICollection types)
{
foreach (TypeDefinition type in types) {
DispatchType (type);
if (type.HasFields && HasSubSteps (on_fields))
BrowseFields (type.Fields);
if (type.HasMethods && HasSubSteps (on_methods))
BrowseMethods (type.Methods);
if (type.HasProperties && HasSubSteps (on_properties))
BrowseProperties (type.Properties);
if (type.HasEvents && HasSubSteps (on_events))
BrowseEvents (type.Events);
if (type.HasNestedTypes)
BrowseTypes (type.NestedTypes);
}
}
void BrowseFields (ICollection fields)
{
foreach (FieldDefinition field in fields)
DispatchField (field);
}
void BrowseMethods (ICollection methods)
{
foreach (MethodDefinition method in methods)
DispatchMethod (method);
}
void BrowseProperties (ICollection properties)
{
foreach (PropertyDefinition property in properties)
DispatchProperty (property);
}
void BrowseEvents (ICollection events)
{
foreach (EventDefinition @event in events)
DispatchEvent (@event);
}
void DispatchAssembly (AssemblyDefinition assembly)
{
foreach (var substep in on_assemblies) {
var bs = substep as BaseSubStep;
if (bs != null)
bs.Annotations.Push (substep);
substep.ProcessAssembly (assembly);
if (bs != null)
bs.Annotations.Pop ();
}
}
void DispatchType (TypeDefinition type)
{
foreach (var substep in on_types) {
var bs = substep as BaseSubStep;
if (bs != null)
bs.Annotations.Push (substep);
substep.ProcessType (type);
if (bs != null)
bs.Annotations.Pop ();
}
}
void DispatchField (FieldDefinition field)
{
foreach (var substep in on_fields)
substep.ProcessField (field);
}
void DispatchMethod (MethodDefinition method)
{
foreach (var substep in on_methods)
substep.ProcessMethod (method);
}
void DispatchProperty (PropertyDefinition property)
{
foreach (var substep in on_properties)
substep.ProcessProperty (property);
}
void DispatchEvent (EventDefinition @event)
{
foreach (var substep in on_events)
substep.ProcessEvent (@event);
}
void InitializeSubSteps (LinkContext context)
{
foreach (var substep in substeps)
substep.Initialize (context);
}
void CategorizeSubSteps (AssemblyDefinition assembly)
{
on_assemblies = null;
on_types = null;
on_fields = null;
on_methods = null;
on_properties = null;
on_events = null;
foreach (var substep in substeps)
CategorizeSubStep (substep, assembly);
}
void CategorizeSubStep (ISubStep substep, AssemblyDefinition assembly)
{
if (!substep.IsActiveFor (assembly))
return;
CategorizeTarget (substep, SubStepTargets.Assembly, ref on_assemblies);
CategorizeTarget (substep, SubStepTargets.Type, ref on_types);
CategorizeTarget (substep, SubStepTargets.Field, ref on_fields);
CategorizeTarget (substep, SubStepTargets.Method, ref on_methods);
CategorizeTarget (substep, SubStepTargets.Property, ref on_properties);
CategorizeTarget (substep, SubStepTargets.Event, ref on_events);
}
static void CategorizeTarget (ISubStep substep, SubStepTargets target, ref List<ISubStep> list)
{
if (!Targets (substep, target))
return;
if (list == null)
list = new List<ISubStep> ();
list.Add (substep);
}
static bool Targets (ISubStep substep, SubStepTargets target)
{
return (substep.Targets & target) == target;
}
IEnumerator IEnumerable.GetEnumerator ()
{
return GetEnumerator ();
}
public IEnumerator<ISubStep> GetEnumerator ()
{
return substeps.GetEnumerator ();
}
}
}