Skip to content

Commit a2f8857

Browse files
committed
[Xamarin.Android.Build.Tasks] Fix the RemoveResourceDesignerStep to work under .NET 6
The current implementation of the `RemoveResourceDesignerStep` does not work under .NET 6. This is mostly down to the fact that we didn't `override` the require methods to make it work in that environment. This PR does also rework the `RemoveResourceDesignerStep` to split some of the functionality out into a new base class. This new base class will be used in the future by the Resource Assembly linker step. Since much of the code is identical.
1 parent 9f038d8 commit a2f8857

File tree

2 files changed

+187
-119
lines changed

2 files changed

+187
-119
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
using Mono.Cecil;
2+
using Mono.Linker;
3+
using Mono.Linker.Steps;
4+
using System;
5+
using System.Linq;
6+
using Xamarin.Android.Tasks;
7+
using System.Collections.Generic;
8+
using Mono.Cecil.Cil;
9+
using System.Text.RegularExpressions;
10+
#if ILLINK
11+
using Microsoft.Android.Sdk.ILLink;
12+
#endif
13+
14+
15+
namespace MonoDroid.Tuner {
16+
public abstract class LinkDesignerBase : BaseStep {
17+
public virtual void LogMessage (string message)
18+
{
19+
Context.LogMessage (message);
20+
}
21+
22+
public virtual AssemblyDefinition Resolve (AssemblyNameReference name)
23+
{
24+
return Context.Resolve (name);
25+
}
26+
27+
protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplication, out TypeDefinition designer, out CustomAttribute designerAttribute)
28+
{
29+
string designerFullName = null;
30+
designer = null;
31+
designerAttribute = null;
32+
foreach (CustomAttribute attribute in assembly.CustomAttributes)
33+
{
34+
if (attribute.AttributeType.FullName == "Android.Runtime.ResourceDesignerAttribute")
35+
{
36+
designerAttribute = attribute;
37+
if (attribute.HasProperties)
38+
{
39+
foreach (var p in attribute.Properties)
40+
{
41+
if (p.Name == "IsApplication" && (bool)p.Argument.Value == (mainApplication ? mainApplication : (bool)p.Argument.Value))
42+
{
43+
designerFullName = attribute.ConstructorArguments[0].Value.ToString ();
44+
break;
45+
}
46+
}
47+
}
48+
break;
49+
50+
}
51+
}
52+
if (string.IsNullOrEmpty(designerFullName))
53+
return false;
54+
55+
foreach (ModuleDefinition module in assembly.Modules)
56+
{
57+
foreach (TypeDefinition type in module.Types)
58+
{
59+
if (type.FullName == designerFullName)
60+
{
61+
designer = type;
62+
return true;
63+
}
64+
}
65+
}
66+
return false;
67+
}
68+
69+
protected void ClearDesignerClass (TypeDefinition designer)
70+
{
71+
LogMessage ($" TryRemoving {designer.FullName}");
72+
designer.NestedTypes.Clear ();
73+
designer.Methods.Clear ();
74+
designer.Fields.Clear ();
75+
designer.Properties.Clear ();
76+
designer.CustomAttributes.Clear ();
77+
designer.Interfaces.Clear ();
78+
designer.Events.Clear ();
79+
}
80+
81+
protected Dictionary<string, int> BuildResourceDesignerFieldLookup (TypeDefinition type)
82+
{
83+
var output = new Dictionary<string, int> ();
84+
foreach (TypeDefinition definition in type.NestedTypes)
85+
{
86+
foreach (FieldDefinition field in definition.Fields)
87+
{
88+
string key = $"{definition.Name}::{field.Name}";
89+
if (!output.ContainsKey (key))
90+
output.Add(key, int.Parse (field.Constant?.ToString () ?? "0"));
91+
}
92+
}
93+
return output;
94+
}
95+
96+
protected void FixType (TypeDefinition type, TypeDefinition localDesigner)
97+
{
98+
foreach (MethodDefinition method in type.Methods)
99+
{
100+
if (!method.HasBody)
101+
continue;
102+
FixBody (method.Body, localDesigner);
103+
}
104+
foreach (PropertyDefinition property in type.Properties)
105+
{
106+
if (property.GetMethod != null && property.GetMethod.HasBody)
107+
{
108+
FixBody (property.GetMethod.Body, localDesigner);
109+
}
110+
if (property.SetMethod != null && property.SetMethod.HasBody)
111+
{
112+
FixBody (property.SetMethod.Body, localDesigner);
113+
}
114+
}
115+
foreach (TypeDefinition nestedType in type.NestedTypes)
116+
{
117+
FixType (nestedType, localDesigner);
118+
}
119+
}
120+
121+
protected void FixupAssemblyTypes (AssemblyDefinition assembly, TypeDefinition designer)
122+
{
123+
foreach (ModuleDefinition module in assembly.Modules)
124+
{
125+
foreach (TypeDefinition type in module.Types)
126+
{
127+
if (type.FullName == designer.FullName)
128+
continue;
129+
FixType (type, designer);
130+
}
131+
}
132+
}
133+
134+
protected override void ProcessAssembly (AssemblyDefinition assembly)
135+
{
136+
LoadDesigner ();
137+
138+
var action = Annotations.HasAction (assembly) ? Annotations.GetAction (assembly) : AssemblyAction.Skip;
139+
if (action == AssemblyAction.Delete)
140+
return;
141+
142+
if (ProcessAssemblyDesigner (assembly)) {
143+
if (action == AssemblyAction.Skip || action == AssemblyAction.Copy)
144+
Annotations.SetAction (assembly, AssemblyAction.Save);
145+
}
146+
}
147+
148+
internal abstract bool ProcessAssemblyDesigner (AssemblyDefinition assemblyDefinition);
149+
protected abstract void LoadDesigner ();
150+
protected abstract void FixBody (MethodBody body, TypeDefinition designer);
151+
}
152+
}

src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/RemoveResourceDesignerStep.cs

Lines changed: 35 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,33 @@
77
using System.Collections.Generic;
88
using Mono.Cecil.Cil;
99
using System.Text.RegularExpressions;
10+
#if ILLINK
11+
using Microsoft.Android.Sdk.ILLink;
12+
#endif
1013

1114
namespace MonoDroid.Tuner
1215
{
13-
public class RemoveResourceDesignerStep : BaseStep
16+
public class RemoveResourceDesignerStep : LinkDesignerBase
1417
{
1518
TypeDefinition mainDesigner = null;
1619
AssemblyDefinition mainAssembly = null;
1720
CustomAttribute mainDesignerAttribute;
1821
Dictionary<string, int> designerConstants;
1922
Regex opCodeRegex = new Regex (@"([\w]+): ([\w]+) ([\w.]+) ([\w:./]+)");
20-
23+
#if ILLINK
2124
protected override void Process ()
2225
{
26+
cache = Context;
27+
}
28+
#else
29+
readonly
30+
#endif
31+
IMetadataResolver cache;
32+
33+
protected override void LoadDesigner ()
34+
{
35+
if (mainAssembly != null)
36+
return;
2337
// resolve the MainAssembly Resource designer TypeDefinition
2438
AndroidLinkConfiguration config = AndroidLinkConfiguration.GetInstance (Context);
2539
if (config == null)
@@ -31,95 +45,26 @@ protected override void Process ()
3145
}
3246
}
3347
if (mainDesigner == null) {
34-
Context.LogMessage ($" Main Designer not found.");
48+
LogMessage ($" Main Designer not found.");
3549
return;
3650
}
37-
Context.LogMessage ($" Main Designer found {mainDesigner.FullName}.");
51+
LogMessage ($" Main Designer found {mainDesigner.FullName}.");
3852
designerConstants = BuildResourceDesignerFieldLookup (mainDesigner);
3953
}
4054

4155
protected override void EndProcess ()
4256
{
4357
if (mainDesigner != null) {
44-
Context.LogMessage ($" Setting Action on {mainAssembly.Name} to Save.");
58+
LogMessage ($" Setting Action on {mainAssembly.Name} to Save.");
4559
Annotations.SetAction (mainAssembly, AssemblyAction.Save);
4660
}
4761
}
4862

49-
bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplication, out TypeDefinition designer, out CustomAttribute designerAttribute)
50-
{
51-
string designerFullName = null;
52-
designer = null;
53-
designerAttribute = null;
54-
foreach (CustomAttribute attribute in assembly.CustomAttributes)
55-
{
56-
if (attribute.AttributeType.FullName == "Android.Runtime.ResourceDesignerAttribute")
57-
{
58-
designerAttribute = attribute;
59-
if (attribute.HasProperties)
60-
{
61-
foreach (var p in attribute.Properties)
62-
{
63-
if (p.Name == "IsApplication" && (bool)p.Argument.Value == (mainApplication ? mainApplication : (bool)p.Argument.Value))
64-
{
65-
designerFullName = attribute.ConstructorArguments[0].Value.ToString ();
66-
break;
67-
}
68-
}
69-
}
70-
break;
71-
72-
}
73-
}
74-
if (string.IsNullOrEmpty(designerFullName))
75-
return false;
76-
77-
foreach (ModuleDefinition module in assembly.Modules)
78-
{
79-
foreach (TypeDefinition type in module.Types)
80-
{
81-
if (type.FullName == designerFullName)
82-
{
83-
designer = type;
84-
return true;
85-
}
86-
}
87-
}
88-
return false;
89-
}
90-
91-
Dictionary<string, int> BuildResourceDesignerFieldLookup (TypeDefinition type)
92-
{
93-
var output = new Dictionary<string, int> ();
94-
foreach (TypeDefinition definition in type.NestedTypes)
95-
{
96-
foreach (FieldDefinition field in definition.Fields)
97-
{
98-
string key = $"{definition.Name}::{field.Name}";
99-
if (!output.ContainsKey (key))
100-
output.Add(key, int.Parse (field.Constant?.ToString () ?? "0"));
101-
}
102-
}
103-
return output;
104-
}
105-
106-
void ClearDesignerClass (TypeDefinition designer)
107-
{
108-
Context.LogMessage ($" TryRemoving {designer.FullName}");
109-
designer.NestedTypes.Clear ();
110-
designer.Methods.Clear ();
111-
designer.Fields.Clear ();
112-
designer.Properties.Clear ();
113-
designer.CustomAttributes.Clear ();
114-
designer.Interfaces.Clear ();
115-
designer.Events.Clear ();
116-
}
117-
118-
void FixBody (MethodBody body, TypeDefinition localDesigner)
63+
protected override void FixBody (MethodBody body, TypeDefinition designer)
11964
{
12065
Dictionary<Instruction, int> instructions = new Dictionary<Instruction, int>();
12166
var processor = body.GetILProcessor ();
122-
string designerFullName = $"{localDesigner.FullName}/";
67+
string designerFullName = $"{designer.FullName}/";
12368
foreach (var i in body.Instructions)
12469
{
12570
string line = i.ToString ();
@@ -134,77 +79,48 @@ void FixBody (MethodBody body, TypeDefinition localDesigner)
13479
}
13580
}
13681
if (instructions.Count > 0)
137-
Context.LogMessage ($" Fixing up {body.Method.FullName}");
82+
LogMessage ($" Fixing up {body.Method.FullName}");
13883
foreach (var i in instructions)
13984
{
14085
var newCode = Extensions.CreateLoadArraySizeOrOffsetInstruction (i.Value);
141-
Context.LogMessage ($" Replacing {i.Key}");
142-
Context.LogMessage ($" With {newCode}");
86+
LogMessage ($" Replacing {i.Key}");
87+
LogMessage ($" With {newCode}");
14388
processor.Replace(i.Key, newCode);
14489
}
14590
}
14691

147-
void FixType (TypeDefinition type, TypeDefinition localDesigner)
148-
{
149-
foreach (MethodDefinition method in type.Methods)
150-
{
151-
if (!method.HasBody)
152-
continue;
153-
FixBody (method.Body, localDesigner);
154-
}
155-
foreach (PropertyDefinition property in type.Properties)
156-
{
157-
if (property.GetMethod != null && property.GetMethod.HasBody)
158-
{
159-
FixBody (property.GetMethod.Body, localDesigner);
160-
}
161-
if (property.SetMethod != null && property.SetMethod.HasBody)
162-
{
163-
FixBody (property.SetMethod.Body, localDesigner);
164-
}
165-
}
166-
foreach (TypeDefinition nestedType in type.NestedTypes)
167-
{
168-
FixType (nestedType, localDesigner);
169-
}
170-
}
171-
172-
protected override void ProcessAssembly (AssemblyDefinition assembly)
92+
internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly)
17393
{
17494
if (mainDesigner == null)
175-
return;
95+
return false;
17696
var fileName = assembly.Name.Name + ".dll";
17797
if (MonoAndroidHelper.IsFrameworkAssembly (fileName))
178-
return;
98+
return false;
17999

180-
Context.LogMessage ($" Fixing up {assembly.Name.Name}");
100+
LogMessage ($" Fixing up {assembly.Name.Name}");
181101
TypeDefinition localDesigner = null;
182102
CustomAttribute designerAttribute;
183103
if (assembly != mainAssembly) {
184-
Context.LogMessage ($" {assembly.Name.Name} is not the main assembly. ");
104+
LogMessage ($" {assembly.Name.Name} is not the main assembly. ");
185105
if (!FindResourceDesigner (assembly, mainApplication: false, designer: out localDesigner, designerAttribute: out designerAttribute)) {
186106
Context.LogMessage ($" {assembly.Name.Name} does not have a designer file.");
187-
return;
107+
return false;
188108
}
189109
} else {
190-
Context.LogMessage ($" {assembly.Name.Name} is the main assembly. ");
110+
LogMessage ($" {assembly.Name.Name} is the main assembly. ");
191111
localDesigner = mainDesigner;
192112
designerAttribute = mainDesignerAttribute;
193113
}
194114

195-
Context.LogMessage ($" {assembly.Name.Name} has designer {localDesigner.FullName}.");
115+
LogMessage ($" {assembly.Name.Name} has designer {localDesigner.FullName}.");
116+
117+
FixupAssemblyTypes (assembly, localDesigner);
196118

197-
foreach (var mod in assembly.Modules) {
198-
foreach (var type in mod.Types) {
199-
if (type == localDesigner)
200-
continue;
201-
FixType (type, localDesigner);
202-
}
203-
}
204119
ClearDesignerClass (localDesigner);
205120
if (designerAttribute != null) {
206121
assembly.CustomAttributes.Remove (designerAttribute);
207122
}
123+
return true;
208124
}
209125
}
210126
}

0 commit comments

Comments
 (0)