//
// (C) 2006 Jb Evain
// (C) 2007 Novell, Inc.
+// Copyright 2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
namespace Mono.Linker.Steps {
+ public class XmlResolutionException : Exception {
+ public XmlResolutionException (string message, Exception innerException)
+ : base (message, innerException)
+ {
+ }
+ }
+
public class ResolveFromXmlStep : ResolveStep {
static readonly string _signature = "signature";
static readonly string _ns = string.Empty;
XPathDocument _document;
+ string _xmlDocumentLocation;
- public ResolveFromXmlStep (XPathDocument document)
+ public ResolveFromXmlStep (XPathDocument document, string xmlDocumentLocation = "<unspecified>")
{
_document = document;
+ _xmlDocumentLocation = xmlDocumentLocation;
}
- public override void Process (LinkContext context)
+ protected override void Process ()
{
XPathNavigator nav = _document.CreateNavigator ();
nav.MoveToFirstChild ();
- ProcessAssemblies (context, nav.SelectChildren ("assembly", _ns));
+
+ // This step can be created with XML files that aren't necessarily
+ // linker descriptor files. So bail if we don't have a <linker> element.
+ if (nav.LocalName != "linker")
+ return;
+
+ try {
+ ProcessAssemblies (Context, nav.SelectChildren ("assembly", _ns));
+ } catch (Exception ex) {
+ throw new XmlResolutionException (string.Format ("Failed to process XML description: {0}", _xmlDocumentLocation), ex);
+ }
}
void ProcessAssemblies (LinkContext context, XPathNodeIterator iterator)
}
}
- static void MarkAndPreserveAll (TypeDefinition type)
+ void MarkAndPreserveAll (TypeDefinition type)
{
Annotations.Mark (type);
Annotations.SetPreserve (type, TypePreserve.All);
continue;
}
- TypeDefinition type = assembly.MainModule.Types [fullname];
+ TypeDefinition type = assembly.MainModule.GetType (fullname);
if (type == null)
continue;
return new Regex (pattern.Replace(".", @"\.").Replace("*", "(.*)"));
}
+ void MatchType (TypeDefinition type, Regex regex, XPathNavigator nav)
+ {
+ if (regex.Match (type.FullName).Success)
+ ProcessType (type, nav);
+
+ if (!type.HasNestedTypes)
+ return;
+
+ foreach (var nt in type.NestedTypes)
+ MatchType (nt, regex, nav);
+ }
+
void ProcessTypePattern (string fullname, AssemblyDefinition assembly, XPathNavigator nav)
{
Regex regex = CreateRegexFromPattern (fullname);
foreach (TypeDefinition type in assembly.MainModule.Types) {
- if (!regex.Match (type.FullName).Success)
- continue;
-
- ProcessType (type, nav);
+ MatchType (type, regex, nav);
}
}
Annotations.Mark (type);
+ if (type.IsNested) {
+ var parent = type;
+ while (parent.IsNested) {
+ parent = parent.DeclaringType;
+ Annotations.Mark (parent);
+ }
+ }
+
switch (preserve) {
case TypePreserve.Nothing:
if (!nav.HasChildren)
void ProcessFields (TypeDefinition type, XPathNodeIterator iterator)
{
while (iterator.MoveNext ()) {
- if (GetAttribute (iterator.Current, "signature") != null)
- ProcessFieldSignature (type, iterator.Current);
+ string value = GetSignature (iterator.Current);
+ if (!String.IsNullOrEmpty (value))
+ ProcessFieldSignature (type, value);
- if (GetAttribute (iterator.Current, "name") != null)
- ProcessFieldName (type, iterator.Current);
+ value = GetAttribute (iterator.Current, "name");
+ if (!String.IsNullOrEmpty (value))
+ ProcessFieldName (type, value);
}
}
- void ProcessFieldSignature (TypeDefinition type, XPathNavigator nav)
+ void ProcessFieldSignature (TypeDefinition type, string signature)
{
- string signature = GetSignature (nav);
FieldDefinition field = GetField (type, signature);
MarkField (type, field, signature);
}
AddUnresolveMarker (string.Format ("T: {0}; F: {1}", type, signature));
}
- void ProcessFieldName (TypeDefinition type, XPathNavigator nav)
+ void ProcessFieldName (TypeDefinition type, string name)
{
if (!type.HasFields)
return;
- string name = GetAttribute (nav, "name");
foreach (FieldDefinition field in type.Fields)
if (field.Name == name)
MarkField (type, field, name);
void ProcessMethods (TypeDefinition type, XPathNodeIterator iterator)
{
while (iterator.MoveNext()) {
- if (GetAttribute (iterator.Current, "signature") != null)
- ProcessMethodSignature (type, iterator.Current);
+ string value = GetSignature (iterator.Current);
+ if (!String.IsNullOrEmpty (value))
+ ProcessMethodSignature (type, value);
- if (GetAttribute (iterator.Current, "name") != null)
- ProcessMethodName (type, iterator.Current);
+ value = GetAttribute (iterator.Current, "name");
+ if (!String.IsNullOrEmpty (value))
+ ProcessMethodName (type, value);
}
}
- void ProcessMethodSignature (TypeDefinition type, XPathNavigator nav)
+ void ProcessMethodSignature (TypeDefinition type, string signature)
{
- string signature = GetSignature (nav);
MethodDefinition meth = GetMethod (type, signature);
MarkMethod (type, meth, signature);
}
- private void MarkMethod (TypeDefinition type, MethodDefinition method, string signature)
+ void MarkMethod (TypeDefinition type, MethodDefinition method, string signature)
{
if (method != null) {
Annotations.Mark (method);
AddUnresolveMarker (string.Format ("T: {0}; M: {1}", type, signature));
}
- void ProcessMethodName (TypeDefinition type, XPathNavigator nav)
+ void ProcessMethodName (TypeDefinition type, string name)
{
- string name = GetAttribute (nav, "name");
- if (name == ".ctor" || name == ".cctor" && type.HasConstructors)
- foreach (MethodDefinition ctor in type.Constructors)
- if (name == ctor.Name)
- MarkMethod (type, ctor, name);
+ if (!type.HasMethods)
+ return;
- if (type.HasMethods)
- foreach (MethodDefinition method in type.Methods)
- if (name == method.Name)
- MarkMethod (type, method, name);
+ foreach (MethodDefinition method in type.Methods)
+ if (name == method.Name)
+ MarkMethod (type, method, name);
}
static MethodDefinition GetMethod (TypeDefinition type, string signature)
if (signature == GetMethodSignature (meth))
return meth;
- if (type.HasConstructors)
- foreach (MethodDefinition ctor in type.Constructors)
- if (signature == GetMethodSignature (ctor))
- return ctor;
-
return null;
}
static string GetMethodSignature (MethodDefinition meth)
{
StringBuilder sb = new StringBuilder ();
- sb.Append (meth.ReturnType.ReturnType.FullName);
+ sb.Append (meth.ReturnType.FullName);
sb.Append (" ");
sb.Append (meth.Name);
sb.Append ("(");