Browse Source

Update to .NET 10 (#19869)

* Update to .NET 10 and C# 14

* Remove reflection usage in AvaloniaAccessHelper

* Fix Android nullability errors

* Fix WindowMetrics.WindowInsets removed from AndroidX

* Update pipelines

* Fix ValidateApiDiff for missing frameworks

* Fix Windows integration tests

* Update Xamarin.AndroidX.Window to 1.5.0

* Fix MacCatalyst supported version

* Remove unused Xunit.Extensions.Ordering

* Try to fix macOS integration tests

* Update pipeline runner to macOS 15

* Disable LeakTests

* Fix .NET Framework unit tests

* Fix BuildTests

* Bump minimum Android API level to 24

* Update to .NET 10 RTM

* Update XamlX

* update android insets and activity code to handle deprecated behaviors in api 36

---------

Co-authored-by: Emmanuel Hansen <emmausssss@gmail.com>
pull/19927/merge
Julien Lebosquain 4 weeks ago
committed by GitHub
parent
commit
fb0f3848f9
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      Directory.Build.props
  2. 4
      api/Avalonia.nupkg.xml
  3. 17
      azure-pipelines-integrationtests.yml
  4. 34
      azure-pipelines.yml
  5. 12
      build/Base.props
  6. 2
      build/Moq.props
  7. 16
      build/TargetFrameworks.props
  8. 5
      build/UnitTests.NetCore.targets
  9. 2
      build/XUnit.props
  10. 2
      external/XamlX
  11. 2
      global.json
  12. 20
      nukebuild/ApiDiffHelper.cs
  13. 10
      nukebuild/Build.cs
  14. 4
      nukebuild/_build.csproj
  15. 2
      packages/Avalonia/AvaloniaPrivateApis.targets
  16. 2
      packages/Avalonia/AvaloniaSingleProject.targets
  17. 2
      samples/ControlCatalog.Android/ControlCatalog.Android.csproj
  18. 4
      samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj
  19. 2
      samples/ControlCatalog.MacCatalyst/ControlCatalog.MacCatalyst.csproj
  20. 2
      samples/Directory.Build.props
  21. 2
      samples/IntegrationTestApp/bundle.sh
  22. 28
      samples/XEmbedSample/XEmbedSample.csproj
  23. 33
      src/Android/Avalonia.Android/Automation/ToggleNodeInfoProvider.cs
  24. 4
      src/Android/Avalonia.Android/Avalonia.Android.csproj
  25. 47
      src/Android/Avalonia.Android/AvaloniaAccessHelper.cs
  26. 25
      src/Android/Avalonia.Android/AvaloniaActivity.cs
  27. 43
      src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
  28. 17
      src/Android/Avalonia.Android/Platform/AndroidScreens.cs
  29. 3
      src/Avalonia.Base/Data/Core/BindingExpression.cs
  30. 3
      src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs
  31. 3
      src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ExpressionTreeIndexerNode.cs
  32. 3
      src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs
  33. 1
      src/Avalonia.Base/Data/Core/Plugins/BindingPlugins.cs
  34. 6
      src/Avalonia.Base/Data/Core/Plugins/ReflectionMethodAccessorPlugin.cs
  35. 4
      src/Avalonia.Base/Diagnostics/TrimmingMessages.cs
  36. 2
      src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionParser.cs
  37. 6
      src/Avalonia.Base/Utilities/Polyfills.cs
  38. 1
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  39. 4
      src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs
  40. 4
      src/Avalonia.Native/Metal.cs
  41. 1
      src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
  42. 14
      src/Avalonia.Remote.Protocol/MetsysBson.cs
  43. 2
      src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
  44. 5
      src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
  45. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
  46. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlQueryTransformer.cs
  47. 3
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
  48. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  49. 8
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs
  50. 5
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlPropertyInfoAccessorFactoryEmitter.cs
  51. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/IncludeXamlIlSre.props
  52. 3
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs
  53. 1
      src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs
  54. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  55. 6
      src/Markup/Avalonia.Markup/Data/Binding.cs
  56. 3
      src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionNodeFactory.cs
  57. 1
      src/Windows/Avalonia.Win32.Interoperability/WinForms/WinFormsAvaloniaControlHost.cs
  58. 4
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  59. 2
      src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs
  60. 2
      src/iOS/Avalonia.iOS/IOSLauncher.cs
  61. 2
      src/iOS/Avalonia.iOS/iOSScreens.cs
  62. 1
      src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
  63. 28
      src/tools/DevGenerators/CompilerDynamicDependenciesGenerator.cs
  64. 8
      tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs
  65. 2
      tests/Avalonia.Headless.NUnit.PerTest.UnitTests/Avalonia.Headless.NUnit.PerTest.UnitTests.csproj
  66. 1
      tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj
  67. 2
      tests/Avalonia.IntegrationTests.Appium/DefaultAppFixture.cs
  68. 2
      tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj
  69. 2
      tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
  70. 2
      tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
  71. 4
      tests/BuildTests/BuildTests.Android/BuildTests.Android.csproj
  72. 2
      tests/BuildTests/BuildTests.Browser/BuildTests.Browser.csproj
  73. 2
      tests/BuildTests/BuildTests.Desktop/BuildTests.Desktop.csproj
  74. 2
      tests/BuildTests/BuildTests.FSharp/BuildTests.FSharp.fsproj
  75. 2
      tests/BuildTests/BuildTests.NativeAot/BuildTests.NativeAot.csproj
  76. 2
      tests/BuildTests/BuildTests.WpfHybrid/BuildTests.WpfHybrid.csproj
  77. 2
      tests/BuildTests/BuildTests.iOS/BuildTests.iOS.csproj
  78. 2
      tests/BuildTests/BuildTests/BuildTests.csproj

2
Directory.Build.props

@ -8,7 +8,7 @@
<!-- https://github.com/dotnet/msbuild/issues/2661 -->
<AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies>
<RunApiCompat>False</RunApiCompat>
<LangVersion>12</LangVersion>
<LangVersion>14.0</LangVersion>
<CreateHardLinksForCopyAdditionalFilesIfPossible>true</CreateHardLinksForCopyAdditionalFilesIfPossible>
<CreateHardLinksForCopyFilesToOutputDirectoryIfPossible>true</CreateHardLinksForCopyFilesToOutputDirectoryIfPossible>
<CreateHardLinksForCopyLocalIfPossible>true</CreateHardLinksForCopyLocalIfPossible>

4
api/Avalonia.nupkg.xml

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
@ -181,4 +181,4 @@
<Left>baseline/Avalonia/lib/netstandard2.0/Avalonia.OpenGL.dll</Left>
<Right>current/Avalonia/lib/netstandard2.0/Avalonia.OpenGL.dll</Right>
</Suppression>
</Suppressions>
</Suppressions>

17
azure-pipelines-integrationtests.yml

@ -5,13 +5,13 @@ jobs:
steps:
- task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime'
displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
version: 6.0.x
version: 8.0.x
- task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK'
displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@ -31,11 +31,10 @@ jobs:
pkill IntegrationTestApp
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
./build.sh CompileNative
sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
rm -rf $(osascript -e "POSIX path of (path to application id \"net.avaloniaui.avalonia.integrationtestapp\")")
pkill IntegrationTestApp
./samples/IntegrationTestApp/bundle.sh
open -n ./samples/IntegrationTestApp/bin/Debug/net8.0/osx-$arch/publish/IntegrationTestApp.app
open -n ./samples/IntegrationTestApp/bin/Debug/net10.0/osx-$arch/publish/IntegrationTestApp.app
pkill IntegrationTestApp
displayName: 'Build IntegrationTestApp'
@ -57,17 +56,17 @@ jobs:
- job: Windows
pool:
vmImage: 'windows-2022'
vmImage: 'windows-2025'
steps:
- task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime'
displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
version: 6.0.x
version: 8.0.x
- task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK'
displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true

34
azure-pipelines.yml

@ -2,12 +2,12 @@ jobs:
- job: GetPRNumber
pool:
vmImage: 'ubuntu-22.04'
vmImage: 'ubuntu-24.04'
variables:
SolutionDir: '$(Build.SourcesDirectory)'
steps:
- task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK'
displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@ -23,16 +23,16 @@ jobs:
- job: Linux
pool:
vmImage: 'ubuntu-22.04'
vmImage: 'ubuntu-24.04'
steps:
- task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime'
displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
version: 6.0.x
version: 8.0.x
- task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK'
displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@ -62,16 +62,16 @@ jobs:
variables:
SolutionDir: '$(Build.SourcesDirectory)'
pool:
vmImage: 'macos-13'
vmImage: 'macos-15'
steps:
- task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime'
displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
version: 6.0.x
version: 8.0.x
- task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK'
displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@ -95,11 +95,11 @@ jobs:
inputs:
actions: 'build'
scheme: ''
sdk: 'macosx14.2'
sdk: 'macosx26.0'
configuration: 'Release'
xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
xcodeVersion: 'specifyPath' # Options: 8, 9, default, specifyPath
xcodeDeveloperDir: '/Applications/Xcode_15.2.app/Contents/Developer'
xcodeDeveloperDir: '/Applications/Xcode_26.0.app/Contents/Developer'
args: '-derivedDataPath ./'
- task: CmdLine@2
@ -134,18 +134,18 @@ jobs:
- job: Windows
pool:
vmImage: 'windows-2022'
vmImage: 'windows-2025'
variables:
SolutionDir: '$(Build.SourcesDirectory)'
steps:
- task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime'
displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
version: 6.0.x
version: 8.0.x
- task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK'
displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@ -160,7 +160,7 @@ jobs:
displayName: 'Install Nuke'
inputs:
script: |
dotnet tool install --global Nuke.GlobalTool --version 6.2.1
dotnet tool install --global Nuke.GlobalTool --version 9.0.4
- task: CmdLine@2
displayName: 'Run Nuke'

12
build/Base.props

@ -1,12 +1,8 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- '!NET6_0_OR_GREATER' equivalent -->
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))">
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
</ItemGroup>
<!-- '!NET8_0_OR_GREATER' equivalent -->
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')))">
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" />
<PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.10" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="9.0.10" />
</ItemGroup>
</Project>

2
build/Moq.props

@ -1,5 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="Moq" Version="4.20.72" />
</ItemGroup>
</Project>

16
build/TargetFrameworks.props

@ -1,17 +1,17 @@
<Project>
<PropertyGroup>
<AvsCurrentTargetFramework>net8.0</AvsCurrentTargetFramework>
<AvsCurrentTargetFramework>net10.0</AvsCurrentTargetFramework>
<AvsCurrentWindowsTargetFramework>$(AvsCurrentTargetFramework)-windows</AvsCurrentWindowsTargetFramework>
<AvsCurrentMacOSTargetFramework>$(AvsCurrentTargetFramework)-macos</AvsCurrentMacOSTargetFramework>
<AvsCurrentAndroidTargetFramework>$(AvsCurrentTargetFramework)-android34.0</AvsCurrentAndroidTargetFramework>
<AvsCurrentMacCatalystTargetFramework>$(AvsCurrentTargetFramework)-maccatalyst17.0</AvsCurrentMacCatalystTargetFramework>
<AvsCurrentIOSTargetFramework>$(AvsCurrentTargetFramework)-ios17.0</AvsCurrentIOSTargetFramework>
<AvsCurrentTvOSTargetFramework>$(AvsCurrentTargetFramework)-tvos17.0</AvsCurrentTvOSTargetFramework>
<AvsCurrentAndroidTargetFramework>$(AvsCurrentTargetFramework)-android36.0</AvsCurrentAndroidTargetFramework>
<AvsCurrentMacCatalystTargetFramework>$(AvsCurrentTargetFramework)-maccatalyst26.0</AvsCurrentMacCatalystTargetFramework>
<AvsCurrentIOSTargetFramework>$(AvsCurrentTargetFramework)-ios26.0</AvsCurrentIOSTargetFramework>
<AvsCurrentTvOSTargetFramework>$(AvsCurrentTargetFramework)-tvos26.0</AvsCurrentTvOSTargetFramework>
<AvsCurrentBrowserTargetFramework>$(AvsCurrentTargetFramework)-browser</AvsCurrentBrowserTargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(AvsSkipBuildingLegacyTargetFrameworks)' != 'True'">
<AvsLegacyTargetFrameworks>net6.0</AvsLegacyTargetFrameworks>
<AvsLegacyWindowsTargetFrameworks>net6.0-windows</AvsLegacyWindowsTargetFrameworks>
<AvsLegacyTargetFrameworks>net8.0</AvsLegacyTargetFrameworks>
<AvsLegacyWindowsTargetFrameworks>net8.0-windows</AvsLegacyWindowsTargetFrameworks>
</PropertyGroup>
<PropertyGroup>
@ -20,7 +20,7 @@
<AvsMinSupportedIOSVersion>13.0</AvsMinSupportedIOSVersion>
<AvsMinSupportedTvOSVersion>13.0</AvsMinSupportedTvOSVersion>
<AvsMinSupportedMacCatalystVersion>13.1</AvsMinSupportedMacCatalystVersion>
<AvsMinSupportedAndroidVersion>21.0</AvsMinSupportedAndroidVersion>
<AvsMinSupportedAndroidVersion>24.0</AvsMinSupportedAndroidVersion>
<!-- Desktop OS min version is not set in any of ours backends, but only used in some samples. -->
<!-- Avalonia technically supports 10.12. -->
<AvsMinSupportedMacOsVersion>10.15</AvsMinSupportedMacOsVersion>

5
build/UnitTests.NetCore.targets

@ -3,7 +3,4 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
</ItemGroup>
</Project>
</Project>

2
build/XUnit.props

@ -8,7 +8,7 @@
<PackageReference Include="xunit.runner.console" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" Condition="'$(TargetFramework)' != 'netstandard2.0'" />
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
</ItemGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)\avalonia.snk</AssemblyOriginatorKeyFile>

2
external/XamlX

@ -1 +1 @@
Subproject commit 83567b8a50bbf612a0b1420a3dc6d8e8ebee2399
Subproject commit c32d3040e536ae9768233ea5a445697632578bd0

2
global.json

@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.411",
"version": "10.0.100",
"rollForward": "latestFeature"
},
"msbuild-sdks": {

20
nukebuild/ApiDiffHelper.cs

@ -326,25 +326,11 @@ public static class ApiDiffHelper
var frameworkDiffs = new List<FrameworkDiffInfo>();
// Handle frameworks that exist only in the current package.
foreach (var framework in currentFolderNames.Keys.Except(baselineFolderNames.Keys))
{
var folderName = currentFolderNames[framework];
Directory.CreateDirectory(baselineFolderPath / folderName);
baselineFolderNames.Add(framework, folderName);
}
// Handle frameworks that exist only for the baseline package.
foreach (var framework in baselineFolderNames.Keys.Except(currentFolderNames.Keys))
{
var folderName = baselineFolderNames[framework];
Directory.CreateDirectory(currentFolderPath / folderName);
currentFolderNames.Add(framework, folderName);
}
foreach (var (framework, currentFolderName) in currentFolderNames)
{
var baselineFolderName = baselineFolderNames[framework];
// Ignore new frameworks that didn't exist in the baseline package. Empty folders make the ApiDiff tool crash.
if (!baselineFolderNames.TryGetValue(framework, out var baselineFolderName))
continue;
frameworkDiffs.Add(new FrameworkDiffInfo(
framework,

10
nukebuild/Build.cs

@ -240,11 +240,11 @@ partial class Build : NukeBuild
var tfm = fw;
if (tfm == "$(AvsCurrentTargetFramework)")
{
tfm = "net8.0";
tfm = "net10.0";
}
if (tfm == "$(AvsLegacyTargetFrameworks)")
{
tfm = "net6.0";
tfm = "net8.0";
}
if (tfm.StartsWith("net4")
@ -416,13 +416,13 @@ partial class Build : NukeBuild
ApiDiffHelper.MergePackageMarkdownDiffFiles(outputFolderPath, baselineDisplay, currentDisplay);
});
Target RunTests => _ => _
.DependsOn(RunCoreLibsTests)
.DependsOn(RunRenderTests)
.DependsOn(RunToolsTests)
.DependsOn(RunHtmlPreviewerTests)
.DependsOn(RunLeakTests);
.DependsOn(RunHtmlPreviewerTests);
//.DependsOn(RunLeakTests); // dotMemory Unit doesn't support modern .NET versions, see https://youtrack.jetbrains.com/issue/DMU-300/
Target Package => _ => _
.DependsOn(RunTests)

4
nukebuild/_build.csproj

@ -21,8 +21,8 @@
<PackageReference Include="Mono.Cecil" Version="0.11.5" />
<PackageReference Include="Microsoft.Build.Framework" Version="17.14.8" PrivateAssets="All" />
<PackageReference Include="NuGet.Protocol" Version="6.14.0" />
<PackageDownload Include="Microsoft.DotNet.ApiCompat.Tool" Version="[10.0.100-preview.7.25380.108]" />
<PackageDownload Include="Microsoft.DotNet.ApiDiff.Tool" Version="[10.0.100-rc.1.25414.111]" />
<PackageDownload Include="Microsoft.DotNet.ApiCompat.Tool" Version="[10.0.100]" />
<PackageDownload Include="Microsoft.DotNet.ApiDiff.Tool" Version="[10.0.100-rtm.25531.102]" />
<PackageDownload Include="dotnet-ilrepack" Version="[1.0.0]" />
</ItemGroup>

2
packages/Avalonia/AvaloniaPrivateApis.targets

@ -13,7 +13,7 @@
</Target>
<Target Name="AddReferencePathsToRealAvaloniaAssemblies" BeforeTargets="CoreCompile" Condition="'$(AvaloniaAccessUnstablePrivateApis.ToLowerInvariant())'=='true'">
<PropertyGroup>
<AvaloniaUnstableApiFrameworkToUse>net6.0</AvaloniaUnstableApiFrameworkToUse>
<AvaloniaUnstableApiFrameworkToUse>net8.0</AvaloniaUnstableApiFrameworkToUse>
<AvaloniaUnstableApiFrameworkToUse Condition="$(TargetFramework.StartsWith('net4')) == 'true' or $(TargetFramework.StartsWith('net5')) == 'true' or $(TargetFramework.StartsWith('netsta')) == 'true' or $(TargetFramework.StartsWith('netcore')) == 'true'">netstandard2.0</AvaloniaUnstableApiFrameworkToUse>
</PropertyGroup>
<ItemGroup>

2
packages/Avalonia/AvaloniaSingleProject.targets

@ -98,7 +98,7 @@
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tvos'">13.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'macos'">10.15</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">24.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup>

2
samples/ControlCatalog.Android/ControlCatalog.Android.csproj

@ -26,7 +26,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.4" />
<PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.17" />
</ItemGroup>
<ItemGroup>

4
samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj

@ -9,8 +9,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.2" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>

2
samples/ControlCatalog.MacCatalyst/ControlCatalog.MacCatalyst.csproj

@ -5,7 +5,7 @@
<ProvisioningType>manual</ProvisioningType>
<TargetFramework>$(AvsCurrentMacCatalystTargetFramework)</TargetFramework>
<!-- Used to support Desktop Mode Idiom, min supported version is 13.1, which supports iPad scaling. -->
<SupportedOSPlatformVersion>14.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion>15.0</SupportedOSPlatformVersion>
<UseInterpreter>true</UseInterpreter>
</PropertyGroup>

2
samples/Directory.Build.props

@ -4,7 +4,7 @@
<IsPackable>false</IsPackable>
<AvaloniaPreviewerNetCoreToolPath>$(MSBuildThisFileDirectory)..\src\tools\Avalonia.Designer.HostApp\bin\Debug\netstandard2.0\Avalonia.Designer.HostApp.dll</AvaloniaPreviewerNetCoreToolPath>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<LangVersion>12</LangVersion>
<LangVersion>14.0</LangVersion>
<NoWarn>$(NoWarn);CS8002</NoWarn> <!-- ignore signing warnings for samples -->
</PropertyGroup>

2
samples/IntegrationTestApp/bundle.sh

@ -9,4 +9,4 @@ arch="arm64"
fi
dotnet restore -r osx-$arch
dotnet msbuild -t:BundleApp -p:RuntimeIdentifier=osx-$arch
dotnet msbuild -t:BundleApp -p:RuntimeIdentifier=osx-$arch -p:SelfContained=true

28
samples/XEmbedSample/XEmbedSample.csproj

@ -1,20 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(AvsCurrentTargetFramework)</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GtkSharp" Version="3.24.24.95" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="GtkSharp" Version="3.24.24.95"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" />
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj"/>
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj"/>
</ItemGroup>
</Project>

33
src/Android/Avalonia.Android/Automation/ToggleNodeInfoProvider.cs

@ -1,5 +1,4 @@
using System.Reflection;
using Android.OS;
using Android.OS;
using AndroidX.Core.View.Accessibility;
using AndroidX.CustomView.Widget;
using Avalonia.Automation.Peers;
@ -9,18 +8,11 @@ namespace Avalonia.Android.Automation
{
internal class ToggleNodeInfoProvider : NodeInfoProvider<IToggleProvider>
{
private static PropertyInfo? s_checkedProperty;
public ToggleNodeInfoProvider(ExploreByTouchHelper owner, AutomationPeer peer, int virtualViewId) :
base(owner, peer, virtualViewId)
{
}
static ToggleNodeInfoProvider()
{
s_checkedProperty = typeof(AccessibilityNodeInfoCompat).GetProperty(nameof(AccessibilityNodeInfoCompat.Checked));
}
public override bool PerformNodeAction(int action, Bundle? arguments)
{
IToggleProvider provider = GetProvider();
@ -40,25 +32,12 @@ namespace Avalonia.Android.Automation
nodeInfo.Clickable = true;
IToggleProvider provider = GetProvider();
s_checkedProperty ??= nodeInfo.GetType().GetProperty(nameof(nodeInfo.Checked));
if (s_checkedProperty?.PropertyType == typeof(int))
nodeInfo.Checked = provider.ToggleState switch
{
// Needed for Xamarin.AndroidX.Core 1.17+
s_checkedProperty.SetValue(this,
provider.ToggleState switch
{
ToggleState.On => 1,
ToggleState.Indeterminate => 2,
_ => 0
});
}
else if (s_checkedProperty?.PropertyType == typeof(bool))
{
// Needed for Xamarin.AndroidX.Core < 1.17
s_checkedProperty.SetValue(this, provider.ToggleState == ToggleState.On);
}
ToggleState.On => 1,
ToggleState.Indeterminate => 2,
_ => 0
};
nodeInfo.Checkable = true;
}
}

4
src/Android/Avalonia.Android/Avalonia.Android.csproj

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.7.0.5" />
<PackageReference Include="Xamarin.AndroidX.Window" Version="1.3.0.5" />
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.7.1.1" />
<PackageReference Include="Xamarin.AndroidX.Window" Version="1.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />

47
src/Android/Avalonia.Android/AvaloniaAccessHelper.cs

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using Android.Content.PM;
using Android.OS;
using AndroidX.Core.View.Accessibility;
using AndroidX.CustomView.Widget;
@ -15,20 +13,6 @@ namespace Avalonia.Android
{
internal class AvaloniaAccessHelper : ExploreByTouchHelper
{
private const string AUTOMATION_PROVIDER_NAMESPACE = "Avalonia.Automation.Provider";
private static readonly IReadOnlyDictionary<string, NodeInfoProviderInitializer>
s_providerTypeInitializers = new Dictionary<string, NodeInfoProviderInitializer>()
{
{ typeof(IExpandCollapseProvider).FullName!, (owner, peer, id) => new ExpandCollapseNodeInfoProvider(owner, peer, id) },
{ typeof(IInvokeProvider).FullName!, (owner, peer, id) => new InvokeNodeInfoProvider(owner, peer, id) },
{ typeof(IRangeValueProvider).FullName!, (owner, peer, id) => new RangeValueNodeInfoProvider(owner, peer, id) },
{ typeof(IScrollProvider).FullName!, (owner, peer, id) => new ScrollNodeInfoProvider(owner, peer, id) },
{ typeof(ISelectionItemProvider).FullName!, (owner, peer, id) => new SelectionItemNodeInfoProvider(owner, peer, id) },
{ typeof(IToggleProvider).FullName!, (owner, peer, id) => new ToggleNodeInfoProvider(owner, peer, id) },
{ typeof(IValueProvider).FullName!, (owner, peer, id) => new ValueNodeInfoProvider(owner, peer, id) },
};
private readonly Dictionary<int, AutomationPeer> _peers;
private readonly Dictionary<AutomationPeer, int> _peerIds;
@ -96,17 +80,20 @@ namespace Avalonia.Android
}
};
Type peerType = peer.GetType();
IEnumerable<Type> providerTypes = peerType.GetInterfaces()
.Where(x => x.Namespace!.StartsWith(AUTOMATION_PROVIDER_NAMESPACE));
foreach (Type providerType in providerTypes)
{
if (s_providerTypeInitializers.TryGetValue(providerType.FullName!, out NodeInfoProviderInitializer? ctor))
{
INodeInfoProvider nodeInfoProvider = ctor(this, peer, peerViewId);
nodeInfoProviders.Add(nodeInfoProvider);
}
}
if (peer is IExpandCollapseProvider)
nodeInfoProviders.Add(new ExpandCollapseNodeInfoProvider(this, peer, peerViewId));
if (peer is IInvokeProvider)
nodeInfoProviders.Add(new InvokeNodeInfoProvider(this, peer, peerViewId));
if (peer is IRangeValueProvider)
nodeInfoProviders.Add(new RangeValueNodeInfoProvider(this, peer, peerViewId));
if (peer is IScrollProvider)
nodeInfoProviders.Add(new ScrollNodeInfoProvider(this, peer, peerViewId));
if (peer is ISelectionItemProvider)
nodeInfoProviders.Add(new SelectionItemNodeInfoProvider(this, peer, peerViewId));
if (peer is IToggleProvider)
nodeInfoProviders.Add(new ToggleNodeInfoProvider(this, peer, peerViewId));
if (peer is IValueProvider)
nodeInfoProviders.Add(new ValueNodeInfoProvider(this, peer, peerViewId));
}
virtualViewId = peerViewId;
@ -151,9 +138,9 @@ namespace Avalonia.Android
.Aggregate(false, (a, b) => a | b);
}
protected override void OnPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfoCompat nodeInfo)
protected override void OnPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfoCompat? nodeInfo)
{
if (!_peers.TryGetValue(virtualViewId, out AutomationPeer? peer))
if (nodeInfo is null || !_peers.TryGetValue(virtualViewId, out AutomationPeer? peer))
{
return; // BAIL!! No work to be done
}

25
src/Android/Avalonia.Android/AvaloniaActivity.cs

@ -7,6 +7,7 @@ using Android.Content.PM;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Window;
using AndroidX.AppCompat.App;
using Avalonia.Android.Platform;
using Avalonia.Android.Platform.Storage;
@ -17,9 +18,9 @@ namespace Avalonia.Android;
/// <summary>
/// Common implementation of android activity that is integrated with Avalonia views.
/// If you need a base class for main activity of Avalonia app, see <see cref="AvaloniaMainActivity"/> or <see cref="AvaloniaMainActivity{TApp}"/>.
/// If you need a base class for main activity of Avalonia app, see <see cref="AvaloniaMainActivity"/>.
/// </summary>
public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity
public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity, IOnBackInvokedCallback
{
private EventHandler<ActivatedEventArgs>? _onActivated, _onDeactivated;
private GlobalLayoutListener? _listener;
@ -77,6 +78,9 @@ public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity
[ObsoletedOSPlatform("android33.0")]
public override void OnBackPressed()
{
if (OperatingSystem.IsAndroidVersionAtLeast(33))
return;
var eventArgs = new AndroidBackRequestedEventArgs();
BackRequested?.Invoke(this, eventArgs);
@ -120,12 +124,22 @@ public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity
protected override void OnStop()
{
_onDeactivated?.Invoke(this, new ActivatedEventArgs(ActivationKind.Background));
if (OperatingSystem.IsAndroidVersionAtLeast(33))
{
OnBackInvokedDispatcher.UnregisterOnBackInvokedCallback(this);
}
base.OnStop();
}
protected override void OnStart()
{
_onActivated?.Invoke(this, new ActivatedEventArgs(ActivationKind.Background));
if (OperatingSystem.IsAndroidVersionAtLeast(33))
{
OnBackInvokedDispatcher.RegisterOnBackInvokedCallback(IOnBackInvokedDispatcher.PriorityDefault, this);
}
base.OnStart();
}
@ -186,6 +200,13 @@ public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity
_view = new AvaloniaView(this) { Content = initialContent };
}
public void OnBackInvoked()
{
var eventArgs = new AndroidBackRequestedEventArgs();
BackRequested?.Invoke(this, eventArgs);
}
private class GlobalLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
{
private readonly AvaloniaView _view;

43
src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs

@ -127,10 +127,13 @@ namespace Avalonia.Android.Platform
WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars() |
WindowInsetsCompat.Type.DisplayCutout() : 0);
return new Thickness(inset.Left / renderScaling,
inset.Top / renderScaling,
inset.Right / renderScaling,
inset.Bottom / renderScaling);
if (inset is not null)
{
return new Thickness(inset.Left / renderScaling,
inset.Top / renderScaling,
inset.Right / renderScaling,
inset.Bottom / renderScaling);
}
}
return default;
@ -145,9 +148,10 @@ namespace Avalonia.Android.Platform
if (insets != null)
{
var navbarInset = insets.GetInsets(WindowInsetsCompat.Type.NavigationBars()).Bottom;
var navbarInset = insets.GetInsets(WindowInsetsCompat.Type.NavigationBars())?.Bottom ?? 0;
var imeInset = insets.GetInsets(WindowInsetsCompat.Type.Ime())?.Bottom ?? 0;
var height = Math.Max((float)((insets.GetInsets(WindowInsetsCompat.Type.Ime()).Bottom - navbarInset) / _topLevel.RenderScaling), 0);
var height = Math.Max((float)((imeInset - navbarInset) / _topLevel.RenderScaling), 0);
return new Rect(0, _topLevel.ClientSize.Height - SafeAreaPadding.Bottom - height, _topLevel.ClientSize.Width, height);
}
@ -156,7 +160,7 @@ namespace Avalonia.Android.Platform
}
}
public WindowInsetsCompat OnApplyWindowInsets(View v, WindowInsetsCompat insets)
public WindowInsetsCompat? OnApplyWindowInsets(View? v, WindowInsetsCompat? insets)
{
insets = ViewCompat.OnApplyWindowInsets(v, insets);
NotifySafeAreaChanged(SafeAreaPadding);
@ -166,15 +170,14 @@ namespace Avalonia.Android.Platform
_previousRect = OccludedRect;
}
State = insets.IsVisible(WindowInsetsCompat.Type.Ime()) ? InputPaneState.Open : InputPaneState.Closed;
State = insets is not null && insets.IsVisible(WindowInsetsCompat.Type.Ime()) ? InputPaneState.Open : InputPaneState.Closed;
// Workaround for weird inset values for android 11
if(Build.VERSION.SdkInt == BuildVersionCodes.R)
{
var imeInset = insets.GetInsets(WindowInsetsCompat.Type.Ime());
if(_previousImeInset == default)
_previousImeInset = imeInset;
if(imeInset.Bottom != _previousImeInset.Bottom)
var imeInset = insets?.GetInsets(WindowInsetsCompat.Type.Ime());
_previousImeInset ??= imeInset;
if ((imeInset?.Bottom ?? 0) != (_previousImeInset?.Bottom ?? 0))
{
NotifyStateChanged(State, _previousRect, OccludedRect, TimeSpan.Zero, null);
}
@ -285,7 +288,9 @@ namespace Avalonia.Android.Platform
if (_isDisplayEdgeToEdgeForced)
{
// Allow having fully transparent navbars when on api level 35
if (OperatingSystem.IsAndroidVersionAtLeast(35))
if (OperatingSystem.IsAndroidVersionAtLeast(36))
Window.NavigationBarContrastEnforced = false;
else if (OperatingSystem.IsAndroidVersionAtLeast(35))
Window.NavigationBarContrastEnforced = _systemBarColor != Colors.Transparent;
return;
}
@ -319,18 +324,18 @@ namespace Avalonia.Android.Platform
SystemBarColor = _systemBarColor;
}
public override WindowInsetsAnimationCompat.BoundsCompat OnStart(WindowInsetsAnimationCompat animation, WindowInsetsAnimationCompat.BoundsCompat bounds)
public override WindowInsetsAnimationCompat.BoundsCompat? OnStart(WindowInsetsAnimationCompat? animation, WindowInsetsAnimationCompat.BoundsCompat? bounds)
{
if ((animation.TypeMask & WindowInsetsCompat.Type.Ime()) != 0)
if (animation is not null && bounds is not null && (animation.TypeMask & WindowInsetsCompat.Type.Ime()) != 0)
{
var insets = ViewCompat.GetRootWindowInsets(Window.DecorView);
if (insets != null)
{
var navbarInset = insets.GetInsets(WindowInsetsCompat.Type.NavigationBars()).Bottom;
var height = Math.Max(0, (float)((bounds.LowerBound.Bottom - navbarInset) / _topLevel.RenderScaling));
var navbarInset = insets.GetInsets(WindowInsetsCompat.Type.NavigationBars())?.Bottom ?? 0;
var height = Math.Max(0, (float)(((bounds.LowerBound?.Bottom ?? 0) - navbarInset) / _topLevel.RenderScaling));
var upperRect = new Rect(0, _topLevel.ClientSize.Height - SafeAreaPadding.Bottom - height, _topLevel.ClientSize.Width, height);
height = Math.Max(0, (float)((bounds.UpperBound.Bottom - navbarInset) / _topLevel.RenderScaling));
height = Math.Max(0, (float)(((bounds.UpperBound?.Bottom ?? 0) - navbarInset) / _topLevel.RenderScaling));
var lowerRect = new Rect(0, _topLevel.ClientSize.Height - SafeAreaPadding.Bottom - height, _topLevel.ClientSize.Width, height);
var duration = TimeSpan.FromMilliseconds(animation.DurationMillis);
@ -344,7 +349,7 @@ namespace Avalonia.Android.Platform
return base.OnStart(animation, bounds);
}
public override WindowInsetsCompat OnProgress(WindowInsetsCompat insets, IList<WindowInsetsAnimationCompat> runningAnimations)
public override WindowInsetsCompat? OnProgress(WindowInsetsCompat? insets, IList<WindowInsetsAnimationCompat>? runningAnimations)
{
return insets;
}

17
src/Android/Avalonia.Android/Platform/AndroidScreens.cs

@ -32,11 +32,18 @@ internal class AndroidScreen(Display display) : PlatformScreen(new PlatformHandl
var metrics = metricsCalc.ComputeMaximumWindowMetrics(displayContext);
Bounds = new(metrics.Bounds.Left, metrics.Bounds.Top, metrics.Bounds.Width(), metrics.Bounds.Height());
var inset = metrics.WindowInsets.GetInsets(WindowInsetsCompat.Type.SystemBars());
WorkingArea = new(Bounds.X + inset.Left,
Bounds.Y + inset.Top,
Bounds.Width - (inset.Left + inset.Right),
Bounds.Height - (inset.Top + inset.Bottom));
var windowInsets = new WindowInsetsCompat.Builder().Build();
if (windowInsets?.GetInsets(WindowInsetsCompat.Type.SystemBars()) is { } inset)
{
WorkingArea = new(Bounds.X + inset.Left,
Bounds.Y + inset.Top,
Bounds.Width - (inset.Left + inset.Right),
Bounds.Height - (inset.Top + inset.Bottom));
}
else
{
WorkingArea = Bounds;
}
if (context.Resources?.Configuration is { } config)
{

3
src/Avalonia.Base/Data/Core/BindingExpression.cs

@ -190,6 +190,9 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
/// <param name="targetNullValue">The null target value.</param>
/// <param name="allowReflection">Whether to allow reflection for target type conversion.</param>
[RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
internal static BindingExpression Create<TIn, TOut>(
TIn source,
Expression<Func<TIn, TOut>> expression,

3
src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs

@ -7,6 +7,9 @@ using Avalonia.Reactive;
namespace Avalonia.Data.Core.ExpressionNodes.Reflection;
[RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
internal sealed class DynamicPluginStreamNode : ExpressionNode
{
private IDisposable? _subscription;

3
src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ExpressionTreeIndexerNode.cs

@ -16,6 +16,9 @@ internal sealed class ExpressionTreeIndexerNode : CollectionNodeBase, ISettableN
private readonly Delegate _getDelegate;
private readonly Delegate _firstArgumentDelegate;
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
public ExpressionTreeIndexerNode(IndexExpression expression)
{
var valueParameter = Expression.Parameter(expression.Type);

3
src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs

@ -11,6 +11,9 @@ using Avalonia.Data.Core.ExpressionNodes.Reflection;
namespace Avalonia.Data.Core.Parsers;
[RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
internal class BindingExpressionVisitor<TIn> : ExpressionVisitor
{
private static readonly PropertyInfo AvaloniaObjectIndexer;

1
src/Avalonia.Base/Data/Core/Plugins/BindingPlugins.cs

@ -28,6 +28,7 @@ namespace Avalonia.Data.Core.Plugins
new ObservableStreamPlugin(),
};
[UnconditionalSuppressMessage("AOT", "IL3050", Justification = "We're checking if dynamic code is supported.")]
static BindingPlugins()
{
// When building with AOT, don't create ReflectionMethodAccessorPlugin instance.

6
src/Avalonia.Base/Data/Core/Plugins/ReflectionMethodAccessorPlugin.cs

@ -7,6 +7,9 @@ using System.Reflection;
namespace Avalonia.Data.Core.Plugins
{
[RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
internal class ReflectionMethodAccessorPlugin : IPropertyAccessorPlugin
{
private readonly Dictionary<(Type, string), MethodInfo?> _methodLookup =
@ -81,6 +84,9 @@ namespace Avalonia.Data.Core.Plugins
return found;
}
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
private sealed class Accessor : PropertyAccessorBase
{
public Accessor(WeakReference<object?> reference, MethodInfo method)

4
src/Avalonia.Base/Diagnostics/TrimmingMessages.cs

@ -9,11 +9,13 @@ internal static class TrimmingMessages
public const string TypeConversionRequiresUnreferencedCodeMessage = "Conversion methods are required for type conversion, including op_Implicit, op_Explicit, Parse and TypeConverter.";
public const string ReflectionBindingRequiresUnreferencedCodeMessage = "BindingExpression and ReflectionBinding heavily use reflection. Consider using CompiledBindings instead.";
public const string ReflectionBindingRequiresDynamicCodeMessage = "BindingExpression and ReflectionBinding require dynamic code. Consider using CompiledBindings instead.";
public const string ReflectionBindingSupressWarningMessage = "BindingExpression and ReflectionBinding internal heavily use reflection.";
public const string CompiledBindingSafeSupressWarningMessage = "CompiledBinding preserves members used in the expression tree.";
public const string ExpressionNodeRequiresUnreferencedCodeMessage = "ExpressionNode might require unreferenced code.";
public const string ExpressionNodeRequiresDynamicCodeMessage = "ExpressionNode requires dynamic code.";
public const string ExpressionSafeSupressWarningMessage = "Typed Expressions preserves members used in the expression tree.";
public const string SelectorsParseRequiresUnreferencedCodeMessage = "Selectors runtime parser might require unreferenced code. Consider using stronly typed selectors factory with 'new Style(s => s.OfType<Button>())' syntax.";
@ -28,4 +30,6 @@ internal static class TrimmingMessages
public const string IgnoreNativeAotSupressWarningMessage = "This method is not supported by NativeAOT.";
public const string DesignTimeSupressWarningMessage = "This method is design time only.";
public const string TypesInCoreOrAvaloniaAssembly = "The types reside in the core assembly or in an explicitly loaded Avalonia assembly and will always be found.";
}

2
src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionParser.cs

@ -145,7 +145,7 @@ namespace Avalonia.Rendering.Composition.Expressions
};
private static readonly ExpressionType[][] OperatorPrecedenceGroupsReversed =
OperatorPrecedenceGroups.Reverse().ToArray();
OperatorPrecedenceGroups.AsEnumerable().Reverse().ToArray();
// a*b+c [a,b,c] [*,+], call with (0, 2)
// ToExpression(a*b) + ToExpression(c)

6
src/Avalonia.Base/Utilities/Polyfills.cs

@ -33,11 +33,11 @@ namespace System.Diagnostics.CodeAnalysis
struct S
{
int field;
int _field;
// Okay: `field` has the ref-safe-to-escape of `this` which is *calling method* because
// it is a `ref`
[UnscopedRef] ref int Prop1 => ref field;
[UnscopedRef] ref int Prop1 => ref _field;
}
}
#endif
#endif

1
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@ -128,6 +128,7 @@
<Compile Include="../Avalonia.Base/Compatibility/NullableAttributes.cs" Link="Compatibility/NullableAttributes.cs" />
<Compile Include="../Avalonia.Base/Compatibility/TrimmingAttributes.cs" Link="Compatibility/TrimmingAttributes.cs" />
<Compile Include="../Avalonia.Base/Utilities/SpanHelpers.cs" Link="Utilities/SpanHelpers.cs" />
<Compile Include="../Avalonia.Base/Diagnostics/TrimmingMessages.cs" Link="Diagnostics/TrimmingMessages.cs" />
<Compile Include="../Shared/StringCompatibilityExtensions.cs" Link="Compatibility/StringCompatibilityExtensions.cs" />
<Compile Include="../Shared/IsExternalInit.cs" Link="Compatibility/IsExternalInit.cs" />
<PackageReference Include="Mono.Cecil" Version="0.11.5" />

4
src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs

@ -236,7 +236,9 @@ namespace Avalonia.Native
if (context.Context.GetIOKitRegistryId(&registryId) != 0)
{
// We are reversing bytes to match MoltenVK (LUID is a Vulkan term after all)
DeviceLuid = BitConverter.GetBytes(registryId).Reverse().ToArray();
var bytes = BitConverter.GetBytes(registryId);
bytes.Reverse();
DeviceLuid = bytes;
}
}

4
src/Avalonia.Native/Metal.cs

@ -93,7 +93,9 @@ internal class MetalExternalObjectsFeature : IMetalExternalObjectsFeature
ulong registryId;
if (_device.GetIOKitRegistryId(&registryId) != 0)
{
DeviceLuid = BitConverter.GetBytes(registryId).Reverse().ToArray();
var bytes = BitConverter.GetBytes(registryId);
bytes.Reverse();
DeviceLuid = bytes;
}
}

1
src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj

@ -6,6 +6,7 @@
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Avalonia.Base\Diagnostics\TrimmingMessages.cs" />
<Compile Include="..\Avalonia.Base\Input\Key.cs" />
<Compile Include="..\Avalonia.Base\Input\PhysicalKey.cs" />
<Compile Include="..\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Visible="False" />

14
src/Avalonia.Remote.Protocol/MetsysBson.cs

@ -38,10 +38,10 @@ using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using Avalonia;
using Metsys.Bson.Configuration;
// ReSharper disable All
@ -1422,6 +1422,9 @@ namespace Metsys.Bson.Configuration
ITypeConfiguration<T> IgnoreIfNull(Expression<Func<T, object>> expression);
}
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
internal class TypeConfiguration<T> : ITypeConfiguration<T>
{
private readonly BsonConfiguration _configuration;
@ -1461,6 +1464,9 @@ namespace Metsys.Bson.Configuration
namespace Metsys.Bson.Configuration
{
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
public static class ExpressionHelper
{
public static string GetName(this MemberExpression expression)
@ -1493,6 +1499,9 @@ namespace Metsys.Bson.Configuration
return null;
}
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
private class ExpressionNameVisitor
{
public string Visit(Expression expression)
@ -1580,6 +1589,9 @@ namespace Metsys.Bson.Configuration
private BsonConfiguration() { }
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
public static void ForType<T>(Action<ITypeConfiguration<T>> action)
{
action(new TypeConfiguration<T>(Instance));

2
src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj

@ -14,7 +14,7 @@
<Import Project="../../../build/TrimmingEnable.props" />
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="7.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="10.0.0" />
</ItemGroup>
<ItemGroup>

5
src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj

@ -6,10 +6,15 @@
<IsAotCompatible>false</IsAotCompatible>
<DefineConstants>$(DefineConstants);XAMLX_INTERNAL;XAML_RUNTIME_LOADER</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="../../Avalonia.Base/Diagnostics/TrimmingMessages.cs" Link="Diagnostics/AvaloniaTrimmingMessages.cs" />
</ItemGroup>
<Import Project="IncludeXamlIlSre.props" />
<Import Project="..\..\..\build\DevAnalyzers.props" />
<Import Project="..\..\..\build\TrimmingEnable.props" />

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs

@ -19,6 +19,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class AvaloniaXamlIlLanguage
{
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
public static (XamlLanguageTypeMappings language, XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult> emit) Configure(IXamlTypeSystem typeSystem)
{
var runtimeHelpers = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
@ -83,6 +84,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public const string ContextNameScopeFieldName = "AvaloniaNameScope";
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
private static void EmitNameScopeField(
XamlLanguageTypeMappings mappings,
IXamlTypeSystem typeSystem,
@ -100,6 +102,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
.Stfld(field);
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
private static void EmitEagerParentStackProvider(
XamlLanguageTypeMappings mappings,
IXamlTypeSystem typeSystem,
@ -170,6 +173,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
private readonly IXamlType _avaloniaListConverter;
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
public AttributeResolver(IXamlTypeSystem typeSystem, XamlLanguageTypeMappings mappings)
{
_typeConverterAttribute = mappings.TypeConverterAttributes.First();

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlQueryTransformer.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Avalonia.Markup.Parsers;
using Avalonia.Styling;
@ -134,6 +135,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
protected abstract void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen);
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
protected void EmitCall(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen, Func<IXamlMethod, bool> method)
{
var queries = context.Configuration.TypeSystem.GetType("Avalonia.Styling.StyleQueries");
@ -307,6 +309,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
if (_queries.Count == 0)
@ -385,6 +388,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
if (_queries.Count == 0)

3
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using Avalonia.Markup.Parsers;
@ -307,6 +308,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
protected abstract void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen);
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
protected void EmitCall(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen, Func<IXamlMethod, bool> method)
{
var selectors = context.Configuration.TypeSystem.GetType("Avalonia.Styling.Selectors");
@ -550,6 +552,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
if (_selectors.Count == 0)

2
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@ -143,6 +143,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlMethod AddHandler { get; }
public IXamlMethod AddHandlerT { get; }
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
internal InteractivityWellKnownTypes(TransformerConfiguration cfg)
{
var ts = cfg.TypeSystem;
@ -176,6 +177,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public InteractivityWellKnownTypes Interactivity { get; }
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
{
RuntimeHelpers = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");

8
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Emit;
using Avalonia.Markup.Parsers;
@ -137,6 +138,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return node.Property.Getter?.ReturnType;
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
private static XamlIlBindingPathNode TransformBindingPath(AstTransformationContext context, IXamlLineInfo lineInfo, Func<IXamlType> startTypeResolver, IXamlType selfType, IEnumerable<BindingExpressionGrammar.INode> bindingExpression)
{
List<IXamlIlBindingPathElementNode> transformNodes = new List<IXamlIlBindingPathElementNode>();
@ -743,6 +745,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public IXamlType Type { get; }
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
[UnconditionalSuppressMessage("Trimming", "IL2062", Justification = "All Action<> and Func<> types are explicitly preserved.")]
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
IXamlTypeBuilder<IXamlILEmitter>? newDelegateTypeBuilder = null;
@ -824,6 +828,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public IXamlType Type { get; }
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
var trampolineBuilder = context.Configuration.GetExtra<XamlIlTrampolineBuilder>();
@ -894,6 +899,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
_isNotifyingCollection = isNotifyingCollection;
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
var intType = context.Configuration.TypeSystem.GetType("System.Int32");
@ -940,6 +946,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
var intType = context.Configuration.TypeSystem.GetType("System.Int32");
@ -1002,6 +1009,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public List<IXamlIlBindingPathElementNode> Elements { get; }
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
public XamlILNodeEmitResult Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
var intType = context.Configuration.TypeSystem.GetType("System.Int32");

5
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlPropertyInfoAccessorFactoryEmitter.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
@ -37,6 +38,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return EmitCreateAccessorFactoryDelegate(context, codeGen);
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
private void EmitLoadPropertyAccessorFactory(XamlIlEmitContext context, IXamlILEmitter codeGen, IXamlType type, string accessorFactoryName, bool isStatic = true)
{
var types = context.GetAvaloniaTypes();
@ -48,6 +50,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
codeGen.Ldftn(type.GetMethod(accessorFactorySignature));
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
public IXamlType EmitLoadIndexerAccessorFactory(XamlIlEmitContext context, IXamlILEmitter codeGen, IXamlAstValueNode value)
{
var intType = context.Configuration.TypeSystem.GetType("System.Int32");
@ -62,6 +65,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return EmitCreateAccessorFactoryDelegate(context, codeGen);
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
private IXamlType InitializeClosureType(XamlIlEmitContext context)
{
var types = context.GetAvaloniaTypes();
@ -101,6 +105,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return _indexerClosureTypeBuilder.CreateType();
}
[UnconditionalSuppressMessage("Trimming", "IL2122", Justification = TrimmingMessages.TypesInCoreOrAvaloniaAssembly)]
private IXamlType EmitCreateAccessorFactoryDelegate(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
var types = context.GetAvaloniaTypes();

2
src/Markup/Avalonia.Markup.Xaml.Loader/IncludeXamlIlSre.props

@ -11,6 +11,6 @@
</ItemGroup>
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))">
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
</ItemGroup>
</Project>

3
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs

@ -9,6 +9,9 @@ using System.Globalization;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
[RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ReflectionBindingRequiresDynamicCodeMessage)]
#endif
public class ReflectionBindingExtension
{
public ReflectionBindingExtension()

1
src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs

@ -35,6 +35,7 @@ namespace Avalonia.Markup.Xaml.Templates
}
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "If ItemsSource is a CompiledBinding, then path members will be preserved")]
[UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Dynamic code should be available if reflection bindings are used")]
public InstancedBinding? ItemsSelector(object item)
{
if (ItemsSource != null)

2
src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

@ -241,7 +241,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
=> RootObject;
public IEnumerable<object> Parents
=> _parentResourceNodes.Reverse();
=> _parentResourceNodes.AsEnumerable().Reverse();
public IReadOnlyList<object> DirectParentsStack
=> _parentResourceNodes;

6
src/Markup/Avalonia.Markup/Data/Binding.cs

@ -16,6 +16,9 @@ namespace Avalonia.Data
/// A XAML binding.
/// </summary>
[RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ReflectionBindingRequiresDynamicCodeMessage)]
#endif
public class Binding : BindingBase
{
/// <summary>
@ -90,6 +93,9 @@ namespace Avalonia.Data
/// ITreeDataTemplate in time for 11.0. We should revisit this in 12.0.
/// </remarks>
// TODO12: Refactor
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
internal BindingExpression CreateObservableForTreeDataTemplate(object source)
{
if (!string.IsNullOrEmpty(ElementName))

3
src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionNodeFactory.cs

@ -15,6 +15,9 @@ namespace Avalonia.Markup.Parsers
internal static class ExpressionNodeFactory
{
[RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ReflectionBindingRequiresDynamicCodeMessage)]
#endif
public static List<ExpressionNode>? CreateFromAst(
List<BindingExpressionGrammar.INode> astNodes,
Func<string?, string, Type>? typeResolver,

1
src/Windows/Avalonia.Win32.Interoperability/WinForms/WinFormsAvaloniaControlHost.cs

@ -32,6 +32,7 @@ public class WinFormsAvaloniaControlHost : WinFormsControl, IMessageFilter
/// <summary>
/// Gets or sets the Avalonia control hosted by the <see cref="WinFormsAvaloniaControlHost"/> element.
/// </summary>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public AvControl? Content
{
get => _content;

4
src/Windows/Avalonia.Win32/Avalonia.Win32.csproj

@ -7,8 +7,8 @@
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))">
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.6.1" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.106">

2
src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs

@ -40,7 +40,7 @@ namespace Avalonia.iOS
public UIWindow? Window { get; set; }
[Export("application:didFinishLaunchingWithOptions:")]
public bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
public bool FinishedLaunching(UIApplication application, NSDictionary? launchOptions)
{
var builder = CreateAppBuilder();
builder = CustomizeAppBuilder(builder);

2
src/iOS/Avalonia.iOS/IOSLauncher.cs

@ -12,7 +12,7 @@ internal class IOSLauncher : ILauncher
{
_ = uri ?? throw new ArgumentNullException(nameof(uri));
if (uri.IsAbsoluteUri && UIApplication.SharedApplication.CanOpenUrl(uri))
if (uri.IsAbsoluteUri && UIApplication.SharedApplication.CanOpenUrl(uri!))
{
return UIApplication.SharedApplication.OpenUrlAsync(uri!, new UIApplicationOpenUrlOptions());
}

2
src/iOS/Avalonia.iOS/iOSScreens.cs

@ -69,7 +69,7 @@ internal class iOSScreens : ScreensBase<UIScreen, iOSScreen>
protected override Screen? ScreenFromTopLevelCore(ITopLevelImpl topLevel)
{
var uiScreen = (topLevel as AvaloniaView.TopLevelImpl)?.View.Window.Screen;
var uiScreen = (topLevel as AvaloniaView.TopLevelImpl)?.View.Window?.Screen;
return uiScreen is not null && TryGetScreen(uiScreen, out var screen) ? screen : null;
}
}

1
src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj

@ -16,6 +16,7 @@
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerDynamicDependencies.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Compatibility\NullableAttributes.cs" Link="Compatibility\NullableAttributes.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Link="Compatibility\TrimmingAttributes.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Diagnostics\TrimmingMessages.cs" Link="Diagnostics/AvaloniaTrimmingMessages.cs" />
<Compile Include="..\..\Shared\StringCompatibilityExtensions.cs" Link="Compatibility\StringCompatibilityExtensions.cs" />
<Compile Include="..\..\..\src\Shared\IsExternalInit.cs" Link="Compatibility\IsExternalInit.cs" />
</ItemGroup>

28
src/tools/DevGenerators/CompilerDynamicDependenciesGenerator.cs

@ -1,4 +1,7 @@
using System.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
@ -21,15 +24,13 @@ public class CompilerDynamicDependenciesGenerator : IIncrementalGenerator
context.RegisterSourceOutput(invocationSyntaxes.Collect(), static (context, invocations) =>
{
var types = invocations
.Select(t => t.ArgumentList.Arguments[0].GetText().ToString())
.Select(t => t.ArgumentList.Arguments[0].GetText().ToString().Trim('"'))
.Append("System.Action")
.Concat(Enumerable.Range(1, 16).Select(i => $"System.Action`{i}"))
.Concat(Enumerable.Range(1, 17).Select(i => $"System.Func`{i}"))
.Distinct()
.Select(t => t
.Replace("\"", "")
.Replace("`1", "<>")
.Replace("`2", "<,>")
.Replace("`3", "<,,>")
.Replace("`4", "<,,,>"))
.OrderBy(t => t)
.Select(ToCSharpTypeName)
.OrderBy(t => t, StringComparer.Ordinal)
.ToArray();
if (types.Length == 0)
{
@ -74,4 +75,13 @@ namespace Avalonia.Markup.Xaml.XamlIl
context.AddSource("CompilerDynamicDependenciesAttribute.generated.cs", attributesBuilder.ToString());
});
}
private static string ToCSharpTypeName(string clrTypeName)
{
var index = clrTypeName.LastIndexOf('`');
if (index < 0 || !int.TryParse(clrTypeName.Substring(index + 1), NumberStyles.None, CultureInfo.InvariantCulture, out var argCount))
return clrTypeName;
return $"{clrTypeName.Substring(0, index)}<{new string(',', argCount - 1)}>";
}
}

8
tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs

@ -29,25 +29,25 @@ namespace Avalonia.DesignerSupport.Tests
[SkippableTheory,
InlineData(
@"..\..\..\..\..\tests/Avalonia.DesignerSupport.TestApp/bin/$BUILD/net8.0/",
@"..\..\..\..\..\tests/Avalonia.DesignerSupport.TestApp/bin/$BUILD/net10.0/",
"Avalonia.DesignerSupport.TestApp",
"Avalonia.DesignerSupport.TestApp.dll",
@"..\..\..\..\..\tests\Avalonia.DesignerSupport.TestApp\MainWindow.xaml",
"win32"),
InlineData(
@"..\..\..\..\..\samples\ControlCatalog.NetCore\bin\$BUILD\net8.0\",
@"..\..\..\..\..\samples\ControlCatalog.NetCore\bin\$BUILD\net10.0\",
"ControlCatalog.NetCore",
"ControlCatalog.dll",
@"..\..\..\..\..\samples\ControlCatalog\MainWindow.xaml",
"win32"),
InlineData(
@"..\..\..\..\..\tests/Avalonia.DesignerSupport.TestApp/bin/$BUILD/net8.0/",
@"..\..\..\..\..\tests/Avalonia.DesignerSupport.TestApp/bin/$BUILD/net10.0/",
"Avalonia.DesignerSupport.TestApp",
"Avalonia.DesignerSupport.TestApp.dll",
@"..\..\..\..\..\tests\Avalonia.DesignerSupport.TestApp\MainWindow.xaml",
"avalonia-remote"),
InlineData(
@"..\..\..\..\..\samples\ControlCatalog.NetCore\bin\$BUILD\net8.0\",
@"..\..\..\..\..\samples\ControlCatalog.NetCore\bin\$BUILD\net10.0\",
"ControlCatalog.NetCore",
"ControlCatalog.dll",
@"..\..\..\..\..\samples\ControlCatalog\MainWindow.xaml",

2
tests/Avalonia.Headless.NUnit.PerTest.UnitTests/Avalonia.Headless.NUnit.PerTest.UnitTests.csproj

@ -14,7 +14,7 @@
<ItemGroup>
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
</ItemGroup>
<ItemGroup>

1
tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj

@ -16,7 +16,6 @@
<ItemGroup>
<PackageReference Include="Appium.WebDriver" Version="4.4.0" Condition="'$(IsRunningAppium2)' == 'false'" />
<PackageReference Include="Appium.WebDriver" Version="5.0.0-rc.8" Condition="'$(IsRunningAppium2)' == 'true'" />
<PackageReference Include="Xunit.Extensions.Ordering" Version="1.4.5" />
</ItemGroup>
<Import Project="..\..\build\XUnit.props" />

2
tests/Avalonia.IntegrationTests.Appium/DefaultAppFixture.cs

@ -9,7 +9,7 @@ namespace Avalonia.IntegrationTests.Appium
{
public class DefaultAppFixture : IDisposable
{
private const string TestAppPath = @"..\..\..\..\..\samples\IntegrationTestApp\bin\Debug\net8.0\IntegrationTestApp.exe";
private const string TestAppPath = @"..\..\..\..\..\samples\IntegrationTestApp\bin\Debug\net10.0\IntegrationTestApp.exe";
private const string TestAppBundleId = "net.avaloniaui.avalonia.integrationtestapp";
public DefaultAppFixture()

2
tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net462</TargetFrameworks>
<TargetFrameworks>$(AvsCurrentTargetFramework)</TargetFrameworks>
</PropertyGroup>
<Import Project="..\..\build\JetBrains.dotMemoryUnit.props" />
<Import Project="..\..\build\Moq.props" />

2
tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<TargetFrameworks>$(AvsCurrentTargetFramework);net47</TargetFrameworks>
<TargetFrameworks>$(AvsCurrentTargetFramework);net481</TargetFrameworks>
<OutputType>Library</OutputType>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

2
tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>$(AvsCurrentTargetFramework);net481</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputType>Library</OutputType>
<IsPackable>false</IsPackable>

4
tests/BuildTests/BuildTests.Android/BuildTests.Android.csproj

@ -2,8 +2,8 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0-android</TargetFramework>
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
<TargetFramework>net10.0-android</TargetFramework>
<SupportedOSPlatformVersion>24</SupportedOSPlatformVersion>
<Nullable>enable</Nullable>
<ApplicationId>com.Avalonia.BuildTests</ApplicationId>
<ApplicationVersion>1</ApplicationVersion>

2
tests/BuildTests/BuildTests.Browser/BuildTests.Browser.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.WebAssembly">
<PropertyGroup>
<TargetFramework>net8.0-browser</TargetFramework>
<TargetFramework>net10.0-browser</TargetFramework>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>

2
tests/BuildTests/BuildTests.Desktop/BuildTests.Desktop.csproj

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>

2
tests/BuildTests/BuildTests.FSharp/BuildTests.FSharp.fsproj

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>

2
tests/BuildTests/BuildTests.NativeAot/BuildTests.NativeAot.csproj

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
</PropertyGroup>

2
tests/BuildTests/BuildTests.WpfHybrid/BuildTests.WpfHybrid.csproj

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net10.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>

2
tests/BuildTests/BuildTests.iOS/BuildTests.iOS.csproj

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0-ios</TargetFramework>
<TargetFramework>net10.0-ios</TargetFramework>
<SupportedOSPlatformVersion>13.0</SupportedOSPlatformVersion>
<Nullable>enable</Nullable>
</PropertyGroup>

2
tests/BuildTests/BuildTests/BuildTests.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<EnableDefaultItems>false</EnableDefaultItems>

Loading…
Cancel
Save