|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq;
using System.Xml;
using ILLink.Shared;
using Mono.Cecil;
using Mono.Linker.Steps;
namespace Mono.Linker
{
public class EmbeddedXmlInfo
{
static EmbeddedResource? GetEmbeddedXml (AssemblyDefinition assembly, Func<Resource, bool> predicate)
{
return assembly.Modules
.SelectMany (mod => mod.Resources)
.Where (res => res.ResourceType == ResourceType.Embedded)
.Where (res => res.Name.EndsWith (".xml", StringComparison.OrdinalIgnoreCase))
.Where (res => predicate (res))
.SingleOrDefault () as EmbeddedResource;
}
public void ProcessDescriptors (AssemblyDefinition assembly, LinkContext context)
{
if (context.Annotations.GetAction (assembly) == AssemblyAction.Skip)
return;
var rsc = GetEmbeddedXml (assembly, res => ShouldProcessRootDescriptorResource (assembly, context, res.Name));
if (rsc == null)
return;
DescriptorMarker? marker = null;
try {
context.LogMessage ($"Processing embedded trimming descriptor '{rsc.Name}' from '{assembly.Name}'.");
marker = GetExternalResolveStep (context, rsc, assembly);
} catch (XmlException ex) {
/* This could happen if some broken XML file is embedded. */
context.LogError (null, DiagnosticId.XmlException, rsc.Name, ex.ToString ());
}
marker?.Mark ();
}
public SubstitutionInfo? ProcessSubstitutions (AssemblyDefinition assembly, LinkContext context)
{
if (context.Annotations.GetAction (assembly) == AssemblyAction.Skip)
return null;
var rsc = GetEmbeddedXml (assembly, res => res.Name.Equals ("ILLink.Substitutions.xml", StringComparison.OrdinalIgnoreCase));
if (rsc == null)
return null;
BodySubstitutionParser? parser = null;
try {
context.LogMessage ($"Processing embedded substitution descriptor '{rsc.Name}' from '{assembly.Name}'.");
parser = GetExternalSubstitutionParser (context, rsc, assembly);
} catch (XmlException ex) {
context.LogError (null, DiagnosticId.XmlException, rsc.Name, ex.ToString ());
}
if (parser == null)
return null;
var substitutionInfo = new SubstitutionInfo ();
parser.Parse (substitutionInfo);
return substitutionInfo;
}
public AttributeInfo? ProcessAttributes (AssemblyDefinition assembly, LinkContext context)
{
if (context.Annotations.GetAction (assembly) == AssemblyAction.Skip)
return null;
var rsc = GetEmbeddedXml (assembly, res => res.Name.Equals ("ILLink.LinkAttributes.xml", StringComparison.OrdinalIgnoreCase));
if (rsc == null)
return null;
LinkAttributesParser? parser = null;
try {
context.LogMessage ($"Processing embedded '{rsc.Name}' from '{assembly.Name}'.");
parser = GetExternalLinkAttributesParser (context, rsc, assembly);
} catch (XmlException ex) {
context.LogError (null, DiagnosticId.XmlException, rsc.Name, ex.ToString ());
}
if (parser == null)
return null;
var attributeInfo = new AttributeInfo ();
parser.Parse (attributeInfo);
return attributeInfo;
}
static string GetAssemblyName (string descriptor)
{
int pos = descriptor.LastIndexOf ('.');
if (pos == -1)
return descriptor;
return descriptor.Substring (0, pos);
}
static bool ShouldProcessRootDescriptorResource (AssemblyDefinition assembly, LinkContext context, string resourceName)
{
if (resourceName.Equals ("ILLink.Descriptors.xml", StringComparison.OrdinalIgnoreCase))
return true;
if (GetAssemblyName (resourceName) != assembly.Name.Name)
return false;
switch (context.Annotations.GetAction (assembly)) {
case AssemblyAction.Link:
case AssemblyAction.AddBypassNGen:
case AssemblyAction.AddBypassNGenUsed:
case AssemblyAction.Copy:
return true;
default:
return false;
}
}
protected virtual DescriptorMarker GetExternalResolveStep (LinkContext context, EmbeddedResource resource, AssemblyDefinition assembly)
{
return new DescriptorMarker (context, resource.GetResourceStream (), resource, assembly, "resource " + resource.Name + " in " + assembly.FullName);
}
protected virtual BodySubstitutionParser GetExternalSubstitutionParser (LinkContext context, EmbeddedResource resource, AssemblyDefinition assembly)
{
return new BodySubstitutionParser (context, resource.GetResourceStream (), resource, assembly, "resource " + resource.Name + " in " + assembly.FullName);
}
protected virtual LinkAttributesParser GetExternalLinkAttributesParser (LinkContext context, EmbeddedResource resource, AssemblyDefinition assembly)
{
return new LinkAttributesParser (context, resource.GetResourceStream (), resource, assembly, "resource " + resource.Name + " in " + assembly.FullName);
}
}
}
|