Skip to content
  • Dean Ellis's avatar
    [LayoutBindings] Fix '[Preserve]' is obsolete warnings (#8529) · 751eb965
    Dean Ellis authored
    Fixes: https://github.com/xamarin/xamarin-android/issues/7480
    
    Context: e6048334
    
    When [Layout Bindings][0] are enabled, a set of `partial` classes
    will be generated which "mirrors" the `.axml` structure in C#.
    
    Consider:
    
    	dotnet new android -n com.example.codebehind
    
    You enable Code-Behind by:
    
     1. Setting the `$(AndroidGenerateLayoutBindings)` MSBuild property
        to `true`.
     2. Using `android:id` on elements within `.axml` files.
    
    Consider this patch to the above `dotnet new`:
    
    	diff --git a/Resources/layout/activity_main.xml b/Resources/layout/activity_main.xml
    	index f949852..c74521c 100644
    	--- a/Resources/layout/activity_main.xml
    	+++ b/Resources/layout/activity_main.xml
    	@@ -8,6 +8,7 @@
    	         android:layout_width="wrap_content"
    	         android:layout_height="wrap_content"
    	         android:layout_centerInParent="true"
    	+        android:id="@+id/text"
    	         android:text="@string/app_text"
    	     />
    	 </RelativeLayout>
    	diff --git a/com.example.codebehind.csproj b/com.example.codebehind.csproj
    	index 3fdbcb5..8190f84 100644
    	--- a/com.example.codebehind.csproj
    	+++ b/com.example.codebehind.csproj
    	@@ -8,5 +8,6 @@
    	     <ApplicationId>com.companyname.com.example.codebehind</ApplicationId>
    	     <ApplicationVersion>1</ApplicationVersion>
    	     <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
    	+    <AndroidGenerateLayoutBindings>true</AndroidGenerateLayoutBindings>
    	   </PropertyGroup>
    	 </Project>
    
    The resulting output contains
    `$(IntermediateOutputPath)codebehind\Binding.activity_main.g.cs`,
    which declares a type based on the `.axml` file name, and a mirror of
    the structure:
    
    	namespace Binding {
    	    // typename based on `activity_main.xml` filename
    	    sealed partial class activity_main : global::Xamarin.Android.Design.LayoutBinding {
    	        [global::Android.Runtime.PreserveAttribute (Conditional=true)]
    	        public activity_main (Activity client, …);
    	        // …
    
    	        // `text` is via `android:id="@+id/text"`
    	        public TextView text => …;
    	    }
    	}
    
    The problem is the use of `PreserveAttribute` in the generated code;
    it's been `[Obsolete]` since e6048334 (over two years ago), which
    means all projects using Layout Bindings and Layout Code-Behind always
    have [CS0618][1] warnings.
    
    Remove the emission of `PreserveAttribute`, so that CS0618 is no
    longer generated.
    
    Additionally, within the generated files disable the [CS1591][2] and
    [CS8981][3] warnings:
    
      * CS1591 is around missing XML documentation comments.  These code
        behind files do not have XML documentation comments, so if/when
        `$(DocumentationFile)` is set, these will be emitted for the
        generated code.  We do not currently plan on emitting XML
        documentation comments, so disable this warning.
    
      * CS8981 is emitted when a type name consists solely of lowercase
        characters.  As the generated Binding types are based on the
        filename -- which is frequently all lowercase -- this warning
        may be emitted.
    
    Finally, add `#nullable enable` to `LayoutBinding.cs` and fix the
    nullable reference type warnings.
    
    [0]: https://github.com/xamarin/xamarin-android/blob/2f4e01ec15102dd9cd922cbd833f6482d69512b5/Documentation/guides/LayoutCodeBehind.md
    [1]: https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-messages/cs0618
    [2]: https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-messages/cs1591
    [3]: https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-messages/warning-waves#cs8981---the-type-name-only-contains-lower-cased-ascii-characters
    751eb965