Skip to content

Commit fdd34a1

Browse files
[One .NET] support latest C# 10 language features
Fixes: #6075 Fixes: #6076 Context: dotnet/macios#12173 We need to make two sets of changes for C# 10: 1. Support "global usings". Our .NET 6 templates should have no `using` statements at the top of `.cs` files. 2. Use `$(Nullable)` `enable` by default in project templates. To test this, our .NET 6 MSBuild tests use `Nullable=enable` by default and do no include `using` statements. I've made a new `MainActivity.cs` for our .NET 6 MSBuild tests. The "legacy" Xamarin.Android tests will use the original file. Our default `global using` are: global using global::Android.App; global using global::Android.Widget; global using Bundle = global::Android.OS.Bundle; The last one is intentionally not bringing in `Android.OS`, because `Android.OS.Environment` would conflict with `System.Environment`. I also had to write our own target to generate the using for `Bundle`, because the dotnet/sdk always prepends `global::`: https://github.com/dotnet/sdk/blob/86946f52cd012cefd811b25287a8da034bf082a3/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.GenerateImplicitNamespaceImports.targets#L46
1 parent babd603 commit fdd34a1

File tree

16 files changed

+96
-83
lines changed

16 files changed

+96
-83
lines changed

src/Microsoft.Android.Templates/android-activity/Activity1.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
using Android.App;
2-
using Android.OS;
3-
using Android.Runtime;
4-
using Android.Widget;
5-
61
namespace AndroidApp1
72
{
83
[Activity(Label = "@string/app_name", MainLauncher = true)]
94
public class Activity1 : Activity
105
{
11-
protected override void OnCreate(Bundle savedInstanceState)
6+
protected override void OnCreate(Bundle? savedInstanceState)
127
{
138
base.OnCreate(savedInstanceState);
149

src/Microsoft.Android.Templates/android-bindinglib/AndroidBinding1.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
<TargetFramework>net6.0-android</TargetFramework>
44
<SupportedOSPlatformVersion>SUPPORTED_OS_PLATFORM_VERSION</SupportedOSPlatformVersion>
55
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">AndroidBinding1</RootNamespace>
6+
<Nullable>enable</Nullable>
67
</PropertyGroup>
78
</Project>

src/Microsoft.Android.Templates/android/AndroidApp1.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
<SupportedOSPlatformVersion>SUPPORTED_OS_PLATFORM_VERSION</SupportedOSPlatformVersion>
55
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">AndroidApp1</RootNamespace>
66
<OutputType>Exe</OutputType>
7+
<Nullable>enable</Nullable>
78
</PropertyGroup>
89
</Project>

src/Microsoft.Android.Templates/android/MainActivity.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
using Android.App;
2-
using Android.OS;
3-
using Android.Runtime;
4-
using Android.Widget;
5-
61
namespace AndroidApp1
72
{
83
[Activity(Label = "@string/app_name", MainLauncher = true)]
94
public class MainActivity : Activity
105
{
11-
protected override void OnCreate(Bundle savedInstanceState)
6+
protected override void OnCreate(Bundle? savedInstanceState)
127
{
138
base.OnCreate(savedInstanceState);
149

src/Microsoft.Android.Templates/androidlib/AndroidLib1.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
<TargetFramework>net6.0-android</TargetFramework>
44
<SupportedOSPlatformVersion>SUPPORTED_OS_PLATFORM_VERSION</SupportedOSPlatformVersion>
55
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">AndroidLib1</RootNamespace>
6+
<Nullable>enable</Nullable>
67
</PropertyGroup>
78
</Project>

src/Microsoft.Android.Templates/androidlib/Class1.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using System;
2-
31
namespace AndroidLib1
42
{
53
public class Class1

src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,7 @@
106106
<FileVersion Condition=" '$(FileVersion)' == '' ">$(ApplicationVersion)</FileVersion>
107107
</PropertyGroup>
108108

109+
<!-- Import this as part of DefaultProperties.target to support Xamarin.Legacy.Sdk -->
110+
<Import Project="Microsoft.Android.Sdk.ImplicitNamespaceImports.targets" />
111+
109112
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<!--
2+
***********************************************************************************************
3+
Microsoft.Android.Sdk.ImplicitNamespaceImports.targets
4+
5+
This file contains @(Import) items for C# 10 global usings.
6+
7+
***********************************************************************************************
8+
-->
9+
<Project>
10+
<!--
11+
There's a master switch, $(DisableImplicitNamespaceImports),
12+
which, if set, will prevent all implicit namespace imports.
13+
This is done automatically, we don't have to check
14+
$(DisableImplicitNamespaceImports) here.
15+
-->
16+
<ItemGroup Condition=" '$(DisableImplicitNamespaceImports_Android)' != 'true' ">
17+
<Import Include="Android.App" />
18+
<Import Include="Android.Widget" />
19+
</ItemGroup>
20+
21+
<!--
22+
NOTE: Bundle is specifically imported by itself, so
23+
Android.OS.Environment doesn't conflict with System.Environment.
24+
We have to write our own .cs file to do this, because dotnet/sdk
25+
always prefixes with `global::`, see:
26+
https://github.com/dotnet/sdk/blob/86946f52cd012cefd811b25287a8da034bf082a3/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.GenerateImplicitNamespaceImports.targets#L46
27+
-->
28+
<Target Name="_AndroidGenerateImplicitNamespaceImports"
29+
Condition=" '$(DisableImplicitNamespaceImports_Android)' != 'true' "
30+
AfterTargets="CoreGenerateImplicitNamespaceImports">
31+
<PropertyGroup>
32+
<_AndroidGeneratedImplicitNamespaceImportFile>$(IntermediateOutputPath)$(MSBuildProjectName).AndroidImplicitNamespaceImports$(DefaultLanguageSourceExtension)</_AndroidGeneratedImplicitNamespaceImportFile>
33+
</PropertyGroup>
34+
<ItemGroup>
35+
<_AndroidImportFileLine Include="// %3Cautogenerated />"/>
36+
<_AndroidImportFileLine Include="global using Bundle = global::Android.OS.Bundle%3B"/>
37+
</ItemGroup>
38+
<WriteLinesToFile
39+
Lines="@(_AndroidImportFileLine)"
40+
File="$(_AndroidGeneratedImplicitNamespaceImportFile)"
41+
Overwrite="true"
42+
WriteOnlyWhenDifferent="true"
43+
/>
44+
<ItemGroup>
45+
<Compile Include="$(_AndroidGeneratedImplicitNamespaceImportFile)" />
46+
<FileWrites Include="$(_AndroidGeneratedImplicitNamespaceImportFile)" />
47+
</ItemGroup>
48+
</Target>
49+
50+
</Project>

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ public void DotNetNew ([Values ("android", "androidlib", "android-bindinglib")]
204204
Assert.IsTrue (dotnet.New ("android-activity"), "`dotnet new android-activity` should succeed");
205205
Assert.IsTrue (dotnet.New ("android-layout", Path.Combine (dotnet.ProjectDirectory, "Resources", "layout")), "`dotnet new android-layout` should succeed");
206206
Assert.IsTrue (dotnet.Build (), "`dotnet build` should succeed");
207+
dotnet.AssertHasNoWarnings ();
207208
}
208209

209210
[Test]

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public static class KnownProperties
3636
public const string AndroidFastDeploymentType = "AndroidFastDeploymentType";
3737
public const string AndroidClassParser = "AndroidClassParser";
3838
public const string _AndroidAllowDeltaInstall = "_AndroidAllowDeltaInstall";
39+
public const string Nullable = "Nullable";
3940
}
4041
}
4142

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XASdkProject.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static XASdkProject ()
2828
var assembly = typeof (XASdkProject).Assembly;
2929
using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.AndroidManifest.xml")))
3030
default_android_manifest = sr.ReadToEnd ();
31-
using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.MainActivity.cs")))
31+
using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.DotNet.MainActivity.cs")))
3232
default_main_activity_cs = sr.ReadToEnd ();
3333
using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.LayoutMain.axml")))
3434
default_layout_main = sr.ReadToEnd ();
@@ -61,6 +61,7 @@ public XASdkProject (string outputType = "Exe", [CallerMemberName] string packag
6161
JavaPackageName = JavaPackageName ?? PackageName.ToLowerInvariant ();
6262
GlobalPackagesFolder = FileSystemUtils.FindNugetGlobalPackageFolder ();
6363
SetProperty (KnownProperties.OutputType, outputType);
64+
SetProperty (KnownProperties.Nullable, "enable");
6465

6566
// Add relevant Android content to our project without writing it to the .csproj file
6667
if (outputType == "Exe") {

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public class XamarinAndroidApplicationProject : XamarinAndroidCommonProject
2424

2525
static XamarinAndroidApplicationProject ()
2626
{
27-
using (var sr = new StreamReader (typeof(XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.MainActivity.cs")))
27+
var folder = Builder.UseDotNet ? "DotNet" : "Base";
28+
using (var sr = new StreamReader (typeof(XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream ($"Xamarin.ProjectTools.Resources.{folder}.MainActivity.cs")))
2829
default_main_activity_cs = sr.ReadToEnd ();
2930
using (var sr = new StreamReader (typeof(XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.MainActivity.fs")))
3031
default_main_activity_fs = sr.ReadToEnd ();
@@ -40,6 +41,7 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
4041
{
4142
if (Builder.UseDotNet) {
4243
SetProperty (KnownProperties.OutputType, "Exe");
44+
SetProperty (KnownProperties.Nullable, "enable");
4345
SetProperty ("XamarinAndroidSupportSkipVerifyVersions", "True");
4446
SetProperty ("_FastDeploymentDiagnosticLogging", "True");
4547

@@ -81,7 +83,7 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
8183
}
8284

8385
// it is exposed as public because we may want to slightly modify this.
84-
public string DefaultMainActivity {
86+
public virtual string DefaultMainActivity {
8587
get { return Language == XamarinAndroidProjectLanguage.FSharp ? default_main_activity_fs : default_main_activity_cs; }
8688
}
8789

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidLibraryProject.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public XamarinAndroidLibraryProject (string debugConfigurationName = "Debug", st
1515
: base (debugConfigurationName, releaseConfigurationName)
1616
{
1717
if (!Builder.UseDotNet) {
18+
SetProperty (KnownProperties.Nullable, "enable");
1819
SetProperty ("AndroidApplication", "False");
1920
SetProperty ("AndroidResgenFile", Path.Combine ("Resources", "Resource.designer.cs"));
2021
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinFormsAndroidApplicationProject.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public XamarinFormsAndroidApplicationProject (string debugConfigurationName = "D
4242
: base (debugConfigurationName, releaseConfigurationName, packageName)
4343
{
4444
if (Builder.UseDotNet) {
45+
// NOTE: `Xamarin.Forms` namespace will collide with `Android.App` otherwise:
46+
SetProperty ("DisableImplicitNamespaceImports_Android", "true");
4547
PackageReferences.Add (KnownPackages.XamarinForms_4_7_0_1142);
4648
} else {
4749
PackageReferences.Add (KnownPackages.XamarinForms_4_0_0_425677);
@@ -76,6 +78,8 @@ public XamarinFormsAndroidApplicationProject (string debugConfigurationName = "D
7678
MainPage = MainPage_xaml_cs;
7779
}
7880

81+
public override string DefaultMainActivity => default_main_activity_cs;
82+
7983
public string MainPage { get; set; }
8084

8185
protected virtual string MainPageXaml () => ProcessSourceTemplate (MainPage_xaml);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace ${ROOT_NAMESPACE}
2+
{
3+
[Android.Runtime.Register ("${JAVA_PACKAGENAME}.MainActivity"), Activity (Label = "${PROJECT_NAME}", MainLauncher = true, Icon = "@drawable/icon")]
4+
public class MainActivity : Activity
5+
{
6+
int count = 1;
7+
8+
protected override void OnCreate (Bundle? bundle)
9+
{
10+
base.OnCreate (bundle);
11+
12+
// Set our view from the "main" layout resource
13+
SetContentView (Resource.Layout.Main);
14+
15+
var button = FindViewById<Button> (Resource.Id.myButton);
16+
button!.Click += delegate {
17+
button.Text = string.Format ("{0} clicks!", count++);
18+
};
19+
20+
//${AFTER_ONCREATE}
21+
}
22+
}
23+
//${AFTER_MAINACTIVITY}
24+
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9,72 +9,7 @@
99
<Import Project="..\..\..\..\external\xamarin-android-tools\src\Microsoft.Android.Build.BaseTasks\MSBuildReferences.projitems" />
1010
<ItemGroup>
1111
<Compile Remove="Resources\**\*.cs" />
12-
<EmbeddedResource Include="Resources\AndroidX\Tabbar.xml">
13-
<LogicalName>Xamarin.ProjectTools.Resources.AndroidX.Tabbar.xml</LogicalName>
14-
</EmbeddedResource>
15-
<EmbeddedResource Include="Resources\AndroidX\Toolbar.xml">
16-
<LogicalName>Xamarin.ProjectTools.Resources.AndroidX.Toolbar.xml</LogicalName>
17-
</EmbeddedResource>
18-
<EmbeddedResource Include="Resources\Wear\LayoutMain.axml">
19-
<LogicalName>Xamarin.ProjectTools.Resources.Wear.LayoutMain.axml</LogicalName>
20-
</EmbeddedResource>
21-
<EmbeddedResource Include="Resources\Wear\LayoutRectMain.axml">
22-
<LogicalName>Xamarin.ProjectTools.Resources.Wear.LayoutRectMain.axml</LogicalName>
23-
</EmbeddedResource>
24-
<EmbeddedResource Include="Resources\Wear\LayoutRoundMain.axml">
25-
<LogicalName>Xamarin.ProjectTools.Resources.Wear.LayoutRoundMain.axml</LogicalName>
26-
</EmbeddedResource>
27-
<EmbeddedResource Include="Resources\Wear\MainActivity.cs">
28-
<LogicalName>Xamarin.ProjectTools.Resources.Wear.MainActivity.cs</LogicalName>
29-
</EmbeddedResource>
30-
<EmbeddedResource Include="Resources\Wear\Strings.xml">
31-
<LogicalName>Xamarin.ProjectTools.Resources.Wear.Strings.xml</LogicalName>
32-
</EmbeddedResource>
33-
<EmbeddedResource Include="Resources\Base\AndroidManifest.xml">
34-
<LogicalName>Xamarin.ProjectTools.Resources.Base.AndroidManifest.xml</LogicalName>
35-
</EmbeddedResource>
36-
<EmbeddedResource Include="Resources\Base\Icon.png">
37-
<LogicalName>Xamarin.ProjectTools.Resources.Base.Icon.png</LogicalName>
38-
</EmbeddedResource>
39-
<EmbeddedResource Include="Resources\Base\LayoutMain.axml">
40-
<LogicalName>Xamarin.ProjectTools.Resources.Base.LayoutMain.axml</LogicalName>
41-
</EmbeddedResource>
42-
<EmbeddedResource Include="Resources\Base\MainActivity.cs">
43-
<LogicalName>Xamarin.ProjectTools.Resources.Base.MainActivity.cs</LogicalName>
44-
</EmbeddedResource>
45-
<EmbeddedResource Include="Resources\Base\MainActivity.fs">
46-
<LogicalName>Xamarin.ProjectTools.Resources.Base.MainActivity.fs</LogicalName>
47-
</EmbeddedResource>
48-
<EmbeddedResource Include="Resources\Base\AssemblyInfo.fs">
49-
<LogicalName>Xamarin.ProjectTools.Resources.Base.AssemblyInfo.fs</LogicalName>
50-
</EmbeddedResource>
51-
<EmbeddedResource Include="Resources\Base\Image.9.png">
52-
<LogicalName>Xamarin.ProjectTools.Resources.Base.Image.9.png</LogicalName>
53-
</EmbeddedResource>
54-
<EmbeddedResource Include="Resources\Base\Image2.9.png">
55-
<LogicalName>Xamarin.ProjectTools.Resources.Base.Image2.9.png</LogicalName>
56-
</EmbeddedResource>
57-
<EmbeddedResource Include="Resources\Base\test.keystore">
58-
<LogicalName>Xamarin.ProjectTools.Resources.Base.test.keystore</LogicalName>
59-
</EmbeddedResource>
60-
<EmbeddedResource Include="Resources\Base\classes.jar">
61-
<LogicalName>Xamarin.ProjectTools.Resources.Base.classes.jar</LogicalName>
62-
</EmbeddedResource>
63-
<EmbeddedResource Include="Resources\Base\custom.aotprofile" />
64-
<EmbeddedResource Include="Resources\Base\BuildReleaseArm64SimpleDotNet.apkdesc" />
65-
<EmbeddedResource Include="Resources\Base\BuildReleaseArm64SimpleLegacy.apkdesc" />
66-
<EmbeddedResource Include="Resources\Base\BuildReleaseArm64XFormsDotNet.apkdesc" />
67-
<EmbeddedResource Include="Resources\Base\BuildReleaseArm64XFormsLegacy.apkdesc" />
68-
<EmbeddedResource Include="Resources\Forms\MainActivity.cs" />
69-
<EmbeddedResource Include="Resources\Forms\App.xaml" />
70-
<EmbeddedResource Include="Resources\Forms\App.xaml.cs" />
71-
<EmbeddedResource Include="Resources\Forms\MainPage.xaml" />
72-
<EmbeddedResource Include="Resources\Forms\MainPage.xaml.cs" />
73-
<EmbeddedResource Include="Resources\Forms\MainPageMaps.xaml" />
74-
<EmbeddedResource Include="Resources\Forms\Tabbar.axml" />
75-
<EmbeddedResource Include="Resources\Forms\Toolbar.axml" />
76-
<EmbeddedResource Include="Resources\Forms\colors.xml" />
77-
<EmbeddedResource Include="Resources\Forms\styles.xml" />
12+
<EmbeddedResource Include="Resources\**\*" />
7813
</ItemGroup>
7914
<ItemGroup>
8015
<Content Include="..\..\..\..\.nuget\NuGet.exe">

0 commit comments

Comments
 (0)