Skip to content

Commit 1e8f513

Browse files
authored
[generator] Remove androidx.annotation from Annotation names (dotnet#882)
Context: dotnet/android#6300 A confluence of several "funny" things happened with dotnet/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.
1 parent 8f7ddcd commit 1e8f513

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotatedItem.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,37 @@ IEnumerable<string> ParseArguments (string args)
9898
yield return x;
9999
}
100100
}
101+
102+
public override string ToString ()
103+
{
104+
var s = new System.Text.StringBuilder ();
105+
foreach (var a in Annotations) {
106+
s.Append ("@").Append (a.Name);
107+
if (a.Values.Count > 0) {
108+
s.Append ("(");
109+
AppendAnnotationValue (a.Values [0]);
110+
for (int i = 1; i < a.Values.Count; ++i) {
111+
s.Append (", ");
112+
AppendAnnotationValue (a.Values [i]);
113+
}
114+
s.Append (")");
115+
}
116+
s.Append (" ");
117+
}
118+
s.Append (TypeName).Append (".").Append (MemberName);
119+
if (Arguments?.Length > 0) {
120+
s.Append ("(").Append (Arguments [0]);
121+
for (int i = 1; i < Arguments.Length; ++i) {
122+
s.Append (", ").Append (Arguments [i]);
123+
}
124+
s.Append (")");
125+
}
126+
return s.ToString ();
127+
128+
void AppendAnnotationValue (AnnotationValue d)
129+
{
130+
s.Append (d.Name).Append("=").Append (d.ValueAsArray);
131+
}
132+
}
101133
}
102134
}

src/Xamarin.Android.Tools.AnnotationSupport/Objects/AnnotationData.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,20 @@ namespace Xamarin.AndroidTools.AnnotationSupport
77
{
88
public class AnnotationData : AnnotationObject
99
{
10+
static readonly string[] Prefixes = new[] {
11+
"android.support.annotation.",
12+
"androidx.annotation.",
13+
};
1014
public AnnotationData (XElement e)
1115
{
1216
var a = e.Attribute ("name");
1317
Name = a == null ? null : a.Value;
14-
string predef = "android.support.annotation.";
15-
if (Name.StartsWith (predef, StringComparison.Ordinal))
18+
foreach (var predef in Prefixes) {
19+
if (!Name.StartsWith (predef, StringComparison.Ordinal))
20+
continue;
1621
Name = Name.Substring (predef.Length);
22+
break;
23+
}
1724
Values = e.Elements ("val").Select (c => new AnnotationValue (c)).ToArray ();
1825
}
1926

0 commit comments

Comments
 (0)