diff --git a/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs b/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs index 457c91add45..3f18da73069 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs +++ b/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs @@ -1,27 +1,29 @@ -using System; +#nullable enable + +using System; using System.Diagnostics.CodeAnalysis; using Android.App; using Android.Views; namespace Xamarin.Android.Design { - public delegate Java.Lang.Object OnLayoutItemNotFoundHandler (int resourceId, Type expectedViewType); + public delegate Java.Lang.Object? OnLayoutItemNotFoundHandler (int resourceId, Type expectedViewType); abstract class LayoutBinding { const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; - Activity boundActivity; - View boundView; - OnLayoutItemNotFoundHandler onLayoutItemNotFound; + Activity? boundActivity; + View? boundView; + OnLayoutItemNotFoundHandler? onLayoutItemNotFound; - protected LayoutBinding (Activity activity, OnLayoutItemNotFoundHandler onLayoutItemNotFound = null) + protected LayoutBinding (Activity activity, OnLayoutItemNotFoundHandler? onLayoutItemNotFound = null) { boundActivity = activity ?? throw new ArgumentNullException (nameof (activity)); this.onLayoutItemNotFound = onLayoutItemNotFound; } - protected LayoutBinding (View view, OnLayoutItemNotFoundHandler onLayoutItemNotFound = null) + protected LayoutBinding (View view, OnLayoutItemNotFoundHandler? onLayoutItemNotFound = null) { boundView = view ?? throw new ArgumentNullException (nameof (view)); this.onLayoutItemNotFound = onLayoutItemNotFound; @@ -38,14 +40,14 @@ protected T FindView < if (cachedField != null) return cachedField; - T ret; + T? ret = null; if (boundActivity != null) ret = boundActivity.FindViewById (resourceId); - else + else if (boundView != null) ret = boundView.FindViewById (resourceId); if (ret == null && onLayoutItemNotFound != null) - ret = (T)onLayoutItemNotFound (resourceId, typeof (T)); + ret = (T?)onLayoutItemNotFound (resourceId, typeof (T)); if (ret == null) throw new global::System.InvalidOperationException ($"View not found (Resource ID: {resourceId})"); @@ -71,8 +73,8 @@ T __FindFragment< T > ( int resourceId, - Func finder, - ref T cachedField) + Func finder, + ref T? cachedField) where T: Java.Lang.Object { if (cachedField != null) @@ -80,7 +82,7 @@ T __FindFragment< var ret = finder (EnsureActivity ()); if (ret == null && onLayoutItemNotFound != null) - ret = (T)onLayoutItemNotFound (resourceId, typeof (T)); + ret = (T?)onLayoutItemNotFound (resourceId, typeof (T)); if (ret == null) throw new InvalidOperationException ($"Fragment not found (ID: {resourceId}; Type: {typeof (T)})"); @@ -89,29 +91,25 @@ T __FindFragment< return ret; } #if __ANDROID_11__ +#pragma warning disable CA1422 protected T FindFragment< [DynamicallyAccessedMembers (Constructors)] T > ( int resourceId, - global::Android.App.Fragment __ignoreMe, - ref T cachedField + global::Android.App.Fragment? __ignoreMe, + ref T? cachedField ) where T: global::Android.App.Fragment { - return __FindFragment (resourceId, (activity) => activity.FragmentManager.FindFragmentById (resourceId), ref cachedField); + return __FindFragment (resourceId, (activity) => activity.FragmentManager?.FindFragmentById (resourceId), ref cachedField); } +#pragma warning restore CA1422 #endif // __ANDROID_11__ -#if __HAVE_SUPPORT__ - protected T FindFragment (int resourceId, global::Android.Support.V4.App.Fragment __ignoreMe, ref T cachedField) where T: global::Android.Support.V4.App.Fragment - { - return __FindFragment (resourceId, (activity) => activity.FragmentManager.FindFragmentById (resourceId), ref cachedField); - } -#endif // __HAVE_SUPPORT__ - #if __HAVE_ANDROIDX__ - protected T FindFragment (int resourceId, global::AndroidX.Fragment.App.Fragment __ignoreMe, ref T cachedField) where T: global::AndroidX.Fragment.App.Fragment + protected T FindFragment (int resourceId, global::AndroidX.Fragment.App.Fragment? __ignoreMe, ref T? cachedField) + where T : global::AndroidX.Fragment.App.Fragment { return __FindFragment(resourceId, (activity) => { if (activity is AndroidX.Fragment.App.FragmentActivity activity_) { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.BindingGenerator.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.BindingGenerator.cs index b404d91156e..a31cecb1c08 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.BindingGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.BindingGenerator.cs @@ -30,8 +30,6 @@ public sealed class State // generating code for the partial Activity class public string BindingClassName { get; } - public bool LinkerPreserveConstructors { get; set; } - public List ExtraImportNamespaces { get; } = new List (); public string AndroidFragmentType { get; } @@ -155,20 +153,18 @@ protected virtual void WriteOnSetContentViewPartials (State state) WritePartialClassOnSetContentViewPartial_Int (state); } - public State BeginBindingFile (StreamWriter writer, string layoutResourceId, string classNamespace, string className, string androidFragmentType, bool linkerPreserveConstructors = true) + public State BeginBindingFile (StreamWriter writer, string layoutResourceId, string classNamespace, string className, string androidFragmentType) { - var state = new State (writer, className, !String.IsNullOrWhiteSpace (classNamespace), androidFragmentType) { - LinkerPreserveConstructors = linkerPreserveConstructors - }; + var state = new State (writer, className, !String.IsNullOrWhiteSpace (classNamespace), androidFragmentType); BeginBindingFile (state, layoutResourceId, classNamespace, className); - WriteBindingConstructors (state, className, state.LinkerPreserveConstructors); + WriteBindingConstructors (state, className); return state; } protected abstract void BeginBindingFile (State state, string layoutResourceId, string classNamespace, string className); public abstract void EndBindingFile (State state); - protected abstract void WriteBindingConstructors (State state, string className, bool linkerPreserve); + protected abstract void WriteBindingConstructors (State state, string className); protected abstract void WriteBindingViewProperty (State state, LayoutWidget widget, string resourceNamespace); protected abstract void WriteBindingFragmentProperty (State state, LayoutWidget widget, string resourceNamespace); protected abstract void WriteBindingMixedProperty (State state, LayoutWidget widget, string resourceNamespace); @@ -287,10 +283,11 @@ protected void WriteBindingPropertyBackingField (State state, LayoutWidget widge WriteResetLocation (state); } - public void WriteComment (State state, string text) + public void WriteComment (State state, params string [] text) { EnsureArgument (state, nameof (state)); - WriteLineIndent (state, $"{LineCommentString}{text}"); + foreach (string line in text) + WriteLineIndent (state, $"{LineCommentString}{line}"); } public void WriteComment (State state, ICollection lines) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.CSharpBindingGenerator.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.CSharpBindingGenerator.cs index bc2b9ff6db4..92372d223e7 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.CSharpBindingGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.CSharpBindingGenerator.cs @@ -157,8 +157,33 @@ void WriteClassClose (State state) WriteLineIndent (state, "}"); } + void WriteDisableWarnings (State state) + { + state.WriteLine ("#pragma warning disable CS8981"); + state.WriteLine ("#pragma warning disable CS1591"); + } + + void WriteEnableWarnings (State state) + { + state.WriteLine ("#pragma warning restore CS1591"); + state.WriteLine ("#pragma warning restore CS8981"); + } + + void WriteAutoGeneratedComment (State state) + { + state.WriteLine (@"//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------"); + } + void WriteFilePreamble (State state, string classNamespace) { + WriteAutoGeneratedComment (state); WriteUsings (state); state.WriteLine (); WriteNamespaceOpen (state, classNamespace); @@ -172,6 +197,7 @@ void WriteNamespaceOpen (State state, string classNamespace) state.WriteLine ($"namespace {classNamespace}"); state.WriteLine ("{"); state.IncreaseIndent (); + WriteDisableWarnings (state); } void WriteNamespaceClose (State state) @@ -179,6 +205,7 @@ void WriteNamespaceClose (State state) if (!state.IsInNamespace) return; + WriteEnableWarnings (state); state.DecreaseIndent (); state.WriteLine ("}"); } @@ -200,15 +227,14 @@ void WriteUsing (State state, string ns) state.WriteLine ($"using global::{ns};"); } - protected override void WriteBindingConstructors (State state, string className, bool linkerPreserve) + protected override void WriteBindingConstructors (State state, string className) { - WriteConstructor (state, className, "Android.App.Activity", linkerPreserve); - WriteConstructor (state, className, "Android.Views.View", linkerPreserve); + WriteConstructor (state, className, "Android.App.Activity"); + WriteConstructor (state, className, "Android.Views.View"); } - void WriteConstructor (State state, string className, string clientType, bool linkerPreserve) + void WriteConstructor (State state, string className, string clientType) { - WritePreserveAtribute (state, linkerPreserve); WriteLineIndent (state, $"public {className} ("); state.IncreaseIndent (); WriteLineIndent (state, $"global::{clientType} client,"); @@ -221,14 +247,6 @@ void WriteConstructor (State state, string className, string clientType, bool li state.WriteLine (); } - void WritePreserveAtribute (State state, bool linkerPreserve) - { - if (!linkerPreserve) - return; - - WriteLineIndent (state, $"[global::Android.Runtime.PreserveAttribute (Conditional=true)]"); - } - public override void EndBindingFile (State state) { EnsureArgument (state, nameof (state)); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs index b6d89a6aaf6..22f9d4cf338 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs @@ -24,6 +24,10 @@ public class GenerateResourceDesignerIntermediateClass : AndroidTask namespace %NAMESPACE% { #pragma warning disable IDE0002 + /// + /// Android Resource Designer class. + /// Exposes the Android Resource designer assembly into the project Namespace. + /// public partial class Resource : %BASECLASS% { } #pragma warning restore IDE0002 diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/CodeBehindTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/CodeBehindTests.cs index b79a61409d8..59a6d1742ed 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/CodeBehindTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/CodeBehindTests.cs @@ -339,6 +339,7 @@ void SuccessfulBuild_AndroidX (TestProjectInfo testInfo, bool many, bool dtb, Lo CopyLogs (testInfo, true); Assert.That (success, Is.True, "Build should have succeeded"); + Assert.IsTrue (StringAssertEx.ContainsText (builder.LastBuildOutput, " 0 Warning(s)"), $"{builder.BuildLogFile} should have no MSBuild warnings."); CopyGeneratedFiles (testInfo); @@ -508,7 +509,8 @@ string GetBuildTarget (bool isDTB) string[] GetBuildProperties (LocalBuilder builder, bool manyBuild, bool dtbBuild, bool referenceAndroidX, params string[] extraConstants) { var ret = new List { - "AndroidGenerateLayoutBindings=true" + "AndroidGenerateLayoutBindings=true", + "\"NoWarn=CS0414;CA1416;CS1591;XA1005;XA4225\"" }; if (manyBuild) ret.Add ("ForceParallelBuild=true"); diff --git a/tests/CodeBehind/BuildTests/CodeBehindBuildTests.NET.csproj b/tests/CodeBehind/BuildTests/CodeBehindBuildTests.NET.csproj index 841b92a40eb..2175ae82a5d 100644 --- a/tests/CodeBehind/BuildTests/CodeBehindBuildTests.NET.csproj +++ b/tests/CodeBehind/BuildTests/CodeBehindBuildTests.NET.csproj @@ -64,6 +64,6 @@ - + diff --git a/tests/CodeBehind/BuildTests/MainMergeActivity.cs b/tests/CodeBehind/BuildTests/MainMergeActivity.cs index ec57f9540c8..d5b8600ed75 100644 --- a/tests/CodeBehind/BuildTests/MainMergeActivity.cs +++ b/tests/CodeBehind/BuildTests/MainMergeActivity.cs @@ -24,6 +24,8 @@ protected override void OnCreate (Bundle savedInstanceState) #if NOT_CONFLICTING_FRAGMENT CommonSampleLibrary.LogFragment log2 = secondary_log_fragment; +#elif __HAVE_ANDROIDX__ + global::AndroidX.Fragment.App.Fragment log2 = secondary_log_fragment; #else global::Android.App.Fragment log2 = secondary_log_fragment; #endif diff --git a/tests/CodeBehind/BuildTests/Properties/AndroidManifest.xml b/tests/CodeBehind/BuildTests/Properties/AndroidManifest.xml index a0230c27bfe..72a51695329 100644 --- a/tests/CodeBehind/BuildTests/Properties/AndroidManifest.xml +++ b/tests/CodeBehind/BuildTests/Properties/AndroidManifest.xml @@ -1,6 +1,5 @@  - diff --git a/tests/CodeBehind/CommonSampleLibrary/CommonSampleLibrary.NET.csproj b/tests/CodeBehind/CommonSampleLibrary/CommonSampleLibrary.NET.csproj index 6b1daa622d0..3765f0d1a57 100644 --- a/tests/CodeBehind/CommonSampleLibrary/CommonSampleLibrary.NET.csproj +++ b/tests/CodeBehind/CommonSampleLibrary/CommonSampleLibrary.NET.csproj @@ -5,4 +5,10 @@ CommonSampleLibrary false + + $(DefineConstants);$(ExtraConstants) + + + + diff --git a/tests/CodeBehind/CommonSampleLibrary/Logger/LogFragment.cs b/tests/CodeBehind/CommonSampleLibrary/Logger/LogFragment.cs index eec0fe59ae9..b6b29ff06fb 100644 --- a/tests/CodeBehind/CommonSampleLibrary/Logger/LogFragment.cs +++ b/tests/CodeBehind/CommonSampleLibrary/Logger/LogFragment.cs @@ -19,14 +19,21 @@ using Android.Views; using Android.Widget; using Android.Graphics; +using Android.Util; namespace CommonSampleLibrary { + #pragma warning disable CA1422 /** * Simple fraggment which contains a LogView and uses is to output log data it receives * through the LogNode interface. */ - public class LogFragment : Fragment + public class LogFragment : +#if __HAVE_ANDROIDX__ + AndroidX.Fragment.App.Fragment +#else + Fragment +#endif { LogView mLogView; ScrollView mScrollView; @@ -60,7 +67,7 @@ public View InflateViews () mLogView.Gravity = GravityFlags.Bottom; mLogView.SetTextAppearance (Activity, Android.Resource.Style.TextAppearanceMedium); - + mScrollView.AddView (mLogView); return mScrollView; } @@ -77,5 +84,6 @@ public LogView LogView { get { return mLogView; } } } + #pragma warning restore CA1422 }