You've already forked linux-packaging-mono
Imported Upstream version 4.2.0.179
Former-commit-id: 0a113cb3a6feb7873f632839b1307cc6033cd595
This commit is contained in:
committed by
Jo Shields
parent
183bba2c9a
commit
6992685b86
@@ -26,8 +26,11 @@
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
using Mono.Cecil;
|
||||
@@ -44,10 +47,37 @@ namespace Mono.Linker.Steps {
|
||||
protected override void Process ()
|
||||
{
|
||||
foreach (string name in Assembly.GetExecutingAssembly ().GetManifestResourceNames ()) {
|
||||
if (!IsReferenced (GetAssemblyName (name)))
|
||||
if (Path.GetExtension (name) != ".xml" || !IsReferenced (GetAssemblyName (name)))
|
||||
continue;
|
||||
|
||||
Context.Pipeline.AddStepAfter (typeof (TypeMapStep), GetResolveStep (name));
|
||||
try {
|
||||
if (Context.LogInternalExceptions)
|
||||
Console.WriteLine ("Processing resource linker descriptor: {0}", name);
|
||||
Context.Pipeline.AddStepAfter (typeof (TypeMapStep), GetResolveStep (name));
|
||||
} catch (XmlException ex) {
|
||||
/* This could happen if some broken XML file is included. */
|
||||
if (Context.LogInternalExceptions)
|
||||
Console.WriteLine ("Error processing {0}: {1}", name, ex);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var rsc in Context.GetAssemblies ()
|
||||
.SelectMany (asm => asm.Modules)
|
||||
.SelectMany (mod => mod.Resources)
|
||||
.Where (res => res.ResourceType == ResourceType.Embedded)
|
||||
.Where (res => Path.GetExtension (res.Name) == ".xml")
|
||||
.Where (res => IsReferenced (GetAssemblyName (res.Name)))
|
||||
.Cast<EmbeddedResource> ()) {
|
||||
try {
|
||||
if (Context.LogInternalExceptions)
|
||||
Console.WriteLine ("Processing embedded resource linker descriptor: {0}", rsc.Name);
|
||||
|
||||
Context.Pipeline.AddStepAfter (typeof (TypeMapStep), GetExternalResolveStep (rsc));
|
||||
} catch (XmlException ex) {
|
||||
/* This could happen if some broken XML file is embedded. */
|
||||
if (Context.LogInternalExceptions)
|
||||
Console.WriteLine ("Error processing {0}: {1}", rsc.Name, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,11 +99,23 @@ namespace Mono.Linker.Steps {
|
||||
return false;
|
||||
}
|
||||
|
||||
static ResolveFromXmlStep GetExternalResolveStep (EmbeddedResource resource)
|
||||
{
|
||||
return new ResolveFromXmlStep (GetExternalDescriptor (resource));
|
||||
}
|
||||
|
||||
static ResolveFromXmlStep GetResolveStep (string descriptor)
|
||||
{
|
||||
return new ResolveFromXmlStep (GetDescriptor (descriptor));
|
||||
}
|
||||
|
||||
static XPathDocument GetExternalDescriptor (EmbeddedResource resource)
|
||||
{
|
||||
using (var sr = new StreamReader (resource.GetResourceStream ())) {
|
||||
return new XPathDocument (new StringReader (sr.ReadToEnd ()));
|
||||
}
|
||||
}
|
||||
|
||||
static XPathDocument GetDescriptor (string descriptor)
|
||||
{
|
||||
using (StreamReader sr = new StreamReader (GetResource (descriptor))) {
|
||||
|
@@ -346,9 +346,25 @@ namespace Mono.Linker.Steps {
|
||||
// even if we (just before saving) will resolve all type references (bug #26752)
|
||||
void MarkWithResolvedScope (TypeReference type)
|
||||
{
|
||||
// we cannot set the Scope of a TypeSpecification so there's no point in resolving it
|
||||
if ((type == null) || (type is TypeSpecification))
|
||||
if (type == null)
|
||||
return;
|
||||
|
||||
// a GenericInstanceType can could contains generic arguments with scope that
|
||||
// needs to be updated out of the PCL facade (bug #28823)
|
||||
var git = (type as GenericInstanceType);
|
||||
if ((git != null) && git.HasGenericArguments) {
|
||||
foreach (var ga in git.GenericArguments)
|
||||
MarkWithResolvedScope (ga);
|
||||
return;
|
||||
}
|
||||
// we cannot set the Scope of a TypeSpecification but it's element type can be set
|
||||
// e.g. System.String[] -> System.String
|
||||
var ts = (type as TypeSpecification);
|
||||
if (ts != null) {
|
||||
MarkWithResolvedScope (ts.GetElementType ());
|
||||
return;
|
||||
}
|
||||
|
||||
var td = type.Resolve ();
|
||||
if (td != null)
|
||||
type.Scope = td.Scope;
|
||||
@@ -498,6 +514,8 @@ namespace Mono.Linker.Steps {
|
||||
MarkMethodsIf (type.Methods, IsStaticConstructorPredicate);
|
||||
}
|
||||
|
||||
DoAdditionalTypeProcessing (type);
|
||||
|
||||
Annotations.Mark (type);
|
||||
|
||||
ApplyPreserveInfo (type);
|
||||
@@ -505,6 +523,11 @@ namespace Mono.Linker.Steps {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Allow subclassers to mark additional things when marking a method
|
||||
protected virtual void DoAdditionalTypeProcessing (TypeDefinition method)
|
||||
{
|
||||
}
|
||||
|
||||
void MarkTypeSpecialCustomAttributes (TypeDefinition type)
|
||||
{
|
||||
if (!type.HasCustomAttributes)
|
||||
@@ -554,17 +577,21 @@ namespace Mono.Linker.Steps {
|
||||
return argument != null;
|
||||
}
|
||||
|
||||
protected void MarkNamedMethod (TypeDefinition type, string method_name)
|
||||
protected int MarkNamedMethod (TypeDefinition type, string method_name)
|
||||
{
|
||||
if (!type.HasMethods)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
int count = 0;
|
||||
foreach (MethodDefinition method in type.Methods) {
|
||||
if (method.Name != method_name)
|
||||
continue;
|
||||
|
||||
MarkMethod (method);
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute)
|
||||
@@ -941,11 +968,18 @@ namespace Mono.Linker.Steps {
|
||||
if (ShouldParseMethodBody (method))
|
||||
MarkMethodBody (method.Body);
|
||||
|
||||
DoAdditionalMethodProcessing (method);
|
||||
|
||||
Annotations.Mark (method);
|
||||
|
||||
ApplyPreserveMethods (method);
|
||||
}
|
||||
|
||||
// Allow subclassers to mark additional things when marking a method
|
||||
protected virtual void DoAdditionalMethodProcessing (MethodDefinition method)
|
||||
{
|
||||
}
|
||||
|
||||
void MarkBaseMethods (MethodDefinition method)
|
||||
{
|
||||
IList base_methods = Annotations.GetBaseMethods (method);
|
||||
|
@@ -57,6 +57,12 @@ namespace Mono.Linker.Steps {
|
||||
{
|
||||
XPathNavigator nav = _document.CreateNavigator ();
|
||||
nav.MoveToFirstChild ();
|
||||
|
||||
// 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;
|
||||
|
||||
ProcessAssemblies (Context, nav.SelectChildren ("assembly", _ns));
|
||||
}
|
||||
|
||||
|
@@ -42,8 +42,17 @@ namespace Mono.Linker.Steps {
|
||||
protected override void Process ()
|
||||
{
|
||||
assemblies = Context.GetAssemblies ();
|
||||
foreach (var assembly in assemblies)
|
||||
foreach (var assembly in assemblies) {
|
||||
SweepAssembly (assembly);
|
||||
if (Annotations.GetAction (assembly) == AssemblyAction.Copy) {
|
||||
// Copy assemblies can still contain Type references with
|
||||
// type forwarders from Delete assemblies
|
||||
// thus try to resolve all the type references and see
|
||||
// if some changed the scope. if yes change the action to Save
|
||||
if (ResolveAllTypeReferences (assembly))
|
||||
Annotations.SetAction (assembly, AssemblyAction.Save);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SweepAssembly (AssemblyDefinition assembly)
|
||||
@@ -124,15 +133,16 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
}
|
||||
|
||||
void ResolveAllTypeReferences (AssemblyDefinition assembly)
|
||||
bool ResolveAllTypeReferences (AssemblyDefinition assembly)
|
||||
{
|
||||
if (resolvedTypeReferences == null)
|
||||
resolvedTypeReferences = new HashSet<AssemblyDefinition> ();
|
||||
if (resolvedTypeReferences.Contains (assembly))
|
||||
return;
|
||||
return false;
|
||||
resolvedTypeReferences.Add (assembly);
|
||||
|
||||
var hash = new Dictionary<TypeReference,IMetadataScope> ();
|
||||
bool changes = false;
|
||||
|
||||
foreach (TypeReference tr in assembly.MainModule.GetTypeReferences ()) {
|
||||
if (hash.ContainsKey (tr))
|
||||
@@ -141,8 +151,11 @@ namespace Mono.Linker.Steps {
|
||||
IMetadataScope scope = tr.Scope;
|
||||
// at this stage reference might include things that can't be resolved
|
||||
// and if it is (resolved) it needs to be kept only if marked (#16213)
|
||||
if ((td != null) && Annotations.IsMarked (td))
|
||||
if ((td != null) && Annotations.IsMarked (td)) {
|
||||
scope = assembly.MainModule.Import (td).Scope;
|
||||
if (tr.Scope != scope)
|
||||
changes = true;
|
||||
}
|
||||
hash.Add (tr, scope);
|
||||
}
|
||||
if (assembly.MainModule.HasExportedTypes) {
|
||||
@@ -163,6 +176,8 @@ namespace Mono.Linker.Steps {
|
||||
foreach (var e in hash) {
|
||||
e.Key.Scope = e.Value;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
void SweepType (TypeDefinition type)
|
||||
|
@@ -179,81 +179,118 @@ namespace Mono.Linker.Steps {
|
||||
if (!type.HasMethods)
|
||||
return null;
|
||||
|
||||
foreach (MethodDefinition candidate in type.Methods)
|
||||
if (MethodMatch (candidate, method))
|
||||
Dictionary<string,string> gp = null;
|
||||
foreach (MethodDefinition candidate in type.Methods) {
|
||||
if (MethodMatch (candidate, method, ref gp))
|
||||
return candidate;
|
||||
if (gp != null)
|
||||
gp.Clear ();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static bool MethodMatch (MethodDefinition candidate, MethodDefinition method)
|
||||
static bool MethodMatch (MethodDefinition candidate, MethodDefinition method, ref Dictionary<string,string> genericParameters)
|
||||
{
|
||||
if (!candidate.IsVirtual)
|
||||
return false;
|
||||
|
||||
if (candidate.HasParameters != method.HasParameters)
|
||||
return false;
|
||||
|
||||
if (candidate.Name != method.Name)
|
||||
return false;
|
||||
|
||||
if (!TypeMatch (candidate.ReturnType, method.ReturnType))
|
||||
if (candidate.HasGenericParameters != method.HasGenericParameters)
|
||||
return false;
|
||||
|
||||
if (candidate.Parameters.Count != method.Parameters.Count)
|
||||
// we need to track what the generic parameter represent - as we cannot allow it to
|
||||
// differ between the return type or any parameter
|
||||
if (!TypeMatch (candidate.ReturnType, method.ReturnType, ref genericParameters))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < candidate.Parameters.Count; i++)
|
||||
if (!TypeMatch (candidate.Parameters [i].ParameterType, method.Parameters [i].ParameterType))
|
||||
if (!candidate.HasParameters)
|
||||
return true;
|
||||
|
||||
var cp = candidate.Parameters;
|
||||
var mp = method.Parameters;
|
||||
if (cp.Count != mp.Count)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < cp.Count; i++) {
|
||||
if (!TypeMatch (cp [i].ParameterType, mp [i].ParameterType, ref genericParameters))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TypeMatch (IModifierType a, IModifierType b)
|
||||
static bool TypeMatch (IModifierType a, IModifierType b, ref Dictionary<string,string> gp)
|
||||
{
|
||||
if (!TypeMatch (a.ModifierType, b.ModifierType))
|
||||
if (!TypeMatch (a.ModifierType, b.ModifierType, ref gp))
|
||||
return false;
|
||||
|
||||
return TypeMatch (a.ElementType, b.ElementType);
|
||||
return TypeMatch (a.ElementType, b.ElementType, ref gp);
|
||||
}
|
||||
|
||||
static bool TypeMatch (TypeSpecification a, TypeSpecification b)
|
||||
static bool TypeMatch (TypeSpecification a, TypeSpecification b, ref Dictionary<string,string> gp)
|
||||
{
|
||||
if (a is GenericInstanceType)
|
||||
return TypeMatch ((GenericInstanceType) a, (GenericInstanceType) b);
|
||||
var gita = a as GenericInstanceType;
|
||||
if (gita != null)
|
||||
return TypeMatch (gita, (GenericInstanceType) b, ref gp);
|
||||
|
||||
if (a is IModifierType)
|
||||
return TypeMatch ((IModifierType) a, (IModifierType) b);
|
||||
var mta = a as IModifierType;
|
||||
if (mta != null)
|
||||
return TypeMatch (mta, (IModifierType) b, ref gp);
|
||||
|
||||
return TypeMatch (a.ElementType, b.ElementType);
|
||||
return TypeMatch (a.ElementType, b.ElementType, ref gp);
|
||||
}
|
||||
|
||||
static bool TypeMatch (GenericInstanceType a, GenericInstanceType b)
|
||||
static bool TypeMatch (GenericInstanceType a, GenericInstanceType b, ref Dictionary<string,string> gp)
|
||||
{
|
||||
if (!TypeMatch (a.ElementType, b.ElementType))
|
||||
if (!TypeMatch (a.ElementType, b.ElementType, ref gp))
|
||||
return false;
|
||||
|
||||
if (a.GenericArguments.Count != b.GenericArguments.Count)
|
||||
if (a.HasGenericArguments != b.HasGenericArguments)
|
||||
return false;
|
||||
|
||||
if (a.GenericArguments.Count == 0)
|
||||
if (!a.HasGenericArguments)
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < a.GenericArguments.Count; i++)
|
||||
if (!TypeMatch (a.GenericArguments [i], b.GenericArguments [i]))
|
||||
var gaa = a.GenericArguments;
|
||||
var gab = b.GenericArguments;
|
||||
if (gaa.Count != gab.Count)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < gaa.Count; i++) {
|
||||
if (!TypeMatch (gaa [i], gab [i], ref gp))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TypeMatch (TypeReference a, TypeReference b)
|
||||
static bool TypeMatch (TypeReference a, TypeReference b, ref Dictionary<string,string> gp)
|
||||
{
|
||||
if (a is GenericParameter)
|
||||
return true;
|
||||
var gpa = a as GenericParameter;
|
||||
if (gpa != null) {
|
||||
if (gp == null)
|
||||
gp = new Dictionary<string, string> ();
|
||||
string match;
|
||||
if (!gp.TryGetValue (gpa.FullName, out match)) {
|
||||
// first use, we assume it will always be used this way
|
||||
gp.Add (gpa.FullName, b.ToString ());
|
||||
return true;
|
||||
}
|
||||
// re-use, it should match the previous usage
|
||||
return match == b.ToString ();
|
||||
}
|
||||
|
||||
if (a is TypeSpecification || b is TypeSpecification) {
|
||||
if (a.GetType () != b.GetType ())
|
||||
return false;
|
||||
|
||||
return TypeMatch ((TypeSpecification) a, (TypeSpecification) b);
|
||||
return TypeMatch ((TypeSpecification) a, (TypeSpecification) b, ref gp);
|
||||
}
|
||||
|
||||
return a.FullName == b.FullName;
|
||||
|
@@ -93,6 +93,8 @@ namespace Mono.Linker {
|
||||
set { _symbolWriterProvider = value; }
|
||||
}
|
||||
|
||||
public bool LogInternalExceptions { get; set; } = false;
|
||||
|
||||
public LinkContext (Pipeline pipeline)
|
||||
: this (pipeline, new AssemblyResolver ())
|
||||
{
|
||||
|
Reference in New Issue
Block a user