xamarin-macios/tools/linker/MonoTouch.Tuner/MonoTouchTypeMap.cs

116 строки
3.2 KiB
C#

//
// MonoTouchTypeMapStep.cs
//
// Authors:
// Sebastien Pouliot <sebastien@xamarin.com>
//
// Copyright 2012-2013 Xamarin Inc.
//
using System;
using System.Collections;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Linker.Steps;
using Mono.Tuner;
using Xamarin.Linker;
using Xamarin.Tuner;
namespace MonoTouch.Tuner {
public class MonoTouchTypeMapStep : TypeMapStep {
HashSet<TypeDefinition> cached_isnsobject = new HashSet<TypeDefinition> ();
HashSet<TypeDefinition> needs_isdirectbinding_check = new HashSet<TypeDefinition> ();
HashSet<MethodDefinition> generated_code = new HashSet<MethodDefinition> ();
DerivedLinkContext LinkContext {
get {
return (DerivedLinkContext) base.Context;
}
}
protected override void EndProcess ()
{
base.EndProcess ();
LinkContext.CachedIsNSObject = cached_isnsobject;
LinkContext.NeedsIsDirectBindingCheck = needs_isdirectbinding_check;
LinkContext.GeneratedCode = generated_code;
}
protected override void MapType (TypeDefinition type)
{
base.MapType (type);
// we'll remove [GeneratedCode] in RemoveAttribute but we need this information later
// when processing Dispose methods in MonoTouchMarkStep
if (type.HasMethods) {
foreach (MethodDefinition m in type.Methods) {
if (m.IsGeneratedCode (LinkContext))
generated_code.Add (m);
}
}
// additional checks for NSObject to check if the type is a *generated* bindings
// bonus: we cache, for every type, whether or not it inherits from NSObject (very useful later)
if (!IsNSObject (type))
return;
// if not, it's a user type, the IsDirectBinding check is required by all ancestors
if (!IsGeneratedBindings (type, LinkContext))
NeedsIsDirectBindingCheck (type);
#if DEBUG
else
Console.WriteLine ("{0} does NOT needs IsDirectBinding check", type);
#endif
}
// called once for each 'type' so it's a nice place to cache the result
// and ensure later steps re-use the same, pre-computed, result
bool IsNSObject (TypeDefinition type)
{
if (!type.IsNSObject (LinkContext))
return false;
cached_isnsobject.Add (type);
return true;
}
// type has a "public .ctor (IntPtr)" with a [CompilerGenerated] attribute
static bool IsGeneratedBindings (TypeDefinition type, DerivedLinkContext link_context)
{
if (type.IsNested)
return IsGeneratedBindings (type.DeclaringType, link_context);
if (!type.HasMethods)
return false;
foreach (MethodDefinition m in type.Methods) {
if (!m.IsConstructor)
continue;
if (!m.HasParameters)
continue;
if (m.Parameters.Count != 1)
continue;
if (!m.Parameters [0].ParameterType.Is ("System", "IntPtr"))
continue;
return m.IsGeneratedCode (link_context);
}
return false;
}
void NeedsIsDirectBindingCheck (TypeDefinition type)
{
// all ancestors must be disallowed
// so we can short-circuit the recursion if we already have processed it
if (needs_isdirectbinding_check.Contains (type))
return;
needs_isdirectbinding_check.Add (type);
var base_type = type.BaseType;
if (base_type != null)
NeedsIsDirectBindingCheck (base_type.Resolve ());
}
}
}