Skip to content

AndroidAnnotationSupport needs better invalid XML fixup #883

Closed
@jonpryor

Description

@jonpryor

Context: https://issuetracker.google.com/issues/116182838
Context: 4073f3e

In 2018-September, Google started providing various XML files which were not valid XML. We worked around this in commit 4073f3e by using HtmlAgilityPack to "loosely parse" the XML.

The problem with commit 4073f3e is that the resulting "intermediate" XML isn't "the same". Given XML of:

  <!-- valid XML; API-28 -->
   <item name="android.accounts.AccountManager android.accounts.AccountManagerFuture&lt;android.os.Bundle&gt; addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback&lt;android.os.Bundle&gt;, android.os.Handler)">
     <annotation name="android.support.annotation.RequiresPermission">
      <val name="value" val="&quot;android.permission.MANAGE_ACCOUNTS&quot;" />
       <val name="apis" val="&quot;..22&quot;" />
     </annotation>
   </item>

    <!-- invalid XML; API-29 -->
   <item name="android.accounts.AccountManager android.accounts.AccountManagerFuture&lt;android.os.Bundle&gt; addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)">
     <annotation name="androidx.annotation.RequiresPermission">
       <val name="value" val="&quot;android.permission.MANAGE_ACCOUNTS&quot;" />
       <val name="apis" val="&quot;..22&quot;" />
     </annotation>
   </item>

Consider this fragment:

using System;
using System.Collections.Generic;
using System.Linq;
using Xamarin.AndroidTools.AnnotationSupport;

class App {
    public static void Main ()
    {
        Console.WriteLine ("- API-28");
        var a28 = AndroidAnnotationsSupport.ParseArchive ("$HOME/android-toolchain/sdk/platforms/android-28/data/annotations.zip");
        Console.WriteLine ("- API-29");
        var a29 = AndroidAnnotationsSupport.ParseArchive ("$HOME/android-toolchain/sdk/platforms/android-29/data/annotations.zip");

        var addAccount_28 = a28.Where (a => a.TypeName == "android.accounts.AccountManager" && a.MemberName == "addAccount")
            .First ();
        var addAccount_29 = a29.Where (a => a.TypeName == "android.accounts.AccountManager" && a.MemberName == "addAccount")
            .First ();
        
        Console.WriteLine ($"API-28: {addAccount_28}");
        foreach (var a in addAccount_28.Annotations) {
            Console.WriteLine ($" Name={a.Name}");
            var v = string.Join (", ", a.Values);
            Console.WriteLine ($" Values={v}");
        }
        
        Console.WriteLine ($"API-29: {addAccount_29}");
        foreach (var a in addAccount_29.Annotations) {
            Console.WriteLine ($" Name={a.Name}");
            var v = string.Join (", ", a.Values);
            Console.WriteLine ($" Values={v}");
        }
    }
}

When run, we get:

API-28: @RequiresPermission(value=System.String[], apis=System.String[]) android.accounts.AccountManager.addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)
 Name=RequiresPermission
 Values=value = "android.permission.MANAGE_ACCOUNTS", apis = "..22"
API-29: @RequiresPermission(value=System.String[], apis=System.String[]) android.accounts.AccountManager.addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)
 Name=RequiresPermission
 Values=value = &quot;android.permission.MANAGE_ACCOUNTS&quot;, apis = &quot;..22&quot;

Note how the Values value changes, from android.permission.MANAGE_ACCOUNTS to &quot;android.permission.MANAGE_ACCOUNTS&quot. This value eventually becomes the RequiresPermission attribute value, resulting in "downstream" Mono.Android.dll changes:

-[global::Android.Runtime.RequiresPermission ("android.permission.MANAGE_ACCOUNTS")]
+[global::Android.Runtime.RequiresPermission ("quot;android.permission.MANAGE_ACCOUNTS&quot")]

which results in hundreds of "API changes" reported by the _CheckApiCompatibility target.

For Great Sanity™, we want the "invalid XML" path to produce the same value as the "valid XML" path, especially considering that the //item/annotation/val/@val attribute value is the same.

Metadata

Metadata

Assignees

Labels

enhancementProposed change to current functionalitygeneratorIssues binding a Java library (generator, class-parse, etc.)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions