diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs index 70de2500931..bcc78f1cf6f 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs @@ -23,30 +23,18 @@ namespace MonoDroid.Tuner /// /// NOTE: this step is subclassed so it can be called directly from Xamarin.Android.Build.Tasks /// - public class FixAbstractMethodsStep : -#if ILLINK - BaseMarkHandler -#else // !ILLINK - BaseStep -#endif // !ILLINK + public class FixAbstractMethodsStep : BaseStep { - #if ILLINK - public override void Initialize (LinkContext context, MarkContext markContext) - { - this.cache = context; - base.Initialize (context, markContext); - markContext.RegisterMarkTypeAction (type => ProcessType (type)); - } + IMetadataResolver cache => Context; #else // !ILLINK + readonly IMetadataResolver cache; + public FixAbstractMethodsStep (IMetadataResolver cache) { this.cache = cache; } - - readonly #endif // !ILLINK - IMetadataResolver cache; bool CheckShouldProcessAssembly (AssemblyDefinition assembly) { @@ -74,29 +62,78 @@ void UpdateAssemblyAction (AssemblyDefinition assembly) } #if ILLINK + readonly List assemblies = new (); + + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + assemblies.Add (assembly); + } + + protected override void EndProcess () + { + foreach (var assembly in GetReferencedAssemblies().ToList()) { + ProcessAssembly_Actual(assembly); + } + + IEnumerable GetReferencedAssemblies () + { + var loaded = new HashSet (assemblies); + var toProcess = new Queue (assemblies); + + while (toProcess.Count > 0) { + var assembly = toProcess.Dequeue (); + foreach (var reference in ResolveReferences (assembly)) { + if (!loaded.Add (reference)) + continue; + yield return reference; + toProcess.Enqueue (reference); + } + } + } + + ICollection ResolveReferences (AssemblyDefinition assembly) + { + List references = new List (); + if (assembly == null) + return references; + + foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences) { + AssemblyDefinition? definition = Context.Resolve (reference); + if (definition != null) + references.Add (definition); + } + + return references; + } + } + protected void ProcessType (TypeDefinition type) { var assembly = type.Module.Assembly; if (!CheckShouldProcessAssembly (assembly)) return; - if (!MightNeedFix (type)) - return; - if (!FixAbstractMethods (type)) return; UpdateAssemblyAction (assembly); MarkAbstractMethodErrorType (); } -#else // !ILLINK +#endif // ILLINK + +#if ILLINK + void ProcessAssembly_Actual (AssemblyDefinition assembly) +#else // !ILLINK protected override void ProcessAssembly (AssemblyDefinition assembly) +#endif // !ILLINK { if (!CheckShouldProcessAssembly (assembly)) return; if (FixAbstractMethods (assembly)) { +#if !ILLINK Context.SafeReadSymbols (assembly); +#endif // !ILLINK UpdateAssemblyAction (assembly); MarkAbstractMethodErrorType (); } @@ -106,12 +143,19 @@ internal bool FixAbstractMethods (AssemblyDefinition assembly) { bool changed = false; foreach (var type in assembly.MainModule.Types) { - if (MightNeedFix (type)) - changed |= FixAbstractMethods (type); + changed |= FixAbstractMethodsNested (type); } return changed; + + bool FixAbstractMethodsNested (TypeDefinition type) + { + bool changed = FixAbstractMethods (type); + foreach (var nested in type.NestedTypes) { + changed |= FixAbstractMethodsNested (nested); + } + return changed; + } } -#endif // !ILLINK readonly HashSet warnedAssemblies = new (StringComparer.Ordinal); @@ -242,6 +286,9 @@ bool HaveSameSignature (TypeReference iface, MethodDefinition iMethod, MethodDef bool FixAbstractMethods (TypeDefinition type) { + if (!MightNeedFix (type)) + return false; + if (!type.HasInterfaces) return false; diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets index e99bfb0e722..d58bb7a0b43 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets @@ -50,6 +50,7 @@ This file contains the .NET 5-specific targets to customize ILLink <_TrimmerCustomSteps Include="$(_AndroidLinkerCustomStepAssembly)" BeforeStep="MarkStep" Type="Microsoft.Android.Sdk.ILLink.SetupStep" /> + <_TrimmerCustomSteps Include="$(_AndroidLinkerCustomStepAssembly)" BeforeStep="MarkStep" Type="MonoDroid.Tuner.FixAbstractMethodsStep" /> <_TrimmerCustomSteps Include="$(_AndroidLinkerCustomStepAssembly)" Type="Microsoft.Android.Sdk.ILLink.PreserveSubStepDispatcher" /> <_TrimmerCustomSteps Include="$(_AndroidLinkerCustomStepAssembly)" Type="MonoDroid.Tuner.MarkJavaObjects" /> @@ -57,7 +58,6 @@ This file contains the .NET 5-specific targets to customize ILLink <_TrimmerCustomSteps Include="$(_AndroidLinkerCustomStepAssembly)" Type="MonoDroid.Tuner.PreserveApplications" /> <_TrimmerCustomSteps Include="$(_AndroidLinkerCustomStepAssembly)" Type="Microsoft.Android.Sdk.ILLink.PreserveRegistrations" /> <_TrimmerCustomSteps Include="$(_AndroidLinkerCustomStepAssembly)" Type="Microsoft.Android.Sdk.ILLink.PreserveJavaInterfaces" /> - <_TrimmerCustomSteps Include="$(_AndroidLinkerCustomStepAssembly)" Type="MonoDroid.Tuner.FixAbstractMethodsStep" /> <_TrimmerCustomSteps Condition=" '$(_ProguardProjectConfiguration)' != '' "