Skip to content

Commit

Permalink
[generator] Remove androidx.annotation from Annotation names (dotnet#882
Browse files Browse the repository at this point in the history
)

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.
  • Loading branch information
jonpryor authored Sep 16, 2021
1 parent 8f7ddcd commit 1e8f513
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,37 @@ IEnumerable<string> 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);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
}

Expand Down

0 comments on commit 1e8f513

Please sign in to comment.