From 2c062849352b2c9444834395a9285877bdbcdb43 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 16 Sep 2021 13:33:26 -0400 Subject: [PATCH] [generator] Remove androidx.annotation from Annotation names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Context: https://github.com/xamarin/xamarin-android/pull/6300 A confluence of several "funny" things happened with xamarin/xamarin-android#6300, which attempts to use the Android SDK platform-tools 31.0.3 package, up from 30.0.2: 1. The new platform-tools package *removes* the file `platform-tools/api/annotations.zip`. To work around that, we need to instead use the `data/annotations.zip` file from the Android platform directory, e.g. `$ANDROID_SDK_ROOT/platforms/android-30/data/annotations.zip`. 2. Between API-28 and API-29, `annotations.zip` changes the package name used for annotations, from e.g. `android.support.annotation.RequiresPermission` to `androidx.annotation.RequiresPermission`. In isolation, okay, but then we hit: 3. `AnnotationData` *removes* the "known" package-prefix of `android.support.annotation.`, and all use of `AnnotationData.Name` is via `string.operator==`, *not* `string.Contains()` or `string.IndexOf()`. The result of all these changes together is API breakage in `Mono.Android.dll` between API-28 and API-29: …/Mono.Android.targets(257,5): error : CannotRemoveAttribute : Attribute 'Android.Runtime.RequiresPermissionAttribute' exists on 'Android.Accounts.AccountManager.AddAccount(System.String, System.String, System.String[], Android.OS.Bundle, Android.App.Activity, Android.Accounts.IAccountManagerCallback, Android.OS.Handler)' in the contract but not the implementation. Or, in C# `diff -u` terms: --- obj/Debug/monoandroid10/android-28/mcw/Android.Accounts.AccountManager.cs 2021-09-16 09:00:53.000000000 -0400 +++ obj/Debug/monoandroid10/android-29/mcw/Android.Accounts.AccountManager.cs 2021-09-16 10:41:15.000000000 -0400 @@ -217,7 +217,6 @@ // Metadata.xml XPath method reference: path="/api/package[@name='android.accounts']/class[@name='AccountManager']/method[@name='addAccount' and count(parameter)=7 and parameter[1][@type='java.lang.String'] and parameter[2][@type='java.lang.String'] and parameter[3][@type='java.lang.String[]'] and parameter[4][@type='android.os.Bundle'] and parameter[5][@type='android.app.Activity'] and parameter[6][@type='android.accounts.AccountManagerCallback<android.os.Bundle>'] and parameter[7][@type='android.os.Handler']]" [Register ("addAccount", "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Landroid/os/Bundle;Landroid/app/Activity;Landroid/accounts/AccountManagerCallback;Landroid/os/Handler;)Landroid/accounts/AccountManagerFuture;", "GetAddAccount_Ljava_lang_String_Ljava_lang_String_arrayLjava_lang_String_Landroid_os_Bundle_Landroid_app_Activity_Landroid_accounts_AccountManagerCallback_Landroid_os_Handler_Handler")] - [global::Android.Runtime.RequiresPermission ("android.permission.MANAGE_ACCOUNTS")] public virtual unsafe Android.Accounts.IAccountManagerFuture? AddAccount (string? accountType, string? authTokenType, string[]? requiredFeatures, Android.OS.Bundle? addAccountOptions, Android.App.Activity? activity, Android.Accounts.IAccountManagerCallback? @callback, Android.OS.Handler? handler) { const string __id = "addAccount.(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Landroid/os/Bundle;Landroid/app/Activity;Landroid/accounts/AccountManagerCallback;Landroid/os/Handler;)Landroid/accounts/AccountManagerFuture;"; Fix this breakage by updating `AnnotationData` to remove the package name for `androidx.annotation` as well. Additionally, add an `AnnotatedItem.ToString()` override to simplify future printf-style debugging. --- .../Objects/AnnotatedItem.cs | 32 +++++++++++++++++++ .../Objects/AnnotationData.cs | 11 +++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotatedItem.cs b/src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotatedItem.cs index e4d334f19..e2c62bc8e 100644 --- a/src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotatedItem.cs +++ b/src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotatedItem.cs @@ -98,5 +98,37 @@ IEnumerable ParseArguments (string args) yield return x; } } + + public override string ToString () + { + var s = new System.Text.StringBuilder (); + foreach (var a in Annotations) { + s.Append ("@").Append (a.Name); + if (a.Values.Count > 0) { + s.Append ("("); + AppendAnnotationValue (a.Values [0]); + for (int i = 1; i < a.Values.Count; ++i) { + s.Append (", "); + AppendAnnotationValue (a.Values [i]); + } + s.Append (")"); + } + s.Append (" "); + } + s.Append (TypeName).Append (".").Append (MemberName); + if (Arguments?.Length > 0) { + s.Append ("(").Append (Arguments [0]); + for (int i = 1; i < Arguments.Length; ++i) { + s.Append (", ").Append (Arguments [i]); + } + s.Append (")"); + } + return s.ToString (); + + void AppendAnnotationValue (AnnotationValue d) + { + s.Append (d.Name).Append("=").Append (d.ValueAsArray); + } + } } } diff --git a/src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotationData.cs b/src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotationData.cs index 51d4bc05d..e6d5cbcff 100644 --- a/src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotationData.cs +++ b/src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotationData.cs @@ -7,13 +7,20 @@ namespace Xamarin.AndroidTools.AnnotationSupport { public class AnnotationData : AnnotationObject { + static readonly string[] Prefixes = new[] { + "android.support.annotation.", + "androidx.annotation.", + }; public AnnotationData (XElement e) { var a = e.Attribute ("name"); Name = a == null ? null : a.Value; - string predef = "android.support.annotation."; - if (Name.StartsWith (predef, StringComparison.Ordinal)) + foreach (var predef in Prefixes) { + if (!Name.StartsWith (predef, StringComparison.Ordinal)) + continue; Name = Name.Substring (predef.Length); + break; + } Values = e.Elements ("val").Select (c => new AnnotationValue (c)).ToArray (); }