127 строки
4.4 KiB
C#
127 строки
4.4 KiB
C#
using System.Collections.Generic;
|
|
|
|
using Mono.Cecil;
|
|
using Mono.Linker;
|
|
using Mono.Collections.Generic;
|
|
|
|
using Registrar;
|
|
using Xamarin.Bundler;
|
|
|
|
namespace Xamarin.Tuner
|
|
{
|
|
public class DerivedLinkContext : LinkContext
|
|
{
|
|
internal StaticRegistrar StaticRegistrar;
|
|
internal Target Target;
|
|
Symbols required_symbols;
|
|
|
|
// SDK candidates - they will be preserved only if the application (not the SDK) uses it
|
|
List<ICustomAttributeProvider> srs_data_contract = new List<ICustomAttributeProvider> ();
|
|
List<ICustomAttributeProvider> xml_serialization = new List<ICustomAttributeProvider> ();
|
|
|
|
HashSet<TypeDefinition> cached_isnsobject;
|
|
// Tristate:
|
|
// null = don't know, must check at runtime (can't inline)
|
|
// true/false = corresponding constant value
|
|
Dictionary<TypeDefinition, bool?> isdirectbinding_value;
|
|
|
|
public HashSet<TypeDefinition> CachedIsNSObject {
|
|
get { return cached_isnsobject; }
|
|
set { cached_isnsobject = value; }
|
|
}
|
|
|
|
public Dictionary<TypeDefinition, bool?> IsDirectBindingValue {
|
|
get { return isdirectbinding_value; }
|
|
set { isdirectbinding_value = value; }
|
|
}
|
|
|
|
public IList<ICustomAttributeProvider> DataContract {
|
|
get {
|
|
return srs_data_contract;
|
|
}
|
|
}
|
|
|
|
public IList<ICustomAttributeProvider> XmlSerialization {
|
|
get {
|
|
return xml_serialization;
|
|
}
|
|
}
|
|
|
|
public Symbols RequiredSymbols {
|
|
get {
|
|
if (required_symbols == null)
|
|
required_symbols = new Symbols ();
|
|
return required_symbols;
|
|
}
|
|
}
|
|
|
|
public DerivedLinkContext (Pipeline pipeline, AssemblyResolver resolver)
|
|
: base (pipeline, resolver)
|
|
{
|
|
UserAction = AssemblyAction.Link;
|
|
}
|
|
|
|
public Dictionary<IMetadataTokenProvider, object> GetAllCustomAttributes (string storage_name)
|
|
{
|
|
return Annotations?.GetCustomAnnotations (storage_name);
|
|
}
|
|
|
|
public List<ICustomAttribute> GetCustomAttributes (ICustomAttributeProvider provider, string storage_name)
|
|
{
|
|
var annotations = Annotations?.GetCustomAnnotations (storage_name);
|
|
object storage = null;
|
|
if (annotations?.TryGetValue (provider, out storage) != true)
|
|
return null;
|
|
return (List<ICustomAttribute>) storage;
|
|
}
|
|
|
|
// Stores custom attributes in the link context, so that the attribute can be retrieved and
|
|
// inspected even if it's linked away.
|
|
public void StoreCustomAttribute (ICustomAttributeProvider provider, CustomAttribute attribute, string storage_name)
|
|
{
|
|
var dict = Annotations.GetCustomAnnotations (storage_name);
|
|
List<ICustomAttribute> attribs;
|
|
object attribObjects;
|
|
if (!dict.TryGetValue (provider, out attribObjects)) {
|
|
attribs = new List<ICustomAttribute> ();
|
|
dict [provider] = attribs;
|
|
} else {
|
|
attribs = (List<ICustomAttribute>) attribObjects;
|
|
}
|
|
// Make sure the attribute is resolved, since after removing the attribute
|
|
// it won't be able to do it. The 'CustomAttribute.Resolve' method is private, but fetching
|
|
// any property will cause it to be called.
|
|
// We also need to store the constructor's DeclaringType separately, because it may
|
|
// be nulled out from the constructor by the linker if the attribute type itself is linked away.
|
|
var dummy = attribute.HasConstructorArguments;
|
|
attribs.Add (new AttributeStorage { Attribute = attribute, AttributeType = attribute.Constructor.DeclaringType });
|
|
}
|
|
|
|
public List<ICustomAttribute> GetCustomAttributes (ICustomAttributeProvider provider, string @namespace, string name)
|
|
{
|
|
// The equivalent StoreCustomAttribute method below ignores the namespace (it's not needed so far since all attribute names we care about are unique),
|
|
// so we need to retrieve the attributes the same way (using the name only).
|
|
return GetCustomAttributes (provider, name);
|
|
}
|
|
|
|
public void StoreCustomAttribute (ICustomAttributeProvider provider, CustomAttribute attribute)
|
|
{
|
|
StoreCustomAttribute (provider, attribute, attribute.AttributeType.Name);
|
|
}
|
|
|
|
class AttributeStorage : ICustomAttribute
|
|
{
|
|
public CustomAttribute Attribute;
|
|
public TypeReference AttributeType { get; set; }
|
|
|
|
public bool HasFields => Attribute.HasFields;
|
|
public bool HasProperties => Attribute.HasProperties;
|
|
public bool HasConstructorArguments => Attribute.HasConstructorArguments;
|
|
|
|
public Collection<CustomAttributeNamedArgument> Fields => Attribute.Fields;
|
|
public Collection<CustomAttributeNamedArgument> Properties => Attribute.Properties;
|
|
public Collection<CustomAttributeArgument> ConstructorArguments => Attribute.ConstructorArguments;
|
|
}
|
|
}
|
|
}
|