Welcome to mirror list, hosted at ThFree Co, Russian Federation.

EmbeddedXmlInfo.cs « Linker « linker « src - github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 84f9c71ad218430ca7f22e3de3a13deca899c0fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// 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 static 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 static 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 linker 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 static 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 static 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;
			}
		}

		static DescriptorMarker GetExternalResolveStep (LinkContext context, EmbeddedResource resource, AssemblyDefinition assembly)
		{
			return new DescriptorMarker (context, resource.GetResourceStream (), resource, assembly, "resource " + resource.Name + " in " + assembly.FullName);
		}

		static BodySubstitutionParser GetExternalSubstitutionParser (LinkContext context, EmbeddedResource resource, AssemblyDefinition assembly)
		{
			return new BodySubstitutionParser (context, resource.GetResourceStream (), resource, assembly, "resource " + resource.Name + " in " + assembly.FullName);
		}

		static LinkAttributesParser GetExternalLinkAttributesParser (LinkContext context, EmbeddedResource resource, AssemblyDefinition assembly)
		{
			return new LinkAttributesParser (context, resource.GetResourceStream (), resource, assembly, "resource " + resource.Name + " in " + assembly.FullName);
		}
	}
}