diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 8f7351101e77..de1c51d3d000 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -21,7 +21,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "10.0.0-prerelease.24511.1", + "version": "9.0.0-prerelease.24510.3", "commands": [ "xharness" ] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 04fe3e69daa7..8b63aa03be17 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,3 +8,4 @@ # Blazor Desktop /src/BlazorWebView/ @dotnet/dotnet-maui-blazor-eng /src/Templates/src/templates/maui-blazor/ @dotnet/dotnet-maui-blazor-eng +/src/Templates/src/templates/maui-blazor-solution/ @dotnet/dotnet-maui-blazor-eng diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b56ed2e76dde..e4e9e48e730c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -41,6 +41,7 @@ updates: - "Microsoft.Graphics.Win2D" - "Microsoft.Windows.SDK.BuildTools" - "Microsoft.WindowsAppSDK" + - "Microsoft.Web.WebView2" xunit: patterns: - "xunit" @@ -57,7 +58,7 @@ updates: - dependency-name: "Newtonsoft.Json" # needs to be done manually to match VS - dependency-name: "Microsoft.Build*" # these packages neet to be kept on old version that supports netstandard2.0 - dependency-name: "Selenium.*" # needs to be done manually because other packages need to be compiled with these new versions - + labels: - "nuget" - "dependencies" diff --git a/.gitignore b/.gitignore index 69887dd81422..bd1b26cc4f05 100644 --- a/.gitignore +++ b/.gitignore @@ -376,3 +376,9 @@ Directory.Build.Override.props # Only the "snapshots" directory should be added to Git, not the "snapshots-diff" directory snapshots-diff/ + +#install of dotnet version +/.dotnet +.dotnet +temp +.packages diff --git a/Directory.Build.props b/Directory.Build.props index e54c3b07725d..409a1aeeef8a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ - + true portable true @@ -11,6 +11,9 @@ false $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)src/ + false + false + false @@ -40,14 +43,14 @@ all moderate - + - <_MauiDotNetVersionMajor Condition="'$(_MauiDotNetVersionMajor)' == ''">8 + <_MauiDotNetVersionMajor Condition="'$(_MauiDotNetVersionMajor)' == ''">9 <_MauiDotNetVersionMinor Condition="'$(_MauiDotNetVersionMinor)' == ''">0 <_MauiDotNetVersion Condition="'$(_MauiDotNetVersion)' == ''">$(_MauiDotNetVersionMajor).$(_MauiDotNetVersionMinor) <_MauiDotNetTfm Condition="'$(_MauiDotNetTfm)' == ''">net$(_MauiDotNetVersion) - - <_MauiPreviousDotNetVersionMajor Condition="'$(_MauiPreviousDotNetVersionMajor)' == ''">7 + + <_MauiPreviousDotNetVersionMajor Condition="'$(_MauiPreviousDotNetVersionMajor)' == ''">8 <_MauiPreviousDotNetVersionMinor Condition="'$(_MauiPreviousDotNetVersionMinor)' == ''">0 <_MauiPreviousDotNetVersion Condition="'$(_MauiPreviousDotNetVersion)' == ''">$(_MauiPreviousDotNetVersionMajor).$(_MauiPreviousDotNetVersionMinor) <_MauiPreviousDotNetVersionNoDot Condition="'$(_MauiPreviousDotNetVersionNoDot)' == ''">$(_MauiPreviousDotNetVersionMajor)$(_MauiPreviousDotNetVersionMinor) @@ -104,6 +107,7 @@ true + true true true @@ -114,7 +118,8 @@ $(DefineConstants);WINDOWS $(DefineConstants);COMPATIBILITY_ENABLED - snupkg + $(DefineConstants);ENABLE_PREVIOUS_TFM_BUILDS + true @@ -122,29 +127,34 @@ true + + + 10.0.19041.44 + + - 17.5 - 17.5 - 17.5 - 14.5 - 34.0 + 18.0 + 18.0 + 18.0 + 15.0 + 35.0 - 17.0 - 17.0 - 17.0 - 14.0 - 34.0 + 18.0 + 18.0 + 18.0 + 15.0 + 35.0 10.0.19041.0 10.0.20348.0 7.0 - 16.1 - 16.1 - 16.1 - 13.0 - 33.0 + 17.5 + 17.5 + 17.5 + 14.5 + 35.0 10.0.19041.0 10.0.20348.0 7.0 @@ -178,6 +188,11 @@ net$(_MauiDotNetVersion)-android;$(MauiSamplePlatforms) net$(_MauiDotNetVersion)-maccatalyst;$(MauiSamplePlatforms) net$(_MauiDotNetVersion)-ios;$(MauiSamplePlatforms) + net$(_MauiPreviousDotNetVersion)-tizen;$(MauiSamplePreviousPlatforms) + $(WindowsMauiPreviousPlatforms);$(MauiSamplePreviousPlatforms) + net$(_MauiPreviousDotNetVersion)-android;$(MauiSamplePreviousPlatforms) + net$(_MauiPreviousDotNetVersion)-maccatalyst;$(MauiSamplePreviousPlatforms) + net$(_MauiPreviousDotNetVersion)-ios;$(MauiSamplePreviousPlatforms) $(WindowsMauiPlatforms);$(MauiDeviceTestsPlatforms) @@ -200,9 +215,8 @@ - $(MSBuildThisFileDirectory)bin/ - $(DotNetOutputPath)temp/ - $(DotNetOutputPath)dotnet/ + $(RepoRoot)temp/ + $(RepoRoot).dotnet/ $(DotNetDirectory)dotnet $(DotNetDirectory)packs/ $(DotNetDirectory)library-packs/ @@ -211,7 +225,7 @@ <_MauiBuildTasksLocation>$(_MauiBuildTasksLocation) <_MauiBuildTasksLocation Condition="'$(_MauiBuildTasksLocation)' == ''">$(MSBuildThisFileDirectory).buildtasks\ <_MauiAOTProfileLocation>$(MauiSrcDirectory)Controls\src\Build.Tasks\nuget\buildTransitive\netstandard2.0\ - $(MauiRootDirectory)eng/microsoft.maui.controls.snk + $(MauiRootDirectory)eng/microsoft.maui.controls.snk $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb True True diff --git a/Directory.Build.targets b/Directory.Build.targets index 7a66bac1ceee..cdfa0ed38f55 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -19,14 +19,20 @@ - + True + + + + $(NoWarn);MSB4011;NETSDK1206 + + - 11.0 - 11.0 + 13.0 + 13.0 $(NoWarn);CA1416 @@ -37,14 +43,14 @@ $(NoWarn);CA1416 - 13.1 - 13.1 + 15.0 + 15.0 $(NoWarn);CA1416 - 10.14 - 10.14 + 12.0 + 12.0 21.0 @@ -55,8 +61,8 @@ 6.5 - @@ -65,7 +71,7 @@ 10.0.17763.0 - @@ -79,9 +85,9 @@ - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT index b93840c3b5c2..3ea5936c902a 100644 --- a/THIRD-PARTY-NOTICES.TXT +++ b/THIRD-PARTY-NOTICES.TXT @@ -521,3 +521,63 @@ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= + + +License notice for .NET Community Toolkit +========================================= + +(https://github.com/CommunityToolkit/dotnet/blob/main/License.md) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= + + +License notice for BenchmarkDotNet +========================================= + +(https://github.com/dotnet/BenchmarkDotNet/blob/master/LICENSE.md) + +The MIT License (MIT) + +Copyright (c) 2013–2024 .NET Foundation and contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= diff --git a/build.cmd b/build.cmd index 4dded3f9274a..c70d2b3757e4 100644 --- a/build.cmd +++ b/build.cmd @@ -1,6 +1,9 @@ -@ECHO OFF -SETLOCAL -PowerShell -NoProfile -NoLogo -ExecutionPolicy Bypass -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = ''; try { & '%~dp0build.ps1' %*; exit $LASTEXITCODE } catch { write-host $_; exit 1 }" -SET exit_code=%ERRORLEVEL% -ECHO build.cmd completed -EXIT /b %exit_code% \ No newline at end of file +@echo off +setlocal + +set _args=%* +if "%~1"=="-?" set _args=-help +if "%~1"=="/?" set _args=-help + +powershell -ExecutionPolicy ByPass -NoProfile -Command "& '%~dp0eng\build.ps1'" %_args% +exit /b %ERRORLEVEL% \ No newline at end of file diff --git a/build.ps1 b/build.ps1 old mode 100644 new mode 100755 diff --git a/build.sh b/build.sh index 6dbd8964f81b..a5e46e950a35 100755 --- a/build.sh +++ b/build.sh @@ -1,30 +1,16 @@ #!/usr/bin/env bash -# script inspired by https://andrewlock.net/simplifying-the-cake-global-tool-bootstrapper-scripts-in-netcore3-with-local-tools/ +source="${BASH_SOURCE[0]}" -# Define default arguments. -SCRIPT="build.cake" -CAKE_ARGUMENTS=() +# resolve $SOURCE until the file is no longer a symlink +while [[ -h $source ]]; do + scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + source="$(readlink "$source")" -# Parse arguments. -for i in "$@"; do - case $1 in - -s|--script) SCRIPT="$2"; shift ;; - --) shift; CAKE_ARGUMENTS+=("$@"); break ;; - *) CAKE_ARGUMENTS+=("$1") ;; - esac - shift + # if $source was a relative symlink, we need to resolve it relative to the path where the + # symlink file was located + [[ $source != /* ]] && source="$scriptroot/$source" done -# Restore Cake tool -dotnet tool restore - -if [ $? -ne 0 ]; then - echo "An error occurred while installing Cake." - exit 1 -fi - -echo "${CAKE_ARGUMENTS[@]}" - -# Start Cake -dotnet tool run dotnet-cake "$SCRIPT" "${CAKE_ARGUMENTS[@]}" +scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" +"$scriptroot/eng/build.sh" $@ \ No newline at end of file diff --git a/docs/design/FeatureSwitches.md b/docs/design/FeatureSwitches.md new file mode 100644 index 000000000000..26a91ad5837f --- /dev/null +++ b/docs/design/FeatureSwitches.md @@ -0,0 +1,73 @@ +# Feature Switches + +Certain features of MAUI can be enabled or disabled using feature switches. The easiest way to control the features is by putting the corresponding MSBuild property into the app's project file. Disabling unnecessary features can help reducing the app size when combined with the [`full` trimming mode](https://learn.microsoft.com/dotnet/core/deploying/trimming/trimming-options). + +The following switches are toggled for applications running on Mono for `TrimMode=full` as well as NativeAOT. + +| MSBuild Property Name | AppContext Setting | Description | +|-|-|-| +| MauiEnableIVisualAssemblyScanning | Microsoft.Maui.RuntimeFeature.IsIVisualAssemblyScanningEnabled | When enabled, MAUI will scan assemblies for types implementing `IVisual` and for `[assembly: Visual(...)]` attributes and register these types. | +| MauiShellSearchResultsRendererDisplayMemberNameSupported | Microsoft.Maui.RuntimeFeature.IsShellSearchResultsRendererDisplayMemberNameSupported | When disabled, it is necessary to always set `ItemTemplate` of any `SearchHandler`. Displaying search results through `DisplayMemberName` will not work. | +| MauiQueryPropertyAttributeSupport | Microsoft.Maui.RuntimeFeature.IsQueryPropertyAttributeSupported | When disabled, the `[QueryProperty(...)]` attributes won't be used to set values to properties when navigating. | +| MauiImplicitCastOperatorsUsageViaReflectionSupport | Microsoft.Maui.RuntimeFeature.IsImplicitCastOperatorsUsageViaReflectionSupported | When disabled, MAUI won't look for implicit cast operators when converting values from one type to another. This feature is not trim-compatible. | +| _MauiBindingInterceptorsSupport | Microsoft.Maui.RuntimeFeature.AreBindingInterceptorsSupported | When disabled, MAUI won't intercept any calls to `SetBinding` methods and try to compile them. Enabled by default. | +| MauiEnableXamlCBindingWithSourceCompilation | Microsoft.Maui.RuntimeFeature.XamlCBindingWithSourceCompilationEnabled | When enabled, MAUI will compile all bindings, including those where the `Source` property is used. | + +## MauiEnableIVisualAssemblyScanning + +When this feature is not enabled, custom and third party `IVisual` types will not be automatically discovered and registered. + +## MauiShellSearchResultsRendererDisplayMemberNameSupported + +When this feature is disabled, any value set to [`SearchHandler.DisplayMemberName`](https://learn.microsoft.com/dotnet/api/microsoft.maui.controls.searchhandler.displaymembername) will be ignored. Consider implementing a custom `ItemTemplate` to define the appearance of search results (see [Shell search documentation](https://learn.microsoft.com/dotnet/maui/fundamentals/shell/search#define-search-results-item-appearance)). + +## MauiQueryPropertyAttributeSupport + +When disabled, the `[QueryProperty(...)]` attributes won't be used to set values to properties when navigating. Instead, implement the [`IQueryAttributable`](https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/shell/navigation#process-navigation-data-using-a-single-method) interface whenever you need to accept query parameters. + +## MauiImplicitCastOperatorsUsageViaReflectionSupport + +When disabled, MAUI won't look for implicit cast operators when converting values from one type to another. This can affect the following scenarios: +- bindings between properties with different types, +- setting a property value of a bindable object with a value of different type. + +If your library or your app defines an implicit operator on a type that can be used in one of the previous scenarios, you should define a custom `TypeConverter` for your type and attach it to the type using the `[TypeConverter(typeof(MyTypeConverter))]` attribute. + +_Note: Prefer using the `TypeConverterAttribute` as it can help the trimmer achieve better binary size in certain scenarios._ + +## _MauiBindingInterceptorsSupport + +When enabled, MAUI will enable a source generator which will identify calls to the `SetBinding(this BindableObject target, BindableProperty property, Func getter, ...)` methods and generate optimized bindings based on the lambda expression passed as the `getter` parameter. + +This feature is a counterpart of [XAML Compiled bindings](https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings). + +It is necessary to use this feature instead of the string-based bindings in NativeAOT apps and in apps with full trimming enabled. + +### Example use-case + +String-based binding in code: +```c# +label.BindingContext = new PageViewModel { Customer = new CustomerViewModel { Name = "John" } }; +label.SetBinding(Label.TextProperty, "Customer.Name"); +``` + +Compiled binding in code: +```csharp +label.SetBinding(Label.TextProperty, static vm => vm.Customer.Name); +// or with type inference: +label.SetBinding(Label.TextProperty, static (PageViewModel vm) => vm.Customer.Name); +``` + +Compiled binding in XAML: +```xml + diff --git a/eng/Publishing.props b/eng/Publishing.props index a2ad98846735..388a242f3906 100644 --- a/eng/Publishing.props +++ b/eng/Publishing.props @@ -1,5 +1,6 @@ + 3 true \ No newline at end of file diff --git a/eng/Signing.props b/eng/Signing.props index 3eb8ded367d9..559e2aab3604 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -1,44 +1,26 @@ - - true true - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - + + - - - - - - - - - - - --> diff --git a/eng/Tools.props b/eng/Tools.props new file mode 100644 index 000000000000..3e275b8d8e3f --- /dev/null +++ b/eng/Tools.props @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 6e3506c7151f..adbf2d69c3b9 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,27 +1,50 @@ - + https://github.com/dotnet/xharness - 8c6d5afd99c713777165f4378462085a5679c223 + 8c0dc6866c1b786baf476dd767323b24f102bee4 - + https://github.com/dotnet/xharness - 8c6d5afd99c713777165f4378462085a5679c223 + 8c0dc6866c1b786baf476dd767323b24f102bee4 - + https://github.com/dotnet/xharness - 8c6d5afd99c713777165f4378462085a5679c223 + 8c0dc6866c1b786baf476dd767323b24f102bee4 - + https://github.com/dotnet/arcade - 60ae233c3d77f11c5fdb53e570b64d503b13ba59 + 05c72bb3c9b38138276a8029017f2ef905dcc7fa - + https://github.com/dotnet/arcade - 9f6799fdc16ae19b3e9478c55b997a6aab839d09 - + 05c72bb3c9b38138276a8029017f2ef905dcc7fa + + + https://github.com/dotnet/arcade + 05c72bb3c9b38138276a8029017f2ef905dcc7fa + + + https://github.com/dotnet/arcade + 05c72bb3c9b38138276a8029017f2ef905dcc7fa + + + https://github.com/dotnet/arcade + 05c72bb3c9b38138276a8029017f2ef905dcc7fa + + + https://github.com/dotnet/arcade + 05c72bb3c9b38138276a8029017f2ef905dcc7fa + + + https://github.com/dotnet/arcade + 05c72bb3c9b38138276a8029017f2ef905dcc7fa + + + https://github.com/dotnet/arcade + 05c72bb3c9b38138276a8029017f2ef905dcc7fa diff --git a/eng/Versions.props b/eng/Versions.props index 550a08d780a7..fe15f4ded00d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,12 +1,14 @@ - 8.0.99 - 8 + 9.0.0 + 9 0 - 99 - 8.0.100 - ci.net8 + 10 + 9.0.100 + ci.net9 + + true @@ -18,8 +20,7 @@ true + as for the patches and revisions should be manually updated per assembly if it is serviced. --> 1.0.0.0 false @@ -27,56 +28,76 @@ - 7.0.101 + 8.0.82 - 8.0.100 + 9.0.100-rc.2.24474.11 + $(MicrosoftNETSdkPackageVersion) - 8.0.0 + 9.0.0-rc.2.24473.5 $(MicrosoftNETCoreAppRefPackageVersion) $(MicrosoftNETCoreAppRefPackageVersion) $(MicrosoftNETCoreAppRefPackageVersion) $(MicrosoftNETCoreAppRefPackageVersion) - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 + 9.0.0-rc.2.24473.5 - 34.0.113 + 35.0.0-rc.2.152 - 17.5.8020 - 14.5.8020 - 17.5.8020 - 17.5.8020 + 18.0.9600-net9-rc2 + 15.0.9600-net9-rc2 + 18.0.9600-net9-rc2 + 18.0.9600-net9-rc2 - 8.0.130 + 8.0.148 - 8.0.0 + 9.0.0-rc.2.24468.8 + $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion) - 1.5.240802000 + 1.6.240923002 10.0.22621.756 1.2.0 + 1.0.2792.45 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 - 8.0.0 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + 9.0.0-rc.2.24474.3 + + 8.0.7 + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) + $(MicrosoftAspNetCorePackageVersion) - 8.0.0 + 9.0.0-preview* 3.3.4 3.3.4 3.0.1 @@ -86,14 +107,13 @@ 4.3.0 4.3.0 6.0.0 - <_MicrosoftWebWebView2Version>1.0.2592.51 - <_XamarinAndroidGlideVersion>4.15.1.2 - <_XamarinAndroidXSecurityVersion>1.1.0.1-alpha06 - <_XamarinGoogleCryptoTinkAndroidVersion>1.10.0 + <_XamarinAndroidGlideVersion>4.16.0.6 + <_XamarinAndroidXSecurityVersion>1.1.0.2-alpha06 + <_XamarinGoogleCryptoTinkAndroidVersion>1.15.0.1 - 118.1.0.3 + 119.0.0.2 diff --git a/eng/build.ps1 b/eng/build.ps1 new file mode 100644 index 000000000000..da8194d920c1 --- /dev/null +++ b/eng/build.ps1 @@ -0,0 +1,146 @@ +[CmdletBinding(PositionalBinding=$false)] +Param( + [switch][Alias('h')]$help, + [switch][Alias('t')]$test, + [ValidateSet("Debug","Release")][string[]][Alias('c')]$configuration = @("Debug"), + [string][Alias('v')]$verbosity = "minimal", + [switch]$vs, + [ValidateSet("windows","linux","osx")][string]$os, + [switch]$testnobuild, + [ValidateSet("x86","x64","arm","arm64")][string[]][Alias('a')]$arch = @([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant()), + + # Run tests with code coverage + [Parameter(ParameterSetName='CommandLine')] + [switch] $testCoverage, + + [Parameter(ValueFromRemainingArguments=$true)][String[]]$properties +) + +function Get-Help() { + Write-Host "Common settings:" + Write-Host " -arch (-a) Target platform: x86, x64, arm or arm64." + Write-Host " [Default: Your machine's architecture.]" + Write-Host " -binaryLog (-bl) Output binary log." + Write-Host " -configuration (-c) Build configuration: Debug or Release." + Write-Host " [Default: Debug]" + Write-Host " -help (-h) Print help and exit." + Write-Host " -os Target operating system: windows, linux or osx." + Write-Host " [Default: Your machine's OS.]" + Write-Host " -verbosity (-v) MSBuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]." + Write-Host " [Default: Minimal]" + Write-Host " -vs Open the solution with Visual Studio using the locally acquired SDK." + Write-Host "" + + Write-Host "Actions (defaults to -restore -build):" + Write-Host " -build (-b) Build all source projects." + Write-Host " This assumes -restore has been run already." + Write-Host " -clean Clean the solution." + Write-Host " -pack Package build outputs into NuGet packages." + Write-Host " -publish Publish artifacts (e.g. symbols)." + Write-Host " This assumes -build has been run already." + Write-Host " -rebuild Rebuild all source projects." + Write-Host " -restore Restore dependencies." + Write-Host " -sign Sign build outputs." + Write-Host " -test (-t) Incrementally builds and runs tests." + Write-Host " Use in conjunction with -testnobuild to only run tests." + Write-Host " -testCoverage Run unit tests and capture code coverage information." + Write-Host "" + + Write-Host "Libraries settings:" + Write-Host " -testnobuild Skip building tests when invoking -test." + Write-Host "" + + Write-Host "Command-line arguments not listed above are passed through to MSBuild." + Write-Host "The above arguments can be shortened as much as to be unambiguous." + Write-Host "(Example: -con for configuration, -t for test, etc.)." + Write-Host "" +} + +if ($help) { + Get-Help + exit 0 +} + +if ($vs) { + $solution = Split-Path $PSScriptRoot -Parent | Join-Path -ChildPath "xcsync.sln" + + . $PSScriptRoot\common\tools.ps1 + + # This tells .NET Core to use the bootstrapped runtime + $env:DOTNET_ROOT=InitializeDotNetCli -install:$true -createSdkLocationFile:$true + + # This tells MSBuild to load the SDK from the directory of the bootstrapped SDK + $env:DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR=$env:DOTNET_ROOT + + # Put our local dotnet.exe on PATH first so Visual Studio knows which one to use + $env:PATH=($env:DOTNET_ROOT + ";" + $env:PATH); + + # Launch Visual Studio with the locally defined environment variables + ."$solution" + + exit 0 +} + +# Check if an action is passed in +$actions = "b","build","r","restore","rebuild","sign","testnobuild","publish","clean" +$actionPassedIn = @(Compare-Object -ReferenceObject @($PSBoundParameters.Keys) -DifferenceObject $actions -ExcludeDifferent -IncludeEqual).Length -ne 0 +if ($null -ne $properties -and $actionPassedIn -ne $true) { + $actionPassedIn = @(Compare-Object -ReferenceObject $properties -DifferenceObject $actions.ForEach({ "-" + $_ }) -ExcludeDifferent -IncludeEqual).Length -ne 0 +} + +if (!$actionPassedIn) { + $arguments = "-restore -build" +} + +foreach ($argument in $PSBoundParameters.Keys) +{ + switch($argument) + { + "testCoverage" { <# this argument is handled in this script only #> } + "os" { $arguments += " /p:TargetOS=$($PSBoundParameters[$argument])" } + "properties" { $arguments += " " + $properties } + "verbosity" { $arguments += " -$argument " + $($PSBoundParameters[$argument]) } + "configuration" { $configuration = (Get-Culture).TextInfo.ToTitleCase($($PSBoundParameters[$argument])); $arguments += " -configuration $configuration" } + "arch" { $arguments += " /p:TargetArchitecture=$($PSBoundParameters[$argument])" } + default { $arguments += " /p:$argument=$($PSBoundParameters[$argument])" } + } +} + +if ($env:TreatWarningsAsErrors -eq 'false') { + $arguments += " -warnAsError 0" +} + +Write-Host "& `"$PSScriptRoot/common/build.ps1`" $arguments" +Invoke-Expression "& `"$PSScriptRoot/common/build.ps1`" $arguments" + + +# Perform code coverage as the last operation, this enables the following scenarios: +# .\build.cmd -restore -build -c Release -testCoverage +if ($testCoverage) { + try { + # Install required toolset + . $PSScriptRoot/common/tools.ps1 + InitializeDotNetCli -install $true | Out-Null + + Push-Location $PSScriptRoot/../ + + $testResultPath = "./artifacts/TestResults/$configuration"; + + # Run tests and collect code coverage + ./.dotnet/dotnet dotnet-coverage collect --settings ./eng/CodeCoverage.config --output $testResultPath/local.cobertura.xml "build.cmd -test -configuration $configuration" + + # Generate the code coverage report and open it in the browser + ./.dotnet/dotnet reportgenerator -reports:$testResultPath/*.cobertura.xml -targetdir:$testResultPath/CoverageResultsHtml -reporttypes:HtmlInline_AzurePipelines + Start-Process $testResultPath/CoverageResultsHtml/index.html + } + catch { + Write-Host $_.Exception.Message -Foreground "Red" + Write-Host $_.ScriptStackTrace -Foreground "DarkGray" + exit $global:LASTEXITCODE; + } + finally { + Pop-Location + } +} + +exit 0 \ No newline at end of file diff --git a/eng/build.sh b/eng/build.sh new file mode 100755 index 000000000000..e1883c70e83c --- /dev/null +++ b/eng/build.sh @@ -0,0 +1,182 @@ +#!/usr/bin/env bash + +set -ue + +source="${BASH_SOURCE[0]}" + +# resolve $source until the file is no longer a symlink +while [[ -h "$source" ]]; do + scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + source="$(readlink "$source")" + # if $source was a relative symlink, we need to resolve it relative to the path where the + # symlink file was located + [[ $source != /* ]] && source="$scriptroot/$source" +done +scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + +usage() +{ + echo "Common settings:" + echo " --arch (-a) Target platform: x86, x64, arm or arm64." + echo " [Default: Your machine's architecture.]" + echo " --binaryLog (-bl) Output binary log." + echo " --configuration (-c) Build configuration: Debug or Release." + echo " [Default: Debug]" + echo " --help (-h) Print help and exit." + echo " --os Target operating system: windows, linux, or osx." + echo " [Default: Your machine's OS.]" + echo " --verbosity (-v) MSBuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]." + echo " [Default: Minimal]" + echo "" + + echo "Actions (defaults to --restore --build):" + echo " --build (-b) Build all source projects." + echo " This assumes --restore has been run already." + echo " --clean Clean the solution." + echo " --pack Package build outputs into NuGet packages." + echo " --publish Publish artifacts (e.g. symbols)." + echo " This assumes --build has been run already." + echo " --rebuild Rebuild all source projects." + echo " --restore (-r) Restore dependencies." + echo " --sign Sign build outputs." + echo " --test (-t) Incrementally builds and runs tests." + echo " Use in conjunction with --testnobuild to only run tests." + echo " --testCoverage Run unit tests and capture code coverage information." + echo "" + + echo "Libraries settings:" + echo " --testnobuild Skip building tests when invoking -test." + echo "" + + echo "Command line arguments starting with '/p:' are passed through to MSBuild." + echo "Arguments can also be passed in with a single hyphen." + echo "" +} + +arguments='' +extraargs='' +testCoverage=false + +# Check if an action is passed in +declare -a actions=("b" "build" "r" "restore" "rebuild" "testnobuild" "sign" "publish" "clean") +actInt=($(comm -12 <(printf '%s\n' "${actions[@]/#/-}" | sort) <(printf '%s\n' "${@/#--/-}" | sort))) + +while [[ $# > 0 ]]; do + opt="$(echo "${1/#--/-}" | tr "[:upper:]" "[:lower:]")" + + case "$opt" in + -help|-h|-\?|/?) + usage + exit 0 + ;; + + -arch|-a) + if [ -z ${2+x} ]; then + echo "No architecture supplied. See help (--help) for supported architectures." 1>&2 + exit 1 + fi + passedArch="$(echo "$2" | tr "[:upper:]" "[:lower:]")" + case "$passedArch" in + x64|x86|arm|arm64) + arch=$passedArch + ;; + *) + echo "Unsupported target architecture '$2'." + echo "The allowed values are x86, x64, arm, arm64." + exit 1 + ;; + esac + arguments="$arguments /p:TargetArchitecture=$arch" + shift 2 + ;; + + -configuration|-c) + if [ -z ${2+x} ]; then + echo "No configuration supplied. See help (--help) for supported configurations." 1>&2 + exit 1 + fi + passedConfig="$(echo "$2" | tr "[:upper:]" "[:lower:]")" + case "$passedConfig" in + debug|release) + val="$(tr '[:lower:]' '[:upper:]' <<< ${passedConfig:0:1})${passedConfig:1}" + ;; + *) + echo "Unsupported target configuration '$2'." + echo "The allowed values are Debug and Release." + exit 1 + ;; + esac + arguments="$arguments -configuration $val" + shift 2 + ;; + + -os) + if [ -z ${2+x} ]; then + echo "No target operating system supplied. See help (--help) for supported target operating systems." 1>&2 + exit 1 + fi + passedOS="$(echo "$2" | tr "[:upper:]" "[:lower:]")" + case "$passedOS" in + windows) + os="windows" ;; + linux) + os="linux" ;; + osx) + os="osx" ;; + *) + echo "Unsupported target OS '$2'." + echo "Try 'build.sh --help' for values supported by '--os'." + exit 1 + ;; + esac + arguments="$arguments /p:TargetOS=$os" + shift 2 + ;; + + -testnobuild) + arguments="$arguments /p:TestNoBuild=true" + shift 1 + ;; + + -testcoverage) + testCoverage=true + ;; + + *) + extraargs="$extraargs $1" + shift 1 + ;; + esac +done + +if [ ${#actInt[@]} -eq 0 ]; then + arguments="-restore -build $arguments" +fi + +if [[ "${TreatWarningsAsErrors:-}" == "false" ]]; then + arguments="$arguments -warnAsError 0" +fi + +arguments="$arguments $extraargs" +"$scriptroot/common/build.sh" $arguments + + +# Perform code coverage as the last operation, this enables the following scenarios: +# .\build.sh --restore --build --c Release --testCoverage +if [[ "$testCoverage" == true ]]; then + # Install required toolset + . "$DIR/common/tools.sh" + InitializeDotNetCli true > /dev/null + + repoRoot=$(realpath $DIR/../) + testResultPath="$repoRoot/artifacts/TestResults/$configuration" + + # Run tests and collect code coverage + $repoRoot/.dotnet/dotnet 'dotnet-coverage' collect --settings $repoRoot/eng/CodeCoverage.config --output $testResultPath/local.cobertura.xml "$repoRoot/build.sh --test --configuration $configuration" + + # Generate the code coverage report and open it in the browser + $repoRoot/.dotnet/dotnet reportgenerator -reports:$testResultPath/*.cobertura.xml -targetdir:$testResultPath/CoverageResultsHtml -reporttypes:HtmlInline_AzurePipelines + echo "" + echo -e "\e[32mCode coverage results:\e[0m $testResultPath/CoverageResultsHtml/index.html" + echo "" +fi \ No newline at end of file diff --git a/eng/cake/dotnet.cake b/eng/cake/dotnet.cake index b44ec9b05e4a..2ea746497bbf 100644 --- a/eng/cake/dotnet.cake +++ b/eng/cake/dotnet.cake @@ -3,7 +3,7 @@ // Contains .NET - related Cake targets var ext = IsRunningOnWindows() ? ".exe" : ""; -var dotnetPath = $"./bin/dotnet/dotnet{ext}"; +var dotnetPath = $"./.dotnet/dotnet{ext}"; string configuration = GetBuildVariable("configuration", GetBuildVariable("BUILD_CONFIGURATION", "DEBUG")); var localDotnet = GetBuildVariable("workloads", "local") == "local"; var vsVersion = GetBuildVariable("VS", ""); @@ -36,6 +36,14 @@ var NuGetOnlyPackages = new string[] { "Microsoft.Maui.Resizetizer.*.{nupkg,snupkg}", "Microsoft.AspNetCore.Components.WebView.*.{nupkg,snupkg}", }; +public enum RuntimeVariant +{ + Mono, + NativeAOT +} + +RuntimeVariant RUNTIME_VARIANT = Argument("runtimevariant", RuntimeVariant.Mono); +bool USE_NATIVE_AOT = RUNTIME_VARIANT == RuntimeVariant.NativeAOT ? true : false; ProcessTFMSwitches(); @@ -178,7 +186,27 @@ Task("dotnet-samples") ["RestoreConfigFile"] = tempDir.CombineWithFilePath("NuGet.config").FullPath, }; } - RunMSBuildWithDotNet("./Microsoft.Maui.Samples.slnf", properties, binlogPrefix: "sample-"); + + string projectsToBuild; + if (USE_NATIVE_AOT) + { + if (configuration.Equals("Debug", StringComparison.OrdinalIgnoreCase)) + { + var errMsg = $"Error: Building dotnet-samples with NativeAOT is only supported in Release configuration"; + Error(errMsg); + throw new Exception(errMsg); + } + projectsToBuild = "./src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj"; + properties["_UseNativeAot"] = "true"; + properties["RuntimeIdentifier"] = "iossimulator-x64"; + properties["BuildIpa"] = "true"; + } + else + { + projectsToBuild = "./Microsoft.Maui.Samples.slnf"; + } + + RunMSBuildWithDotNet(projectsToBuild, properties, binlogPrefix: "sample-"); }); // Builds the host app for the UI Tests @@ -247,9 +275,10 @@ Task("dotnet-test") var tests = new [] { "**/Controls.Core.UnitTests.csproj", - "**/Controls.Core.Design.UnitTests.csproj", + // "**/Controls.Core.Design.UnitTests.csproj", "**/Controls.Xaml.UnitTests.csproj", "**/SourceGen.UnitTests.csproj", + "**/Controls.BindingSourceGen.UnitTests.csproj", "**/Core.UnitTests.csproj", "**/Essentials.UnitTests.csproj", "**/Resizetizer.UnitTests.csproj", @@ -269,11 +298,12 @@ Task("dotnet-test") { try { - RunTestWithLocalDotNet(project.FullPath); + RunTestWithLocalDotNet(project.FullPath, configuration, dotnetPath); } catch { success = false; + Error($"Test project failed: {project}"); } } } @@ -549,7 +579,7 @@ bool RunPackTarget() Dictionary GetDotNetEnvironmentVariables() { Dictionary envVariables = new Dictionary(); - var dotnet = MakeAbsolute(Directory("./bin/dotnet/")).ToString(); + var dotnet = MakeAbsolute(Directory("./.dotnet/")).ToString(); envVariables.Add("DOTNET_INSTALL_DIR", dotnet); envVariables.Add("DOTNET_ROOT", dotnet); @@ -568,10 +598,11 @@ Dictionary GetDotNetEnvironmentVariables() return envVariables; } -void SetDotNetEnvironmentVariables() +void SetDotNetEnvironmentVariables(string dotnetDir = null) { - var dotnet = MakeAbsolute(Directory("./bin/dotnet/")).ToString(); + var dotnet = dotnetDir ?? MakeAbsolute(Directory("./.dotnet/")).ToString(); + SetEnvironmentVariable("VSDebugger_ValidateDotnetDebugLibSignatures", "0"); SetEnvironmentVariable("DOTNET_INSTALL_DIR", dotnet); SetEnvironmentVariable("DOTNET_ROOT", dotnet); SetEnvironmentVariable("DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR", dotnet); @@ -693,7 +724,10 @@ void RunMSBuildWithDotNet( .SetConfiguration(configuration) .SetMaxCpuCount(maxCpuCount) .WithTarget(target) - .EnableBinaryLogger(binlog); + .EnableBinaryLogger(binlog) + + // .SetVerbosity(Verbosity.Diagnostic) + ; if (warningsAsError) { @@ -720,9 +754,7 @@ void RunMSBuildWithDotNet( if (!string.IsNullOrEmpty(targetFramework)) args.Append($"-f {targetFramework}"); - - //args.Append("/tl"); - + return args; }; @@ -732,15 +764,7 @@ void RunMSBuildWithDotNet( DotNetBuild(sln, dotnetBuildSettings); } -void RunTestWithLocalDotNet(string csproj) -{ - if(localDotnet) - SetDotNetEnvironmentVariables(); - - RunTestWithLocalDotNet(csproj, configuration, dotnetPath, argsExtra: null, noBuild: true, resultsFileNameWithoutExtension: null); -} - -void RunTestWithLocalDotNet(string csproj, string config, string pathDotnet = null, Dictionary argsExtra = null, bool noBuild = false, string resultsFileNameWithoutExtension = null, string filter = "") +void RunTestWithLocalDotNet(string csproj, string config, string pathDotnet = null, Dictionary argsExtra = null, bool noBuild = false, string resultsFileNameWithoutExtension = null, string filter = "", int maxCpuCount = 0) { if (string.IsNullOrWhiteSpace(filter)) { @@ -757,6 +781,15 @@ void RunTestWithLocalDotNet(string csproj, string config, string pathDotnet = nu var name = System.IO.Path.GetFileNameWithoutExtension(csproj); var logDirectory = GetLogDirectory(); + if (!string.IsNullOrWhiteSpace(pathDotnet) && localDotnet) + { + // Make sure the path doesn't refer to the dotnet executable and make path absolute + var localDotnetRoot = MakeAbsolute(Directory(System.IO.Path.GetDirectoryName(pathDotnet))); + Information("new dotnet root: {0}", localDotnetRoot); + + SetDotNetEnvironmentVariables(localDotnetRoot.FullPath); + } + if (string.IsNullOrWhiteSpace(resultsFileNameWithoutExtension)) { binlog = $"{logDirectory}/{name}-{config}.binlog"; @@ -780,18 +813,26 @@ void RunTestWithLocalDotNet(string csproj, string config, string pathDotnet = nu $"console;verbosity=normal" }, ResultsDirectory = GetTestResultsDirectory(), - //Verbosity = Cake.Common.Tools.DotNetCore.DotNetCoreVerbosity.Diagnostic, + // Verbosity = Cake.Common.Tools.DotNetCore.DotNetCoreVerbosity.Diagnostic, ArgumentCustomization = args => { args.Append($"-bl:{binlog}"); - // args.Append($"/tl"); + if(maxCpuCount > 0) + { + args.Append($"-maxcpucount:{maxCpuCount}"); + } + if(argsExtra != null) { foreach(var prop in argsExtra) { args.Append($"/p:{prop.Key}={prop.Value}"); - } - } + } + } + + // https://github.com/microsoft/vstest/issues/5112 + args.Append($"/p:VStestUseMSBuildOutput=false"); + return args; } }; @@ -801,7 +842,11 @@ void RunTestWithLocalDotNet(string csproj, string config, string pathDotnet = nu settings.ToolPath = pathDotnet; } - DotNetTest(csproj, settings); + try { + DotNetTest(csproj, settings); + } finally { + Information("Test Run complete: {0}", results); + } } DirectoryPath PrepareSeparateBuildContext(string dirName, string props = null, string targets = null) diff --git a/eng/cake/helpers.cake b/eng/cake/helpers.cake index 3037497718af..d299c3d7421c 100644 --- a/eng/cake/helpers.cake +++ b/eng/cake/helpers.cake @@ -92,18 +92,6 @@ public void PrintEnvironmentVariables() }; } -void SetDotNetEnvironmentVariables(string dotnetDir) -{ - var dotnet = dotnetDir ?? MakeAbsolute(Directory("./bin/dotnet/")).ToString(); - - SetEnvironmentVariable("DOTNET_INSTALL_DIR", dotnet); - SetEnvironmentVariable("DOTNET_ROOT", dotnet); - SetEnvironmentVariable("DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR", dotnet); - SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0"); - SetEnvironmentVariable("MSBuildEnableWorkloadResolver", "true"); - SetEnvironmentVariable("PATH", dotnet, prepend: true); -} - void SetEnvironmentVariable(string name, string value, bool prepend = false) { var target = EnvironmentVariableTarget.Process; diff --git a/eng/common/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1 index efa2fd72bfaa..5db4ad71ee2f 100644 --- a/eng/common/SetupNugetSources.ps1 +++ b/eng/common/SetupNugetSources.ps1 @@ -1,17 +1,10 @@ -# This file is a temporary workaround for internal builds to be able to restore from private AzDO feeds. -# This file should be removed as part of this issue: https://github.com/dotnet/arcade/issues/4080 +# This script adds internal feeds required to build commits that depend on internal package sources. For instance, +# dotnet6-internal would be added automatically if dotnet6 was found in the nuget.config file. In addition also enables +# disabled internal Maestro (darc-int*) feeds. # -# What the script does is iterate over all package sources in the pointed NuGet.config and add a credential entry -# under for each Maestro managed private feed. Two additional credential -# entries are also added for the two private static internal feeds: dotnet3-internal and dotnet3-internal-transport. +# Optionally, this script also adds a credential entry for each of the internal feeds if supplied. # -# This script needs to be called in every job that will restore packages and which the base repo has -# private AzDO feeds in the NuGet.config. -# -# See example YAML call for this script below. Note the use of the variable `$(dn-bot-dnceng-artifact-feeds-rw)` -# from the AzureDevOps-Artifact-Feeds-Pats variable group. -# -# Any disabledPackageSources entries which start with "darc-int" will be re-enabled as part of this script executing +# See example call for this script below. # # - task: PowerShell@2 # displayName: Setup Private Feeds Credentials @@ -21,11 +14,18 @@ # arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token # env: # Token: $(dn-bot-dnceng-artifact-feeds-rw) +# +# Note that the NuGetAuthenticate task should be called after SetupNugetSources. +# This ensures that: +# - Appropriate creds are set for the added internal feeds (if not supplied to the scrupt) +# - The credential provider is installed. +# +# This logic is also abstracted into enable-internal-sources.yml. [CmdletBinding()] param ( [Parameter(Mandatory = $true)][string]$ConfigFile, - [Parameter(Mandatory = $true)][string]$Password + $Password ) $ErrorActionPreference = "Stop" @@ -48,11 +48,17 @@ function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Usern else { Write-Host "Package source $SourceName already present." } + AddCredential -Creds $creds -Source $SourceName -Username $Username -pwd $pwd } # Add a credential node for the specified source function AddCredential($creds, $source, $username, $pwd) { + # If no cred supplied, don't do anything. + if (!$pwd) { + return; + } + # Looks for credential configuration for the given SourceName. Create it if none is found. $sourceElement = $creds.SelectSingleNode($Source) if ($sourceElement -eq $null) @@ -110,11 +116,6 @@ if (!(Test-Path $ConfigFile -PathType Leaf)) { ExitWithExitCode 1 } -if (!$Password) { - Write-PipelineTelemetryError -Category 'Build' -Message 'Eng/common/SetupNugetSources.ps1 returned a non-zero exit code. Please supply a valid PAT' - ExitWithExitCode 1 -} - # Load NuGet.config $doc = New-Object System.Xml.XmlDocument $filename = (Get-Item $ConfigFile).FullName @@ -127,11 +128,14 @@ if ($sources -eq $null) { $doc.DocumentElement.AppendChild($sources) | Out-Null } -# Looks for a node. Create it if none is found. -$creds = $doc.DocumentElement.SelectSingleNode("packageSourceCredentials") -if ($creds -eq $null) { - $creds = $doc.CreateElement("packageSourceCredentials") - $doc.DocumentElement.AppendChild($creds) | Out-Null +$creds = $null +if ($Password) { + # Looks for a node. Create it if none is found. + $creds = $doc.DocumentElement.SelectSingleNode("packageSourceCredentials") + if ($creds -eq $null) { + $creds = $doc.CreateElement("packageSourceCredentials") + $doc.DocumentElement.AppendChild($creds) | Out-Null + } } # Check for disabledPackageSources; we'll enable any darc-int ones we find there @@ -153,7 +157,7 @@ if ($dotnet31Source -ne $null) { AddPackageSource -Sources $sources -SourceName "dotnet3.1-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v2" -Creds $creds -Username $userName -pwd $Password } -$dotnetVersions = @('5','6','7','8') +$dotnetVersions = @('5','6','7','8','9') foreach ($dotnetVersion in $dotnetVersions) { $feedPrefix = "dotnet" + $dotnetVersion; @@ -164,4 +168,4 @@ foreach ($dotnetVersion in $dotnetVersions) { } } -$doc.Save($filename) \ No newline at end of file +$doc.Save($filename) diff --git a/eng/common/SetupNugetSources.sh b/eng/common/SetupNugetSources.sh index d387c7eac95e..4604b61b0323 100755 --- a/eng/common/SetupNugetSources.sh +++ b/eng/common/SetupNugetSources.sh @@ -1,28 +1,27 @@ #!/usr/bin/env bash -# This file is a temporary workaround for internal builds to be able to restore from private AzDO feeds. -# This file should be removed as part of this issue: https://github.com/dotnet/arcade/issues/4080 +# This script adds internal feeds required to build commits that depend on internal package sources. For instance, +# dotnet6-internal would be added automatically if dotnet6 was found in the nuget.config file. In addition also enables +# disabled internal Maestro (darc-int*) feeds. +# +# Optionally, this script also adds a credential entry for each of the internal feeds if supplied. # -# What the script does is iterate over all package sources in the pointed NuGet.config and add a credential entry -# under for each Maestro's managed private feed. Two additional credential -# entries are also added for the two private static internal feeds: dotnet3-internal and dotnet3-internal-transport. -# -# This script needs to be called in every job that will restore packages and which the base repo has -# private AzDO feeds in the NuGet.config. -# -# See example YAML call for this script below. Note the use of the variable `$(dn-bot-dnceng-artifact-feeds-rw)` -# from the AzureDevOps-Artifact-Feeds-Pats variable group. -# -# Any disabledPackageSources entries which start with "darc-int" will be re-enabled as part of this script executing. +# See example call for this script below. # # - task: Bash@3 -# displayName: Setup Private Feeds Credentials +# displayName: Setup Internal Feeds # inputs: # filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh -# arguments: $(Build.SourcesDirectory)/NuGet.config $Token +# arguments: $(Build.SourcesDirectory)/NuGet.config # condition: ne(variables['Agent.OS'], 'Windows_NT') -# env: -# Token: $(dn-bot-dnceng-artifact-feeds-rw) +# - task: NuGetAuthenticate@1 +# +# Note that the NuGetAuthenticate task should be called after SetupNugetSources. +# This ensures that: +# - Appropriate creds are set for the added internal feeds (if not supplied to the scrupt) +# - The credential provider is installed. +# +# This logic is also abstracted into enable-internal-sources.yml. ConfigFile=$1 CredToken=$2 @@ -48,11 +47,6 @@ if [ ! -f "$ConfigFile" ]; then ExitWithExitCode 1 fi -if [ -z "$CredToken" ]; then - Write-PipelineTelemetryError -category 'Build' "Error: Eng/common/SetupNugetSources.sh returned a non-zero exit code. Please supply a valid PAT" - ExitWithExitCode 1 -fi - if [[ `uname -s` == "Darwin" ]]; then NL=$'\\\n' TB='' @@ -105,7 +99,7 @@ if [ "$?" == "0" ]; then PackageSources+=('dotnet3.1-internal-transport') fi -DotNetVersions=('5' '6' '7' '8') +DotNetVersions=('5' '6' '7' '8' '9') for DotNetVersion in ${DotNetVersions[@]} ; do FeedPrefix="dotnet${DotNetVersion}"; @@ -140,18 +134,20 @@ PackageSources+="$IFS" PackageSources+=$(grep -oh '"darc-int-[^"]*"' $ConfigFile | tr -d '"') IFS=$PrevIFS -for FeedName in ${PackageSources[@]} ; do - # Check if there is no existing credential for this FeedName - grep -i "<$FeedName>" $ConfigFile - if [ "$?" != "0" ]; then - echo "Adding credentials for $FeedName." +if [ "$CredToken" ]; then + for FeedName in ${PackageSources[@]} ; do + # Check if there is no existing credential for this FeedName + grep -i "<$FeedName>" $ConfigFile + if [ "$?" != "0" ]; then + echo "Adding credentials for $FeedName." - PackageSourceCredentialsNodeFooter="" - NewCredential="${TB}${TB}<$FeedName>${NL}${NL}${NL}" + PackageSourceCredentialsNodeFooter="" + NewCredential="${TB}${TB}<$FeedName>${NL}${NL}${NL}" - sed -i.bak "s|$PackageSourceCredentialsNodeFooter|$NewCredential${NL}$PackageSourceCredentialsNodeFooter|" $ConfigFile - fi -done + sed -i.bak "s|$PackageSourceCredentialsNodeFooter|$NewCredential${NL}$PackageSourceCredentialsNodeFooter|" $ConfigFile + fi + done +fi # Re-enable any entries in disabledPackageSources where the feed name contains darc-int grep -i "" $ConfigFile diff --git a/eng/common/build.cmd b/eng/common/build.cmd new file mode 100644 index 000000000000..99daf368abae --- /dev/null +++ b/eng/common/build.cmd @@ -0,0 +1,3 @@ +@echo off +powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0build.ps1""" %*" +exit /b %ErrorLevel% diff --git a/eng/common/build.ps1 b/eng/common/build.ps1 index 33a6f2d0e248..438f9920c43e 100644 --- a/eng/common/build.ps1 +++ b/eng/common/build.ps1 @@ -19,6 +19,7 @@ Param( [switch] $pack, [switch] $publish, [switch] $clean, + [switch][Alias('pb')]$productBuild, [switch][Alias('bl')]$binaryLog, [switch][Alias('nobl')]$excludeCIBinarylog, [switch] $ci, @@ -58,6 +59,7 @@ function Print-Usage() { Write-Host " -sign Sign build outputs" Write-Host " -publish Publish artifacts (e.g. symbols)" Write-Host " -clean Clean the solution" + Write-Host " -productBuild Build the solution in the way it will be built in the full .NET product (VMR) build (short: -pb)" Write-Host "" Write-Host "Advanced settings:" @@ -120,6 +122,7 @@ function Build { /p:Deploy=$deploy ` /p:Test=$test ` /p:Pack=$pack ` + /p:DotNetBuildRepo=$productBuild ` /p:IntegrationTest=$integrationTest ` /p:PerformanceTest=$performanceTest ` /p:Sign=$sign ` diff --git a/eng/common/build.sh b/eng/common/build.sh index 50af40cdd2ce..ac1ee8620cd2 100755 --- a/eng/common/build.sh +++ b/eng/common/build.sh @@ -22,6 +22,9 @@ usage() echo " --sourceBuild Source-build the solution (short: -sb)" echo " Will additionally trigger the following actions: --restore, --build, --pack" echo " If --configuration is not set explicitly, will also set it to 'Release'" + echo " --productBuild Build the solution in the way it will be built in the full .NET product (VMR) build (short: -pb)" + echo " Will additionally trigger the following actions: --restore, --build, --pack" + echo " If --configuration is not set explicitly, will also set it to 'Release'" echo " --rebuild Rebuild solution" echo " --test Run all unit tests in the solution (short: -t)" echo " --integrationTest Run all integration tests in the solution" @@ -59,6 +62,7 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" restore=false build=false source_build=false +product_build=false rebuild=false test=false integration_test=false @@ -105,7 +109,7 @@ while [[ $# > 0 ]]; do -binarylog|-bl) binary_log=true ;; - -excludeCIBinarylog|-nobl) + -excludecibinarylog|-nobl) exclude_ci_binary_log=true ;; -pipelineslog|-pl) @@ -126,6 +130,13 @@ while [[ $# > 0 ]]; do -sourcebuild|-sb) build=true source_build=true + product_build=true + restore=true + pack=true + ;; + -productBuild|-pb) + build=true + product_build=true restore=true pack=true ;; @@ -219,7 +230,9 @@ function Build { /p:RepoRoot="$repo_root" \ /p:Restore=$restore \ /p:Build=$build \ + /p:DotNetBuildRepo=$product_build \ /p:ArcadeBuildFromSource=$source_build \ + /p:DotNetBuildSourceOnly=$source_build \ /p:Rebuild=$rebuild \ /p:Test=$test \ /p:Pack=$pack \ diff --git a/eng/common/core-templates/job/job.yml b/eng/common/core-templates/job/job.yml new file mode 100644 index 000000000000..ba53ebfbd513 --- /dev/null +++ b/eng/common/core-templates/job/job.yml @@ -0,0 +1,247 @@ +parameters: +# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + cancelTimeoutInMinutes: '' + condition: '' + container: '' + continueOnError: false + dependsOn: '' + displayName: '' + pool: '' + steps: [] + strategy: '' + timeoutInMinutes: '' + variables: [] + workspace: '' + templateContext: {} + +# Job base template specific parameters + # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md + # publishing defaults + artifacts: '' + enableMicrobuild: false + enablePublishBuildArtifacts: false + enablePublishBuildAssets: false + enablePublishTestResults: false + enablePublishUsingPipelines: false + enableBuildRetry: false + mergeTestResults: false + testRunTitle: '' + testResultsFormat: '' + name: '' + componentGovernanceSteps: [] + preSteps: [] + artifactPublishSteps: [] + runAsPublic: false + +# 1es specific parameters + is1ESPipeline: '' + +jobs: +- job: ${{ parameters.name }} + + ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: + cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} + + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} + + ${{ if ne(parameters.container, '') }}: + container: ${{ parameters.container }} + + ${{ if ne(parameters.continueOnError, '') }}: + continueOnError: ${{ parameters.continueOnError }} + + ${{ if ne(parameters.dependsOn, '') }}: + dependsOn: ${{ parameters.dependsOn }} + + ${{ if ne(parameters.displayName, '') }}: + displayName: ${{ parameters.displayName }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + + ${{ if ne(parameters.strategy, '') }}: + strategy: ${{ parameters.strategy }} + + ${{ if ne(parameters.timeoutInMinutes, '') }}: + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + + ${{ if ne(parameters.templateContext, '') }}: + templateContext: ${{ parameters.templateContext }} + + variables: + - ${{ if ne(parameters.enableTelemetry, 'false') }}: + - name: DOTNET_CLI_TELEMETRY_PROFILE + value: '$(Build.Repository.Uri)' + - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: + - name: EnableRichCodeNavigation + value: 'true' + # Retry signature validation up to three times, waiting 2 seconds between attempts. + # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures + - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY + value: 3,2000 + - ${{ each variable in parameters.variables }}: + # handle name-value variable syntax + # example: + # - name: [key] + # value: [value] + - ${{ if ne(variable.name, '') }}: + - name: ${{ variable.name }} + value: ${{ variable.value }} + + # handle variable groups + - ${{ if ne(variable.group, '') }}: + - group: ${{ variable.group }} + + # handle template variable syntax + # example: + # - template: path/to/template.yml + # parameters: + # [key]: [value] + - ${{ if ne(variable.template, '') }}: + - template: ${{ variable.template }} + ${{ if ne(variable.parameters, '') }}: + parameters: ${{ variable.parameters }} + + # handle key-value variable syntax. + # example: + # - [key]: [value] + - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: + - ${{ each pair in variable }}: + - name: ${{ pair.key }} + value: ${{ pair.value }} + + # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds + - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - group: DotNet-HelixApi-Access + + ${{ if ne(parameters.workspace, '') }}: + workspace: ${{ parameters.workspace }} + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if ne(parameters.preSteps, '') }}: + - ${{ each preStep in parameters.preSteps }}: + - ${{ preStep }} + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - task: MicroBuildSigningPlugin@4 + displayName: Install MicroBuild plugin + inputs: + signType: $(_SignType) + zipSources: false + feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json + env: + TeamName: $(_TeamName) + MicroBuildOutputFolderOverride: '$(Agent.TempDirectory)' + continueOnError: ${{ parameters.continueOnError }} + condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + + - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: + - task: NuGetAuthenticate@1 + + - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: + - task: DownloadPipelineArtifact@2 + inputs: + buildType: current + artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} + targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} + itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} + + - ${{ each step in parameters.steps }}: + - ${{ step }} + + - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: + - task: RichCodeNavIndexer@0 + displayName: RichCodeNav Upload + inputs: + languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} + environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'internal') }} + richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin + uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} + continueOnError: true + + - ${{ each step in parameters.componentGovernanceSteps }}: + - ${{ step }} + + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - task: MicroBuildCleanup@1 + displayName: Execute Microbuild cleanup tasks + condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + env: + TeamName: $(_TeamName) + + # Publish test results + - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: + - task: PublishTestResults@2 + displayName: Publish XUnit Test Results + inputs: + testResultsFormat: 'xUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() + - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: + - task: PublishTestResults@2 + displayName: Publish TRX Test Results + inputs: + testResultsFormat: 'VSTest' + testResultsFiles: '*.trx' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() + + # gather artifacts + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - task: CopyFiles@2 + displayName: Gather binaries for publish to artifacts + inputs: + SourceFolder: 'artifacts/bin' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' + - task: CopyFiles@2 + displayName: Gather packages for publish to artifacts + inputs: + SourceFolder: 'artifacts/packages' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - task: CopyFiles@2 + displayName: Gather logs for publish to artifacts + inputs: + SourceFolder: 'artifacts/log' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log' + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: + - task: CopyFiles@2 + displayName: Gather logs for publish to artifacts + inputs: + SourceFolder: 'artifacts/log/$(_BuildConfig)' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + continueOnError: true + condition: always() + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - task: CopyFiles@2 + displayName: Gather buildconfiguration for build retry + inputs: + SourceFolder: '$(Build.SourcesDirectory)/eng/common/BuildConfiguration' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/eng/common/BuildConfiguration' + continueOnError: true + condition: always() + - ${{ each step in parameters.artifactPublishSteps }}: + - ${{ step }} diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml new file mode 100644 index 000000000000..00feec8ebbc3 --- /dev/null +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -0,0 +1,121 @@ +parameters: + # Optional: dependencies of the job + dependsOn: '' + + # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool + pool: '' + + CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex + GithubPat: $(BotAccount-dotnet-bot-repo-PAT) + + SourcesDirectory: $(Build.SourcesDirectory) + CreatePr: true + AutoCompletePr: false + ReusePr: true + UseLfLineEndings: true + UseCheckedInLocProjectJson: false + SkipLocProjectJsonGeneration: false + LanguageSet: VS_Main_Languages + LclSource: lclFilesInRepo + LclPackageId: '' + RepoType: gitHub + GitHubOrg: dotnet + MirrorRepo: '' + MirrorBranch: main + condition: '' + JobNameSuffix: '' + is1ESPipeline: '' +jobs: +- job: OneLocBuild${{ parameters.JobNameSuffix }} + + dependsOn: ${{ parameters.dependsOn }} + + displayName: OneLocBuild${{ parameters.JobNameSuffix }} + + variables: + - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat + - name: _GenerateLocProjectArguments + value: -SourcesDirectory ${{ parameters.SourcesDirectory }} + -LanguageSet "${{ parameters.LanguageSet }}" + -CreateNeutralXlfs + - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: + - name: _GenerateLocProjectArguments + value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: + - task: Powershell@2 + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 + arguments: $(_GenerateLocProjectArguments) + displayName: Generate LocProject.json + condition: ${{ parameters.condition }} + + - task: OneLocBuild@2 + displayName: OneLocBuild + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + inputs: + locProj: eng/Localize/LocProject.json + outDir: $(Build.ArtifactStagingDirectory) + lclSource: ${{ parameters.LclSource }} + lclPackageId: ${{ parameters.LclPackageId }} + isCreatePrSelected: ${{ parameters.CreatePr }} + isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} + ${{ if eq(parameters.CreatePr, true) }}: + isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} + ${{ if eq(parameters.RepoType, 'gitHub') }}: + isShouldReusePrSelected: ${{ parameters.ReusePr }} + packageSourceAuth: patAuth + patVariable: ${{ parameters.CeapexPat }} + ${{ if eq(parameters.RepoType, 'gitHub') }}: + repoType: ${{ parameters.RepoType }} + gitHubPatVariable: "${{ parameters.GithubPat }}" + ${{ if ne(parameters.MirrorRepo, '') }}: + isMirrorRepoSelected: true + gitHubOrganization: ${{ parameters.GitHubOrg }} + mirrorRepo: ${{ parameters.MirrorRepo }} + mirrorBranch: ${{ parameters.MirrorBranch }} + condition: ${{ parameters.condition }} + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish Localization Files + pathToPublish: '$(Build.ArtifactStagingDirectory)/loc' + publishLocation: Container + artifactName: Loc + condition: ${{ parameters.condition }} + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish LocProject.json + pathToPublish: '$(Build.SourcesDirectory)/eng/Localize/' + publishLocation: Container + artifactName: Loc + condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml new file mode 100644 index 000000000000..3d3356e31967 --- /dev/null +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -0,0 +1,158 @@ +parameters: + configuration: 'Debug' + + # Optional: condition for the job to run + condition: '' + + # Optional: 'true' if future jobs should run even if this job fails + continueOnError: false + + # Optional: dependencies of the job + dependsOn: '' + + # Optional: Include PublishBuildArtifacts task + enablePublishBuildArtifacts: false + + # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool + pool: {} + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. + runAsPublic: false + + # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing + publishUsingPipelines: false + + # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing + publishAssetsImmediately: false + + artifactsPublishingAdditionalParameters: '' + + signingValidationAdditionalParameters: '' + + is1ESPipeline: '' + +jobs: +- job: Asset_Registry_Publish + + dependsOn: ${{ parameters.dependsOn }} + timeoutInMinutes: 150 + + ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: + displayName: Publish Assets + ${{ else }}: + displayName: Publish to Build Asset Registry + + variables: + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - group: Publish-Build-Assets + - group: AzureDevOps-Artifact-Feeds-Pats + - name: runCodesignValidationInjection + value: false + # unconditional - needed for logs publishing (redactor tool version) + - template: /eng/common/core-templates/post-build/common-variables.yml + + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Publishing-Internal + image: windows.vs2019.amd64 + os: windows + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - checkout: self + fetchDepth: 3 + clean: true + + - task: DownloadBuildArtifacts@0 + displayName: Download artifact + inputs: + artifactName: AssetManifests + downloadPath: '$(Build.StagingDirectory)/Download' + checkDownloadedFiles: true + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + + - task: NuGetAuthenticate@1 + + - task: AzureCLI@2 + displayName: Publish Build Assets + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: ps + scriptLocation: scriptPath + scriptPath: $(Build.SourcesDirectory)/eng/common/sdk-task.ps1 + arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet + /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' + /p:MaestroApiEndpoint=https://maestro.dot.net + /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} + /p:OfficialBuildId=$(Build.BuildNumber) + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + + - task: powershell@2 + displayName: Create ReleaseConfigs Artifact + inputs: + targetType: inline + script: | + New-Item -Path "$(Build.StagingDirectory)/ReleaseConfigs" -ItemType Directory -Force + $filePath = "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" + Add-Content -Path $filePath -Value $(BARBuildId) + Add-Content -Path $filePath -Value "$(DefaultChannels)" + Add-Content -Path $filePath -Value $(IsStableBuild) + + $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" + if (Test-Path -Path $symbolExclusionfile) + { + Write-Host "SymbolExclusionFile exists" + Copy-Item -Path $symbolExclusionfile -Destination "$(Build.StagingDirectory)/ReleaseConfigs" + } + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish ReleaseConfigs Artifact + pathToPublish: '$(Build.StagingDirectory)/ReleaseConfigs' + publishLocation: Container + artifactName: ReleaseConfigs + + - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: AzureCLI@2 + displayName: Publish Using Darc + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: ps + scriptLocation: scriptPath + scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: > + -BuildId $(BARBuildId) + -PublishingInfraVersion 3 + -AzdoToken '$(System.AccessToken)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: + - template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + JobLabel: 'Publish_Artifacts_Logs' diff --git a/eng/common/core-templates/job/source-build.yml b/eng/common/core-templates/job/source-build.yml new file mode 100644 index 000000000000..c4713c8b6ede --- /dev/null +++ b/eng/common/core-templates/job/source-build.yml @@ -0,0 +1,93 @@ +parameters: + # This template adds arcade-powered source-build to CI. The template produces a server job with a + # default ID 'Source_Build_Complete' to put in a dependency list if necessary. + + # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. + jobNamePrefix: 'Source_Build' + + # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for + # managed-only repositories. This is an object with these properties: + # + # name: '' + # The name of the job. This is included in the job ID. + # targetRID: '' + # The name of the target RID to use, instead of the one auto-detected by Arcade. + # nonPortable: false + # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than + # linux-x64), and compiling against distro-provided packages rather than portable ones. + # skipPublishValidation: false + # Disables publishing validation. By default, a check is performed to ensure no packages are + # published by source-build. + # container: '' + # A container to use. Runs in docker. + # pool: {} + # A pool to use. Runs directly on an agent. + # buildScript: '' + # Specifies the build script to invoke to perform the build in the repo. The default + # './build.sh' should work for typical Arcade repositories, but this is customizable for + # difficult situations. + # jobProperties: {} + # A list of job properties to inject at the top level, for potential extensibility beyond + # container and pool. + platform: {} + + is1ESPipeline: '' + + # If set to true and running on a non-public project, + # Internal nuget and blob storage locations will be enabled. + # This is not enabled by default because many repositories do not need internal sources + # and do not need to have the required service connections approved in the pipeline. + enableInternalSources: false + +jobs: +- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} + displayName: Source-Build (${{ parameters.platform.name }}) + + ${{ each property in parameters.platform.jobProperties }}: + ${{ property.key }}: ${{ property.value }} + + ${{ if ne(parameters.platform.container, '') }}: + container: ${{ parameters.platform.container }} + + ${{ if eq(parameters.platform.pool, '') }}: + # The default VM host AzDO pool. This should be capable of running Docker containers: almost all + # source-build builds run in Docker, including the default managed platform. + # /eng/common/core-templates/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic + ${{ if eq(parameters.is1ESPipeline, 'true') }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] + demands: ImageOverride -equals build.ubuntu.2004.amd64 + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] + image: 1es-mariner-2 + os: linux + ${{ else }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] + demands: ImageOverride -equals Build.Ubuntu.2204.Amd64.Open + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] + demands: ImageOverride -equals Build.Ubuntu.2204.Amd64 + ${{ if ne(parameters.platform.pool, '') }}: + pool: ${{ parameters.platform.pool }} + + workspace: + clean: all + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if eq(parameters.enableInternalSources, true) }}: + - template: /eng/common/core-templates/steps/enable-internal-sources.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + - template: /eng/common/core-templates/steps/enable-internal-runtimes.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + - template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + platform: ${{ parameters.platform }} diff --git a/eng/common/core-templates/job/source-index-stage1.yml b/eng/common/core-templates/job/source-index-stage1.yml new file mode 100644 index 000000000000..205fb5b3a395 --- /dev/null +++ b/eng/common/core-templates/job/source-index-stage1.yml @@ -0,0 +1,81 @@ +parameters: + runAsPublic: false + sourceIndexUploadPackageVersion: 2.0.0-20240522.1 + sourceIndexProcessBinlogPackageVersion: 1.0.1-20240522.1 + sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json + sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" + preSteps: [] + binlogPath: artifacts/log/Debug/Build.binlog + condition: '' + dependsOn: '' + pool: '' + is1ESPipeline: '' + +jobs: +- job: SourceIndexStage1 + dependsOn: ${{ parameters.dependsOn }} + condition: ${{ parameters.condition }} + variables: + - name: SourceIndexUploadPackageVersion + value: ${{ parameters.sourceIndexUploadPackageVersion }} + - name: SourceIndexProcessBinlogPackageVersion + value: ${{ parameters.sourceIndexProcessBinlogPackageVersion }} + - name: SourceIndexPackageSource + value: ${{ parameters.sourceIndexPackageSource }} + - name: BinlogPath + value: ${{ parameters.binlogPath }} + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $(DncEngPublicBuildPool) + image: 1es-windows-2022-open + os: windows + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ each preStep in parameters.preSteps }}: + - ${{ preStep }} + + - task: UseDotNet@2 + displayName: Use .NET 8 SDK + inputs: + packageType: sdk + version: 8.0.x + installationPath: $(Agent.TempDirectory)/dotnet + workingDirectory: $(Agent.TempDirectory) + + - script: | + $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(sourceIndexProcessBinlogPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(sourceIndexUploadPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + displayName: Download Tools + # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. + workingDirectory: $(Agent.TempDirectory) + + - script: ${{ parameters.sourceIndexBuildCommand }} + displayName: Build Repository + + - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output + displayName: Process Binlog into indexable sln + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - task: AzureCLI@2 + displayName: Log in to Azure and upload stage1 artifacts to source index + inputs: + azureSubscription: 'SourceDotNet Stage1 Publish' + addSpnToEnvironment: true + scriptType: 'ps' + scriptLocation: 'inlineScript' + inlineScript: | + $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 diff --git a/eng/common/core-templates/jobs/codeql-build.yml b/eng/common/core-templates/jobs/codeql-build.yml new file mode 100644 index 000000000000..f2144252cc65 --- /dev/null +++ b/eng/common/core-templates/jobs/codeql-build.yml @@ -0,0 +1,33 @@ +parameters: + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + continueOnError: false + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + jobs: [] + # Optional: if specified, restore and use this version of Guardian instead of the default. + overrideGuardianVersion: '' + is1ESPipeline: '' + +jobs: +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + enableMicrobuild: false + enablePublishBuildArtifacts: false + enablePublishTestResults: false + enablePublishBuildAssets: false + enablePublishUsingPipelines: false + enableTelemetry: true + + variables: + - group: Publish-Build-Assets + # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in + # sync with the packages.config file. + - name: DefaultGuardianVersion + value: 0.109.0 + - name: GuardianPackagesConfigFile + value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config + - name: GuardianVersion + value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} + + jobs: ${{ parameters.jobs }} + diff --git a/eng/common/core-templates/jobs/jobs.yml b/eng/common/core-templates/jobs/jobs.yml new file mode 100644 index 000000000000..ea69be4341c6 --- /dev/null +++ b/eng/common/core-templates/jobs/jobs.yml @@ -0,0 +1,119 @@ +parameters: + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + continueOnError: false + + # Optional: Include PublishBuildArtifacts task + enablePublishBuildArtifacts: false + + # Optional: Enable publishing using release pipelines + enablePublishUsingPipelines: false + + # Optional: Enable running the source-build jobs to build repo from source + enableSourceBuild: false + + # Optional: Parameters for source-build template. + # See /eng/common/core-templates/jobs/source-build.yml for options + sourceBuildParameters: [] + + graphFileGeneration: + # Optional: Enable generating the graph files at the end of the build + enabled: false + # Optional: Include toolset dependencies in the generated graph files + includeToolset: false + + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + jobs: [] + + # Optional: Override automatically derived dependsOn value for "publish build assets" job + publishBuildAssetsDependsOn: '' + + # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. + publishAssetsImmediately: false + + # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) + artifactsPublishingAdditionalParameters: '' + signingValidationAdditionalParameters: '' + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. + runAsPublic: false + + enableSourceIndex: false + sourceIndexParams: {} + + artifacts: {} + is1ESPipeline: '' + +# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, +# and some (Microbuild) should only be applied to non-PR cases for internal builds. + +jobs: +- ${{ each job in parameters.jobs }}: + - ${{ if eq(parameters.is1ESPipeline, 'true') }}: + - template: /eng/common/templates-official/job/job.yml + parameters: + # pass along parameters + ${{ each parameter in parameters }}: + ${{ if ne(parameter.key, 'jobs') }}: + ${{ parameter.key }}: ${{ parameter.value }} + + # pass along job properties + ${{ each property in job }}: + ${{ if ne(property.key, 'job') }}: + ${{ property.key }}: ${{ property.value }} + + name: ${{ job.job }} + + - ${{ else }}: + - template: /eng/common/templates/job/job.yml + parameters: + # pass along parameters + ${{ each parameter in parameters }}: + ${{ if ne(parameter.key, 'jobs') }}: + ${{ parameter.key }}: ${{ parameter.value }} + + # pass along job properties + ${{ each property in job }}: + ${{ if ne(property.key, 'job') }}: + ${{ property.key }}: ${{ property.value }} + + name: ${{ job.job }} + +- ${{ if eq(parameters.enableSourceBuild, true) }}: + - template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + allCompletedJobId: Source_Build_Complete + ${{ each parameter in parameters.sourceBuildParameters }}: + ${{ parameter.key }}: ${{ parameter.value }} + +- ${{ if eq(parameters.enableSourceIndex, 'true') }}: + - template: ../job/source-index-stage1.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + runAsPublic: ${{ parameters.runAsPublic }} + ${{ each parameter in parameters.sourceIndexParams }}: + ${{ parameter.key }}: ${{ parameter.value }} + +- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: + - template: ../job/publish-build-assets.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + continueOnError: ${{ parameters.continueOnError }} + dependsOn: + - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.publishBuildAssetsDependsOn }}: + - ${{ job.job }} + - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.jobs }}: + - ${{ job.job }} + - ${{ if eq(parameters.enableSourceBuild, true) }}: + - Source_Build_Complete + + runAsPublic: ${{ parameters.runAsPublic }} + publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} + publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} + enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} diff --git a/eng/common/core-templates/jobs/source-build.yml b/eng/common/core-templates/jobs/source-build.yml new file mode 100644 index 000000000000..a10ccfbee6de --- /dev/null +++ b/eng/common/core-templates/jobs/source-build.yml @@ -0,0 +1,58 @@ +parameters: + # This template adds arcade-powered source-build to CI. A job is created for each platform, as + # well as an optional server job that completes when all platform jobs complete. + + # The name of the "join" job for all source-build platforms. If set to empty string, the job is + # not included. Existing repo pipelines can use this job depend on all source-build jobs + # completing without maintaining a separate list of every single job ID: just depend on this one + # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. + allCompletedJobId: '' + + # See /eng/common/core-templates/job/source-build.yml + jobNamePrefix: 'Source_Build' + + # This is the default platform provided by Arcade, intended for use by a managed-only repo. + defaultManagedPlatform: + name: 'Managed' + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9' + + # Defines the platforms on which to run build jobs. One job is created for each platform, and the + # object in this array is sent to the job template as 'platform'. If no platforms are specified, + # one job runs on 'defaultManagedPlatform'. + platforms: [] + + is1ESPipeline: '' + + # If set to true and running on a non-public project, + # Internal nuget and blob storage locations will be enabled. + # This is not enabled by default because many repositories do not need internal sources + # and do not need to have the required service connections approved in the pipeline. + enableInternalSources: false + +jobs: + +- ${{ if ne(parameters.allCompletedJobId, '') }}: + - job: ${{ parameters.allCompletedJobId }} + displayName: Source-Build Complete + pool: server + dependsOn: + - ${{ each platform in parameters.platforms }}: + - ${{ parameters.jobNamePrefix }}_${{ platform.name }} + - ${{ if eq(length(parameters.platforms), 0) }}: + - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} + +- ${{ each platform in parameters.platforms }}: + - template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobNamePrefix: ${{ parameters.jobNamePrefix }} + platform: ${{ platform }} + enableInternalSources: ${{ parameters.enableInternalSources }} + +- ${{ if eq(length(parameters.platforms), 0) }}: + - template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobNamePrefix: ${{ parameters.jobNamePrefix }} + platform: ${{ parameters.defaultManagedPlatform }} + enableInternalSources: ${{ parameters.enableInternalSources }} diff --git a/eng/common/core-templates/post-build/common-variables.yml b/eng/common/core-templates/post-build/common-variables.yml new file mode 100644 index 000000000000..d5627a994ae5 --- /dev/null +++ b/eng/common/core-templates/post-build/common-variables.yml @@ -0,0 +1,22 @@ +variables: + - group: Publish-Build-Assets + + # Whether the build is internal or not + - name: IsInternalBuild + value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} + + # Default Maestro++ API Endpoint and API Version + - name: MaestroApiEndPoint + value: "https://maestro.dot.net" + - name: MaestroApiVersion + value: "2020-02-20" + + - name: SourceLinkCLIVersion + value: 3.0.0 + - name: SymbolToolVersion + value: 1.0.1 + - name: BinlogToolVersion + value: 1.0.11 + + - name: runCodesignValidationInjection + value: false diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml new file mode 100644 index 000000000000..454fd75c7aff --- /dev/null +++ b/eng/common/core-templates/post-build/post-build.yml @@ -0,0 +1,316 @@ +parameters: + # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. + # Publishing V1 is no longer supported + # Publishing V2 is no longer supported + # Publishing V3 is the default + - name: publishingInfraVersion + displayName: Which version of publishing should be used to promote the build definition? + type: number + default: 3 + values: + - 3 + + - name: BARBuildId + displayName: BAR Build Id + type: number + default: 0 + + - name: PromoteToChannelIds + displayName: Channel to promote BARBuildId to + type: string + default: '' + + - name: enableSourceLinkValidation + displayName: Enable SourceLink validation + type: boolean + default: false + + - name: enableSigningValidation + displayName: Enable signing validation + type: boolean + default: true + + - name: enableSymbolValidation + displayName: Enable symbol validation + type: boolean + default: false + + - name: enableNugetValidation + displayName: Enable NuGet validation + type: boolean + default: true + + - name: publishInstallersAndChecksums + displayName: Publish installers and checksums + type: boolean + default: true + + - name: SDLValidationParameters + type: object + default: + enable: false + publishGdn: false + continueOnError: false + params: '' + artifactNames: '' + downloadArtifacts: true + + # These parameters let the user customize the call to sdk-task.ps1 for publishing + # symbols & general artifacts as well as for signing validation + - name: symbolPublishingAdditionalParameters + displayName: Symbol publishing additional parameters + type: string + default: '' + + - name: artifactsPublishingAdditionalParameters + displayName: Artifact publishing additional parameters + type: string + default: '' + + - name: signingValidationAdditionalParameters + displayName: Signing validation additional parameters + type: string + default: '' + + # Which stages should finish execution before post-build stages start + - name: validateDependsOn + type: object + default: + - build + + - name: publishDependsOn + type: object + default: + - Validate + + # Optional: Call asset publishing rather than running in a separate stage + - name: publishAssetsImmediately + type: boolean + default: false + + - name: is1ESPipeline + type: boolean + default: false + +stages: +- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + - stage: Validate + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Validate Build Assets + variables: + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobs: + - job: + displayName: NuGet Validation + condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: $(DncEngInternalBuildPool) + image: windows.vs2022.amd64 + os: windows + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 + arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ + + - job: + displayName: Signing Validation + condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + itemPattern: | + ** + !**/Microsoft.SourceBuild.Intermediate.*.nupkg + + # This is necessary whenever we want to publish/restore to an AzDO private feed + # Since sdk-task.ps1 tries to restore packages we need to do this authentication here + # otherwise it'll complain about accessing a private feed. + - task: NuGetAuthenticate@1 + displayName: 'Authenticate to AzDO Feeds' + + # Signing validation will optionally work with the buildmanifest file which is downloaded from + # Azure DevOps above. + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task SigningValidation -restore -msbuildEngine vs + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' + /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' + ${{ parameters.signingValidationAdditionalParameters }} + + - template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + StageLabel: 'Validation' + JobLabel: 'Signing' + BinlogToolVersion: $(BinlogToolVersion) + + - job: + displayName: SourceLink Validation + condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: BlobArtifacts + checkDownloadedFiles: true + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -ExtractPath $(Agent.BuildDirectory)/Extract/ + -GHRepoName $(Build.Repository.Name) + -GHCommit $(Build.SourceVersion) + -SourcelinkCliVersion $(SourceLinkCLIVersion) + continueOnError: true + +- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: + - stage: publish_using_darc + ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + dependsOn: ${{ parameters.publishDependsOn }} + ${{ else }}: + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Publish using Darc + variables: + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobs: + - job: + displayName: Publish Using Darc + timeoutInMinutes: 120 + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: NetCore1ESPool-Publishing-Internal + image: windows.vs2019.amd64 + os: windows + ${{ else }}: + name: NetCore1ESPool-Publishing-Internal + demands: ImageOverride -equals windows.vs2019.amd64 + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: NuGetAuthenticate@1 + + - task: AzureCLI@2 + displayName: Publish Using Darc + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: ps + scriptLocation: scriptPath + scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: > + -BuildId $(BARBuildId) + -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} + -AzdoToken '$(System.AccessToken)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/core-templates/post-build/setup-maestro-vars.yml b/eng/common/core-templates/post-build/setup-maestro-vars.yml new file mode 100644 index 000000000000..f7602980dbe7 --- /dev/null +++ b/eng/common/core-templates/post-build/setup-maestro-vars.yml @@ -0,0 +1,74 @@ +parameters: + BARBuildId: '' + PromoteToChannelIds: '' + is1ESPipeline: '' + +steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Release Configs + inputs: + buildType: current + artifactName: ReleaseConfigs + checkDownloadedFiles: true + + - task: AzureCLI@2 + name: setReleaseVars + displayName: Set Release Configs Vars + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: pscore + scriptLocation: inlineScript + inlineScript: | + try { + if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { + $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt + + $BarId = $Content | Select -Index 0 + $Channels = $Content | Select -Index 1 + $IsStableBuild = $Content | Select -Index 2 + + $AzureDevOpsProject = $Env:System_TeamProject + $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId + $AzureDevOpsBuildId = $Env:Build_BuildId + } + else { + . $(Build.SourcesDirectory)\eng\common\tools.ps1 + $darc = Get-Darc + $buildInfo = & $darc get-build ` + --id ${{ parameters.BARBuildId }} ` + --extended ` + --output-format json ` + --ci ` + | convertFrom-Json + + $BarId = ${{ parameters.BARBuildId }} + $Channels = $Env:PromoteToMaestroChannels -split "," + $Channels = $Channels -join "][" + $Channels = "[$Channels]" + + $IsStableBuild = $buildInfo.stable + $AzureDevOpsProject = $buildInfo.azureDevOpsProject + $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId + $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId + } + + Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" + Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" + Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" + + Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" + Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" + Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" + } + catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + exit 1 + } + env: + PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} diff --git a/eng/common/core-templates/steps/component-governance.yml b/eng/common/core-templates/steps/component-governance.yml new file mode 100644 index 000000000000..cf0649aa9565 --- /dev/null +++ b/eng/common/core-templates/steps/component-governance.yml @@ -0,0 +1,16 @@ +parameters: + disableComponentGovernance: false + componentGovernanceIgnoreDirectories: '' + is1ESPipeline: false + displayName: 'Component Detection' + +steps: +- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: + - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" + displayName: Set skipComponentGovernanceDetection variable +- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: + - task: ComponentGovernanceComponentDetection@0 + continueOnError: true + displayName: ${{ parameters.displayName }} + inputs: + ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} diff --git a/eng/common/core-templates/steps/enable-internal-runtimes.yml b/eng/common/core-templates/steps/enable-internal-runtimes.yml new file mode 100644 index 000000000000..6bdbf62ac500 --- /dev/null +++ b/eng/common/core-templates/steps/enable-internal-runtimes.yml @@ -0,0 +1,32 @@ +# Obtains internal runtime download credentials and populates the 'dotnetbuilds-internal-container-read-token-base64' +# variable with the base64-encoded SAS token, by default + +parameters: +- name: federatedServiceConnection + type: string + default: 'dotnetbuilds-internal-read' +- name: outputVariableName + type: string + default: 'dotnetbuilds-internal-container-read-token-base64' +- name: expiryInHours + type: number + default: 1 +- name: base64Encode + type: boolean + default: true +- name: is1ESPipeline + type: boolean + default: false + +steps: +- ${{ if ne(variables['System.TeamProject'], 'public') }}: + - template: /eng/common/core-templates/steps/get-delegation-sas.yml + parameters: + federatedServiceConnection: ${{ parameters.federatedServiceConnection }} + outputVariableName: ${{ parameters.outputVariableName }} + expiryInHours: ${{ parameters.expiryInHours }} + base64Encode: ${{ parameters.base64Encode }} + storageAccount: dotnetbuilds + container: internal + permissions: rl + is1ESPipeline: ${{ parameters.is1ESPipeline }} \ No newline at end of file diff --git a/eng/common/core-templates/steps/enable-internal-sources.yml b/eng/common/core-templates/steps/enable-internal-sources.yml new file mode 100644 index 000000000000..64f881bffc3c --- /dev/null +++ b/eng/common/core-templates/steps/enable-internal-sources.yml @@ -0,0 +1,47 @@ +parameters: +# This is the Azure federated service connection that we log into to get an access token. +- name: nugetFederatedServiceConnection + type: string + default: 'dnceng-artifacts-feeds-read' +- name: is1ESPipeline + type: boolean + default: false +# Legacy parameters to allow for PAT usage +- name: legacyCredential + type: string + default: '' + +steps: +- ${{ if ne(variables['System.TeamProject'], 'public') }}: + - ${{ if ne(parameters.legacyCredential, '') }}: + - task: PowerShell@2 + displayName: Setup Internal Feeds + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token + env: + Token: ${{ parameters.legacyCredential }} + # If running on dnceng (internal project), just use the default behavior for NuGetAuthenticate. + # If running on DevDiv, NuGetAuthenticate is not really an option. It's scoped to a single feed, and we have many feeds that + # may be added. Instead, we'll use the traditional approach (add cred to nuget.config), but use an account token. + - ${{ else }}: + - ${{ if eq(variables['System.TeamProject'], 'internal') }}: + - task: PowerShell@2 + displayName: Setup Internal Feeds + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config + - ${{ else }}: + - template: /eng/common/templates/steps/get-federated-access-token.yml + parameters: + federatedServiceConnection: ${{ parameters.nugetFederatedServiceConnection }} + outputVariableName: 'dnceng-artifacts-feeds-read-access-token' + - task: PowerShell@2 + displayName: Setup Internal Feeds + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $(dnceng-artifacts-feeds-read-access-token) + # This is required in certain scenarios to install the ADO credential provider. + # It installed by default in some msbuild invocations (e.g. VS msbuild), but needs to be installed for others + # (e.g. dotnet msbuild). + - task: NuGetAuthenticate@1 diff --git a/eng/common/core-templates/steps/generate-sbom.yml b/eng/common/core-templates/steps/generate-sbom.yml new file mode 100644 index 000000000000..d938b60e1bb5 --- /dev/null +++ b/eng/common/core-templates/steps/generate-sbom.yml @@ -0,0 +1,54 @@ +# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. +# PackageName - The name of the package this SBOM represents. +# PackageVersion - The version of the package this SBOM represents. +# ManifestDirPath - The path of the directory where the generated manifest files will be placed +# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. + +parameters: + PackageVersion: 9.0.0 + BuildDropPath: '$(Build.SourcesDirectory)/artifacts' + PackageName: '.NET' + ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom + IgnoreDirectories: '' + sbomContinueOnError: true + is1ESPipeline: false + # disable publishArtifacts if some other step is publishing the artifacts (like job.yml). + publishArtifacts: true + +steps: +- task: PowerShell@2 + displayName: Prep for SBOM generation in (Non-linux) + condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) + inputs: + filePath: ./eng/common/generate-sbom-prep.ps1 + arguments: ${{parameters.manifestDirPath}} + +# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 +- script: | + chmod +x ./eng/common/generate-sbom-prep.sh + ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} + displayName: Prep for SBOM generation in (Linux) + condition: eq(variables['Agent.Os'], 'Linux') + continueOnError: ${{ parameters.sbomContinueOnError }} + +- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 + displayName: 'Generate SBOM manifest' + continueOnError: ${{ parameters.sbomContinueOnError }} + inputs: + PackageName: ${{ parameters.packageName }} + BuildDropPath: ${{ parameters.buildDropPath }} + PackageVersion: ${{ parameters.packageVersion }} + ManifestDirPath: ${{ parameters.manifestDirPath }} + ${{ if ne(parameters.IgnoreDirectories, '') }}: + AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' + +- ${{ if eq(parameters.publishArtifacts, 'true')}}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish SBOM manifest + continueOnError: ${{parameters.sbomContinueOnError}} + targetPath: '${{ parameters.manifestDirPath }}' + artifactName: $(ARTIFACT_NAME) + diff --git a/eng/common/core-templates/steps/get-delegation-sas.yml b/eng/common/core-templates/steps/get-delegation-sas.yml new file mode 100644 index 000000000000..d2901470a7f0 --- /dev/null +++ b/eng/common/core-templates/steps/get-delegation-sas.yml @@ -0,0 +1,46 @@ +parameters: +- name: federatedServiceConnection + type: string +- name: outputVariableName + type: string +- name: expiryInHours + type: number + default: 1 +- name: base64Encode + type: boolean + default: false +- name: storageAccount + type: string +- name: container + type: string +- name: permissions + type: string + default: 'rl' +- name: is1ESPipeline + type: boolean + default: false + +steps: +- task: AzureCLI@2 + displayName: 'Generate delegation SAS Token for ${{ parameters.storageAccount }}/${{ parameters.container }}' + inputs: + azureSubscription: ${{ parameters.federatedServiceConnection }} + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: | + # Calculate the expiration of the SAS token and convert to UTC + $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") + + $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv + + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to generate SAS token." + exit 1 + } + + if ('${{ parameters.base64Encode }}' -eq 'true') { + $sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas)) + } + + Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" + Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$sas" diff --git a/eng/common/core-templates/steps/get-federated-access-token.yml b/eng/common/core-templates/steps/get-federated-access-token.yml new file mode 100644 index 000000000000..3a4d4410c482 --- /dev/null +++ b/eng/common/core-templates/steps/get-federated-access-token.yml @@ -0,0 +1,42 @@ +parameters: +- name: federatedServiceConnection + type: string +- name: outputVariableName + type: string +- name: is1ESPipeline + type: boolean +- name: stepName + type: string + default: 'getFederatedAccessToken' +- name: condition + type: string + default: '' +# Resource to get a token for. Common values include: +# - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps +# - 'https://storage.azure.com/' for storage +# Defaults to Azure DevOps +- name: resource + type: string + default: '499b84ac-1321-427f-aa17-267ca6975798' +- name: isStepOutputVariable + type: boolean + default: false + +steps: +- task: AzureCLI@2 + displayName: 'Getting federated access token for feeds' + name: ${{ parameters.stepName }} + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} + inputs: + azureSubscription: ${{ parameters.federatedServiceConnection }} + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: | + $accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to get access token for resource '${{ parameters.resource }}'" + exit 1 + } + Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" + Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true;isOutput=${{ parameters.isStepOutputVariable }}]$accessToken" \ No newline at end of file diff --git a/eng/common/core-templates/steps/publish-build-artifacts.yml b/eng/common/core-templates/steps/publish-build-artifacts.yml new file mode 100644 index 000000000000..f24ce346684e --- /dev/null +++ b/eng/common/core-templates/steps/publish-build-artifacts.yml @@ -0,0 +1,20 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false +- name: args + type: object + default: {} +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - template: /eng/common/templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ each parameter in parameters.args }}: + ${{ parameter.key }}: ${{ parameter.value }} +- ${{ else }}: + - template: /eng/common/templates-official/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ each parameter in parameters.args }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml new file mode 100644 index 000000000000..80788c523191 --- /dev/null +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -0,0 +1,58 @@ +parameters: + StageLabel: '' + JobLabel: '' + CustomSensitiveDataList: '' + # A default - in case value from eng/common/core-templates/post-build/common-variables.yml is not passed + BinlogToolVersion: '1.0.11' + is1ESPipeline: false + +steps: +- task: Powershell@2 + displayName: Prepare Binlogs to Upload + inputs: + targetType: inline + script: | + New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + continueOnError: true + condition: always() + +- task: PowerShell@2 + displayName: Redact Logs + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1 + # For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml + # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' + # If the file exists - sensitive data for redaction will be sourced from it + # (single entry per line, lines starting with '# ' are considered comments and skipped) + arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs' + -BinlogToolVersion ${{parameters.BinlogToolVersion}} + -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' + '$(publishing-dnceng-devdiv-code-r-build-re)' + '$(MaestroAccessToken)' + '$(dn-bot-all-orgs-artifact-feeds-rw)' + '$(akams-client-id)' + '$(microsoft-symbol-server-pat)' + '$(symweb-symbol-server-pat)' + '$(dn-bot-all-orgs-build-rw-code-rw)' + ${{parameters.CustomSensitiveDataList}} + continueOnError: true + condition: always() + +- task: CopyFiles@2 + displayName: Gather post build logs + inputs: + SourceFolder: '$(Build.SourcesDirectory)/PostBuildLogs' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + +- template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish Logs + pathToPublish: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + publishLocation: Container + artifactName: PostBuildLogs + continueOnError: true + condition: always() diff --git a/eng/common/core-templates/steps/publish-pipeline-artifacts.yml b/eng/common/core-templates/steps/publish-pipeline-artifacts.yml new file mode 100644 index 000000000000..2efec04dc2c1 --- /dev/null +++ b/eng/common/core-templates/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,20 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: args + type: object + default: {} + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - template: /eng/common/templates/steps/publish-pipeline-artifacts.yml + parameters: + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} +- ${{ else }}: + - template: /eng/common/templates-official/steps/publish-pipeline-artifacts.yml + parameters: + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/core-templates/steps/retain-build.yml b/eng/common/core-templates/steps/retain-build.yml new file mode 100644 index 000000000000..83d97a26a01f --- /dev/null +++ b/eng/common/core-templates/steps/retain-build.yml @@ -0,0 +1,28 @@ +parameters: + # Optional azure devops PAT with build execute permissions for the build's organization, + # only needed if the build that should be retained ran on a different organization than + # the pipeline where this template is executing from + Token: '' + # Optional BuildId to retain, defaults to the current running build + BuildId: '' + # Azure devops Organization URI for the build in the https://dev.azure.com/ format. + # Defaults to the organization the current pipeline is running on + AzdoOrgUri: '$(System.CollectionUri)' + # Azure devops project for the build. Defaults to the project the current pipeline is running on + AzdoProject: '$(System.TeamProject)' + +steps: + - task: powershell@2 + inputs: + targetType: 'filePath' + filePath: eng/common/retain-build.ps1 + pwsh: true + arguments: > + -AzdoOrgUri: ${{parameters.AzdoOrgUri}} + -AzdoProject ${{parameters.AzdoProject}} + -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} + -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} + displayName: Enable permanent build retention + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + BUILD_ID: $(Build.BuildId) \ No newline at end of file diff --git a/eng/common/core-templates/steps/send-to-helix.yml b/eng/common/core-templates/steps/send-to-helix.yml new file mode 100644 index 000000000000..68fa739c4ab2 --- /dev/null +++ b/eng/common/core-templates/steps/send-to-helix.yml @@ -0,0 +1,93 @@ +# Please remember to update the documentation if you make changes to these parameters! +parameters: + HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ + HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' + HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number + HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues + HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group + HelixProjectPath: 'eng/common/helixpublish.proj' # optional -- path to the project file to build relative to BUILD_SOURCESDIRECTORY + HelixProjectArguments: '' # optional -- arguments passed to the build command + HelixConfiguration: '' # optional -- additional property attached to a job + HelixPreCommands: '' # optional -- commands to run before Helix work item execution + HelixPostCommands: '' # optional -- commands to run after Helix work item execution + WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects + WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects + WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects + CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload + XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true + XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects + XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects + XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner + XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects + IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion + DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json + DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json + WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." + IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set + HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) + Creator: '' # optional -- if the build is external, use this to specify who is sending the job + DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO + condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() + continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false + +steps: + - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' + displayName: ${{ parameters.DisplayNamePrefix }} (Windows) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixConfiguration: ${{ parameters.HelixConfiguration }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + WorkItemCommand: ${{ parameters.WorkItemCommand }} + WorkItemTimeout: ${{ parameters.WorkItemTimeout }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + XUnitProjects: ${{ parameters.XUnitProjects }} + XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} + XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} + XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} + XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog + displayName: ${{ parameters.DisplayNamePrefix }} (Unix) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixConfiguration: ${{ parameters.HelixConfiguration }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + WorkItemCommand: ${{ parameters.WorkItemCommand }} + WorkItemTimeout: ${{ parameters.WorkItemTimeout }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + XUnitProjects: ${{ parameters.XUnitProjects }} + XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} + XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} + XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} + XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/core-templates/steps/source-build.yml b/eng/common/core-templates/steps/source-build.yml new file mode 100644 index 000000000000..2915d29bb7f6 --- /dev/null +++ b/eng/common/core-templates/steps/source-build.yml @@ -0,0 +1,129 @@ +parameters: + # This template adds arcade-powered source-build to CI. + + # This is a 'steps' template, and is intended for advanced scenarios where the existing build + # infra has a careful build methodology that must be followed. For example, a repo + # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline + # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to + # GitHub. Using this steps template leaves room for that infra to be included. + + # Defines the platform on which to run the steps. See 'eng/common/core-templates/job/source-build.yml' + # for details. The entire object is described in the 'job' template for simplicity, even though + # the usage of the properties on this object is split between the 'job' and 'steps' templates. + platform: {} + is1ESPipeline: false + +steps: +# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) +- script: | + set -x + df -h + + # If file changes are detected, set CopyWipIntoInnerSourceBuildRepo to copy the WIP changes into the inner source build repo. + internalRestoreArgs= + if ! git diff --quiet; then + internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' + # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. + # This only works if there is a username/email configured, which won't be the case in most CI runs. + git config --get user.email + if [ $? -ne 0 ]; then + git config user.email dn-bot@microsoft.com + git config user.name dn-bot + fi + fi + + # If building on the internal project, the internal storage variable may be available (usually only if needed) + # In that case, add variables to allow the download of internal runtimes if the specified versions are not found + # in the default public locations. + internalRuntimeDownloadArgs= + if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then + internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' + fi + + buildConfig=Release + # Check if AzDO substitutes in a build config from a variable, and use it if so. + if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then + buildConfig='$(_BuildConfig)' + fi + + officialBuildArgs= + if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then + officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' + fi + + targetRidArgs= + if [ '${{ parameters.platform.targetRID }}' != '' ]; then + targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' + fi + + runtimeOsArgs= + if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then + runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' + fi + + baseOsArgs= + if [ '${{ parameters.platform.baseOS }}' != '' ]; then + baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' + fi + + publishArgs= + if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then + publishArgs='--publish' + fi + + assetManifestFileName=SourceBuild_RidSpecific.xml + if [ '${{ parameters.platform.name }}' != '' ]; then + assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml + fi + + ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ + --configuration $buildConfig \ + --restore --build --pack $publishArgs -bl \ + $officialBuildArgs \ + $internalRuntimeDownloadArgs \ + $internalRestoreArgs \ + $targetRidArgs \ + $runtimeOsArgs \ + $baseOsArgs \ + /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ + /p:ArcadeBuildFromSource=true \ + /p:DotNetBuildSourceOnly=true \ + /p:DotNetBuildRepo=true \ + /p:AssetManifestFileName=$assetManifestFileName + displayName: Build + +# Upload build logs for diagnosis. +- task: CopyFiles@2 + displayName: Prepare BuildLogs staging directory + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + **/*.log + **/*.binlog + artifacts/sb/prebuilt-report/** + TargetFolder: '$(Build.StagingDirectory)/BuildLogs' + CleanTargetFolder: true + continueOnError: true + condition: succeededOrFailed() + +- template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish BuildLogs + targetPath: '$(Build.StagingDirectory)/BuildLogs' + artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) + continueOnError: true + condition: succeededOrFailed() + sbomEnabled: false # we don't need SBOM for logs + +# Manually inject component detection so that we can ignore the source build upstream cache, which contains +# a nupkg cache of input packages (a local feed). +# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' +# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + displayName: Component Detection (Exclude upstream cache) + is1ESPipeline: ${{ parameters.is1ESPipeline }} + componentGovernanceIgnoreDirectories: '$(Build.SourcesDirectory)/artifacts/sb/src/artifacts/obj/source-built-upstream-cache' + disableComponentGovernance: ${{ eq(variables['System.TeamProject'], 'public') }} diff --git a/eng/common/core-templates/variables/pool-providers.yml b/eng/common/core-templates/variables/pool-providers.yml new file mode 100644 index 000000000000..41053d382a2e --- /dev/null +++ b/eng/common/core-templates/variables/pool-providers.yml @@ -0,0 +1,8 @@ +parameters: + is1ESPipeline: false + +variables: + - ${{ if eq(parameters.is1ESPipeline, 'true') }}: + - template: /eng/common/templates-official/variables/pool-providers.yml + - ${{ else }}: + - template: /eng/common/templates/variables/pool-providers.yml \ No newline at end of file diff --git a/eng/common/cross/armel/sources.list.jessie b/eng/common/cross/armel/sources.list.jessie deleted file mode 100644 index 3d9c3059d897..000000000000 --- a/eng/common/cross/armel/sources.list.jessie +++ /dev/null @@ -1,3 +0,0 @@ -# Debian (jessie) # Stable -deb http://ftp.debian.org/debian/ jessie main contrib non-free -deb-src http://ftp.debian.org/debian/ jessie main contrib non-free diff --git a/eng/common/cross/armv6/sources.list.buster b/eng/common/cross/armv6/sources.list.buster deleted file mode 100644 index f27fc4fb346b..000000000000 --- a/eng/common/cross/armv6/sources.list.buster +++ /dev/null @@ -1,2 +0,0 @@ -deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi -deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi diff --git a/eng/common/cross/build-android-rootfs.sh b/eng/common/cross/build-android-rootfs.sh index f163fb9dae96..7e9ba2b75ed3 100755 --- a/eng/common/cross/build-android-rootfs.sh +++ b/eng/common/cross/build-android-rootfs.sh @@ -5,15 +5,15 @@ __NDK_Version=r21 usage() { echo "Creates a toolchain and sysroot used for cross-compiling for Android." - echo. + echo echo "Usage: $0 [BuildArch] [ApiLevel]" - echo. + echo echo "BuildArch is the target architecture of Android. Currently only arm64 is supported." echo "ApiLevel is the target Android API level. API levels usually match to Android releases. See https://source.android.com/source/build-numbers.html" - echo. + echo echo "By default, the toolchain and sysroot will be generated in cross/android-rootfs/toolchain/[BuildArch]. You can change this behavior" echo "by setting the TOOLCHAIN_DIR environment variable" - echo. + echo echo "By default, the NDK will be downloaded into the cross/android-rootfs/android-ndk-$__NDK_Version directory. If you already have an NDK installation," echo "you can set the NDK_DIR environment variable to have this script use that installation of the NDK." echo "By default, this script will generate a file, android_platform, in the root of the ROOTFS_DIR directory that contains the RID for the supported and tested Android build: android.28-arm64. This file is to replace '/etc/os-release', which is not available for Android." diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index 9caf9b021dbd..4b5e8d7166bd 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -8,7 +8,7 @@ usage() echo "BuildArch can be: arm(default), arm64, armel, armv6, ppc64le, riscv64, s390x, x64, x86" echo "CodeName - optional, Code name for Linux, can be: xenial(default), zesty, bionic, alpine" echo " for alpine can be specified with version: alpineX.YY or alpineedge" - echo " for FreeBSD can be: freebsd12, freebsd13" + echo " for FreeBSD can be: freebsd13, freebsd14" echo " for illumos can be: illumos" echo " for Haiku can be: haiku." echo "lldbx.y - optional, LLDB version, can be: lldb3.9(default), lldb4.0, lldb5.0, lldb6.0 no-lldb. Ignored for alpine and FreeBSD" @@ -30,7 +30,8 @@ __IllumosArch=arm7 __HaikuArch=arm __QEMUArch=arm __UbuntuArch=armhf -__UbuntuRepo="http://ports.ubuntu.com/" +__UbuntuRepo= +__UbuntuSuites="updates security backports" __LLDB_Package="liblldb-3.9-dev" __SkipUnmount=0 @@ -71,9 +72,9 @@ __AlpinePackages+=" krb5-dev" __AlpinePackages+=" openssl-dev" __AlpinePackages+=" zlib-dev" -__FreeBSDBase="12.4-RELEASE" +__FreeBSDBase="13.3-RELEASE" __FreeBSDPkg="1.17.0" -__FreeBSDABI="12" +__FreeBSDABI="13" __FreeBSDPackages="libunwind" __FreeBSDPackages+=" icu" __FreeBSDPackages+=" libinotify" @@ -129,6 +130,7 @@ __AlpineKeys=' 616db30d:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnpUpyWDWjlUk3smlWeA0\nlIMW+oJ38t92CRLHH3IqRhyECBRW0d0aRGtq7TY8PmxjjvBZrxTNDpJT6KUk4LRm\na6A6IuAI7QnNK8SJqM0DLzlpygd7GJf8ZL9SoHSH+gFsYF67Cpooz/YDqWrlN7Vw\ntO00s0B+eXy+PCXYU7VSfuWFGK8TGEv6HfGMALLjhqMManyvfp8hz3ubN1rK3c8C\nUS/ilRh1qckdbtPvoDPhSbTDmfU1g/EfRSIEXBrIMLg9ka/XB9PvWRrekrppnQzP\nhP9YE3x/wbFc5QqQWiRCYyQl/rgIMOXvIxhkfe8H5n1Et4VAorkpEAXdsfN8KSVv\nLSMazVlLp9GYq5SUpqYX3KnxdWBgN7BJoZ4sltsTpHQ/34SXWfu3UmyUveWj7wp0\nx9hwsPirVI00EEea9AbP7NM2rAyu6ukcm4m6ATd2DZJIViq2es6m60AE6SMCmrQF\nwmk4H/kdQgeAELVfGOm2VyJ3z69fQuywz7xu27S6zTKi05Qlnohxol4wVb6OB7qG\nLPRtK9ObgzRo/OPumyXqlzAi/Yvyd1ZQk8labZps3e16bQp8+pVPiumWioMFJDWV\nGZjCmyMSU8V6MB6njbgLHoyg2LCukCAeSjbPGGGYhnKLm1AKSoJh3IpZuqcKCk5C\n8CM1S15HxV78s9dFntEqIokCAwEAAQ== ' __Keyring= +__KeyringFile="/usr/share/keyrings/ubuntu-archive-keyring.gpg" __SkipSigCheck=0 __UseMirror=0 @@ -142,7 +144,6 @@ while :; do case $lowerI in -\?|-h|--help) usage - exit 1 ;; arm) __BuildArch=arm @@ -163,6 +164,7 @@ while :; do __UbuntuArch=armel __UbuntuRepo="http://ftp.debian.org/debian/" __CodeName=jessie + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" ;; armv6) __BuildArch=armv6 @@ -170,10 +172,12 @@ while :; do __QEMUArch=arm __UbuntuRepo="http://raspbian.raspberrypi.org/raspbian/" __CodeName=buster + __KeyringFile="/usr/share/keyrings/raspbian-archive-keyring.gpg" __LLDB_Package="liblldb-6.0-dev" + __UbuntuSuites= - if [[ -e "/usr/share/keyrings/raspbian-archive-keyring.gpg" ]]; then - __Keyring="--keyring /usr/share/keyrings/raspbian-archive-keyring.gpg" + if [[ -e "$__KeyringFile" ]]; then + __Keyring="--keyring $__KeyringFile" fi ;; riscv64) @@ -182,13 +186,8 @@ while :; do __AlpinePackages="${__AlpinePackages// lldb-dev/}" __QEMUArch=riscv64 __UbuntuArch=riscv64 - __UbuntuRepo="http://deb.debian.org/debian-ports" __UbuntuPackages="${__UbuntuPackages// libunwind8-dev/}" unset __LLDB_Package - - if [[ -e "/usr/share/keyrings/debian-ports-archive-keyring.gpg" ]]; then - __Keyring="--keyring /usr/share/keyrings/debian-ports-archive-keyring.gpg --include=debian-ports-archive-keyring" - fi ;; ppc64le) __BuildArch=ppc64le @@ -229,12 +228,19 @@ while :; do __UbuntuRepo="http://archive.ubuntu.com/ubuntu/" ;; lldb*) - version="${lowerI/lldb/}" - parts=(${version//./ }) + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + majorVersion="${version%%.*}" + + [ -z "${version##*.*}" ] && minorVersion="${version#*.}" + if [ -z "$minorVersion" ]; then + minorVersion=0 + fi # for versions > 6.0, lldb has dropped the minor version - if [[ "${parts[0]}" -gt 6 ]]; then - version="${parts[0]}" + if [ "$majorVersion" -le 6 ]; then + version="$majorVersion.$minorVersion" + else + version="$majorVersion" fi __LLDB_Package="liblldb-${version}-dev" @@ -243,15 +249,19 @@ while :; do unset __LLDB_Package ;; llvm*) - version="${lowerI/llvm/}" - parts=(${version//./ }) - __LLVM_MajorVersion="${parts[0]}" - __LLVM_MinorVersion="${parts[1]}" - - # for versions > 6.0, llvm has dropped the minor version - if [[ -z "$__LLVM_MinorVersion" && "$__LLVM_MajorVersion" -le 6 ]]; then - __LLVM_MinorVersion=0; + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + __LLVM_MajorVersion="${version%%.*}" + + [ -z "${version##*.*}" ] && __LLVM_MinorVersion="${version#*.}" + if [ -z "$__LLVM_MinorVersion" ]; then + __LLVM_MinorVersion=0 + fi + + # for versions > 6.0, lldb has dropped the minor version + if [ "$__LLVM_MajorVersion" -gt 6 ]; then + __LLVM_MinorVersion= fi + ;; xenial) # Ubuntu 16.04 if [[ "$__CodeName" != "jessie" ]]; then @@ -278,8 +288,17 @@ while :; do __CodeName=jammy fi ;; + noble) # Ubuntu 24.04 + if [[ "$__CodeName" != "jessie" ]]; then + __CodeName=noble + fi + if [[ -n "$__LLDB_Package" ]]; then + __LLDB_Package="liblldb-18-dev" + fi + ;; jessie) # Debian 8 __CodeName=jessie + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -288,6 +307,7 @@ while :; do stretch) # Debian 9 __CodeName=stretch __LLDB_Package="liblldb-6.0-dev" + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -296,6 +316,7 @@ while :; do buster) # Debian 10 __CodeName=buster __LLDB_Package="liblldb-6.0-dev" + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -303,6 +324,15 @@ while :; do ;; bullseye) # Debian 11 __CodeName=bullseye + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" + + if [[ -z "$__UbuntuRepo" ]]; then + __UbuntuRepo="http://ftp.debian.org/debian/" + fi + ;; + bookworm) # Debian 12 + __CodeName=bookworm + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -310,6 +340,7 @@ while :; do ;; sid) # Debian sid __CodeName=sid + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -323,25 +354,24 @@ while :; do alpine*) __CodeName=alpine __UbuntuRepo= - version="${lowerI/alpine/}" - if [[ "$version" == "edge" ]]; then + if [[ "$lowerI" == "alpineedge" ]]; then __AlpineVersion=edge else - parts=(${version//./ }) - __AlpineMajorVersion="${parts[0]}" - __AlpineMinoVersion="${parts[1]}" - __AlpineVersion="$__AlpineMajorVersion.$__AlpineMinoVersion" + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + __AlpineMajorVersion="${version%%.*}" + __AlpineMinorVersion="${version#*.}" + __AlpineVersion="$__AlpineMajorVersion.$__AlpineMinorVersion" fi ;; - freebsd12) + freebsd13) __CodeName=freebsd __SkipUnmount=1 ;; - freebsd13) + freebsd14) __CodeName=freebsd - __FreeBSDBase="13.2-RELEASE" - __FreeBSDABI="13" + __FreeBSDBase="14.0-RELEASE" + __FreeBSDABI="14" __SkipUnmount=1 ;; illumos) @@ -420,6 +450,10 @@ fi __UbuntuPackages+=" ${__LLDB_Package:-}" +if [[ -z "$__UbuntuRepo" ]]; then + __UbuntuRepo="http://ports.ubuntu.com/" +fi + if [[ -n "$__LLVM_MajorVersion" ]]; then __UbuntuPackages+=" libclang-common-${__LLVM_MajorVersion}${__LLVM_MinorVersion:+.$__LLVM_MinorVersion}-dev" fi @@ -442,13 +476,39 @@ fi mkdir -p "$__RootfsDir" __RootfsDir="$( cd "$__RootfsDir" && pwd )" +__hasWget= +ensureDownloadTool() +{ + if command -v wget &> /dev/null; then + __hasWget=1 + elif command -v curl &> /dev/null; then + __hasWget=0 + else + >&2 echo "ERROR: either wget or curl is required by this script." + exit 1 + fi +} + if [[ "$__CodeName" == "alpine" ]]; then __ApkToolsVersion=2.12.11 - __ApkToolsSHA512SUM=53e57b49230da07ef44ee0765b9592580308c407a8d4da7125550957bb72cb59638e04f8892a18b584451c8d841d1c7cb0f0ab680cc323a3015776affaa3be33 __ApkToolsDir="$(mktemp -d)" __ApkKeysDir="$(mktemp -d)" + arch="$(uname -m)" - wget "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic//v$__ApkToolsVersion/x86_64/apk.static" -P "$__ApkToolsDir" + ensureDownloadTool + + if [[ "$__hasWget" == 1 ]]; then + wget -P "$__ApkToolsDir" "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic/v$__ApkToolsVersion/$arch/apk.static" + else + curl -SLO --create-dirs --output-dir "$__ApkToolsDir" "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic/v$__ApkToolsVersion/$arch/apk.static" + fi + if [[ "$arch" == "x86_64" ]]; then + __ApkToolsSHA512SUM="53e57b49230da07ef44ee0765b9592580308c407a8d4da7125550957bb72cb59638e04f8892a18b584451c8d841d1c7cb0f0ab680cc323a3015776affaa3be33" + elif [[ "$arch" == "aarch64" ]]; then + __ApkToolsSHA512SUM="9e2b37ecb2b56c05dad23d379be84fd494c14bd730b620d0d576bda760588e1f2f59a7fcb2f2080577e0085f23a0ca8eadd993b4e61c2ab29549fdb71969afd0" + else + echo "WARNING: add missing hash for your host architecture. To find the value, use: 'find /tmp -name apk.static -exec sha512sum {} \;'" + fi echo "$__ApkToolsSHA512SUM $__ApkToolsDir/apk.static" | sha512sum -c chmod +x "$__ApkToolsDir/apk.static" @@ -477,20 +537,23 @@ if [[ "$__CodeName" == "alpine" ]]; then fi # initialize DB + # shellcheck disable=SC2086 "$__ApkToolsDir/apk.static" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" --initdb add if [[ "$__AlpineLlvmLibsLookup" == 1 ]]; then + # shellcheck disable=SC2086 __AlpinePackages+=" $("$__ApkToolsDir/apk.static" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" \ - search 'llvm*-libs' | sort | tail -1 | sed 's/-[^-]*//2g')" + search 'llvm*-libs' | grep -E '^llvm' | sort | tail -1 | sed 's/-[^-]*//2g')" fi # install all packages in one go + # shellcheck disable=SC2086 "$__ApkToolsDir/apk.static" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \ @@ -501,12 +564,23 @@ if [[ "$__CodeName" == "alpine" ]]; then elif [[ "$__CodeName" == "freebsd" ]]; then mkdir -p "$__RootfsDir"/usr/local/etc JOBS=${MAXJOBS:="$(getconf _NPROCESSORS_ONLN)"} - wget -O - "https://download.freebsd.org/ftp/releases/${__FreeBSDArch}/${__FreeBSDMachineArch}/${__FreeBSDBase}/base.txz" | tar -C "$__RootfsDir" -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version + + ensureDownloadTool + + if [[ "$__hasWget" == 1 ]]; then + wget -O- "https://download.freebsd.org/ftp/releases/${__FreeBSDArch}/${__FreeBSDMachineArch}/${__FreeBSDBase}/base.txz" | tar -C "$__RootfsDir" -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version + else + curl -SL "https://download.freebsd.org/ftp/releases/${__FreeBSDArch}/${__FreeBSDMachineArch}/${__FreeBSDBase}/base.txz" | tar -C "$__RootfsDir" -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version + fi echo "ABI = \"FreeBSD:${__FreeBSDABI}:${__FreeBSDMachineArch}\"; FINGERPRINTS = \"${__RootfsDir}/usr/share/keys\"; REPOS_DIR = [\"${__RootfsDir}/etc/pkg\"]; REPO_AUTOUPDATE = NO; RUN_SCRIPTS = NO;" > "${__RootfsDir}"/usr/local/etc/pkg.conf echo "FreeBSD: { url: \"pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly\", mirror_type: \"srv\", signature_type: \"fingerprints\", fingerprints: \"${__RootfsDir}/usr/share/keys/pkg\", enabled: yes }" > "${__RootfsDir}"/etc/pkg/FreeBSD.conf mkdir -p "$__RootfsDir"/tmp # get and build package manager - wget -O - "https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz" | tar -C "$__RootfsDir"/tmp -zxf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- "https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz" | tar -C "$__RootfsDir"/tmp -zxf - + else + curl -SL "https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz" | tar -C "$__RootfsDir"/tmp -zxf - + fi cd "$__RootfsDir/tmp/pkg-${__FreeBSDPkg}" # needed for install to succeed mkdir -p "$__RootfsDir"/host/etc @@ -514,27 +588,43 @@ elif [[ "$__CodeName" == "freebsd" ]]; then rm -rf "$__RootfsDir/tmp/pkg-${__FreeBSDPkg}" # install packages we need. INSTALL_AS_USER=$(whoami) "$__RootfsDir"/host/sbin/pkg -r "$__RootfsDir" -C "$__RootfsDir"/usr/local/etc/pkg.conf update + # shellcheck disable=SC2086 INSTALL_AS_USER=$(whoami) "$__RootfsDir"/host/sbin/pkg -r "$__RootfsDir" -C "$__RootfsDir"/usr/local/etc/pkg.conf install --yes $__FreeBSDPackages elif [[ "$__CodeName" == "illumos" ]]; then mkdir "$__RootfsDir/tmp" pushd "$__RootfsDir/tmp" JOBS=${MAXJOBS:="$(getconf _NPROCESSORS_ONLN)"} + + ensureDownloadTool + echo "Downloading sysroot." - wget -O - https://github.com/illumos/sysroot/releases/download/20181213-de6af22ae73b-v1/illumos-sysroot-i386-20181213-de6af22ae73b-v1.tar.gz | tar -C "$__RootfsDir" -xzf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- https://github.com/illumos/sysroot/releases/download/20181213-de6af22ae73b-v1/illumos-sysroot-i386-20181213-de6af22ae73b-v1.tar.gz | tar -C "$__RootfsDir" -xzf - + else + curl -SL https://github.com/illumos/sysroot/releases/download/20181213-de6af22ae73b-v1/illumos-sysroot-i386-20181213-de6af22ae73b-v1.tar.gz | tar -C "$__RootfsDir" -xzf - + fi echo "Building binutils. Please wait.." - wget -O - https://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2 | tar -xjf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- https://ftp.gnu.org/gnu/binutils/binutils-2.42.tar.xz | tar -xJf - + else + curl -SL https://ftp.gnu.org/gnu/binutils/binutils-2.42.tar.xz | tar -xJf - + fi mkdir build-binutils && cd build-binutils - ../binutils-2.33.1/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.10" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" + ../binutils-2.42/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.11" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" make -j "$JOBS" && make install && cd .. echo "Building gcc. Please wait.." - wget -O - https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz | tar -xJf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- https://ftp.gnu.org/gnu/gcc/gcc-13.3.0/gcc-13.3.0.tar.xz | tar -xJf - + else + curl -SL https://ftp.gnu.org/gnu/gcc/gcc-13.3.0/gcc-13.3.0.tar.xz | tar -xJf - + fi CFLAGS="-fPIC" CXXFLAGS="-fPIC" CXXFLAGS_FOR_TARGET="-fPIC" CFLAGS_FOR_TARGET="-fPIC" export CFLAGS CXXFLAGS CXXFLAGS_FOR_TARGET CFLAGS_FOR_TARGET mkdir build-gcc && cd build-gcc - ../gcc-8.4.0/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.10" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" --with-gnu-as \ + ../gcc-13.3.0/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.11" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" --with-gnu-as \ --with-gnu-ld --disable-nls --disable-libgomp --disable-libquadmath --disable-libssp --disable-libvtv --disable-libcilkrts --disable-libada --disable-libsanitizer \ --disable-libquadmath-support --disable-shared --enable-tls make -j "$JOBS" && make install && cd .. @@ -542,9 +632,13 @@ elif [[ "$__CodeName" == "illumos" ]]; then if [[ "$__UseMirror" == 1 ]]; then BaseUrl=https://pkgsrc.smartos.skylime.net fi - BaseUrl="$BaseUrl/packages/SmartOS/trunk/${__illumosArch}/All" + BaseUrl="$BaseUrl/packages/SmartOS/2019Q4/${__illumosArch}/All" echo "Downloading manifest" - wget "$BaseUrl" + if [[ "$__hasWget" == 1 ]]; then + wget "$BaseUrl" + else + curl -SLO "$BaseUrl" + fi echo "Downloading dependencies." read -ra array <<<"$__IllumosPackages" for package in "${array[@]}"; do @@ -552,7 +646,11 @@ elif [[ "$__CodeName" == "illumos" ]]; then # find last occurrence of package in listing and extract its name package="$(sed -En '/.*href="('"$package"'-[0-9].*).tgz".*/h;$!d;g;s//\1/p' All)" echo "Resolved name '$package'" - wget "$BaseUrl"/"$package".tgz + if [[ "$__hasWget" == 1 ]]; then + wget "$BaseUrl"/"$package".tgz + else + curl -SLO "$BaseUrl"/"$package".tgz + fi ar -x "$package".tgz tar --skip-old-files -xzf "$package".tmp.tg* -C "$__RootfsDir" 2>/dev/null done @@ -561,10 +659,17 @@ elif [[ "$__CodeName" == "illumos" ]]; then rm -rf "$__RootfsDir"/{tmp,+*} mkdir -p "$__RootfsDir"/usr/include/net mkdir -p "$__RootfsDir"/usr/include/netpacket - wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/bpf.h - wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/dlt.h - wget -P "$__RootfsDir"/usr/include/netpacket https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/inet/sockmods/netpacket/packet.h - wget -P "$__RootfsDir"/usr/include/sys https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/sys/sdt.h + if [[ "$__hasWget" == 1 ]]; then + wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/bpf.h + wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/dlt.h + wget -P "$__RootfsDir"/usr/include/netpacket https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/inet/sockmods/netpacket/packet.h + wget -P "$__RootfsDir"/usr/include/sys https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/sys/sdt.h + else + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/bpf.h + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/dlt.h + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/netpacket https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/inet/sockmods/netpacket/packet.h + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/sys https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/sys/sdt.h + fi elif [[ "$__CodeName" == "haiku" ]]; then JOBS=${MAXJOBS:="$(getconf _NPROCESSORS_ONLN)"} @@ -574,9 +679,16 @@ elif [[ "$__CodeName" == "haiku" ]]; then mkdir "$__RootfsDir/tmp/download" + ensureDownloadTool + echo "Downloading Haiku package tool" - git clone https://github.com/haiku/haiku-toolchains-ubuntu --depth 1 $__RootfsDir/tmp/script - wget -O "$__RootfsDir/tmp/download/hosttools.zip" $($__RootfsDir/tmp/script/fetch.sh --hosttools) + git clone https://github.com/haiku/haiku-toolchains-ubuntu --depth 1 "$__RootfsDir/tmp/script" + if [[ "$__hasWget" == 1 ]]; then + wget -O "$__RootfsDir/tmp/download/hosttools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --hosttools)" + else + curl -SLo "$__RootfsDir/tmp/download/hosttools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --hosttools)" + fi + unzip -o "$__RootfsDir/tmp/download/hosttools.zip" -d "$__RootfsDir/tmp/bin" DepotBaseUrl="https://depot.haiku-os.org/__api/v2/pkg/get-pkg" @@ -589,14 +701,25 @@ elif [[ "$__CodeName" == "haiku" ]]; then echo "Downloading $package..." # API documented here: https://github.com/haiku/haikudepotserver/blob/master/haikudepotserver-api2/src/main/resources/api2/pkg.yaml#L60 # The schema here: https://github.com/haiku/haikudepotserver/blob/master/haikudepotserver-api2/src/main/resources/api2/pkg.yaml#L598 - hpkgDownloadUrl="$(wget -qO- --post-data='{"name":"'"$package"'","repositorySourceCode":"haikuports_'$__HaikuArch'","versionType":"LATEST","naturalLanguageCode":"en"}' \ - --header='Content-Type:application/json' "$DepotBaseUrl" | jq -r '.result.versions[].hpkgDownloadURL')" - wget -P "$__RootfsDir/tmp/download" "$hpkgDownloadUrl" + if [[ "$__hasWget" == 1 ]]; then + hpkgDownloadUrl="$(wget -qO- --post-data '{"name":"'"$package"'","repositorySourceCode":"haikuports_'$__HaikuArch'","versionType":"LATEST","naturalLanguageCode":"en"}' \ + --header 'Content-Type:application/json' "$DepotBaseUrl" | jq -r '.result.versions[].hpkgDownloadURL')" + wget -P "$__RootfsDir/tmp/download" "$hpkgDownloadUrl" + else + hpkgDownloadUrl="$(curl -sSL -XPOST --data '{"name":"'"$package"'","repositorySourceCode":"haikuports_'$__HaikuArch'","versionType":"LATEST","naturalLanguageCode":"en"}' \ + --header 'Content-Type:application/json' "$DepotBaseUrl" | jq -r '.result.versions[].hpkgDownloadURL')" + curl -SLO --create-dirs --output-dir "$__RootfsDir/tmp/download" "$hpkgDownloadUrl" + fi done for package in haiku haiku_devel; do echo "Downloading $package..." - hpkgVersion="$(wget -qO- $HpkgBaseUrl | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" - wget -P "$__RootfsDir/tmp/download" "$HpkgBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" + if [[ "$__hasWget" == 1 ]]; then + hpkgVersion="$(wget -qO- "$HpkgBaseUrl" | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" + wget -P "$__RootfsDir/tmp/download" "$HpkgBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" + else + hpkgVersion="$(curl -sSL "$HpkgBaseUrl" | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" + curl -SLO --create-dirs --output-dir "$__RootfsDir/tmp/download" "$HpkgBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" + fi done # Set up the sysroot @@ -609,7 +732,11 @@ elif [[ "$__CodeName" == "haiku" ]]; then # Download buildtools echo "Downloading Haiku buildtools" - wget -O "$__RootfsDir/tmp/download/buildtools.zip" $($__RootfsDir/tmp/script/fetch.sh --buildtools --arch=$__HaikuArch) + if [[ "$__hasWget" == 1 ]]; then + wget -O "$__RootfsDir/tmp/download/buildtools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --buildtools --arch=$__HaikuArch)" + else + curl -SLo "$__RootfsDir/tmp/download/buildtools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --buildtools --arch=$__HaikuArch)" + fi unzip -o "$__RootfsDir/tmp/download/buildtools.zip" -d "$__RootfsDir" # Cleaning up temporary files @@ -622,10 +749,22 @@ elif [[ -n "$__CodeName" ]]; then __Keyring="$__Keyring --force-check-gpg" fi + # shellcheck disable=SC2086 + echo running debootstrap "--variant=minbase" $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo" debootstrap "--variant=minbase" $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo" - cp "$__CrossDir/$__BuildArch/sources.list.$__CodeName" "$__RootfsDir/etc/apt/sources.list" + + mkdir -p "$__RootfsDir/etc/apt/sources.list.d/" + cat > "$__RootfsDir/etc/apt/sources.list.d/$__CodeName.sources" <>Start configuring Tizen rootfs" ln -sfn asm-${LINK_ARCH} ./usr/include/asm patch -p1 < $__TIZEN_CROSSDIR/tizen.patch +if [[ "$TIZEN_ARCH" == "riscv64" ]]; then + echo "Fixing broken symlinks in $PWD" + rm ./usr/lib64/libresolv.so + ln -s ../../lib64/libresolv.so.2 ./usr/lib64/libresolv.so + rm ./usr/lib64/libpthread.so + ln -s ../../lib64/libpthread.so.0 ./usr/lib64/libpthread.so + rm ./usr/lib64/libdl.so + ln -s ../../lib64/libdl.so.2 ./usr/lib64/libdl.so + rm ./usr/lib64/libutil.so + ln -s ../../lib64/libutil.so.1 ./usr/lib64/libutil.so + rm ./usr/lib64/libm.so + ln -s ../../lib64/libm.so.6 ./usr/lib64/libm.so + rm ./usr/lib64/librt.so + ln -s ../../lib64/librt.so.1 ./usr/lib64/librt.so + rm ./lib/ld-linux-riscv64-lp64d.so.1 + ln -s ../lib64/ld-linux-riscv64-lp64d.so.1 ./lib/ld-linux-riscv64-lp64d.so.1 +fi echo "<:--stdlib=${CLR_CMAKE_CXX_STANDARD_LIBRARY}>) + add_link_options($<$:--stdlib=${CLR_CMAKE_CXX_STANDARD_LIBRARY}>) +endif() + +option(CLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC "Statically link against the C++ standard library" OFF) +if(CLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC) + add_link_options($<$:-static-libstdc++>) +endif() + +set(CLR_CMAKE_CXX_ABI_LIBRARY "" CACHE STRING "C++ ABI implementation library to link against. Only supported with the Clang compiler.") +if (CLR_CMAKE_CXX_ABI_LIBRARY) + # The user may specify the ABI library with the 'lib' prefix, like 'libstdc++'. Strip the prefix here so the linker finds the right library. + string(REGEX REPLACE "^lib(.+)" "\\1" CLR_CMAKE_CXX_ABI_LIBRARY ${CLR_CMAKE_CXX_ABI_LIBRARY}) + # We need to specify this as a linker-backend option as Clang will filter this option out when linking to libc++. + add_link_options("LINKER:-l${CLR_CMAKE_CXX_ABI_LIBRARY}") +endif() + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/eng/common/darc-init.ps1 b/eng/common/darc-init.ps1 index 8fda30bdce2b..e33743105635 100644 --- a/eng/common/darc-init.ps1 +++ b/eng/common/darc-init.ps1 @@ -1,6 +1,6 @@ param ( $darcVersion = $null, - $versionEndpoint = 'https://maestro.dot.net/api/assets/darc-version?api-version=2019-01-16', + $versionEndpoint = 'https://maestro.dot.net/api/assets/darc-version?api-version=2020-02-20', $verbosity = 'minimal', $toolpath = $null ) diff --git a/eng/common/darc-init.sh b/eng/common/darc-init.sh index c305ae6bd771..36dbd45e1ce8 100755 --- a/eng/common/darc-init.sh +++ b/eng/common/darc-init.sh @@ -2,7 +2,7 @@ source="${BASH_SOURCE[0]}" darcVersion='' -versionEndpoint='https://maestro.dot.net/api/assets/darc-version?api-version=2019-01-16' +versionEndpoint='https://maestro.dot.net/api/assets/darc-version?api-version=2020-02-20' verbosity='minimal' while [[ $# > 0 ]]; do diff --git a/eng/common/dotnet-install.sh b/eng/common/dotnet-install.sh index 7e69e3a9e24a..7b9d97e3bd4d 100755 --- a/eng/common/dotnet-install.sh +++ b/eng/common/dotnet-install.sh @@ -71,6 +71,9 @@ case $cpuname in i[3-6]86) buildarch=x86 ;; + riscv64) + buildarch=riscv64 + ;; *) echo "Unknown CPU $cpuname detected, treating it as x64" buildarch=x64 @@ -82,7 +85,7 @@ if [[ $architecture != "" ]] && [[ $architecture != $buildarch ]]; then dotnetRoot="$dotnetRoot/$architecture" fi -InstallDotNet $dotnetRoot $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey || { +InstallDotNet "$dotnetRoot" $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey || { local exit_code=$? Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "dotnet-install.sh failed (exit code '$exit_code')." >&2 ExitWithExitCode $exit_code diff --git a/eng/common/helixpublish.proj b/eng/common/helixpublish.proj index d7f185856e79..c1323bf41210 100644 --- a/eng/common/helixpublish.proj +++ b/eng/common/helixpublish.proj @@ -1,3 +1,4 @@ + diff --git a/eng/common/internal/Directory.Build.props b/eng/common/internal/Directory.Build.props index dbf99d82a5c2..f1d041c33da5 100644 --- a/eng/common/internal/Directory.Build.props +++ b/eng/common/internal/Directory.Build.props @@ -1,4 +1,11 @@ + + + false + false + + + diff --git a/eng/common/internal/Tools.csproj b/eng/common/internal/Tools.csproj index 7f5ce6d60813..32f79dfb3402 100644 --- a/eng/common/internal/Tools.csproj +++ b/eng/common/internal/Tools.csproj @@ -1,9 +1,10 @@ + net472 - false false + false @@ -27,4 +28,5 @@ + diff --git a/eng/common/native/CommonLibrary.psm1 b/eng/common/native/CommonLibrary.psm1 index ca38268c44d8..f71f6af6cdbc 100644 --- a/eng/common/native/CommonLibrary.psm1 +++ b/eng/common/native/CommonLibrary.psm1 @@ -277,7 +277,8 @@ function Get-MachineArchitecture { if (($ProcessorArchitecture -Eq "AMD64") -Or ($ProcessorArchitecture -Eq "IA64") -Or ($ProcessorArchitecture -Eq "ARM64") -Or - ($ProcessorArchitecture -Eq "LOONGARCH64")) { + ($ProcessorArchitecture -Eq "LOONGARCH64") -Or + ($ProcessorArchitecture -Eq "RISCV64")) { return "x64" } return "x86" diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index 2d5660642b8d..9a0e1f2b4567 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -2,7 +2,9 @@ # # This file detects the C/C++ compiler and exports it to the CC/CXX environment variables # -# NOTE: some scripts source this file and rely on stdout being empty, make sure to not output anything here! +# NOTE: some scripts source this file and rely on stdout being empty, make sure +# to not output *anything* here, unless it is an error message that fails the +# build. if [ -z "$build_arch" ] || [ -z "$compiler" ]; then echo "Usage..." @@ -17,11 +19,9 @@ case "$compiler" in # clangx.y or clang-x.y version="$(echo "$compiler" | tr -d '[:alpha:]-=')" majorVersion="${version%%.*}" - [ -z "${version##*.*}" ] && minorVersion="${version#*.}" - if [ -z "$minorVersion" ] && [ -n "$majorVersion" ] && [ "$majorVersion" -le 6 ]; then - minorVersion=0; - fi + # LLVM based on v18 released in early 2024, with two releases per year + maxVersion="$((18 + ((($(date +%Y) - 2024) * 12 + $(date +%-m) - 3) / 6)))" compiler=clang ;; @@ -29,7 +29,9 @@ case "$compiler" in # gccx.y or gcc-x.y version="$(echo "$compiler" | tr -d '[:alpha:]-=')" majorVersion="${version%%.*}" - [ -z "${version##*.*}" ] && minorVersion="${version#*.}" + + # GCC based on v14 released in early 2024, with one release per year + maxVersion="$((14 + ((($(date +%Y) - 2024) * 12 + $(date +%-m) - 3) / 12)))" compiler=gcc ;; esac @@ -47,91 +49,98 @@ check_version_exists() { desired_version=-1 # Set up the environment to be used for building with the desired compiler. - if command -v "$compiler-$1.$2" > /dev/null; then - desired_version="-$1.$2" - elif command -v "$compiler$1$2" > /dev/null; then - desired_version="$1$2" - elif command -v "$compiler-$1$2" > /dev/null; then - desired_version="-$1$2" + if command -v "$compiler-$1" > /dev/null; then + desired_version="-$1" + elif command -v "$compiler$1" > /dev/null; then + desired_version="$1" fi echo "$desired_version" } +__baseOS="$(uname)" +set_compiler_version_from_CC() { + if [ "$__baseOS" = "Darwin" ]; then + # On Darwin, the versions from -version/-dumpversion refer to Xcode + # versions, not llvm versions, so we can't rely on them. + return + fi + + version="$("$CC" -dumpversion)" + if [ -z "$version" ]; then + echo "Error: $CC -dumpversion didn't provide a version" + exit 1 + fi + + # gcc and clang often display 3 part versions. However, gcc can show only 1 part in some environments. + IFS=. read -r majorVersion _ < /dev/null; then - if [ "$(uname)" != "Darwin" ]; then - echo "Warning: Specific version of $compiler not found, falling back to use the one in PATH." - fi - CC="$(command -v "$compiler")" - CXX="$(command -v "$cxxCompiler")" - else - echo "No usable version of $compiler found." + if ! command -v "$compiler" > /dev/null; then + echo "Error: No compatible version of $compiler was found within the range of $minVersion to $maxVersion. Please upgrade your toolchain or specify the compiler explicitly using CLR_CC and CLR_CXX environment variables." exit 1 fi - else - if [ "$compiler" = "clang" ] && [ "$majorVersion" -lt 5 ]; then - if [ "$build_arch" = "arm" ] || [ "$build_arch" = "armel" ]; then - if command -v "$compiler" > /dev/null; then - echo "Warning: Found clang version $majorVersion which is not supported on arm/armel architectures, falling back to use clang from PATH." - CC="$(command -v "$compiler")" - CXX="$(command -v "$cxxCompiler")" - else - echo "Found clang version $majorVersion which is not supported on arm/armel architectures, and there is no clang in PATH." - exit 1 - fi - fi - fi + + CC="$(command -v "$compiler" 2> /dev/null)" + CXX="$(command -v "$cxxCompiler" 2> /dev/null)" + set_compiler_version_from_CC fi else - desired_version="$(check_version_exists "$majorVersion" "$minorVersion")" + desired_version="$(check_version_exists "$majorVersion")" if [ "$desired_version" = "-1" ]; then - echo "Could not find specific version of $compiler: $majorVersion $minorVersion." + echo "Error: Could not find specific version of $compiler: $majorVersion." exit 1 fi fi if [ -z "$CC" ]; then - CC="$(command -v "$compiler$desired_version")" - CXX="$(command -v "$cxxCompiler$desired_version")" - if [ -z "$CXX" ]; then CXX="$(command -v "$cxxCompiler")"; fi + CC="$(command -v "$compiler$desired_version" 2> /dev/null)" + CXX="$(command -v "$cxxCompiler$desired_version" 2> /dev/null)" + if [ -z "$CXX" ]; then CXX="$(command -v "$cxxCompiler" 2> /dev/null)"; fi + set_compiler_version_from_CC fi else if [ ! -f "$CLR_CC" ]; then - echo "CLR_CC is set but path '$CLR_CC' does not exist" + echo "Error: CLR_CC is set but path '$CLR_CC' does not exist" exit 1 fi CC="$CLR_CC" CXX="$CLR_CXX" + set_compiler_version_from_CC fi if [ -z "$CC" ]; then - echo "Unable to find $compiler." + echo "Error: Unable to find $compiler." exit 1 fi -# Only lld version >= 9 can be considered stable. lld doesn't support s390x. -if [ "$compiler" = "clang" ] && [ -n "$majorVersion" ] && [ "$majorVersion" -ge 9 ] && [ "$build_arch" != "s390x" ]; then - if "$CC" -fuse-ld=lld -Wl,--version >/dev/null 2>&1; then - LDFLAGS="-fuse-ld=lld" +if [ "$__baseOS" != "Darwin" ]; then + # On Darwin, we always want to use the Apple linker. + + # Only lld version >= 9 can be considered stable. lld supports s390x starting from 18.0. + if [ "$compiler" = "clang" ] && [ -n "$majorVersion" ] && [ "$majorVersion" -ge 9 ] && { [ "$build_arch" != "s390x" ] || [ "$majorVersion" -ge 18 ]; }; then + if "$CC" -fuse-ld=lld -Wl,--version >/dev/null 2>&1; then + LDFLAGS="-fuse-ld=lld" + fi fi fi -SCAN_BUILD_COMMAND="$(command -v "scan-build$desired_version")" +SCAN_BUILD_COMMAND="$(command -v "scan-build$desired_version" 2> /dev/null)" export CC CXX LDFLAGS SCAN_BUILD_COMMAND diff --git a/eng/common/native/init-distro-rid.sh b/eng/common/native/init-distro-rid.sh index de1687b2ccbe..83ea7aab0e08 100644 --- a/eng/common/native/init-distro-rid.sh +++ b/eng/common/native/init-distro-rid.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # getNonPortableDistroRid # @@ -11,21 +11,16 @@ # non-portable rid getNonPortableDistroRid() { - local targetOs="$1" - local targetArch="$2" - local rootfsDir="$3" - local nonPortableRid="" + targetOs="$1" + targetArch="$2" + rootfsDir="$3" + nonPortableRid="" if [ "$targetOs" = "linux" ]; then + # shellcheck disable=SC1091 if [ -e "${rootfsDir}/etc/os-release" ]; then - source "${rootfsDir}/etc/os-release" - - if [[ "${ID}" == "rhel" || "${ID}" == "rocky" || "${ID}" == "alpine" ]]; then - # remove the last version digit - VERSION_ID="${VERSION_ID%.*}" - fi - - if [[ "${VERSION_ID:-}" =~ ^([[:digit:]]|\.)+$ ]]; then + . "${rootfsDir}/etc/os-release" + if echo "${VERSION_ID:-}" | grep -qE '^([[:digit:]]|\.)+$'; then nonPortableRid="${ID}.${VERSION_ID}-${targetArch}" else # Rolling release distros either do not set VERSION_ID, set it as blank or @@ -33,45 +28,33 @@ getNonPortableDistroRid() # so omit it here to be consistent with everything else. nonPortableRid="${ID}-${targetArch}" fi - elif [ -e "${rootfsDir}/android_platform" ]; then - source "$rootfsDir"/android_platform + # shellcheck disable=SC1091 + . "${rootfsDir}/android_platform" nonPortableRid="$RID" fi fi if [ "$targetOs" = "freebsd" ]; then - # $rootfsDir can be empty. freebsd-version is shell script and it should always work. - __freebsd_major_version=$($rootfsDir/bin/freebsd-version | { read v; echo "${v%%.*}"; }) + # $rootfsDir can be empty. freebsd-version is a shell script and should always work. + __freebsd_major_version=$("$rootfsDir"/bin/freebsd-version | cut -d'.' -f1) nonPortableRid="freebsd.$__freebsd_major_version-${targetArch}" - elif command -v getprop && getprop ro.product.system.model 2>&1 | grep -qi android; then + elif command -v getprop >/dev/null && getprop ro.product.system.model | grep -qi android; then __android_sdk_version=$(getprop ro.build.version.sdk) nonPortableRid="android.$__android_sdk_version-${targetArch}" elif [ "$targetOs" = "illumos" ]; then __uname_version=$(uname -v) - case "$__uname_version" in - omnios-*) - __omnios_major_version=$(echo "${__uname_version:8:2}") - nonPortableRid=omnios."$__omnios_major_version"-"$targetArch" - ;; - joyent_*) - __smartos_major_version=$(echo "${__uname_version:7:4}") - nonPortableRid=smartos."$__smartos_major_version"-"$targetArch" - ;; - illumos_*) - nonPortableRid=openindiana-"$targetArch" - ;; - esac + nonPortableRid="illumos-${targetArch}" elif [ "$targetOs" = "solaris" ]; then __uname_version=$(uname -v) - __solaris_major_version=$(echo "${__uname_version%.*}") - nonPortableRid=solaris."$__solaris_major_version"-"$targetArch" + __solaris_major_version=$(echo "$__uname_version" | cut -d'.' -f1) + nonPortableRid="solaris.$__solaris_major_version-${targetArch}" elif [ "$targetOs" = "haiku" ]; then - __uname_release=$(uname -r) + __uname_release="$(uname -r)" nonPortableRid=haiku.r"$__uname_release"-"$targetArch" fi - echo "$(echo $nonPortableRid | tr '[:upper:]' '[:lower:]')" + echo "$nonPortableRid" | tr '[:upper:]' '[:lower:]' } # initDistroRidGlobal @@ -85,26 +68,23 @@ getNonPortableDistroRid() # None # # Notes: -# -# It is important to note that the function does not return anything, but it -# exports the following variables on success: -# -# __DistroRid : Non-portable rid of the target platform. -# __PortableTargetOS : OS-part of the portable rid that corresponds to the target platform. -# +# It is important to note that the function does not return anything, but it +# exports the following variables on success: +# __DistroRid : Non-portable rid of the target platform. +# __PortableTargetOS : OS-part of the portable rid that corresponds to the target platform. initDistroRidGlobal() { - local targetOs="$1" - local targetArch="$2" - local rootfsDir="" - if [ "$#" -ge 3 ]; then + targetOs="$1" + targetArch="$2" + rootfsDir="" + if [ $# -ge 3 ]; then rootfsDir="$3" fi if [ -n "${rootfsDir}" ]; then # We may have a cross build. Check for the existence of the rootfsDir if [ ! -e "${rootfsDir}" ]; then - echo "Error rootfsDir has been passed, but the location is not valid." + echo "Error: rootfsDir has been passed, but the location is not valid." exit 1 fi fi @@ -119,7 +99,7 @@ initDistroRidGlobal() STRINGS="$(command -v llvm-strings || true)" fi - # Check for musl-based distros (e.g Alpine Linux, Void Linux). + # Check for musl-based distros (e.g. Alpine Linux, Void Linux). if "${rootfsDir}/usr/bin/ldd" --version 2>&1 | grep -q musl || ( [ -n "$STRINGS" ] && "$STRINGS" "${rootfsDir}/usr/bin/ldd" 2>&1 | grep -q musl ); then __PortableTargetOS="linux-musl" diff --git a/eng/common/native/init-os-and-arch.sh b/eng/common/native/init-os-and-arch.sh index e693617a6c2b..38921d4338f7 100644 --- a/eng/common/native/init-os-and-arch.sh +++ b/eng/common/native/init-os-and-arch.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # Use uname to determine what the OS is. OSName=$(uname -s | tr '[:upper:]' '[:lower:]') @@ -35,6 +35,10 @@ fi case "$CPUName" in arm64|aarch64) arch=arm64 + if [ "$(getconf LONG_BIT)" -lt 64 ]; then + # This is 32-bit OS running on 64-bit CPU (for example Raspberry Pi OS) + arch=arm + fi ;; loongarch64) @@ -50,6 +54,7 @@ case "$CPUName" in ;; armv7l|armv8l) + # shellcheck disable=SC1091 if (NAME=""; . /etc/os-release; test "$NAME" = "Tizen"); then arch=armel else diff --git a/eng/common/post-build/add-build-to-channel.ps1 b/eng/common/post-build/add-build-to-channel.ps1 deleted file mode 100644 index 49938f0c89f7..000000000000 --- a/eng/common/post-build/add-build-to-channel.ps1 +++ /dev/null @@ -1,48 +0,0 @@ -param( - [Parameter(Mandatory=$true)][int] $BuildId, - [Parameter(Mandatory=$true)][int] $ChannelId, - [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, - [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net', - [Parameter(Mandatory=$false)][string] $MaestroApiVersion = '2019-01-16' -) - -try { - . $PSScriptRoot\post-build-utils.ps1 - - # Check that the channel we are going to promote the build to exist - $channelInfo = Get-MaestroChannel -ChannelId $ChannelId - - if (!$channelInfo) { - Write-PipelineTelemetryCategory -Category 'PromoteBuild' -Message "Channel with BAR ID $ChannelId was not found in BAR!" - ExitWithExitCode 1 - } - - # Get info about which channel(s) the build has already been promoted to - $buildInfo = Get-MaestroBuild -BuildId $BuildId - - if (!$buildInfo) { - Write-PipelineTelemetryError -Category 'PromoteBuild' -Message "Build with BAR ID $BuildId was not found in BAR!" - ExitWithExitCode 1 - } - - # Find whether the build is already assigned to the channel or not - if ($buildInfo.channels) { - foreach ($channel in $buildInfo.channels) { - if ($channel.Id -eq $ChannelId) { - Write-Host "The build with BAR ID $BuildId is already on channel $ChannelId!" - ExitWithExitCode 0 - } - } - } - - Write-Host "Promoting build '$BuildId' to channel '$ChannelId'." - - Assign-BuildToChannel -BuildId $BuildId -ChannelId $ChannelId - - Write-Host 'done.' -} -catch { - Write-Host $_ - Write-PipelineTelemetryError -Category 'PromoteBuild' -Message "There was an error while trying to promote build '$BuildId' to channel '$ChannelId'" - ExitWithExitCode 1 -} diff --git a/eng/common/post-build/check-channel-consistency.ps1 b/eng/common/post-build/check-channel-consistency.ps1 index 63f3464c986a..61208d2d1351 100644 --- a/eng/common/post-build/check-channel-consistency.ps1 +++ b/eng/common/post-build/check-channel-consistency.ps1 @@ -4,10 +4,18 @@ param( ) try { - . $PSScriptRoot\post-build-utils.ps1 + $ErrorActionPreference = 'Stop' + Set-StrictMode -Version 2.0 + + # `tools.ps1` checks $ci to perform some actions. Since the post-build + # scripts don't necessarily execute in the same agent that run the + # build.ps1/sh script this variable isn't automatically set. + $ci = $true + $disableConfigureToolsetImport = $true + . $PSScriptRoot\..\tools.ps1 if ($PromoteToChannels -eq "") { - Write-PipelineTaskError -Type 'warning' -Message "This build won't publish assets as it's not configured to any Maestro channel. If that wasn't intended use Darc to configure a default channel using add-default-channel for this branch or to promote it to a channel using add-build-to-channel. See https://github.com/dotnet/arcade/blob/master/Documentation/Darc.md#assigning-an-individual-build-to-a-channel for more info." + Write-PipelineTaskError -Type 'warning' -Message "This build won't publish assets as it's not configured to any Maestro channel. If that wasn't intended use Darc to configure a default channel using add-default-channel for this branch or to promote it to a channel using add-build-to-channel. See https://github.com/dotnet/arcade/blob/main/Documentation/Darc.md#assigning-an-individual-build-to-a-channel for more info." ExitWithExitCode 0 } diff --git a/eng/common/post-build/nuget-validation.ps1 b/eng/common/post-build/nuget-validation.ps1 index dab3534ab538..e5de00c89836 100644 --- a/eng/common/post-build/nuget-validation.ps1 +++ b/eng/common/post-build/nuget-validation.ps1 @@ -2,20 +2,18 @@ # tool: https://github.com/NuGet/NuGetGallery/tree/jver-verify/src/VerifyMicrosoftPackage param( - [Parameter(Mandatory=$true)][string] $PackagesPath, # Path to where the packages to be validated are - [Parameter(Mandatory=$true)][string] $ToolDestinationPath # Where the validation tool should be downloaded to + [Parameter(Mandatory=$true)][string] $PackagesPath # Path to where the packages to be validated are ) -try { - . $PSScriptRoot\post-build-utils.ps1 - - $url = 'https://raw.githubusercontent.com/NuGet/NuGetGallery/3e25ad135146676bcab0050a516939d9958bfa5d/src/VerifyMicrosoftPackage/verify.ps1' - - New-Item -ItemType 'directory' -Path ${ToolDestinationPath} -Force +# `tools.ps1` checks $ci to perform some actions. Since the post-build +# scripts don't necessarily execute in the same agent that run the +# build.ps1/sh script this variable isn't automatically set. +$ci = $true +$disableConfigureToolsetImport = $true +. $PSScriptRoot\..\tools.ps1 - Invoke-WebRequest $url -OutFile ${ToolDestinationPath}\verify.ps1 - - & ${ToolDestinationPath}\verify.ps1 ${PackagesPath}\*.nupkg +try { + & $PSScriptRoot\nuget-verification.ps1 ${PackagesPath}\*.nupkg } catch { Write-Host $_.ScriptStackTrace diff --git a/eng/common/post-build/nuget-verification.ps1 b/eng/common/post-build/nuget-verification.ps1 new file mode 100644 index 000000000000..a365194a9389 --- /dev/null +++ b/eng/common/post-build/nuget-verification.ps1 @@ -0,0 +1,121 @@ +<# +.SYNOPSIS + Verifies that Microsoft NuGet packages have proper metadata. +.DESCRIPTION + Downloads a verification tool and runs metadata validation on the provided NuGet packages. This script writes an + error if any of the provided packages fail validation. All arguments provided to this PowerShell script that do not + match PowerShell parameters are passed on to the verification tool downloaded during the execution of this script. +.PARAMETER NuGetExePath + The path to the nuget.exe binary to use. If not provided, nuget.exe will be downloaded into the -DownloadPath + directory. +.PARAMETER PackageSource + The package source to use to download the verification tool. If not provided, nuget.org will be used. +.PARAMETER DownloadPath + The directory path to download the verification tool and nuget.exe to. If not provided, + %TEMP%\NuGet.VerifyNuGetPackage will be used. +.PARAMETER args + Arguments that will be passed to the verification tool. +.EXAMPLE + PS> .\verify.ps1 *.nupkg + Verifies the metadata of all .nupkg files in the currect working directory. +.EXAMPLE + PS> .\verify.ps1 --help + Displays the help text of the downloaded verifiction tool. +.LINK + https://github.com/NuGet/NuGetGallery/blob/master/src/VerifyMicrosoftPackage/README.md +#> + +# This script was copied from https://github.com/NuGet/NuGetGallery/blob/3e25ad135146676bcab0050a516939d9958bfa5d/src/VerifyMicrosoftPackage/verify.ps1 + +[CmdletBinding(PositionalBinding = $false)] +param( + [string]$NuGetExePath, + [string]$PackageSource = "https://api.nuget.org/v3/index.json", + [string]$DownloadPath, + [Parameter(ValueFromRemainingArguments = $true)] + [string[]]$args +) + +# The URL to download nuget.exe. +$nugetExeUrl = "https://dist.nuget.org/win-x86-commandline/v4.9.4/nuget.exe" + +# The package ID of the verification tool. +$packageId = "NuGet.VerifyMicrosoftPackage" + +# The location that nuget.exe and the verification tool will be downloaded to. +if (!$DownloadPath) { + $DownloadPath = (Join-Path $env:TEMP "NuGet.VerifyMicrosoftPackage") +} + +$fence = New-Object -TypeName string -ArgumentList '=', 80 + +# Create the download directory, if it doesn't already exist. +if (!(Test-Path $DownloadPath)) { + New-Item -ItemType Directory $DownloadPath | Out-Null +} +Write-Host "Using download path: $DownloadPath" + +if ($NuGetExePath) { + $nuget = $NuGetExePath +} else { + $downloadedNuGetExe = Join-Path $DownloadPath "nuget.exe" + + # Download nuget.exe, if it doesn't already exist. + if (!(Test-Path $downloadedNuGetExe)) { + Write-Host "Downloading nuget.exe from $nugetExeUrl..." + $ProgressPreference = 'SilentlyContinue' + try { + Invoke-WebRequest $nugetExeUrl -OutFile $downloadedNuGetExe + $ProgressPreference = 'Continue' + } catch { + $ProgressPreference = 'Continue' + Write-Error $_ + Write-Error "nuget.exe failed to download." + exit + } + } + + $nuget = $downloadedNuGetExe +} + +Write-Host "Using nuget.exe path: $nuget" +Write-Host " " + +# Download the latest version of the verification tool. +Write-Host "Downloading the latest version of $packageId from $packageSource..." +Write-Host $fence +& $nuget install $packageId ` + -Prerelease ` + -OutputDirectory $DownloadPath ` + -Source $PackageSource +Write-Host $fence +Write-Host " " + +if ($LASTEXITCODE -ne 0) { + Write-Error "nuget.exe failed to fetch the verify tool." + exit +} + +# Find the most recently downloaded tool +Write-Host "Finding the most recently downloaded verification tool." +$verifyProbePath = Join-Path $DownloadPath "$packageId.*" +$verifyPath = Get-ChildItem -Path $verifyProbePath -Directory ` + | Sort-Object -Property LastWriteTime -Descending ` + | Select-Object -First 1 +$verify = Join-Path $verifyPath "tools\NuGet.VerifyMicrosoftPackage.exe" +Write-Host "Using verification tool: $verify" +Write-Host " " + +# Execute the verification tool. +Write-Host "Executing the verify tool..." +Write-Host $fence +& $verify $args +Write-Host $fence +Write-Host " " + +# Respond to the exit code. +if ($LASTEXITCODE -ne 0) { + Write-Error "The verify tool found some problems." +} else { + Write-Output "The verify tool succeeded." +} diff --git a/eng/common/post-build/post-build-utils.ps1 b/eng/common/post-build/post-build-utils.ps1 deleted file mode 100644 index 534f6988d5b7..000000000000 --- a/eng/common/post-build/post-build-utils.ps1 +++ /dev/null @@ -1,91 +0,0 @@ -# Most of the functions in this file require the variables `MaestroApiEndPoint`, -# `MaestroApiVersion` and `MaestroApiAccessToken` to be globally available. - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 2.0 - -# `tools.ps1` checks $ci to perform some actions. Since the post-build -# scripts don't necessarily execute in the same agent that run the -# build.ps1/sh script this variable isn't automatically set. -$ci = $true -$disableConfigureToolsetImport = $true -. $PSScriptRoot\..\tools.ps1 - -function Create-MaestroApiRequestHeaders([string]$ContentType = 'application/json') { - Validate-MaestroVars - - $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $headers.Add('Accept', $ContentType) - $headers.Add('Authorization',"Bearer $MaestroApiAccessToken") - return $headers -} - -function Get-MaestroChannel([int]$ChannelId) { - Validate-MaestroVars - - $apiHeaders = Create-MaestroApiRequestHeaders - $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}?api-version=$MaestroApiVersion" - - $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - return $result -} - -function Get-MaestroBuild([int]$BuildId) { - Validate-MaestroVars - - $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken - $apiEndpoint = "$MaestroApiEndPoint/api/builds/${BuildId}?api-version=$MaestroApiVersion" - - $result = try { return Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - return $result -} - -function Get-MaestroSubscriptions([string]$SourceRepository, [int]$ChannelId) { - Validate-MaestroVars - - $SourceRepository = [System.Web.HttpUtility]::UrlEncode($SourceRepository) - $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken - $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions?sourceRepository=$SourceRepository&channelId=$ChannelId&api-version=$MaestroApiVersion" - - $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - return $result -} - -function Assign-BuildToChannel([int]$BuildId, [int]$ChannelId) { - Validate-MaestroVars - - $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken - $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}/builds/${BuildId}?api-version=$MaestroApiVersion" - Invoke-WebRequest -Method Post -Uri $apiEndpoint -Headers $apiHeaders | Out-Null -} - -function Trigger-Subscription([string]$SubscriptionId) { - Validate-MaestroVars - - $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken - $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions/$SubscriptionId/trigger?api-version=$MaestroApiVersion" - Invoke-WebRequest -Uri $apiEndpoint -Headers $apiHeaders -Method Post | Out-Null -} - -function Validate-MaestroVars { - try { - Get-Variable MaestroApiEndPoint | Out-Null - Get-Variable MaestroApiVersion | Out-Null - Get-Variable MaestroApiAccessToken | Out-Null - - if (!($MaestroApiEndPoint -Match '^http[s]?://maestro-(int|prod).westus2.cloudapp.azure.com$')) { - Write-PipelineTelemetryError -Category 'MaestroVars' -Message "MaestroApiEndPoint is not a valid Maestro URL. '$MaestroApiEndPoint'" - ExitWithExitCode 1 - } - - if (!($MaestroApiVersion -Match '^[0-9]{4}-[0-9]{2}-[0-9]{2}$')) { - Write-PipelineTelemetryError -Category 'MaestroVars' -Message "MaestroApiVersion does not match a version string in the format yyyy-MM-DD. '$MaestroApiVersion'" - ExitWithExitCode 1 - } - } - catch { - Write-PipelineTelemetryError -Category 'MaestroVars' -Message 'Error: Variables `MaestroApiEndPoint`, `MaestroApiVersion` and `MaestroApiAccessToken` are required while using this script.' - Write-Host $_ - ExitWithExitCode 1 - } -} diff --git a/eng/common/post-build/publish-using-darc.ps1 b/eng/common/post-build/publish-using-darc.ps1 index 238945cb5ab4..90b58e32a87b 100644 --- a/eng/common/post-build/publish-using-darc.ps1 +++ b/eng/common/post-build/publish-using-darc.ps1 @@ -9,7 +9,12 @@ param( ) try { - . $PSScriptRoot\post-build-utils.ps1 + # `tools.ps1` checks $ci to perform some actions. Since the post-build + # scripts don't necessarily execute in the same agent that run the + # build.ps1/sh script this variable isn't automatically set. + $ci = $true + $disableConfigureToolsetImport = $true + . $PSScriptRoot\..\tools.ps1 $darc = Get-Darc @@ -37,6 +42,7 @@ try { --azdev-pat "$AzdoToken" ` --bar-uri "$MaestroApiEndPoint" ` --ci ` + --verbose ` @optionalParams if ($LastExitCode -ne 0) { diff --git a/eng/common/post-build/redact-logs.ps1 b/eng/common/post-build/redact-logs.ps1 new file mode 100644 index 000000000000..b7fc19591507 --- /dev/null +++ b/eng/common/post-build/redact-logs.ps1 @@ -0,0 +1,89 @@ +[CmdletBinding(PositionalBinding=$False)] +param( + [Parameter(Mandatory=$true, Position=0)][string] $InputPath, + [Parameter(Mandatory=$true)][string] $BinlogToolVersion, + [Parameter(Mandatory=$false)][string] $DotnetPath, + [Parameter(Mandatory=$false)][string] $PackageFeed = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json', + # File with strings to redact - separated by newlines. + # For comments start the line with '# ' - such lines are ignored + [Parameter(Mandatory=$false)][string] $TokensFilePath, + [Parameter(ValueFromRemainingArguments=$true)][String[]]$TokensToRedact +) + +try { + $ErrorActionPreference = 'Stop' + Set-StrictMode -Version 2.0 + + # `tools.ps1` checks $ci to perform some actions. Since the post-build + # scripts don't necessarily execute in the same agent that run the + # build.ps1/sh script this variable isn't automatically set. + $ci = $true + $disableConfigureToolsetImport = $true + . $PSScriptRoot\..\tools.ps1 + + $packageName = 'binlogtool' + + $dotnet = $DotnetPath + + if (!$dotnet) { + $dotnetRoot = InitializeDotNetCli -install:$true + $dotnet = "$dotnetRoot\dotnet.exe" + } + + $toolList = & "$dotnet" tool list -g + + if ($toolList -like "*$packageName*") { + & "$dotnet" tool uninstall $packageName -g + } + + $toolPath = "$PSScriptRoot\..\..\..\.tools" + $verbosity = 'minimal' + + New-Item -ItemType Directory -Force -Path $toolPath + + Push-Location -Path $toolPath + + try { + Write-Host "Installing Binlog redactor CLI..." + Write-Host "'$dotnet' new tool-manifest" + & "$dotnet" new tool-manifest + Write-Host "'$dotnet' tool install $packageName --local --add-source '$PackageFeed' -v $verbosity --version $BinlogToolVersion" + & "$dotnet" tool install $packageName --local --add-source "$PackageFeed" -v $verbosity --version $BinlogToolVersion + + if (Test-Path $TokensFilePath) { + Write-Host "Adding additional sensitive data for redaction from file: " $TokensFilePath + $TokensToRedact += Get-Content -Path $TokensFilePath | Foreach {$_.Trim()} | Where { $_ -notmatch "^# " } + } + + $optionalParams = [System.Collections.ArrayList]::new() + + Foreach ($p in $TokensToRedact) + { + if($p -match '^\$\(.*\)$') + { + Write-Host ("Ignoring token {0} as it is probably unexpanded AzDO variable" -f $p) + } + elseif($p) + { + $optionalParams.Add("-p:" + $p) | Out-Null + } + } + + & $dotnet binlogtool redact --input:$InputPath --recurse --in-place ` + @optionalParams + + if ($LastExitCode -ne 0) { + Write-PipelineTelemetryError -Category 'Redactor' -Type 'warning' -Message "Problems using Redactor tool (exit code: $LastExitCode). But ignoring them now." + } + } + finally { + Pop-Location + } + + Write-Host 'done.' +} +catch { + Write-Host $_ + Write-PipelineTelemetryError -Category 'Redactor' -Message "There was an error while trying to redact logs. Error: $_" + ExitWithExitCode 1 +} diff --git a/eng/common/post-build/sourcelink-validation.ps1 b/eng/common/post-build/sourcelink-validation.ps1 index 4011d324e739..1976ef70fb85 100644 --- a/eng/common/post-build/sourcelink-validation.ps1 +++ b/eng/common/post-build/sourcelink-validation.ps1 @@ -6,7 +6,15 @@ param( [Parameter(Mandatory=$true)][string] $SourcelinkCliVersion # Version of SourceLink CLI to use ) -. $PSScriptRoot\post-build-utils.ps1 +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version 2.0 + +# `tools.ps1` checks $ci to perform some actions. Since the post-build +# scripts don't necessarily execute in the same agent that run the +# build.ps1/sh script this variable isn't automatically set. +$ci = $true +$disableConfigureToolsetImport = $true +. $PSScriptRoot\..\tools.ps1 # Cache/HashMap (File -> Exist flag) used to consult whether a file exist # in the repository at a specific commit point. This is populated by inserting diff --git a/eng/common/post-build/symbols-validation.ps1 b/eng/common/post-build/symbols-validation.ps1 index cd2181bafa05..7146e593ffae 100644 --- a/eng/common/post-build/symbols-validation.ps1 +++ b/eng/common/post-build/symbols-validation.ps1 @@ -322,8 +322,6 @@ function InstallDotnetSymbol { } try { - . $PSScriptRoot\post-build-utils.ps1 - InstallDotnetSymbol foreach ($Job in @(Get-Job)) { diff --git a/eng/common/post-build/trigger-subscriptions.ps1 b/eng/common/post-build/trigger-subscriptions.ps1 deleted file mode 100644 index ac9a95778fcd..000000000000 --- a/eng/common/post-build/trigger-subscriptions.ps1 +++ /dev/null @@ -1,64 +0,0 @@ -param( - [Parameter(Mandatory=$true)][string] $SourceRepo, - [Parameter(Mandatory=$true)][int] $ChannelId, - [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, - [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net', - [Parameter(Mandatory=$false)][string] $MaestroApiVersion = '2019-01-16' -) - -try { - . $PSScriptRoot\post-build-utils.ps1 - - # Get all the $SourceRepo subscriptions - $normalizedSourceRepo = $SourceRepo.Replace('dnceng@', '') - $subscriptions = Get-MaestroSubscriptions -SourceRepository $normalizedSourceRepo -ChannelId $ChannelId - - if (!$subscriptions) { - Write-PipelineTelemetryError -Category 'TriggerSubscriptions' -Message "No subscriptions found for source repo '$normalizedSourceRepo' in channel '$ChannelId'" - ExitWithExitCode 0 - } - - $subscriptionsToTrigger = New-Object System.Collections.Generic.List[string] - $failedTriggeredSubscription = $false - - # Get all enabled subscriptions that need dependency flow on 'everyBuild' - foreach ($subscription in $subscriptions) { - if ($subscription.enabled -and $subscription.policy.updateFrequency -like 'everyBuild' -and $subscription.channel.id -eq $ChannelId) { - Write-Host "Should trigger this subscription: ${$subscription.id}" - [void]$subscriptionsToTrigger.Add($subscription.id) - } - } - - foreach ($subscriptionToTrigger in $subscriptionsToTrigger) { - try { - Write-Host "Triggering subscription '$subscriptionToTrigger'." - - Trigger-Subscription -SubscriptionId $subscriptionToTrigger - - Write-Host 'done.' - } - catch - { - Write-Host "There was an error while triggering subscription '$subscriptionToTrigger'" - Write-Host $_ - Write-Host $_.ScriptStackTrace - $failedTriggeredSubscription = $true - } - } - - if ($subscriptionsToTrigger.Count -eq 0) { - Write-Host "No subscription matched source repo '$normalizedSourceRepo' and channel ID '$ChannelId'." - } - elseif ($failedTriggeredSubscription) { - Write-PipelineTelemetryError -Category 'TriggerSubscriptions' -Message 'At least one subscription failed to be triggered...' - ExitWithExitCode 1 - } - else { - Write-Host 'All subscriptions were triggered successfully!' - } -} -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Category 'TriggerSubscriptions' -Message $_ - ExitWithExitCode 1 -} diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 73828dd30d31..aab40de3fd9a 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.8.1-2" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.10.0-pre.4.0" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/sdl/NuGet.config b/eng/common/sdl/NuGet.config index 5bfbb02ef043..3849bdb3cf51 100644 --- a/eng/common/sdl/NuGet.config +++ b/eng/common/sdl/NuGet.config @@ -5,11 +5,11 @@ - + - + diff --git a/eng/common/sdl/execute-all-sdl-tools.ps1 b/eng/common/sdl/execute-all-sdl-tools.ps1 index 81ded5b7f477..4715d75e974d 100644 --- a/eng/common/sdl/execute-all-sdl-tools.ps1 +++ b/eng/common/sdl/execute-all-sdl-tools.ps1 @@ -6,6 +6,7 @@ Param( [string] $BranchName=$env:BUILD_SOURCEBRANCH, # Optional: name of branch or version of gdn settings; defaults to master [string] $SourceDirectory=$env:BUILD_SOURCESDIRECTORY, # Required: the directory where source files are located [string] $ArtifactsDirectory = (Join-Path $env:BUILD_ARTIFACTSTAGINGDIRECTORY ('artifacts')), # Required: the directory where build artifacts are located + [string] $AzureDevOpsAccessToken, # Required: access token for dnceng; should be provided via KeyVault # Optional: list of SDL tools to run on source code. See 'configure-sdl-tool.ps1' for tools list # format. @@ -74,7 +75,7 @@ try { } Exec-BlockVerbosely { - & $(Join-Path $PSScriptRoot 'init-sdl.ps1') -GuardianCliLocation $guardianCliLocation -Repository $RepoName -BranchName $BranchName -WorkingDirectory $workingDirectory -GuardianLoggerLevel $GuardianLoggerLevel + & $(Join-Path $PSScriptRoot 'init-sdl.ps1') -GuardianCliLocation $guardianCliLocation -Repository $RepoName -BranchName $BranchName -WorkingDirectory $workingDirectory -AzureDevOpsAccessToken $AzureDevOpsAccessToken -GuardianLoggerLevel $GuardianLoggerLevel } $gdnFolder = Join-Path $workingDirectory '.gdn' @@ -103,6 +104,7 @@ try { -TargetDirectory $targetDirectory ` -GdnFolder $gdnFolder ` -ToolsList $tools ` + -AzureDevOpsAccessToken $AzureDevOpsAccessToken ` -GuardianLoggerLevel $GuardianLoggerLevel ` -CrScanAdditionalRunConfigParams $CrScanAdditionalRunConfigParams ` -PoliCheckAdditionalRunConfigParams $PoliCheckAdditionalRunConfigParams ` diff --git a/eng/common/sdl/init-sdl.ps1 b/eng/common/sdl/init-sdl.ps1 index 588ff8e22fbe..3ac1d92b3700 100644 --- a/eng/common/sdl/init-sdl.ps1 +++ b/eng/common/sdl/init-sdl.ps1 @@ -3,6 +3,7 @@ Param( [string] $Repository, [string] $BranchName='master', [string] $WorkingDirectory, + [string] $AzureDevOpsAccessToken, [string] $GuardianLoggerLevel='Standard' ) @@ -20,7 +21,14 @@ $ci = $true # Don't display the console progress UI - it's a huge perf hit $ProgressPreference = 'SilentlyContinue' +# Construct basic auth from AzDO access token; construct URI to the repository's gdn folder stored in that repository; construct location of zip file +$encodedPat = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$AzureDevOpsAccessToken")) +$escapedRepository = [Uri]::EscapeDataString("/$Repository/$BranchName/.gdn") +$uri = "https://dev.azure.com/dnceng/internal/_apis/git/repositories/sdl-tool-cfg/Items?path=$escapedRepository&versionDescriptor[versionOptions]=0&`$format=zip&api-version=5.0" +$zipFile = "$WorkingDirectory/gdn.zip" + Add-Type -AssemblyName System.IO.Compression.FileSystem +$gdnFolder = (Join-Path $WorkingDirectory '.gdn') try { # if the folder does not exist, we'll do a guardian init and push it to the remote repository diff --git a/eng/common/sdl/sdl.ps1 b/eng/common/sdl/sdl.ps1 index 7fe603fe995d..648c5068d7d6 100644 --- a/eng/common/sdl/sdl.ps1 +++ b/eng/common/sdl/sdl.ps1 @@ -4,8 +4,6 @@ function Install-Gdn { [Parameter(Mandatory=$true)] [string]$Path, - [string]$Source = "https://pkgs.dev.azure.com/dnceng/_packaging/Guardian1ESPTUpstreamOrgFeed/nuget/v3/index.json", - # If omitted, install the latest version of Guardian, otherwise install that specific version. [string]$Version ) @@ -21,7 +19,7 @@ function Install-Gdn { $ci = $true . $PSScriptRoot\..\tools.ps1 - $argumentList = @("install", "Microsoft.Guardian.Cli.win-x64", "-Source $Source", "-OutputDirectory $Path", "-NonInteractive", "-NoCache") + $argumentList = @("install", "Microsoft.Guardian.Cli", "-Source https://securitytools.pkgs.visualstudio.com/_packaging/Guardian/nuget/v3/index.json", "-OutputDirectory $Path", "-NonInteractive", "-NoCache") if ($Version) { $argumentList += "-Version $Version" diff --git a/eng/common/sdl/trim-assets-version.ps1 b/eng/common/sdl/trim-assets-version.ps1 index a2e004877045..0daa2a9e9462 100644 --- a/eng/common/sdl/trim-assets-version.ps1 +++ b/eng/common/sdl/trim-assets-version.ps1 @@ -72,4 +72,4 @@ catch { Write-Host $_ Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ ExitWithExitCode 1 -} \ No newline at end of file +} diff --git a/eng/common/template-guidance.md b/eng/common/template-guidance.md new file mode 100644 index 000000000000..5ef6c30ba924 --- /dev/null +++ b/eng/common/template-guidance.md @@ -0,0 +1,133 @@ +# Overview + +Arcade provides templates for public (`/templates`) and 1ES pipeline templates (`/templates-official`) scenarios. Pipelines which are required to be managed by 1ES pipeline templates should reference `/templates-offical`, all other pipelines may reference `/templates`. + +## How to use + +Basic guidance is: + +- 1ES Pipeline Template or 1ES Microbuild template runs should reference `eng/common/templates-official`. Any internal production-graded pipeline should use these templates. + +- All other runs should reference `eng/common/templates`. + +See [azure-pipelines.yml](../../azure-pipelines.yml) (templates-official example) or [azure-pipelines-pr.yml](../../azure-pipelines-pr.yml) (templates example) for examples. + +#### The `templateIs1ESManaged` parameter + +The `templateIs1ESManaged` is available on most templates and affects which of the variants is used for nested templates. See [Development Notes](#development-notes) below for more information on the `templateIs1ESManaged1 parameter. + +- For templates under `job/`, `jobs/`, `steps`, or `post-build/`, this parameter must be explicitly set. + +## Multiple outputs + +1ES pipeline templates impose a policy where every publish artifact execution results in additional security scans being injected into your pipeline. When using `templates-official/jobs/jobs.yml`, Arcade reduces the number of additional security injections by gathering all publishing outputs into the [Build.ArtifactStagingDirectory](https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services), and utilizing the [outputParentDirectory](https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/1es-pipeline-templates/features/outputs#multiple-outputs) feature of 1ES pipeline templates. When implementing your pipeline, if you ensure publish artifacts are located in the `$(Build.ArtifactStagingDirectory)`, and utilize the 1ES provided template context, then you can reduce the number of security scans for your pipeline. + +Example: +``` yaml +# azure-pipelines.yml +extends: + template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate + parameters: + stages: + - stage: build + jobs: + - template: /eng/common/templates-official/jobs/jobs.yml@self + parameters: + # 1ES makes use of outputs to reduce security task injection overhead + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish logs from source' + continueOnError: true + condition: always() + targetPath: $(Build.ArtifactStagingDirectory)/artifacts/log + artifactName: Logs + jobs: + - job: Windows + steps: + - script: echo "friendly neighborhood" > artifacts/marvel/spiderman.txt + # copy build outputs to artifact staging directory for publishing + - task: CopyFiles@2 + displayName: Gather build output + inputs: + SourceFolder: '$(Build.SourcesDirectory)/artifacts/marvel' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/marvel' +``` + +Note: Multiple outputs are ONLY applicable to 1ES PT publishing (only usable when referencing `templates-official`). + +# Development notes + +**Folder / file structure** + +``` text +eng\common\ + [templates || templates-official]\ + job\ + job.yml (shim + artifact publishing logic) + onelocbuild.yml (shim) + publish-build-assets.yml (shim) + source-build.yml (shim) + source-index-stage1.yml (shim) + jobs\ + codeql-build.yml (shim) + jobs.yml (shim) + source-build.yml (shim) + post-build\ + post-build.yml (shim) + common-variabls.yml (shim) + setup-maestro-vars.yml (shim) + steps\ + publish-build-artifacts.yml (logic) + publish-pipeline-artifacts.yml (logic) + component-governance.yml (shim) + generate-sbom.yml (shim) + publish-logs.yml (shim) + retain-build.yml (shim) + send-to-helix.yml (shim) + source-build.yml (shim) + variables\ + pool-providers.yml (logic + redirect) # templates/variables/pool-providers.yml will redirect to templates-official/variables/pool-providers.yml if you are running in the internal project + sdl-variables.yml (logic) + core-templates\ + job\ + job.yml (logic) + onelocbuild.yml (logic) + publish-build-assets.yml (logic) + source-build.yml (logic) + source-index-stage1.yml (logic) + jobs\ + codeql-build.yml (logic) + jobs.yml (logic) + source-build.yml (logic) + post-build\ + common-variabls.yml (logic) + post-build.yml (logic) + setup-maestro-vars.yml (logic) + steps\ + component-governance.yml (logic) + generate-sbom.yml (logic) + publish-build-artifacts.yml (redirect) + publish-logs.yml (logic) + publish-pipeline-artifacts.yml (redirect) + retain-build.yml (logic) + send-to-helix.yml (logic) + source-build.yml (logic) + variables\ + pool-providers.yml (redirect) +``` + +In the table above, a file is designated as "shim", "logic", or "redirect". + +- shim - represents a yaml file which is an intermediate step between pipeline logic and .Net Core Engineering's templates (`core-templates`) and defines the `is1ESPipeline` parameter value. + +- logic - represents actual base template logic. + +- redirect- represents a file in `core-templates` which redirects to the "logic" file in either `templates` or `templates-official`. + +Logic for Arcade's templates live **primarily** in the `core-templates` folder. The exceptions to the location of the logic files are around artifact publishing, which is handled differently between 1es pipeline templates and standard templates. `templates` and `templates-official` provide shim entry points which redirect to `core-templates` while also defining the `is1ESPipeline` parameter. If a shim is referenced in `templates`, then `is1ESPipeline` is set to `false`. If a shim is referenced in `templates-official`, then `is1ESPipeline` is set to `true`. + +Within `templates` and `templates-official`, the templates at the "stages", and "jobs" / "job" level have been replaced with shims. Templates at the "steps" and "variables" level are typically too granular to be replaced with shims and instead persist logic which is directly applicable to either scenario. + +Within `core-templates`, there are a handful of places where logic is dependent on which shim entry point was used. In those places, we redirect back to the respective logic file in `templates` or `templates-official`. diff --git a/eng/common/templates-official/job/job.yml b/eng/common/templates-official/job/job.yml index 1f035fee73f4..605692d2fb77 100644 --- a/eng/common/templates-official/job/job.yml +++ b/eng/common/templates-official/job/job.yml @@ -1,264 +1,80 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - parameters: -# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - cancelTimeoutInMinutes: '' - condition: '' - container: '' - continueOnError: false - dependsOn: '' - displayName: '' - pool: '' - steps: [] - strategy: '' - timeoutInMinutes: '' - variables: [] - workspace: '' - templateContext: '' - -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishBuildAssets: false - enablePublishTestResults: false - enablePublishUsingPipelines: false - enableBuildRetry: false - disableComponentGovernance: '' - componentGovernanceIgnoreDirectories: '' - mergeTestResults: false - testRunTitle: '' - testResultsFormat: '' - name: '' - preSteps: [] - runAsPublic: false # Sbom related params enableSbom: true - PackageVersion: 7.0.0 + runAsPublic: false + PackageVersion: 9.0.0 BuildDropPath: '$(Build.SourcesDirectory)/artifacts' jobs: -- job: ${{ parameters.name }} - - ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: - cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} - - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - - ${{ if ne(parameters.container, '') }}: - container: ${{ parameters.container }} - - ${{ if ne(parameters.continueOnError, '') }}: - continueOnError: ${{ parameters.continueOnError }} - - ${{ if ne(parameters.dependsOn, '') }}: - dependsOn: ${{ parameters.dependsOn }} - - ${{ if ne(parameters.displayName, '') }}: - displayName: ${{ parameters.displayName }} - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - - ${{ if ne(parameters.strategy, '') }}: - strategy: ${{ parameters.strategy }} - - ${{ if ne(parameters.timeoutInMinutes, '') }}: - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - ${{ if ne(parameters.templateContext, '') }}: - templateContext: ${{ parameters.templateContext }} - - variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: - - name: DOTNET_CLI_TELEMETRY_PROFILE - value: '$(Build.Repository.Uri)' - - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - - name: EnableRichCodeNavigation - value: 'true' - # Retry signature validation up to three times, waiting 2 seconds between attempts. - # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures - - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY - value: 3,2000 - - ${{ each variable in parameters.variables }}: - # handle name-value variable syntax - # example: - # - name: [key] - # value: [value] - - ${{ if ne(variable.name, '') }}: - - name: ${{ variable.name }} - value: ${{ variable.value }} - - # handle variable groups - - ${{ if ne(variable.group, '') }}: - - group: ${{ variable.group }} - - # handle template variable syntax - # example: - # - template: path/to/template.yml - # parameters: - # [key]: [value] - - ${{ if ne(variable.template, '') }}: - - template: ${{ variable.template }} - ${{ if ne(variable.parameters, '') }}: - parameters: ${{ variable.parameters }} - - # handle key-value variable syntax. - # example: - # - [key]: [value] - - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: - - ${{ each pair in variable }}: - - name: ${{ pair.key }} - value: ${{ pair.value }} - - # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds - - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: DotNet-HelixApi-Access - - ${{ if ne(parameters.workspace, '') }}: - workspace: ${{ parameters.workspace }} - - steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@4 - displayName: Install MicroBuild plugin - inputs: - signType: $(_SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - env: - TeamName: $(_TeamName) - MicroBuildOutputFolderOverride: '$(Agent.TempDirectory)' - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - - - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - - task: NuGetAuthenticate@1 - - - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - - ${{ each step in parameters.steps }}: - - ${{ step }} - - - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: - - task: RichCodeNavIndexer@0 - displayName: RichCodeNav Upload - inputs: - languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} - environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'production') }} - richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin - uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} - continueOnError: true - - - template: /eng/common/templates-official/steps/component-governance.yml - parameters: - ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - disableComponentGovernance: false - ${{ else }}: - disableComponentGovernance: true - ${{ else }}: - disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks - condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - env: - TeamName: $(_TeamName) - - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: 'artifacts/log' - artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} - displayName: 'Publish logs' - continueOnError: true - condition: always() - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} - continueOnError: true - condition: always() - - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: - - task: PublishTestResults@2 - displayName: Publish XUnit Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: - - task: PublishTestResults@2 - displayName: Publish TRX Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - - template: /eng/common/templates-official/steps/generate-sbom.yml - parameters: - PackageVersion: ${{ parameters.packageVersion}} - BuildDropPath: ${{ parameters.buildDropPath }} - IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: '$(Build.SourcesDirectory)\eng\common\BuildConfiguration' - artifactName: 'BuildConfiguration' - displayName: 'Publish build retry configuration' - continueOnError: true \ No newline at end of file +- template: /eng/common/core-templates/job/job.yml + parameters: + is1ESPipeline: true + + componentGovernanceSteps: + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: + - template: /eng/common/templates/steps/generate-sbom.yml + parameters: + PackageVersion: ${{ parameters.packageVersion }} + BuildDropPath: ${{ parameters.buildDropPath }} + publishArtifacts: false + + # publish artifacts + # for 1ES managed templates, use the templateContext.output to handle multiple outputs. + templateContext: + outputParentDirectory: $(Build.ArtifactStagingDirectory) + outputs: + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - output: buildArtifacts + displayName: Publish pipeline artifacts + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + condition: always() + continueOnError: true + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - output: pipelineArtifact + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log' + artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)_Attempt$(System.JobAttempt)') }} + displayName: 'Publish logs' + continueOnError: true + condition: always() + sbomEnabled: false # we don't need SBOM for logs + + - ${{ if eq(parameters.enablePublishBuildArtifacts, true) }}: + - output: buildArtifacts + displayName: Publish Logs + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + publishLocation: Container + ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + continueOnError: true + condition: always() + sbomEnabled: false # we don't need SBOM for logs + + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - output: pipelineArtifact + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/eng/common/BuildConfiguration' + artifactName: 'BuildConfiguration' + displayName: 'Publish build retry configuration' + continueOnError: true + sbomEnabled: false # we don't need SBOM for BuildConfiguration + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: + - output: pipelineArtifact + displayName: Publish SBOM manifest + continueOnError: true + targetPath: $(Build.ArtifactStagingDirectory)/sbom + artifactName: $(ARTIFACT_NAME) + + # add any outputs provided via root yaml + - ${{ if ne(parameters.templateContext.outputs, '') }}: + - ${{ each output in parameters.templateContext.outputs }}: + - ${{ output }} + + # add any remaining templateContext properties + ${{ each context in parameters.templateContext }}: + ${{ if and(ne(context.key, 'outputParentDirectory'), ne(context.key, 'outputs')) }}: + ${{ context.key }}: ${{ context.value }} + + ${{ each parameter in parameters }}: + ${{ if and(ne(parameter.key, 'templateContext'), ne(parameter.key, 'is1ESPipeline')) }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/onelocbuild.yml b/eng/common/templates-official/job/onelocbuild.yml index 52b4d05d3f8d..0f0c514b912d 100644 --- a/eng/common/templates-official/job/onelocbuild.yml +++ b/eng/common/templates-official/job/onelocbuild.yml @@ -1,112 +1,7 @@ -parameters: - # Optional: dependencies of the job - dependsOn: '' - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: '' - - CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex - GithubPat: $(BotAccount-dotnet-bot-repo-PAT) - - SourcesDirectory: $(Build.SourcesDirectory) - CreatePr: true - AutoCompletePr: false - ReusePr: true - UseLfLineEndings: true - UseCheckedInLocProjectJson: false - SkipLocProjectJsonGeneration: false - LanguageSet: VS_Main_Languages - LclSource: lclFilesInRepo - LclPackageId: '' - RepoType: gitHub - GitHubOrg: dotnet - MirrorRepo: '' - MirrorBranch: main - condition: '' - JobNameSuffix: '' - jobs: -- job: OneLocBuild${{ parameters.JobNameSuffix }} - - dependsOn: ${{ parameters.dependsOn }} - - displayName: OneLocBuild${{ parameters.JobNameSuffix }} - - variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - - name: _GenerateLocProjectArguments - value: -SourcesDirectory ${{ parameters.SourcesDirectory }} - -LanguageSet "${{ parameters.LanguageSet }}" - -CreateNeutralXlfs - - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: - - name: _GenerateLocProjectArguments - value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - - steps: - - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: - - task: Powershell@2 - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 - arguments: $(_GenerateLocProjectArguments) - displayName: Generate LocProject.json - condition: ${{ parameters.condition }} - - - task: OneLocBuild@2 - displayName: OneLocBuild - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - locProj: eng/Localize/LocProject.json - outDir: $(Build.ArtifactStagingDirectory) - lclSource: ${{ parameters.LclSource }} - lclPackageId: ${{ parameters.LclPackageId }} - isCreatePrSelected: ${{ parameters.CreatePr }} - isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} - ${{ if eq(parameters.CreatePr, true) }}: - isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - isShouldReusePrSelected: ${{ parameters.ReusePr }} - packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - repoType: ${{ parameters.RepoType }} - gitHubPatVariable: "${{ parameters.GithubPat }}" - ${{ if ne(parameters.MirrorRepo, '') }}: - isMirrorRepoSelected: true - gitHubOrganization: ${{ parameters.GitHubOrg }} - mirrorRepo: ${{ parameters.MirrorRepo }} - mirrorBranch: ${{ parameters.MirrorBranch }} - condition: ${{ parameters.condition }} - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Localization Files - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/loc' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} +- template: /eng/common/core-templates/job/onelocbuild.yml + parameters: + is1ESPipeline: true - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish LocProject.json - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/Localize/' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} \ No newline at end of file + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/publish-build-assets.yml b/eng/common/templates-official/job/publish-build-assets.yml index 0117328800c8..d667a70e8de7 100644 --- a/eng/common/templates-official/job/publish-build-assets.yml +++ b/eng/common/templates-official/job/publish-build-assets.yml @@ -1,160 +1,7 @@ -parameters: - configuration: 'Debug' - - # Optional: condition for the job to run - condition: '' - - # Optional: 'true' if future jobs should run even if this job fails - continueOnError: false - - # Optional: dependencies of the job - dependsOn: '' - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: {} - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishUsingPipelines: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishAssetsImmediately: false - - artifactsPublishingAdditionalParameters: '' - - signingValidationAdditionalParameters: '' - jobs: -- job: Asset_Registry_Publish - - dependsOn: ${{ parameters.dependsOn }} - timeoutInMinutes: 150 - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - displayName: Publish Assets - ${{ else }}: - displayName: Publish to Build Asset Registry - - variables: - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: Publish-Build-Assets - - group: AzureDevOps-Artifact-Feeds-Pats - - name: runCodesignValidationInjection - value: false - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates-official/post-build/common-variables.yml - - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 - os: windows - steps: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download artifact - inputs: - artifactName: AssetManifests - downloadPath: '$(Build.StagingDirectory)/Download' - checkDownloadedFiles: true - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: NuGetAuthenticate@1 - - - task: AzureCLI@2 - displayName: Publish Build Assets - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/sdk-task.ps1 - arguments: > - -task PublishBuildAssets -restore -msbuildEngine dotnet - /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' - /p:MaestroApiEndpoint=https://maestro-prod.westus2.cloudapp.azure.com - /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} - /p:OfficialBuildId=$(Build.BuildNumber) - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: powershell@2 - displayName: Create ReleaseConfigs Artifact - inputs: - targetType: inline - script: | - New-Item -Path "$(Build.StagingDirectory)/ReleaseConfigs" -ItemType Directory -Force - $filePath = "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" - Add-Content -Path $filePath -Value $(BARBuildId) - Add-Content -Path $filePath -Value "$(DefaultChannels)" - Add-Content -Path $filePath -Value $(IsStableBuild) - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish ReleaseConfigs Artifact - inputs: - PathtoPublish: '$(Build.StagingDirectory)/ReleaseConfigs' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - task: powershell@2 - displayName: Check if SymbolPublishingExclusionsFile.txt exists - inputs: - targetType: inline - script: | - $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" - if(Test-Path -Path $symbolExclusionfile) - { - Write-Host "SymbolExclusionFile exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" - } - else{ - Write-Host "Symbols Exclusion file does not exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" - } - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish SymbolPublishingExclusionsFile Artifact - condition: eq(variables['SymbolExclusionFile'], 'true') - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates-official/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: AzureCLI@2 - displayName: Publish Using Darc - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion 3 - -AzdoToken '$(System.AccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' +- template: /eng/common/core-templates/job/publish-build-assets.yml + parameters: + is1ESPipeline: true - - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - - template: /eng/common/templates-official/steps/publish-logs.yml - parameters: - JobLabel: 'Publish_Artifacts_Logs' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/source-build.yml b/eng/common/templates-official/job/source-build.yml index f983033bb028..1a480034b678 100644 --- a/eng/common/templates-official/job/source-build.yml +++ b/eng/common/templates-official/job/source-build.yml @@ -1,75 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. The template produces a server job with a - # default ID 'Source_Build_Complete' to put in a dependency list if necessary. - - # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. - jobNamePrefix: 'Source_Build' - - # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for - # managed-only repositories. This is an object with these properties: - # - # name: '' - # The name of the job. This is included in the job ID. - # targetRID: '' - # The name of the target RID to use, instead of the one auto-detected by Arcade. - # nonPortable: false - # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than - # linux-x64), and compiling against distro-provided packages rather than portable ones. - # skipPublishValidation: false - # Disables publishing validation. By default, a check is performed to ensure no packages are - # published by source-build. - # container: '' - # A container to use. Runs in docker. - # pool: {} - # A pool to use. Runs directly on an agent. - # buildScript: '' - # Specifies the build script to invoke to perform the build in the repo. The default - # './build.sh' should work for typical Arcade repositories, but this is customizable for - # difficult situations. - # jobProperties: {} - # A list of job properties to inject at the top level, for potential extensibility beyond - # container and pool. - platform: {} - - # If set to true and running on a non-public project, - # Internal blob storage locations will be enabled. - # This is not enabled by default because many repositories do not need internal sources - # and do not need to have the required service connections approved in the pipeline. - enableInternalSources: false - jobs: -- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} - displayName: Source-Build (${{ parameters.platform.name }}) - - ${{ each property in parameters.platform.jobProperties }}: - ${{ property.key }}: ${{ property.value }} - - ${{ if ne(parameters.platform.container, '') }}: - container: ${{ parameters.platform.container }} - - ${{ if eq(parameters.platform.pool, '') }}: - # The default VM host AzDO pool. This should be capable of running Docker containers: almost all - # source-build builds run in Docker, including the default managed platform. - # /eng/common/templates-official/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open - - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] - image: 1es-mariner-2 - os: linux - - ${{ if ne(parameters.platform.pool, '') }}: - pool: ${{ parameters.platform.pool }} - - workspace: - clean: all +- template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: true - steps: - - ${{ if eq(parameters.enableInternalSources, true) }}: - - template: /eng/common/templates-official/steps/enable-internal-runtimes.yml - - template: /eng/common/templates-official/steps/source-build.yml - parameters: - platform: ${{ parameters.platform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/source-index-stage1.yml b/eng/common/templates-official/job/source-index-stage1.yml index 60dfb6b2d1c0..6d5ead316f92 100644 --- a/eng/common/templates-official/job/source-index-stage1.yml +++ b/eng/common/templates-official/job/source-index-stage1.yml @@ -1,83 +1,7 @@ -parameters: - runAsPublic: false - sourceIndexUploadPackageVersion: 2.0.0-20240502.12 - sourceIndexProcessBinlogPackageVersion: 1.0.1-20240129.2 - sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json - sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" - preSteps: [] - binlogPath: artifacts/log/Debug/Build.binlog - condition: '' - dependsOn: '' - pool: '' - jobs: -- job: SourceIndexStage1 - dependsOn: ${{ parameters.dependsOn }} - condition: ${{ parameters.condition }} - variables: - - name: SourceIndexUploadPackageVersion - value: ${{ parameters.sourceIndexUploadPackageVersion }} - - name: SourceIndexProcessBinlogPackageVersion - value: ${{ parameters.sourceIndexProcessBinlogPackageVersion }} - - name: SourceIndexPackageSource - value: ${{ parameters.sourceIndexPackageSource }} - - name: BinlogPath - value: ${{ parameters.binlogPath }} - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $(DncEngPublicBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64.open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $(DncEngInternalBuildPool) - image: windows.vs2022.amd64 - os: windows - - steps: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - task: UseDotNet@2 - displayName: Use .NET 8 SDK - inputs: - packageType: sdk - version: 8.0.x - installationPath: $(Agent.TempDirectory)/dotnet - workingDirectory: $(Agent.TempDirectory) - - - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(sourceIndexProcessBinlogPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(sourceIndexUploadPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - displayName: Download Tools - # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. - workingDirectory: $(Agent.TempDirectory) - - - script: ${{ parameters.sourceIndexBuildCommand }} - displayName: Build Repository - - - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output - displayName: Process Binlog into indexable sln - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: AzureCLI@2 - displayName: Get stage 1 auth token - inputs: - azureSubscription: 'SourceDotNet Stage1 Publish' - addSpnToEnvironment: true - scriptType: 'ps' - scriptLocation: 'inlineScript' - inlineScript: | - echo "##vso[task.setvariable variable=ARM_CLIENT_ID;issecret=true]$env:servicePrincipalId" - echo "##vso[task.setvariable variable=ARM_ID_TOKEN;issecret=true]$env:idToken" - echo "##vso[task.setvariable variable=ARM_TENANT_ID;issecret=true]$env:tenantId" - - - script: | - az login --service-principal -u $(ARM_CLIENT_ID) --tenant $(ARM_TENANT_ID) --allow-no-subscriptions --federated-token $(ARM_ID_TOKEN) - displayName: "Login to Azure" +- template: /eng/common/core-templates/job/source-index-stage1.yml + parameters: + is1ESPipeline: true - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 - displayName: Upload stage1 artifacts to source index + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/codeql-build.yml b/eng/common/templates-official/jobs/codeql-build.yml index b68d3c2f3199..a726322ecfe0 100644 --- a/eng/common/templates-official/jobs/codeql-build.yml +++ b/eng/common/templates-official/jobs/codeql-build.yml @@ -1,31 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - jobs: -- template: /eng/common/templates-official/jobs/jobs.yml +- template: /eng/common/core-templates/jobs/codeql-build.yml parameters: - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishTestResults: false - enablePublishBuildAssets: false - enablePublishUsingPipelines: false - enableTelemetry: true + is1ESPipeline: true - variables: - - group: Publish-Build-Assets - # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in - # sync with the packages.config file. - - name: DefaultGuardianVersion - value: 0.109.0 - - name: GuardianPackagesConfigFile - value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - jobs: ${{ parameters.jobs }} - + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/jobs.yml b/eng/common/templates-official/jobs/jobs.yml index 857a0f8ba43e..007deddaea0f 100644 --- a/eng/common/templates-official/jobs/jobs.yml +++ b/eng/common/templates-official/jobs/jobs.yml @@ -1,97 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: Enable publishing using release pipelines - enablePublishUsingPipelines: false - - # Optional: Enable running the source-build jobs to build repo from source - enableSourceBuild: false - - # Optional: Parameters for source-build template. - # See /eng/common/templates-official/jobs/source-build.yml for options - sourceBuildParameters: [] - - graphFileGeneration: - # Optional: Enable generating the graph files at the end of the build - enabled: false - # Optional: Include toolset dependencies in the generated graph files - includeToolset: false - - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - - # Optional: Override automatically derived dependsOn value for "publish build assets" job - publishBuildAssetsDependsOn: '' - - # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. - publishAssetsImmediately: false - - # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - enableSourceIndex: false - sourceIndexParams: {} - -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - jobs: -- ${{ each job in parameters.jobs }}: - - template: ../job/job.yml - parameters: - # pass along parameters - ${{ each parameter in parameters }}: - ${{ if ne(parameter.key, 'jobs') }}: - ${{ parameter.key }}: ${{ parameter.value }} - - # pass along job properties - ${{ each property in job }}: - ${{ if ne(property.key, 'job') }}: - ${{ property.key }}: ${{ property.value }} - - name: ${{ job.job }} - -- ${{ if eq(parameters.enableSourceBuild, true) }}: - - template: /eng/common/templates-official/jobs/source-build.yml - parameters: - allCompletedJobId: Source_Build_Complete - ${{ each parameter in parameters.sourceBuildParameters }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if eq(parameters.enableSourceIndex, 'true') }}: - - template: ../job/source-index-stage1.yml - parameters: - runAsPublic: ${{ parameters.runAsPublic }} - ${{ each parameter in parameters.sourceIndexParams }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - - ${{ if eq(parameters.enableSourceBuild, true) }}: - - Source_Build_Complete +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: true - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/source-build.yml b/eng/common/templates-official/jobs/source-build.yml index 5cf6a269c0b6..483e7b611f34 100644 --- a/eng/common/templates-official/jobs/source-build.yml +++ b/eng/common/templates-official/jobs/source-build.yml @@ -1,54 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. A job is created for each platform, as - # well as an optional server job that completes when all platform jobs complete. - - # The name of the "join" job for all source-build platforms. If set to empty string, the job is - # not included. Existing repo pipelines can use this job depend on all source-build jobs - # completing without maintaining a separate list of every single job ID: just depend on this one - # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. - allCompletedJobId: '' - - # See /eng/common/templates-official/job/source-build.yml - jobNamePrefix: 'Source_Build' - - # This is the default platform provided by Arcade, intended for use by a managed-only repo. - defaultManagedPlatform: - name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8' - - # Defines the platforms on which to run build jobs. One job is created for each platform, and the - # object in this array is sent to the job template as 'platform'. If no platforms are specified, - # one job runs on 'defaultManagedPlatform'. - platforms: [] - - # If set to true and running on a non-public project, - # Internal nuget and blob storage locations will be enabled. - # This is not enabled by default because many repositories do not need internal sources - # and do not need to have the required service connections approved in the pipeline. - enableInternalSources: false - jobs: +- template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: true -- ${{ if ne(parameters.allCompletedJobId, '') }}: - - job: ${{ parameters.allCompletedJobId }} - displayName: Source-Build Complete - pool: server - dependsOn: - - ${{ each platform in parameters.platforms }}: - - ${{ parameters.jobNamePrefix }}_${{ platform.name }} - - ${{ if eq(length(parameters.platforms), 0) }}: - - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} - -- ${{ each platform in parameters.platforms }}: - - template: /eng/common/templates-official/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ platform }} - enableInternalSources: ${{ parameters.enableInternalSources }} - -- ${{ if eq(length(parameters.platforms), 0) }}: - - template: /eng/common/templates-official/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ parameters.defaultManagedPlatform }} - enableInternalSources: ${{ parameters.enableInternalSources }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/common-variables.yml b/eng/common/templates-official/post-build/common-variables.yml index c24193acfc98..c32fc49233f8 100644 --- a/eng/common/templates-official/post-build/common-variables.yml +++ b/eng/common/templates-official/post-build/common-variables.yml @@ -1,22 +1,8 @@ variables: - - group: Publish-Build-Assets +- template: /eng/common/core-templates/post-build/common-variables.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - # Whether the build is internal or not - - name: IsInternalBuild - value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} - - # Default Maestro++ API Endpoint and API Version - - name: MaestroApiEndPoint - value: "https://maestro-prod.westus2.cloudapp.azure.com" - - name: MaestroApiAccessToken - value: $(MaestroAccessToken) - - name: MaestroApiVersion - value: "2020-02-20" - - - name: SourceLinkCLIVersion - value: 3.0.0 - - name: SymbolToolVersion - value: 1.0.1 - - - name: runCodesignValidationInjection - value: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/post-build.yml b/eng/common/templates-official/post-build/post-build.yml index b81b8770b346..2364c0fd4a52 100644 --- a/eng/common/templates-official/post-build/post-build.yml +++ b/eng/common/templates-official/post-build/post-build.yml @@ -1,287 +1,8 @@ -parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V1 is no longer supported - # Publishing V2 is no longer supported - # Publishing V3 is the default - - name: publishingInfraVersion - displayName: Which version of publishing should be used to promote the build definition? - type: number - default: 3 - values: - - 3 - - - name: BARBuildId - displayName: BAR Build Id - type: number - default: 0 - - - name: PromoteToChannelIds - displayName: Channel to promote BARBuildId to - type: string - default: '' - - - name: enableSourceLinkValidation - displayName: Enable SourceLink validation - type: boolean - default: false - - - name: enableSigningValidation - displayName: Enable signing validation - type: boolean - default: true - - - name: enableSymbolValidation - displayName: Enable symbol validation - type: boolean - default: false - - - name: enableNugetValidation - displayName: Enable NuGet validation - type: boolean - default: true - - - name: publishInstallersAndChecksums - displayName: Publish installers and checksums - type: boolean - default: true - - - name: SDLValidationParameters - type: object - default: - enable: false - publishGdn: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true - - # These parameters let the user customize the call to sdk-task.ps1 for publishing - # symbols & general artifacts as well as for signing validation - - name: symbolPublishingAdditionalParameters - displayName: Symbol publishing additional parameters - type: string - default: '' - - - name: artifactsPublishingAdditionalParameters - displayName: Artifact publishing additional parameters - type: string - default: '' - - - name: signingValidationAdditionalParameters - displayName: Signing validation additional parameters - type: string - default: '' - - # Which stages should finish execution before post-build stages start - - name: validateDependsOn - type: object - default: - - build - - - name: publishDependsOn - type: object - default: - - Validate - - # Optional: Call asset publishing rather than running in a separate stage - - name: publishAssetsImmediately - type: boolean - default: false - stages: -- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - - stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Validate Build Assets - variables: - - template: common-variables.yml - - template: /eng/common/templates-official/variables/pool-providers.yml - jobs: - - job: - displayName: NuGet Validation - condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 - arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ - -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ - - - job: - displayName: Signing Validation - condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - itemPattern: | - ** - !**/Microsoft.SourceBuild.Intermediate.*.nupkg - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@1 - displayName: 'Authenticate to AzDO Feeds' - - # Signing validation will optionally work with the buildmanifest file which is downloaded from - # Azure DevOps above. - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task SigningValidation -restore -msbuildEngine vs - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' - /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' - ${{ parameters.signingValidationAdditionalParameters }} - - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - BinlogToolVersion: $(BinlogToolVersion) - - - job: - displayName: SourceLink Validation - condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 - arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ - -ExtractPath $(Agent.BuildDirectory)/Extract/ - -GHRepoName $(Build.Repository.Name) - -GHCommit $(Build.SourceVersion) - -SourcelinkCliVersion $(SourceLinkCLIVersion) - continueOnError: true - -- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ else }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - - template: /eng/common/templates-official/variables/pool-providers.yml - jobs: - - job: - displayName: Publish Using Darc - timeoutInMinutes: 120 - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: NuGetAuthenticate@1 +- template: /eng/common/core-templates/post-build/post-build.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - - task: AzureCLI@2 - displayName: Publish Using Darc - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(System.AccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/post-build/setup-maestro-vars.yml b/eng/common/templates-official/post-build/setup-maestro-vars.yml index 0c87f149a4ad..024397d87864 100644 --- a/eng/common/templates-official/post-build/setup-maestro-vars.yml +++ b/eng/common/templates-official/post-build/setup-maestro-vars.yml @@ -1,70 +1,8 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - steps: - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: PowerShell@2 - name: setReleaseVars - displayName: Set Release Configs Vars - inputs: - targetType: inline - pwsh: true - script: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 - - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" - - $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $apiHeaders.Add('Accept', 'application/json') - $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - - $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - - $BarId = $Env:BARBuildId - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" - - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } - - Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" +- template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - MAESTRO_API_TOKEN: $(MaestroApiAccessToken) - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/trigger-subscription.yml b/eng/common/templates-official/post-build/trigger-subscription.yml deleted file mode 100644 index da669030daf6..000000000000 --- a/eng/common/templates-official/post-build/trigger-subscription.yml +++ /dev/null @@ -1,13 +0,0 @@ -parameters: - ChannelId: 0 - -steps: -- task: PowerShell@2 - displayName: Triggering subscriptions - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 - arguments: -SourceRepo $(Build.Repository.Uri) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates-official/steps/add-build-to-channel.yml b/eng/common/templates-official/steps/add-build-to-channel.yml deleted file mode 100644 index f67a210d62f3..000000000000 --- a/eng/common/templates-official/steps/add-build-to-channel.yml +++ /dev/null @@ -1,13 +0,0 @@ -parameters: - ChannelId: 0 - -steps: -- task: PowerShell@2 - displayName: Add Build to Channel - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 - arguments: -BuildId $(BARBuildId) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroApiAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates-official/steps/build-reason.yml b/eng/common/templates-official/steps/build-reason.yml deleted file mode 100644 index eba58109b52c..000000000000 --- a/eng/common/templates-official/steps/build-reason.yml +++ /dev/null @@ -1,12 +0,0 @@ -# build-reason.yml -# Description: runs steps if build.reason condition is valid. conditions is a string of valid build reasons -# to include steps (',' separated). -parameters: - conditions: '' - steps: [] - -steps: - - ${{ if and( not(startsWith(parameters.conditions, 'not')), contains(parameters.conditions, variables['build.reason'])) }}: - - ${{ parameters.steps }} - - ${{ if and( startsWith(parameters.conditions, 'not'), not(contains(parameters.conditions, variables['build.reason']))) }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates-official/steps/component-governance.yml b/eng/common/templates-official/steps/component-governance.yml index cbba0596709d..30bb3985ca2b 100644 --- a/eng/common/templates-official/steps/component-governance.yml +++ b/eng/common/templates-official/steps/component-governance.yml @@ -1,13 +1,7 @@ -parameters: - disableComponentGovernance: false - componentGovernanceIgnoreDirectories: '' - steps: -- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: - - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable -- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true - inputs: - ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/enable-internal-runtimes.yml b/eng/common/templates-official/steps/enable-internal-runtimes.yml index 93a8394a666b..f9dd238c6cd5 100644 --- a/eng/common/templates-official/steps/enable-internal-runtimes.yml +++ b/eng/common/templates-official/steps/enable-internal-runtimes.yml @@ -1,28 +1,9 @@ # Obtains internal runtime download credentials and populates the 'dotnetbuilds-internal-container-read-token-base64' # variable with the base64-encoded SAS token, by default - -parameters: -- name: federatedServiceConnection - type: string - default: 'dotnetbuilds-internal-read' -- name: outputVariableName - type: string - default: 'dotnetbuilds-internal-container-read-token-base64' -- name: expiryInHours - type: number - default: 1 -- name: base64Encode - type: boolean - default: true - steps: -- ${{ if ne(variables['System.TeamProject'], 'public') }}: - - template: /eng/common/templates-official/steps/get-delegation-sas.yml - parameters: - federatedServiceConnection: ${{ parameters.federatedServiceConnection }} - outputVariableName: ${{ parameters.outputVariableName }} - expiryInHours: ${{ parameters.expiryInHours }} - base64Encode: ${{ parameters.base64Encode }} - storageAccount: dotnetbuilds - container: internal - permissions: rl +- template: /eng/common/core-templates/steps/enable-internal-runtimes.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/enable-internal-sources.yml b/eng/common/templates-official/steps/enable-internal-sources.yml new file mode 100644 index 000000000000..e6d57182284d --- /dev/null +++ b/eng/common/templates-official/steps/enable-internal-sources.yml @@ -0,0 +1,7 @@ +steps: +- template: /eng/common/core-templates/steps/enable-internal-sources.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/execute-codeql.yml b/eng/common/templates-official/steps/execute-codeql.yml deleted file mode 100644 index 9b4a5ffa30a7..000000000000 --- a/eng/common/templates-official/steps/execute-codeql.yml +++ /dev/null @@ -1,32 +0,0 @@ -parameters: - # Language that should be analyzed. Defaults to csharp - language: csharp - # Build Commands - buildCommands: '' - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - # optional: determines whether to continue the build if the step errors; - sdlContinueOnError: false - -steps: -- template: /eng/common/templates-official/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: '${{ parameters.additionalParameters }} - -CodeQLAdditionalRunConfigParams @("BuildCommands < ${{ parameters.buildCommands }}", "Language < ${{ parameters.language }}")' - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/execute-sdl.yml b/eng/common/templates-official/steps/execute-sdl.yml deleted file mode 100644 index 301d5c591ebd..000000000000 --- a/eng/common/templates-official/steps/execute-sdl.yml +++ /dev/null @@ -1,86 +0,0 @@ -parameters: - overrideGuardianVersion: '' - executeAllSdlToolsScript: '' - overrideParameters: '' - additionalParameters: '' - publishGuardianDirectoryToPipeline: false - sdlContinueOnError: false - condition: '' - -steps: -- task: NuGetAuthenticate@1 - -- task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - -- ${{ if ne(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts -Version ${{ parameters.overrideGuardianVersion }} - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian (Overridden) - -- ${{ if eq(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian - -- ${{ if ne(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} ${{ parameters.overrideParameters }} - displayName: Execute SDL (Overridden) - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if eq(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} - -GuardianCliLocation $(GuardianCliLocation) - -NugetPackageDirectory $(Build.SourcesDirectory)\.packages - -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) - ${{ parameters.additionalParameters }} - displayName: Execute SDL - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if ne(parameters.publishGuardianDirectoryToPipeline, 'false') }}: - # We want to publish the Guardian results and configuration for easy diagnosis. However, the - # '.gdn' dir is a mix of configuration, results, extracted dependencies, and Guardian default - # tooling files. Some of these files are large and aren't useful during an investigation, so - # exclude them by simply deleting them before publishing. (As of writing, there is no documented - # way to selectively exclude a dir from the pipeline artifact publish task.) - - task: DeleteFiles@1 - displayName: Delete Guardian dependencies to avoid uploading - inputs: - SourceFolder: $(Agent.BuildDirectory)/.gdn - Contents: | - c - i - condition: succeededOrFailed() - - - publish: $(Agent.BuildDirectory)/.gdn - artifact: GuardianConfiguration - displayName: Publish GuardianConfiguration - condition: succeededOrFailed() - - # Publish the SARIF files in a container named CodeAnalysisLogs to enable integration - # with the "SARIF SAST Scans Tab" Azure DevOps extension - - task: CopyFiles@2 - displayName: Copy SARIF files - inputs: - flattenFolders: true - sourceFolder: $(Agent.BuildDirectory)/.gdn/rc/ - contents: '**/*.sarif' - targetFolder: $(Build.SourcesDirectory)/CodeAnalysisLogs - condition: succeededOrFailed() - - # Use PublishBuildArtifacts because the SARIF extension only checks this case - # see microsoft/sarif-azuredevops-extension#4 - - task: PublishBuildArtifacts@1 - displayName: Publish SARIF files to CodeAnalysisLogs container - inputs: - pathToPublish: $(Build.SourcesDirectory)/CodeAnalysisLogs - artifactName: CodeAnalysisLogs - condition: succeededOrFailed() \ No newline at end of file diff --git a/eng/common/templates-official/steps/generate-sbom.yml b/eng/common/templates-official/steps/generate-sbom.yml index 1bf43bf807af..9a89a4706d94 100644 --- a/eng/common/templates-official/steps/generate-sbom.yml +++ b/eng/common/templates-official/steps/generate-sbom.yml @@ -1,48 +1,7 @@ -# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. -# PackageName - The name of the package this SBOM represents. -# PackageVersion - The version of the package this SBOM represents. -# ManifestDirPath - The path of the directory where the generated manifest files will be placed -# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. - -parameters: - PackageVersion: 8.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - PackageName: '.NET' - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - IgnoreDirectories: '' - sbomContinueOnError: true - steps: -- task: PowerShell@2 - displayName: Prep for SBOM generation in (Non-linux) - condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) - inputs: - filePath: ./eng/common/generate-sbom-prep.ps1 - arguments: ${{parameters.manifestDirPath}} - -# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 -- script: | - chmod +x ./eng/common/generate-sbom-prep.sh - ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} - displayName: Prep for SBOM generation in (Linux) - condition: eq(variables['Agent.Os'], 'Linux') - continueOnError: ${{ parameters.sbomContinueOnError }} - -- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'Generate SBOM manifest' - continueOnError: ${{ parameters.sbomContinueOnError }} - inputs: - PackageName: ${{ parameters.packageName }} - BuildDropPath: ${{ parameters.buildDropPath }} - PackageVersion: ${{ parameters.packageVersion }} - ManifestDirPath: ${{ parameters.manifestDirPath }} - ${{ if ne(parameters.IgnoreDirectories, '') }}: - AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - -- task: 1ES.PublishPipelineArtifact@1 - displayName: Publish SBOM manifest - continueOnError: ${{parameters.sbomContinueOnError}} - inputs: - targetPath: '${{parameters.manifestDirPath}}' - artifactName: $(ARTIFACT_NAME) +- template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: true + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/get-delegation-sas.yml b/eng/common/templates-official/steps/get-delegation-sas.yml index c0e8f91317f0..c5a9c1f8275c 100644 --- a/eng/common/templates-official/steps/get-delegation-sas.yml +++ b/eng/common/templates-official/steps/get-delegation-sas.yml @@ -1,43 +1,7 @@ -parameters: -- name: federatedServiceConnection - type: string -- name: outputVariableName - type: string -- name: expiryInHours - type: number - default: 1 -- name: base64Encode - type: boolean - default: false -- name: storageAccount - type: string -- name: container - type: string -- name: permissions - type: string - default: 'rl' - steps: -- task: AzureCLI@2 - displayName: 'Generate delegation SAS Token for ${{ parameters.storageAccount }}/${{ parameters.container }}' - inputs: - azureSubscription: ${{ parameters.federatedServiceConnection }} - scriptType: 'pscore' - scriptLocation: 'inlineScript' - inlineScript: | - # Calculate the expiration of the SAS token and convert to UTC - $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") - - $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv - - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to generate SAS token." - exit 1 - } - - if ('${{ parameters.base64Encode }}' -eq 'true') { - $sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas)) - } +- template: /eng/common/core-templates/steps/get-delegation-sas.yml + parameters: + is1ESPipeline: true - Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$sas" + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/get-federated-access-token.yml b/eng/common/templates-official/steps/get-federated-access-token.yml index 55e33bd38f71..c8dcf6b81392 100644 --- a/eng/common/templates-official/steps/get-federated-access-token.yml +++ b/eng/common/templates-official/steps/get-federated-access-token.yml @@ -1,40 +1,7 @@ -parameters: -- name: federatedServiceConnection - type: string -- name: outputVariableName - type: string -- name: stepName - type: string - default: 'getFederatedAccessToken' -- name: condition - type: string - default: '' -# Resource to get a token for. Common values include: -# - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps -# - 'https://storage.azure.com/' for storage -# Defaults to Azure DevOps -- name: resource - type: string - default: '499b84ac-1321-427f-aa17-267ca6975798' -- name: isStepOutputVariable - type: boolean - default: false - steps: -- task: AzureCLI@2 - displayName: 'Getting federated access token for feeds' - name: ${{ parameters.stepName }} - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - inputs: - azureSubscription: ${{ parameters.federatedServiceConnection }} - scriptType: 'pscore' - scriptLocation: 'inlineScript' - inlineScript: | - $accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to get access token for resource '${{ parameters.resource }}'" - exit 1 - } - Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true;isOutput=${{ parameters.isStepOutputVariable }}]$accessToken" \ No newline at end of file +- template: /eng/common/core-templates/steps/get-federated-access-token.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/publish-build-artifacts.yml b/eng/common/templates-official/steps/publish-build-artifacts.yml new file mode 100644 index 000000000000..100a3fc98493 --- /dev/null +++ b/eng/common/templates-official/steps/publish-build-artifacts.yml @@ -0,0 +1,41 @@ +parameters: +- name: displayName + type: string + default: 'Publish to Build Artifact' + +- name: condition + type: string + default: succeeded() + +- name: artifactName + type: string + +- name: pathToPublish + type: string + +- name: continueOnError + type: boolean + default: false + +- name: publishLocation + type: string + default: 'Container' + +- name: is1ESPipeline + type: boolean + default: true + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error +- task: 1ES.PublishBuildArtifacts@1 + displayName: ${{ parameters.displayName }} + condition: ${{ parameters.condition }} + ${{ if parameters.continueOnError }}: + continueOnError: ${{ parameters.continueOnError }} + inputs: + PublishLocation: ${{ parameters.publishLocation }} + PathtoPublish: ${{ parameters.pathToPublish }} + ${{ if parameters.artifactName }}: + ArtifactName: ${{ parameters.artifactName }} + diff --git a/eng/common/templates-official/steps/publish-logs.yml b/eng/common/templates-official/steps/publish-logs.yml index 04012fed182a..579fd531e94c 100644 --- a/eng/common/templates-official/steps/publish-logs.yml +++ b/eng/common/templates-official/steps/publish-logs.yml @@ -1,23 +1,7 @@ -parameters: - StageLabel: '' - JobLabel: '' - steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() +- template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: true -- task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuildLogs - continueOnError: true - condition: always() + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml new file mode 100644 index 000000000000..172f9f0fdc97 --- /dev/null +++ b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,28 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: true + +- name: args + type: object + default: {} + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error +- task: 1ES.PublishPipelineArtifact@1 + displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} + ${{ if parameters.args.condition }}: + condition: ${{ parameters.args.condition }} + ${{ else }}: + condition: succeeded() + ${{ if parameters.args.continueOnError }}: + continueOnError: ${{ parameters.args.continueOnError }} + inputs: + targetPath: ${{ parameters.args.targetPath }} + ${{ if parameters.args.artifactName }}: + artifactName: ${{ parameters.args.artifactName }} + ${{ if parameters.args.properties }}: + properties: ${{ parameters.args.properties }} + ${{ if parameters.args.sbomEnabled }}: + sbomEnabled: ${{ parameters.args.sbomEnabled }} diff --git a/eng/common/templates-official/steps/retain-build.yml b/eng/common/templates-official/steps/retain-build.yml index 83d97a26a01f..5594551508a3 100644 --- a/eng/common/templates-official/steps/retain-build.yml +++ b/eng/common/templates-official/steps/retain-build.yml @@ -1,28 +1,7 @@ -parameters: - # Optional azure devops PAT with build execute permissions for the build's organization, - # only needed if the build that should be retained ran on a different organization than - # the pipeline where this template is executing from - Token: '' - # Optional BuildId to retain, defaults to the current running build - BuildId: '' - # Azure devops Organization URI for the build in the https://dev.azure.com/ format. - # Defaults to the organization the current pipeline is running on - AzdoOrgUri: '$(System.CollectionUri)' - # Azure devops project for the build. Defaults to the project the current pipeline is running on - AzdoProject: '$(System.TeamProject)' - steps: - - task: powershell@2 - inputs: - targetType: 'filePath' - filePath: eng/common/retain-build.ps1 - pwsh: true - arguments: > - -AzdoOrgUri: ${{parameters.AzdoOrgUri}} - -AzdoProject ${{parameters.AzdoProject}} - -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} - -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} - displayName: Enable permanent build retention - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - BUILD_ID: $(Build.BuildId) \ No newline at end of file +- template: /eng/common/core-templates/steps/retain-build.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/send-to-helix.yml b/eng/common/templates-official/steps/send-to-helix.yml index 3eb7e2d5f840..6500f21bf845 100644 --- a/eng/common/templates-official/steps/send-to-helix.yml +++ b/eng/common/templates-official/steps/send-to-helix.yml @@ -1,91 +1,7 @@ -# Please remember to update the documentation if you make changes to these parameters! -parameters: - HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ - HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' - HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number - HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues - HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group - HelixConfiguration: '' # optional -- additional property attached to a job - HelixPreCommands: '' # optional -- commands to run before Helix work item execution - HelixPostCommands: '' # optional -- commands to run after Helix work item execution - WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects - WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects - WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects - CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload - XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true - XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects - XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects - XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner - XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects - IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion - DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." - IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) - Creator: '' # optional -- if the build is external, use this to specify who is sending the job - DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO - condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() - continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false - steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY\eng\common\helixpublish.proj /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' - displayName: ${{ parameters.DisplayNamePrefix }} (Windows) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/eng/common/helixpublish.proj /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog - displayName: ${{ parameters.DisplayNamePrefix }} (Unix) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} +- template: /eng/common/core-templates/steps/send-to-helix.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/source-build.yml b/eng/common/templates-official/steps/source-build.yml index 829f17c34d11..8f92c49e7b06 100644 --- a/eng/common/templates-official/steps/source-build.yml +++ b/eng/common/templates-official/steps/source-build.yml @@ -1,129 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. - - # This is a 'steps' template, and is intended for advanced scenarios where the existing build - # infra has a careful build methodology that must be followed. For example, a repo - # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline - # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to - # GitHub. Using this steps template leaves room for that infra to be included. - - # Defines the platform on which to run the steps. See 'eng/common/templates-official/job/source-build.yml' - # for details. The entire object is described in the 'job' template for simplicity, even though - # the usage of the properties on this object is split between the 'job' and 'steps' templates. - platform: {} - steps: -# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) -- script: | - set -x - df -h - - # If building on the internal project, the artifact feeds variable may be available (usually only if needed) - # In that case, call the feed setup script to add internal feeds corresponding to public ones. - # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. - # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those - # changes. - internalRestoreArgs= - if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then - # Temporarily work around https://github.com/dotnet/arcade/issues/7709 - chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh - $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) - internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' - - # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. - # This only works if there is a username/email configured, which won't be the case in most CI runs. - git config --get user.email - if [ $? -ne 0 ]; then - git config user.email dn-bot@microsoft.com - git config user.name dn-bot - fi - fi - - # If building on the internal project, the internal storage variable may be available (usually only if needed) - # In that case, add variables to allow the download of internal runtimes if the specified versions are not found - # in the default public locations. - internalRuntimeDownloadArgs= - if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' - fi - - buildConfig=Release - # Check if AzDO substitutes in a build config from a variable, and use it if so. - if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then - buildConfig='$(_BuildConfig)' - fi - - officialBuildArgs= - if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then - officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' - fi - - targetRidArgs= - if [ '${{ parameters.platform.targetRID }}' != '' ]; then - targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' - fi - - runtimeOsArgs= - if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then - runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' - fi - - baseOsArgs= - if [ '${{ parameters.platform.baseOS }}' != '' ]; then - baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' - fi - - publishArgs= - if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then - publishArgs='--publish' - fi - - assetManifestFileName=SourceBuild_RidSpecific.xml - if [ '${{ parameters.platform.name }}' != '' ]; then - assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml - fi - - ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ - --configuration $buildConfig \ - --restore --build --pack $publishArgs -bl \ - $officialBuildArgs \ - $internalRuntimeDownloadArgs \ - $internalRestoreArgs \ - $targetRidArgs \ - $runtimeOsArgs \ - $baseOsArgs \ - /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ - /p:ArcadeBuildFromSource=true \ - /p:AssetManifestFileName=$assetManifestFileName - displayName: Build - -# Upload build logs for diagnosis. -- task: CopyFiles@2 - displayName: Prepare BuildLogs staging directory - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/*.log - **/*.binlog - artifacts/source-build/self/prebuilt-report/** - TargetFolder: '$(Build.StagingDirectory)/BuildLogs' - CleanTargetFolder: true - continueOnError: true - condition: succeededOrFailed() - -- task: 1ES.PublishPipelineArtifact@1 - displayName: Publish BuildLogs - inputs: - targetPath: '$(Build.StagingDirectory)/BuildLogs' - artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) - continueOnError: true - condition: succeededOrFailed() +- template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: true -# Manually inject component detection so that we can ignore the source build upstream cache, which contains -# a nupkg cache of input packages (a local feed). -# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' -# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets -- task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection (Exclude upstream cache) - inputs: - ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/source-build/self/src/artifacts/obj/source-built-upstream-cache' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml deleted file mode 100644 index 7870f93bc176..000000000000 --- a/eng/common/templates/job/execute-sdl.yml +++ /dev/null @@ -1,139 +0,0 @@ -parameters: - enable: 'false' # Whether the SDL validation job should execute or not - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - sdlContinueOnError: false # optional: determines whether to continue the build if the step errors; - # optional: determines if build artifacts should be downloaded. - downloadArtifacts: true - # optional: determines if this job should search the directory of downloaded artifacts for - # 'tar.gz' and 'zip' archive files and extract them before running SDL validation tasks. - extractArchiveArtifacts: false - dependsOn: '' # Optional: dependencies of the job - artifactNames: '' # Optional: patterns supplied to DownloadBuildArtifacts - # Usage: - # artifactNames: - # - 'BlobArtifacts' - # - 'Artifacts_Windows_NT_Release' - # Optional: download a list of pipeline artifacts. 'downloadArtifacts' controls build artifacts, - # not pipeline artifacts, so doesn't affect the use of this parameter. - pipelineArtifactNames: [] - -jobs: -- job: Run_SDL - dependsOn: ${{ parameters.dependsOn }} - displayName: Run SDL tool - condition: and(succeededOrFailed(), eq( ${{ parameters.enable }}, 'true')) - variables: - - group: DotNet-VSTS-Bot - - name: AzDOProjectName - value: ${{ parameters.AzDOProjectName }} - - name: AzDOPipelineId - value: ${{ parameters.AzDOPipelineId }} - - name: AzDOBuildId - value: ${{ parameters.AzDOBuildId }} - - template: /eng/common/templates/variables/sdl-variables.yml - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - template: /eng/common/templates/variables/pool-providers.yml - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - checkout: self - clean: true - - # If the template caller didn't provide an AzDO parameter, set them all up as Maestro vars. - - ${{ if not(and(parameters.AzDOProjectName, parameters.AzDOPipelineId, parameters.AzDOBuildId)) }}: - - template: /eng/common/templates/post-build/setup-maestro-vars.yml - - - ${{ if ne(parameters.downloadArtifacts, 'false')}}: - - ${{ if ne(parameters.artifactNames, '') }}: - - ${{ each artifactName in parameters.artifactNames }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Build Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: ${{ artifactName }} - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - ${{ if eq(parameters.artifactNames, '') }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Build Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: specific files - itemPattern: "**" - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - - ${{ each artifactName in parameters.pipelineArtifactNames }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Pipeline Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: ${{ artifactName }} - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - - powershell: eng/common/sdl/trim-assets-version.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts - displayName: Trim the version from the NuGet packages - continueOnError: ${{ parameters.sdlContinueOnError }} - - - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - displayName: Extract Blob Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - displayName: Extract Package Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - ${{ if ne(parameters.extractArchiveArtifacts, 'false') }}: - - powershell: eng/common/sdl/extract-artifact-archives.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts - displayName: Extract Archive Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - template: /eng/common/templates/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: ${{ parameters.additionalParameters }} - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 8ec5c4f2d9f9..d1aeb92fcea5 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -1,259 +1,82 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - -parameters: -# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - cancelTimeoutInMinutes: '' - condition: '' - container: '' - continueOnError: false - dependsOn: '' - displayName: '' - pool: '' - steps: [] - strategy: '' - timeoutInMinutes: '' - variables: [] - workspace: '' - templateContext: '' - -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' - enableMicrobuild: false +parameters: enablePublishBuildArtifacts: false - enablePublishBuildAssets: false - enablePublishTestResults: false - enablePublishUsingPipelines: false - enableBuildRetry: false disableComponentGovernance: '' componentGovernanceIgnoreDirectories: '' - mergeTestResults: false - testRunTitle: '' - testResultsFormat: '' - name: '' - preSteps: [] - runAsPublic: false # Sbom related params enableSbom: true - PackageVersion: 7.0.0 + runAsPublic: false + PackageVersion: 9.0.0 BuildDropPath: '$(Build.SourcesDirectory)/artifacts' jobs: -- job: ${{ parameters.name }} - - ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: - cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} - - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - - ${{ if ne(parameters.container, '') }}: - container: ${{ parameters.container }} - - ${{ if ne(parameters.continueOnError, '') }}: - continueOnError: ${{ parameters.continueOnError }} - - ${{ if ne(parameters.dependsOn, '') }}: - dependsOn: ${{ parameters.dependsOn }} - - ${{ if ne(parameters.displayName, '') }}: - displayName: ${{ parameters.displayName }} - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - - ${{ if ne(parameters.strategy, '') }}: - strategy: ${{ parameters.strategy }} - - ${{ if ne(parameters.timeoutInMinutes, '') }}: - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - ${{ if ne(parameters.templateContext, '') }}: - templateContext: ${{ parameters.templateContext }} - - variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: - - name: DOTNET_CLI_TELEMETRY_PROFILE - value: '$(Build.Repository.Uri)' - - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - - name: EnableRichCodeNavigation - value: 'true' - # Retry signature validation up to three times, waiting 2 seconds between attempts. - # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures - - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY - value: 3,2000 - - ${{ each variable in parameters.variables }}: - # handle name-value variable syntax - # example: - # - name: [key] - # value: [value] - - ${{ if ne(variable.name, '') }}: - - name: ${{ variable.name }} - value: ${{ variable.value }} - - # handle variable groups - - ${{ if ne(variable.group, '') }}: - - group: ${{ variable.group }} +- template: /eng/common/core-templates/job/job.yml + parameters: + is1ESPipeline: false - # handle template variable syntax - # example: - # - template: path/to/template.yml - # parameters: - # [key]: [value] - - ${{ if ne(variable.template, '') }}: - - template: ${{ variable.template }} - ${{ if ne(variable.parameters, '') }}: - parameters: ${{ variable.parameters }} + ${{ each parameter in parameters }}: + ${{ if and(ne(parameter.key, 'steps'), ne(parameter.key, 'is1ESPipeline')) }}: + ${{ parameter.key }}: ${{ parameter.value }} - # handle key-value variable syntax. - # example: - # - [key]: [value] - - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: - - ${{ each pair in variable }}: - - name: ${{ pair.key }} - value: ${{ pair.value }} + steps: + - ${{ each step in parameters.steps }}: + - ${{ step }} - # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds - - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: DotNet-HelixApi-Access - - ${{ if ne(parameters.workspace, '') }}: - workspace: ${{ parameters.workspace }} - - steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@3 - displayName: Install MicroBuild plugin - inputs: - signType: $(_SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - env: - TeamName: $(_TeamName) - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - - - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - - task: NuGetAuthenticate@1 - - - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - - ${{ each step in parameters.steps }}: - - ${{ step }} - - - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: - - task: RichCodeNavIndexer@0 - displayName: RichCodeNav Upload - inputs: - languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} - environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'production') }} - richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin - uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} - continueOnError: true - - - template: /eng/common/templates/steps/component-governance.yml - parameters: - ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - disableComponentGovernance: false - ${{ else }}: - disableComponentGovernance: true - ${{ else }}: - disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks - condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - env: - TeamName: $(_TeamName) - - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - - publish: artifacts/log - artifact: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} - displayName: Publish logs - continueOnError: true - condition: always() - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - - task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} - continueOnError: true - condition: always() - - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: - - task: PublishTestResults@2 - displayName: Publish XUnit Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: - - task: PublishTestResults@2 - displayName: Publish TRX Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - - template: /eng/common/templates/steps/generate-sbom.yml + componentGovernanceSteps: + - template: /eng/common/templates/steps/component-governance.yml parameters: - PackageVersion: ${{ parameters.packageVersion}} - BuildDropPath: ${{ parameters.buildDropPath }} - IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - - publish: $(Build.SourcesDirectory)\eng\common\BuildConfiguration - artifact: BuildConfiguration - displayName: Publish build retry configuration - continueOnError: true + ${{ if eq(parameters.disableComponentGovernance, '') }}: + ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: + disableComponentGovernance: false + ${{ else }}: + disableComponentGovernance: true + ${{ else }}: + disableComponentGovernance: ${{ parameters.disableComponentGovernance }} + componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} + + artifactPublishSteps: + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: false + args: + displayName: Publish pipeline artifacts + pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + publishLocation: Container + artifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + continueOnError: true + condition: always() + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: false + args: + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log' + artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} + displayName: 'Publish logs' + continueOnError: true + condition: always() + sbomEnabled: false # we don't need SBOM for logs + + - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: false + args: + displayName: Publish Logs + pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + publishLocation: Container + artifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: false + args: + targetPath: '$(Build.SourcesDirectory)\eng\common\BuildConfiguration' + artifactName: 'BuildConfiguration' + displayName: 'Publish build retry configuration' + continueOnError: true + sbomEnabled: false # we don't need SBOM for BuildConfiguration diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index 60ab00c4de3a..ff829dc4c700 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -1,109 +1,7 @@ -parameters: - # Optional: dependencies of the job - dependsOn: '' - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: '' - - CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex - GithubPat: $(BotAccount-dotnet-bot-repo-PAT) - - SourcesDirectory: $(Build.SourcesDirectory) - CreatePr: true - AutoCompletePr: false - ReusePr: true - UseLfLineEndings: true - UseCheckedInLocProjectJson: false - SkipLocProjectJsonGeneration: false - LanguageSet: VS_Main_Languages - LclSource: lclFilesInRepo - LclPackageId: '' - RepoType: gitHub - GitHubOrg: dotnet - MirrorRepo: '' - MirrorBranch: main - condition: '' - JobNameSuffix: '' - jobs: -- job: OneLocBuild${{ parameters.JobNameSuffix }} - - dependsOn: ${{ parameters.dependsOn }} - - displayName: OneLocBuild${{ parameters.JobNameSuffix }} - - variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - - name: _GenerateLocProjectArguments - value: -SourcesDirectory ${{ parameters.SourcesDirectory }} - -LanguageSet "${{ parameters.LanguageSet }}" - -CreateNeutralXlfs - - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: - - name: _GenerateLocProjectArguments - value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: - - task: Powershell@2 - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 - arguments: $(_GenerateLocProjectArguments) - displayName: Generate LocProject.json - condition: ${{ parameters.condition }} - - - task: OneLocBuild@2 - displayName: OneLocBuild - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - locProj: eng/Localize/LocProject.json - outDir: $(Build.ArtifactStagingDirectory) - lclSource: ${{ parameters.LclSource }} - lclPackageId: ${{ parameters.LclPackageId }} - isCreatePrSelected: ${{ parameters.CreatePr }} - isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} - ${{ if eq(parameters.CreatePr, true) }}: - isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - isShouldReusePrSelected: ${{ parameters.ReusePr }} - packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - repoType: ${{ parameters.RepoType }} - gitHubPatVariable: "${{ parameters.GithubPat }}" - ${{ if ne(parameters.MirrorRepo, '') }}: - isMirrorRepoSelected: true - gitHubOrganization: ${{ parameters.GitHubOrg }} - mirrorRepo: ${{ parameters.MirrorRepo }} - mirrorBranch: ${{ parameters.MirrorBranch }} - condition: ${{ parameters.condition }} - - - task: PublishBuildArtifacts@1 - displayName: Publish Localization Files - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/loc' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} +- template: /eng/common/core-templates/job/onelocbuild.yml + parameters: + is1ESPipeline: false - - task: PublishBuildArtifacts@1 - displayName: Publish LocProject.json - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/Localize/' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} \ No newline at end of file + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml index cc2b346ba8ba..ab2edec2adb5 100644 --- a/eng/common/templates/job/publish-build-assets.yml +++ b/eng/common/templates/job/publish-build-assets.yml @@ -1,156 +1,7 @@ -parameters: - configuration: 'Debug' - - # Optional: condition for the job to run - condition: '' - - # Optional: 'true' if future jobs should run even if this job fails - continueOnError: false - - # Optional: dependencies of the job - dependsOn: '' - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: {} - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishUsingPipelines: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishAssetsImmediately: false - - artifactsPublishingAdditionalParameters: '' - - signingValidationAdditionalParameters: '' - jobs: -- job: Asset_Registry_Publish - - dependsOn: ${{ parameters.dependsOn }} - timeoutInMinutes: 150 - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - displayName: Publish Assets - ${{ else }}: - displayName: Publish to Build Asset Registry - - variables: - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: Publish-Build-Assets - - group: AzureDevOps-Artifact-Feeds-Pats - - name: runCodesignValidationInjection - value: false - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates/post-build/common-variables.yml - - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download artifact - inputs: - artifactName: AssetManifests - downloadPath: '$(Build.StagingDirectory)/Download' - checkDownloadedFiles: true - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: NuGetAuthenticate@1 - - - task: AzureCLI@2 - displayName: Publish Build Assets - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/sdk-task.ps1 - arguments: > - -task PublishBuildAssets -restore -msbuildEngine dotnet - /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' - /p:MaestroApiEndpoint=https://maestro.dot.net - /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} - /p:OfficialBuildId=$(Build.BuildNumber) - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: powershell@2 - displayName: Create ReleaseConfigs Artifact - inputs: - targetType: inline - script: | - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(BARBuildId) - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value "$(DefaultChannels)" - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(IsStableBuild) - - - task: PublishBuildArtifacts@1 - displayName: Publish ReleaseConfigs Artifact - inputs: - PathtoPublish: '$(Build.StagingDirectory)/ReleaseConfigs.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - task: powershell@2 - displayName: Check if SymbolPublishingExclusionsFile.txt exists - inputs: - targetType: inline - script: | - $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" - if(Test-Path -Path $symbolExclusionfile) - { - Write-Host "SymbolExclusionFile exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" - } - else{ - Write-Host "Symbols Exclusion file does not exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" - } - - - task: PublishBuildArtifacts@1 - displayName: Publish SymbolPublishingExclusionsFile Artifact - condition: eq(variables['SymbolExclusionFile'], 'true') - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: AzureCLI@2 - displayName: Publish Using Darc - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion 3 - -AzdoToken '$(System.AccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' +- template: /eng/common/core-templates/job/publish-build-assets.yml + parameters: + is1ESPipeline: false - - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - - template: /eng/common/templates/steps/publish-logs.yml - parameters: - JobLabel: 'Publish_Artifacts_Logs' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/source-build.yml b/eng/common/templates/job/source-build.yml index c0ff472b697b..e44d47b1d760 100644 --- a/eng/common/templates/job/source-build.yml +++ b/eng/common/templates/job/source-build.yml @@ -1,74 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. The template produces a server job with a - # default ID 'Source_Build_Complete' to put in a dependency list if necessary. - - # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. - jobNamePrefix: 'Source_Build' - - # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for - # managed-only repositories. This is an object with these properties: - # - # name: '' - # The name of the job. This is included in the job ID. - # targetRID: '' - # The name of the target RID to use, instead of the one auto-detected by Arcade. - # nonPortable: false - # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than - # linux-x64), and compiling against distro-provided packages rather than portable ones. - # skipPublishValidation: false - # Disables publishing validation. By default, a check is performed to ensure no packages are - # published by source-build. - # container: '' - # A container to use. Runs in docker. - # pool: {} - # A pool to use. Runs directly on an agent. - # buildScript: '' - # Specifies the build script to invoke to perform the build in the repo. The default - # './build.sh' should work for typical Arcade repositories, but this is customizable for - # difficult situations. - # jobProperties: {} - # A list of job properties to inject at the top level, for potential extensibility beyond - # container and pool. - platform: {} - - # If set to true and running on a non-public project, - # Internal blob storage locations will be enabled. - # This is not enabled by default because many repositories do not need internal sources - # and do not need to have the required service connections approved in the pipeline. - enableInternalSources: false - jobs: -- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} - displayName: Source-Build (${{ parameters.platform.name }}) - - ${{ each property in parameters.platform.jobProperties }}: - ${{ property.key }}: ${{ property.value }} - - ${{ if ne(parameters.platform.container, '') }}: - container: ${{ parameters.platform.container }} - - ${{ if eq(parameters.platform.pool, '') }}: - # The default VM host AzDO pool. This should be capable of running Docker containers: almost all - # source-build builds run in Docker, including the default managed platform. - # /eng/common/templates/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open - - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 - - ${{ if ne(parameters.platform.pool, '') }}: - pool: ${{ parameters.platform.pool }} - - workspace: - clean: all +- template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: false - steps: - - ${{ if eq(parameters.enableInternalSources, true) }}: - - template: /eng/common/templates/steps/enable-internal-runtimes.yml - - template: /eng/common/templates/steps/source-build.yml - parameters: - platform: ${{ parameters.platform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index 0b6bb89dc78a..89f3291593cb 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -1,82 +1,7 @@ -parameters: - runAsPublic: false - sourceIndexUploadPackageVersion: 2.0.0-20240502.12 - sourceIndexProcessBinlogPackageVersion: 1.0.1-20240129.2 - sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json - sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" - preSteps: [] - binlogPath: artifacts/log/Debug/Build.binlog - condition: '' - dependsOn: '' - pool: '' - jobs: -- job: SourceIndexStage1 - dependsOn: ${{ parameters.dependsOn }} - condition: ${{ parameters.condition }} - variables: - - name: SourceIndexUploadPackageVersion - value: ${{ parameters.sourceIndexUploadPackageVersion }} - - name: SourceIndexProcessBinlogPackageVersion - value: ${{ parameters.sourceIndexProcessBinlogPackageVersion }} - - name: SourceIndexPackageSource - value: ${{ parameters.sourceIndexPackageSource }} - - name: BinlogPath - value: ${{ parameters.binlogPath }} - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $(DncEngPublicBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64.open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - task: UseDotNet@2 - displayName: Use .NET 8 SDK - inputs: - packageType: sdk - version: 8.0.x - installationPath: $(Agent.TempDirectory)/dotnet - workingDirectory: $(Agent.TempDirectory) - - - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(sourceIndexProcessBinlogPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(sourceIndexUploadPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - displayName: Download Tools - # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. - workingDirectory: $(Agent.TempDirectory) - - - script: ${{ parameters.sourceIndexBuildCommand }} - displayName: Build Repository - - - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output - displayName: Process Binlog into indexable sln - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: AzureCLI@2 - displayName: Get stage 1 auth token - inputs: - azureSubscription: 'SourceDotNet Stage1 Publish' - addSpnToEnvironment: true - scriptType: 'ps' - scriptLocation: 'inlineScript' - inlineScript: | - echo "##vso[task.setvariable variable=ARM_CLIENT_ID;issecret=true]$env:servicePrincipalId" - echo "##vso[task.setvariable variable=ARM_ID_TOKEN;issecret=true]$env:idToken" - echo "##vso[task.setvariable variable=ARM_TENANT_ID;issecret=true]$env:tenantId" - - - script: | - az login --service-principal -u $(ARM_CLIENT_ID) --tenant $(ARM_TENANT_ID) --allow-no-subscriptions --federated-token $(ARM_ID_TOKEN) - displayName: "Login to Azure" +- template: /eng/common/core-templates/job/source-index-stage1.yml + parameters: + is1ESPipeline: false - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 - displayName: Upload stage1 artifacts to source index + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/codeql-build.yml b/eng/common/templates/jobs/codeql-build.yml index f7dc5ea4aaa6..517f24d6a52c 100644 --- a/eng/common/templates/jobs/codeql-build.yml +++ b/eng/common/templates/jobs/codeql-build.yml @@ -1,31 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - jobs: -- template: /eng/common/templates/jobs/jobs.yml +- template: /eng/common/core-templates/jobs/codeql-build.yml parameters: - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishTestResults: false - enablePublishBuildAssets: false - enablePublishUsingPipelines: false - enableTelemetry: true + is1ESPipeline: false - variables: - - group: Publish-Build-Assets - # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in - # sync with the packages.config file. - - name: DefaultGuardianVersion - value: 0.109.0 - - name: GuardianPackagesConfigFile - value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - jobs: ${{ parameters.jobs }} - + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index 289bb2396ce8..388e9037b3e6 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -1,97 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: Enable publishing using release pipelines - enablePublishUsingPipelines: false - - # Optional: Enable running the source-build jobs to build repo from source - enableSourceBuild: false - - # Optional: Parameters for source-build template. - # See /eng/common/templates/jobs/source-build.yml for options - sourceBuildParameters: [] - - graphFileGeneration: - # Optional: Enable generating the graph files at the end of the build - enabled: false - # Optional: Include toolset dependencies in the generated graph files - includeToolset: false - - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - - # Optional: Override automatically derived dependsOn value for "publish build assets" job - publishBuildAssetsDependsOn: '' - - # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. - publishAssetsImmediately: false - - # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - enableSourceIndex: false - sourceIndexParams: {} - -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - jobs: -- ${{ each job in parameters.jobs }}: - - template: ../job/job.yml - parameters: - # pass along parameters - ${{ each parameter in parameters }}: - ${{ if ne(parameter.key, 'jobs') }}: - ${{ parameter.key }}: ${{ parameter.value }} - - # pass along job properties - ${{ each property in job }}: - ${{ if ne(property.key, 'job') }}: - ${{ property.key }}: ${{ property.value }} - - name: ${{ job.job }} - -- ${{ if eq(parameters.enableSourceBuild, true) }}: - - template: /eng/common/templates/jobs/source-build.yml - parameters: - allCompletedJobId: Source_Build_Complete - ${{ each parameter in parameters.sourceBuildParameters }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if eq(parameters.enableSourceIndex, 'true') }}: - - template: ../job/source-index-stage1.yml - parameters: - runAsPublic: ${{ parameters.runAsPublic }} - ${{ each parameter in parameters.sourceIndexParams }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - - ${{ if eq(parameters.enableSourceBuild, true) }}: - - Source_Build_Complete +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: false - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/source-build.yml b/eng/common/templates/jobs/source-build.yml index 5f46bfa895c1..818d4c326dbb 100644 --- a/eng/common/templates/jobs/source-build.yml +++ b/eng/common/templates/jobs/source-build.yml @@ -1,54 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. A job is created for each platform, as - # well as an optional server job that completes when all platform jobs complete. - - # The name of the "join" job for all source-build platforms. If set to empty string, the job is - # not included. Existing repo pipelines can use this job depend on all source-build jobs - # completing without maintaining a separate list of every single job ID: just depend on this one - # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. - allCompletedJobId: '' - - # See /eng/common/templates/job/source-build.yml - jobNamePrefix: 'Source_Build' - - # This is the default platform provided by Arcade, intended for use by a managed-only repo. - defaultManagedPlatform: - name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8' - - # Defines the platforms on which to run build jobs. One job is created for each platform, and the - # object in this array is sent to the job template as 'platform'. If no platforms are specified, - # one job runs on 'defaultManagedPlatform'. - platforms: [] - - # If set to true and running on a non-public project, - # Internal nuget and blob storage locations will be enabled. - # This is not enabled by default because many repositories do not need internal sources - # and do not need to have the required service connections approved in the pipeline. - enableInternalSources: false - jobs: +- template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: false -- ${{ if ne(parameters.allCompletedJobId, '') }}: - - job: ${{ parameters.allCompletedJobId }} - displayName: Source-Build Complete - pool: server - dependsOn: - - ${{ each platform in parameters.platforms }}: - - ${{ parameters.jobNamePrefix }}_${{ platform.name }} - - ${{ if eq(length(parameters.platforms), 0) }}: - - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} - -- ${{ each platform in parameters.platforms }}: - - template: /eng/common/templates/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ platform }} - enableInternalSources: ${{ parameters.enableInternalSources }} - -- ${{ if eq(length(parameters.platforms), 0) }}: - - template: /eng/common/templates/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ parameters.defaultManagedPlatform }} - enableInternalSources: ${{ parameters.enableInternalSources }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 173914f2364a..7fa105875592 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -1,22 +1,8 @@ variables: - - group: Publish-Build-Assets +- template: /eng/common/core-templates/post-build/common-variables.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - # Whether the build is internal or not - - name: IsInternalBuild - value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} - - # Default Maestro++ API Endpoint and API Version - - name: MaestroApiEndPoint - value: "https://maestro.dot.net" - - name: MaestroApiAccessToken - value: $(MaestroAccessToken) - - name: MaestroApiVersion - value: "2020-02-20" - - - name: SourceLinkCLIVersion - value: 3.0.0 - - name: SymbolToolVersion - value: 1.0.1 - - - name: runCodesignValidationInjection - value: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index c3b6a3012fee..53ede714bdd2 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -1,283 +1,8 @@ -parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V1 is no longer supported - # Publishing V2 is no longer supported - # Publishing V3 is the default - - name: publishingInfraVersion - displayName: Which version of publishing should be used to promote the build definition? - type: number - default: 3 - values: - - 3 - - - name: BARBuildId - displayName: BAR Build Id - type: number - default: 0 - - - name: PromoteToChannelIds - displayName: Channel to promote BARBuildId to - type: string - default: '' - - - name: enableSourceLinkValidation - displayName: Enable SourceLink validation - type: boolean - default: false - - - name: enableSigningValidation - displayName: Enable signing validation - type: boolean - default: true - - - name: enableSymbolValidation - displayName: Enable symbol validation - type: boolean - default: false - - - name: enableNugetValidation - displayName: Enable NuGet validation - type: boolean - default: true - - - name: publishInstallersAndChecksums - displayName: Publish installers and checksums - type: boolean - default: true - - - name: SDLValidationParameters - type: object - default: - enable: false - publishGdn: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true - - # These parameters let the user customize the call to sdk-task.ps1 for publishing - # symbols & general artifacts as well as for signing validation - - name: symbolPublishingAdditionalParameters - displayName: Symbol publishing additional parameters - type: string - default: '' - - - name: artifactsPublishingAdditionalParameters - displayName: Artifact publishing additional parameters - type: string - default: '' - - - name: signingValidationAdditionalParameters - displayName: Signing validation additional parameters - type: string - default: '' - - # Which stages should finish execution before post-build stages start - - name: validateDependsOn - type: object - default: - - build - - - name: publishDependsOn - type: object - default: - - Validate - - # Optional: Call asset publishing rather than running in a separate stage - - name: publishAssetsImmediately - type: boolean - default: false - stages: -- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - - stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Validate Build Assets - variables: - - template: common-variables.yml - - template: /eng/common/templates/variables/pool-providers.yml - jobs: - - job: - displayName: NuGet Validation - condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 - arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ - -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ - - - job: - displayName: Signing Validation - condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - itemPattern: | - ** - !**/Microsoft.SourceBuild.Intermediate.*.nupkg - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@1 - displayName: 'Authenticate to AzDO Feeds' - - # Signing validation will optionally work with the buildmanifest file which is downloaded from - # Azure DevOps above. - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task SigningValidation -restore -msbuildEngine vs - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' - /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' - ${{ parameters.signingValidationAdditionalParameters }} - - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - - - job: - displayName: SourceLink Validation - condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 - arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ - -ExtractPath $(Agent.BuildDirectory)/Extract/ - -GHRepoName $(Build.Repository.Name) - -GHCommit $(Build.SourceVersion) - -SourcelinkCliVersion $(SourceLinkCLIVersion) - continueOnError: true - - - template: /eng/common/templates/job/execute-sdl.yml - parameters: - enable: ${{ parameters.SDLValidationParameters.enable }} - publishGuardianDirectoryToPipeline: ${{ parameters.SDLValidationParameters.publishGdn }} - additionalParameters: ${{ parameters.SDLValidationParameters.params }} - continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }} - artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }} - downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }} - -- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ else }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - - template: /eng/common/templates/variables/pool-providers.yml - jobs: - - job: - displayName: Publish Using Darc - timeoutInMinutes: 120 - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: NuGetAuthenticate@1 +- template: /eng/common/core-templates/post-build/post-build.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - - task: AzureCLI@2 - displayName: Publish Using Darc - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(System.AccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 64b9abc68504..a79fab5b441e 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -1,70 +1,8 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - steps: - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: AzureCLI@2 - name: setReleaseVars - displayName: Set Release Configs Vars - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: pscore - scriptLocation: inlineScript - inlineScript: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 - - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - . $(Build.SourcesDirectory)\eng\common\tools.ps1 - $darc = Get-Darc - $buildInfo = & $darc get-build ` - --id ${{ parameters.BARBuildId }} ` - --extended ` - --output-format json ` - --ci ` - | convertFrom-Json - - $BarId = ${{ parameters.BARBuildId }} - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" - - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } - - Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" +- template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/trigger-subscription.yml b/eng/common/templates/post-build/trigger-subscription.yml deleted file mode 100644 index da669030daf6..000000000000 --- a/eng/common/templates/post-build/trigger-subscription.yml +++ /dev/null @@ -1,13 +0,0 @@ -parameters: - ChannelId: 0 - -steps: -- task: PowerShell@2 - displayName: Triggering subscriptions - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 - arguments: -SourceRepo $(Build.Repository.Uri) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/steps/add-build-to-channel.yml b/eng/common/templates/steps/add-build-to-channel.yml deleted file mode 100644 index f67a210d62f3..000000000000 --- a/eng/common/templates/steps/add-build-to-channel.yml +++ /dev/null @@ -1,13 +0,0 @@ -parameters: - ChannelId: 0 - -steps: -- task: PowerShell@2 - displayName: Add Build to Channel - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 - arguments: -BuildId $(BARBuildId) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroApiAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/steps/build-reason.yml b/eng/common/templates/steps/build-reason.yml deleted file mode 100644 index eba58109b52c..000000000000 --- a/eng/common/templates/steps/build-reason.yml +++ /dev/null @@ -1,12 +0,0 @@ -# build-reason.yml -# Description: runs steps if build.reason condition is valid. conditions is a string of valid build reasons -# to include steps (',' separated). -parameters: - conditions: '' - steps: [] - -steps: - - ${{ if and( not(startsWith(parameters.conditions, 'not')), contains(parameters.conditions, variables['build.reason'])) }}: - - ${{ parameters.steps }} - - ${{ if and( startsWith(parameters.conditions, 'not'), not(contains(parameters.conditions, variables['build.reason']))) }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/component-governance.yml b/eng/common/templates/steps/component-governance.yml index cbba0596709d..c12a5f8d21d7 100644 --- a/eng/common/templates/steps/component-governance.yml +++ b/eng/common/templates/steps/component-governance.yml @@ -1,13 +1,7 @@ -parameters: - disableComponentGovernance: false - componentGovernanceIgnoreDirectories: '' - steps: -- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: - - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable -- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true - inputs: - ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/enable-internal-runtimes.yml b/eng/common/templates/steps/enable-internal-runtimes.yml index 54dc9416c519..b21a8038cc1c 100644 --- a/eng/common/templates/steps/enable-internal-runtimes.yml +++ b/eng/common/templates/steps/enable-internal-runtimes.yml @@ -1,28 +1,10 @@ # Obtains internal runtime download credentials and populates the 'dotnetbuilds-internal-container-read-token-base64' # variable with the base64-encoded SAS token, by default -parameters: -- name: federatedServiceConnection - type: string - default: 'dotnetbuilds-internal-read' -- name: outputVariableName - type: string - default: 'dotnetbuilds-internal-container-read-token-base64' -- name: expiryInHours - type: number - default: 1 -- name: base64Encode - type: boolean - default: true - steps: -- ${{ if ne(variables['System.TeamProject'], 'public') }}: - - template: /eng/common/templates/steps/get-delegation-sas.yml - parameters: - federatedServiceConnection: ${{ parameters.federatedServiceConnection }} - outputVariableName: ${{ parameters.outputVariableName }} - expiryInHours: ${{ parameters.expiryInHours }} - base64Encode: ${{ parameters.base64Encode }} - storageAccount: dotnetbuilds - container: internal - permissions: rl +- template: /eng/common/core-templates/steps/enable-internal-runtimes.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/enable-internal-sources.yml b/eng/common/templates/steps/enable-internal-sources.yml new file mode 100644 index 000000000000..5f87e9abb8aa --- /dev/null +++ b/eng/common/templates/steps/enable-internal-sources.yml @@ -0,0 +1,7 @@ +steps: +- template: /eng/common/core-templates/steps/enable-internal-sources.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/steps/execute-codeql.yml b/eng/common/templates/steps/execute-codeql.yml deleted file mode 100644 index 3930b1630214..000000000000 --- a/eng/common/templates/steps/execute-codeql.yml +++ /dev/null @@ -1,32 +0,0 @@ -parameters: - # Language that should be analyzed. Defaults to csharp - language: csharp - # Build Commands - buildCommands: '' - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - # optional: determines whether to continue the build if the step errors; - sdlContinueOnError: false - -steps: -- template: /eng/common/templates/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: '${{ parameters.additionalParameters }} - -CodeQLAdditionalRunConfigParams @("BuildCommands < ${{ parameters.buildCommands }}", "Language < ${{ parameters.language }}")' - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} \ No newline at end of file diff --git a/eng/common/templates/steps/execute-sdl.yml b/eng/common/templates/steps/execute-sdl.yml deleted file mode 100644 index fe0ebf8c904e..000000000000 --- a/eng/common/templates/steps/execute-sdl.yml +++ /dev/null @@ -1,89 +0,0 @@ -parameters: - overrideGuardianVersion: '' - executeAllSdlToolsScript: '' - overrideParameters: '' - additionalParameters: '' - publishGuardianDirectoryToPipeline: false - sdlContinueOnError: false - condition: '' - -steps: -- task: NuGetAuthenticate@1 - -- task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - -- ${{ if ne(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts -Version ${{ parameters.overrideGuardianVersion }} - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian (Overridden) - -- ${{ if eq(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian - -- ${{ if ne(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} ${{ parameters.overrideParameters }} - displayName: Execute SDL (Overridden) - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - env: - GUARDIAN_DEFAULT_PACKAGE_SOURCE_SECRET: $(System.AccessToken) - -- ${{ if eq(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} - -GuardianCliLocation $(GuardianCliLocation) - -NugetPackageDirectory $(Build.SourcesDirectory)\.packages - ${{ parameters.additionalParameters }} - displayName: Execute SDL - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - env: - GUARDIAN_DEFAULT_PACKAGE_SOURCE_SECRET: $(System.AccessToken) - -- ${{ if ne(parameters.publishGuardianDirectoryToPipeline, 'false') }}: - # We want to publish the Guardian results and configuration for easy diagnosis. However, the - # '.gdn' dir is a mix of configuration, results, extracted dependencies, and Guardian default - # tooling files. Some of these files are large and aren't useful during an investigation, so - # exclude them by simply deleting them before publishing. (As of writing, there is no documented - # way to selectively exclude a dir from the pipeline artifact publish task.) - - task: DeleteFiles@1 - displayName: Delete Guardian dependencies to avoid uploading - inputs: - SourceFolder: $(Agent.BuildDirectory)/.gdn - Contents: | - c - i - condition: succeededOrFailed() - - - publish: $(Agent.BuildDirectory)/.gdn - artifact: GuardianConfiguration - displayName: Publish GuardianConfiguration - condition: succeededOrFailed() - - # Publish the SARIF files in a container named CodeAnalysisLogs to enable integration - # with the "SARIF SAST Scans Tab" Azure DevOps extension - - task: CopyFiles@2 - displayName: Copy SARIF files - inputs: - flattenFolders: true - sourceFolder: $(Agent.BuildDirectory)/.gdn/rc/ - contents: '**/*.sarif' - targetFolder: $(Build.SourcesDirectory)/CodeAnalysisLogs - condition: succeededOrFailed() - - # Use PublishBuildArtifacts because the SARIF extension only checks this case - # see microsoft/sarif-azuredevops-extension#4 - - task: PublishBuildArtifacts@1 - displayName: Publish SARIF files to CodeAnalysisLogs container - inputs: - pathToPublish: $(Build.SourcesDirectory)/CodeAnalysisLogs - artifactName: CodeAnalysisLogs - condition: succeededOrFailed() \ No newline at end of file diff --git a/eng/common/templates/steps/generate-sbom.yml b/eng/common/templates/steps/generate-sbom.yml index 2b21eae42732..26dc00a2e0f3 100644 --- a/eng/common/templates/steps/generate-sbom.yml +++ b/eng/common/templates/steps/generate-sbom.yml @@ -1,48 +1,7 @@ -# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. -# PackageName - The name of the package this SBOM represents. -# PackageVersion - The version of the package this SBOM represents. -# ManifestDirPath - The path of the directory where the generated manifest files will be placed -# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. - -parameters: - PackageVersion: 8.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - PackageName: '.NET' - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - IgnoreDirectories: '' - sbomContinueOnError: true - steps: -- task: PowerShell@2 - displayName: Prep for SBOM generation in (Non-linux) - condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) - inputs: - filePath: ./eng/common/generate-sbom-prep.ps1 - arguments: ${{parameters.manifestDirPath}} - -# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 -- script: | - chmod +x ./eng/common/generate-sbom-prep.sh - ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} - displayName: Prep for SBOM generation in (Linux) - condition: eq(variables['Agent.Os'], 'Linux') - continueOnError: ${{ parameters.sbomContinueOnError }} - -- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'Generate SBOM manifest' - continueOnError: ${{ parameters.sbomContinueOnError }} - inputs: - PackageName: ${{ parameters.packageName }} - BuildDropPath: ${{ parameters.buildDropPath }} - PackageVersion: ${{ parameters.packageVersion }} - ManifestDirPath: ${{ parameters.manifestDirPath }} - ${{ if ne(parameters.IgnoreDirectories, '') }}: - AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - -- task: PublishPipelineArtifact@1 - displayName: Publish SBOM manifest - continueOnError: ${{parameters.sbomContinueOnError}} - inputs: - targetPath: '${{parameters.manifestDirPath}}' - artifactName: $(ARTIFACT_NAME) +- template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/get-delegation-sas.yml b/eng/common/templates/steps/get-delegation-sas.yml index c0e8f91317f0..83760c9798e3 100644 --- a/eng/common/templates/steps/get-delegation-sas.yml +++ b/eng/common/templates/steps/get-delegation-sas.yml @@ -1,43 +1,7 @@ -parameters: -- name: federatedServiceConnection - type: string -- name: outputVariableName - type: string -- name: expiryInHours - type: number - default: 1 -- name: base64Encode - type: boolean - default: false -- name: storageAccount - type: string -- name: container - type: string -- name: permissions - type: string - default: 'rl' - steps: -- task: AzureCLI@2 - displayName: 'Generate delegation SAS Token for ${{ parameters.storageAccount }}/${{ parameters.container }}' - inputs: - azureSubscription: ${{ parameters.federatedServiceConnection }} - scriptType: 'pscore' - scriptLocation: 'inlineScript' - inlineScript: | - # Calculate the expiration of the SAS token and convert to UTC - $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") - - $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv - - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to generate SAS token." - exit 1 - } - - if ('${{ parameters.base64Encode }}' -eq 'true') { - $sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas)) - } +- template: /eng/common/core-templates/steps/get-delegation-sas.yml + parameters: + is1ESPipeline: false - Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$sas" + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/get-federated-access-token.yml b/eng/common/templates/steps/get-federated-access-token.yml index 55e33bd38f71..31e151d9d9e7 100644 --- a/eng/common/templates/steps/get-federated-access-token.yml +++ b/eng/common/templates/steps/get-federated-access-token.yml @@ -1,40 +1,7 @@ -parameters: -- name: federatedServiceConnection - type: string -- name: outputVariableName - type: string -- name: stepName - type: string - default: 'getFederatedAccessToken' -- name: condition - type: string - default: '' -# Resource to get a token for. Common values include: -# - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps -# - 'https://storage.azure.com/' for storage -# Defaults to Azure DevOps -- name: resource - type: string - default: '499b84ac-1321-427f-aa17-267ca6975798' -- name: isStepOutputVariable - type: boolean - default: false - steps: -- task: AzureCLI@2 - displayName: 'Getting federated access token for feeds' - name: ${{ parameters.stepName }} - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - inputs: - azureSubscription: ${{ parameters.federatedServiceConnection }} - scriptType: 'pscore' - scriptLocation: 'inlineScript' - inlineScript: | - $accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to get access token for resource '${{ parameters.resource }}'" - exit 1 - } - Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true;isOutput=${{ parameters.isStepOutputVariable }}]$accessToken" \ No newline at end of file +- template: /eng/common/core-templates/steps/get-federated-access-token.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/steps/publish-build-artifacts.yml b/eng/common/templates/steps/publish-build-artifacts.yml new file mode 100644 index 000000000000..6428a98dfef6 --- /dev/null +++ b/eng/common/templates/steps/publish-build-artifacts.yml @@ -0,0 +1,40 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: displayName + type: string + default: 'Publish to Build Artifact' + +- name: condition + type: string + default: succeeded() + +- name: artifactName + type: string + +- name: pathToPublish + type: string + +- name: continueOnError + type: boolean + default: false + +- name: publishLocation + type: string + default: 'Container' + +steps: +- ${{ if eq(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates cannot be referenced from a 1ES managed template': error +- task: PublishBuildArtifacts@1 + displayName: ${{ parameters.displayName }} + condition: ${{ parameters.condition }} + ${{ if parameters.continueOnError }}: + continueOnError: ${{ parameters.continueOnError }} + inputs: + PublishLocation: ${{ parameters.publishLocation }} + PathtoPublish: ${{ parameters.pathToPublish }} + ${{ if parameters.artifactName }}: + ArtifactName: ${{ parameters.artifactName }} \ No newline at end of file diff --git a/eng/common/templates/steps/publish-logs.yml b/eng/common/templates/steps/publish-logs.yml index 88f238f36bfd..4ea86bd88235 100644 --- a/eng/common/templates/steps/publish-logs.yml +++ b/eng/common/templates/steps/publish-logs.yml @@ -1,23 +1,7 @@ -parameters: - StageLabel: '' - JobLabel: '' - steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() +- template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: false -- task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuildLogs - continueOnError: true - condition: always() + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/publish-pipeline-artifacts.yml b/eng/common/templates/steps/publish-pipeline-artifacts.yml new file mode 100644 index 000000000000..5dd698b212fc --- /dev/null +++ b/eng/common/templates/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,34 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: args + type: object + default: {} + +steps: +- ${{ if eq(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates cannot be referenced from a 1ES managed template': error +- task: PublishPipelineArtifact@1 + displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} + ${{ if parameters.args.condition }}: + condition: ${{ parameters.args.condition }} + ${{ else }}: + condition: succeeded() + ${{ if parameters.args.continueOnError }}: + continueOnError: ${{ parameters.args.continueOnError }} + inputs: + targetPath: ${{ parameters.args.targetPath }} + ${{ if parameters.args.artifactName }}: + artifactName: ${{ parameters.args.artifactName }} + ${{ if parameters.args.publishLocation }}: + publishLocation: ${{ parameters.args.publishLocation }} + ${{ if parameters.args.fileSharePath }}: + fileSharePath: ${{ parameters.args.fileSharePath }} + ${{ if parameters.args.Parallel }}: + parallel: ${{ parameters.args.Parallel }} + ${{ if parameters.args.parallelCount }}: + parallelCount: ${{ parameters.args.parallelCount }} + ${{ if parameters.args.properties }}: + properties: ${{ parameters.args.properties }} \ No newline at end of file diff --git a/eng/common/templates/steps/retain-build.yml b/eng/common/templates/steps/retain-build.yml index 83d97a26a01f..8e841ace3d29 100644 --- a/eng/common/templates/steps/retain-build.yml +++ b/eng/common/templates/steps/retain-build.yml @@ -1,28 +1,7 @@ -parameters: - # Optional azure devops PAT with build execute permissions for the build's organization, - # only needed if the build that should be retained ran on a different organization than - # the pipeline where this template is executing from - Token: '' - # Optional BuildId to retain, defaults to the current running build - BuildId: '' - # Azure devops Organization URI for the build in the https://dev.azure.com/ format. - # Defaults to the organization the current pipeline is running on - AzdoOrgUri: '$(System.CollectionUri)' - # Azure devops project for the build. Defaults to the project the current pipeline is running on - AzdoProject: '$(System.TeamProject)' - steps: - - task: powershell@2 - inputs: - targetType: 'filePath' - filePath: eng/common/retain-build.ps1 - pwsh: true - arguments: > - -AzdoOrgUri: ${{parameters.AzdoOrgUri}} - -AzdoProject ${{parameters.AzdoProject}} - -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} - -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} - displayName: Enable permanent build retention - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - BUILD_ID: $(Build.BuildId) \ No newline at end of file +- template: /eng/common/core-templates/steps/retain-build.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/run-on-unix.yml b/eng/common/templates/steps/run-on-unix.yml deleted file mode 100644 index e1733814f65d..000000000000 --- a/eng/common/templates/steps/run-on-unix.yml +++ /dev/null @@ -1,7 +0,0 @@ -parameters: - agentOs: '' - steps: [] - -steps: -- ${{ if ne(parameters.agentOs, 'Windows_NT') }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/run-on-windows.yml b/eng/common/templates/steps/run-on-windows.yml deleted file mode 100644 index 73e7e9c275a1..000000000000 --- a/eng/common/templates/steps/run-on-windows.yml +++ /dev/null @@ -1,7 +0,0 @@ -parameters: - agentOs: '' - steps: [] - -steps: -- ${{ if eq(parameters.agentOs, 'Windows_NT') }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/run-script-ifequalelse.yml b/eng/common/templates/steps/run-script-ifequalelse.yml deleted file mode 100644 index 3d1242f5587c..000000000000 --- a/eng/common/templates/steps/run-script-ifequalelse.yml +++ /dev/null @@ -1,33 +0,0 @@ -parameters: - # if parameter1 equals parameter 2, run 'ifScript' command, else run 'elsescript' command - parameter1: '' - parameter2: '' - ifScript: '' - elseScript: '' - - # name of script step - name: Script - - # display name of script step - displayName: If-Equal-Else Script - - # environment - env: {} - - # conditional expression for step execution - condition: '' - -steps: -- ${{ if and(ne(parameters.ifScript, ''), eq(parameters.parameter1, parameters.parameter2)) }}: - - script: ${{ parameters.ifScript }} - name: ${{ parameters.name }} - displayName: ${{ parameters.displayName }} - env: ${{ parameters.env }} - condition: ${{ parameters.condition }} - -- ${{ if and(ne(parameters.elseScript, ''), ne(parameters.parameter1, parameters.parameter2)) }}: - - script: ${{ parameters.elseScript }} - name: ${{ parameters.name }} - displayName: ${{ parameters.displayName }} - env: ${{ parameters.env }} - condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml index 3eb7e2d5f840..39f99fc2762d 100644 --- a/eng/common/templates/steps/send-to-helix.yml +++ b/eng/common/templates/steps/send-to-helix.yml @@ -1,91 +1,7 @@ -# Please remember to update the documentation if you make changes to these parameters! -parameters: - HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ - HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' - HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number - HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues - HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group - HelixConfiguration: '' # optional -- additional property attached to a job - HelixPreCommands: '' # optional -- commands to run before Helix work item execution - HelixPostCommands: '' # optional -- commands to run after Helix work item execution - WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects - WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects - WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects - CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload - XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true - XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects - XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects - XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner - XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects - IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion - DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." - IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) - Creator: '' # optional -- if the build is external, use this to specify who is sending the job - DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO - condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() - continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false - steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY\eng\common\helixpublish.proj /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' - displayName: ${{ parameters.DisplayNamePrefix }} (Windows) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/eng/common/helixpublish.proj /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog - displayName: ${{ parameters.DisplayNamePrefix }} (Unix) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} +- template: /eng/common/core-templates/steps/send-to-helix.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index 41bbb915736a..23c1d6f4e9f8 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -1,129 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. - - # This is a 'steps' template, and is intended for advanced scenarios where the existing build - # infra has a careful build methodology that must be followed. For example, a repo - # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline - # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to - # GitHub. Using this steps template leaves room for that infra to be included. - - # Defines the platform on which to run the steps. See 'eng/common/templates/job/source-build.yml' - # for details. The entire object is described in the 'job' template for simplicity, even though - # the usage of the properties on this object is split between the 'job' and 'steps' templates. - platform: {} - steps: -# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) -- script: | - set -x - df -h - - # If building on the internal project, the artifact feeds variable may be available (usually only if needed) - # In that case, call the feed setup script to add internal feeds corresponding to public ones. - # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. - # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those - # changes. - internalRestoreArgs= - if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then - # Temporarily work around https://github.com/dotnet/arcade/issues/7709 - chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh - $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) - internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' - - # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. - # This only works if there is a username/email configured, which won't be the case in most CI runs. - git config --get user.email - if [ $? -ne 0 ]; then - git config user.email dn-bot@microsoft.com - git config user.name dn-bot - fi - fi - - # If building on the internal project, the internal storage variable may be available (usually only if needed) - # In that case, add variables to allow the download of internal runtimes if the specified versions are not found - # in the default public locations. - internalRuntimeDownloadArgs= - if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' - fi - - buildConfig=Release - # Check if AzDO substitutes in a build config from a variable, and use it if so. - if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then - buildConfig='$(_BuildConfig)' - fi - - officialBuildArgs= - if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then - officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' - fi - - targetRidArgs= - if [ '${{ parameters.platform.targetRID }}' != '' ]; then - targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' - fi - - runtimeOsArgs= - if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then - runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' - fi - - baseOsArgs= - if [ '${{ parameters.platform.baseOS }}' != '' ]; then - baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' - fi - - publishArgs= - if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then - publishArgs='--publish' - fi - - assetManifestFileName=SourceBuild_RidSpecific.xml - if [ '${{ parameters.platform.name }}' != '' ]; then - assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml - fi - - ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ - --configuration $buildConfig \ - --restore --build --pack $publishArgs -bl \ - $officialBuildArgs \ - $internalRuntimeDownloadArgs \ - $internalRestoreArgs \ - $targetRidArgs \ - $runtimeOsArgs \ - $baseOsArgs \ - /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ - /p:ArcadeBuildFromSource=true \ - /p:AssetManifestFileName=$assetManifestFileName - displayName: Build - -# Upload build logs for diagnosis. -- task: CopyFiles@2 - displayName: Prepare BuildLogs staging directory - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/*.log - **/*.binlog - artifacts/source-build/self/prebuilt-report/** - TargetFolder: '$(Build.StagingDirectory)/BuildLogs' - CleanTargetFolder: true - continueOnError: true - condition: succeededOrFailed() - -- task: PublishPipelineArtifact@1 - displayName: Publish BuildLogs - inputs: - targetPath: '$(Build.StagingDirectory)/BuildLogs' - artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) - continueOnError: true - condition: succeededOrFailed() +- template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: false -# Manually inject component detection so that we can ignore the source build upstream cache, which contains -# a nupkg cache of input packages (a local feed). -# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' -# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets -- task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection (Exclude upstream cache) - inputs: - ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/source-build/self/src/artifacts/obj/source-built-upstream-cache' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/telemetry-end.yml b/eng/common/templates/steps/telemetry-end.yml deleted file mode 100644 index fadc04ca1b9a..000000000000 --- a/eng/common/templates/steps/telemetry-end.yml +++ /dev/null @@ -1,102 +0,0 @@ -parameters: - maxRetries: 5 - retryDelay: 10 # in seconds - -steps: -- bash: | - if [ "$AGENT_JOBSTATUS" = "Succeeded" ] || [ "$AGENT_JOBSTATUS" = "PartiallySucceeded" ]; then - errorCount=0 - else - errorCount=1 - fi - warningCount=0 - - curlStatus=1 - retryCount=0 - # retry loop to harden against spotty telemetry connections - # we don't retry successes and 4xx client errors - until [[ $curlStatus -eq 0 || ( $curlStatus -ge 400 && $curlStatus -le 499 ) || $retryCount -ge $MaxRetries ]] - do - if [ $retryCount -gt 0 ]; then - echo "Failed to send telemetry to Helix; waiting $RetryDelay seconds before retrying..." - sleep $RetryDelay - fi - - # create a temporary file for curl output - res=`mktemp` - - curlResult=` - curl --verbose --output $res --write-out "%{http_code}"\ - -H 'Content-Type: application/json' \ - -H "X-Helix-Job-Token: $Helix_JobToken" \ - -H 'Content-Length: 0' \ - -X POST -G "https://helix.dot.net/api/2018-03-14/telemetry/job/build/$Helix_WorkItemId/finish" \ - --data-urlencode "errorCount=$errorCount" \ - --data-urlencode "warningCount=$warningCount"` - curlStatus=$? - - if [ $curlStatus -eq 0 ]; then - if [ $curlResult -gt 299 ] || [ $curlResult -lt 200 ]; then - curlStatus=$curlResult - fi - fi - - let retryCount++ - done - - if [ $curlStatus -ne 0 ]; then - echo "Failed to Send Build Finish information after $retryCount retries" - vstsLogOutput="vso[task.logissue type=error;sourcepath=templates/steps/telemetry-end.yml;code=1;]Failed to Send Build Finish information: $curlStatus" - echo "##$vstsLogOutput" - exit 1 - fi - displayName: Send Unix Build End Telemetry - env: - # defined via VSTS variables in start-job.sh - Helix_JobToken: $(Helix_JobToken) - Helix_WorkItemId: $(Helix_WorkItemId) - MaxRetries: ${{ parameters.maxRetries }} - RetryDelay: ${{ parameters.retryDelay }} - condition: and(always(), ne(variables['Agent.Os'], 'Windows_NT')) -- powershell: | - if (($env:Agent_JobStatus -eq 'Succeeded') -or ($env:Agent_JobStatus -eq 'PartiallySucceeded')) { - $ErrorCount = 0 - } else { - $ErrorCount = 1 - } - $WarningCount = 0 - - # Basic retry loop to harden against server flakiness - $retryCount = 0 - while ($retryCount -lt $env:MaxRetries) { - try { - Invoke-RestMethod -Uri "https://helix.dot.net/api/2018-03-14/telemetry/job/build/$env:Helix_WorkItemId/finish?errorCount=$ErrorCount&warningCount=$WarningCount" -Method Post -ContentType "application/json" -Body "" ` - -Headers @{ 'X-Helix-Job-Token'=$env:Helix_JobToken } - break - } - catch { - $statusCode = $_.Exception.Response.StatusCode.value__ - if ($statusCode -ge 400 -and $statusCode -le 499) { - Write-Host "##vso[task.logissue]error Failed to send telemetry to Helix (status code $statusCode); not retrying (4xx client error)" - Write-Host "##vso[task.logissue]error ", $_.Exception.GetType().FullName, $_.Exception.Message - exit 1 - } - Write-Host "Failed to send telemetry to Helix (status code $statusCode); waiting $env:RetryDelay seconds before retrying..." - $retryCount++ - sleep $env:RetryDelay - continue - } - } - - if ($retryCount -ge $env:MaxRetries) { - Write-Host "##vso[task.logissue]error Failed to send telemetry to Helix after $retryCount retries." - exit 1 - } - displayName: Send Windows Build End Telemetry - env: - # defined via VSTS variables in start-job.ps1 - Helix_JobToken: $(Helix_JobToken) - Helix_WorkItemId: $(Helix_WorkItemId) - MaxRetries: ${{ parameters.maxRetries }} - RetryDelay: ${{ parameters.retryDelay }} - condition: and(always(),eq(variables['Agent.Os'], 'Windows_NT')) diff --git a/eng/common/templates/steps/telemetry-start.yml b/eng/common/templates/steps/telemetry-start.yml deleted file mode 100644 index 32c01ef0b553..000000000000 --- a/eng/common/templates/steps/telemetry-start.yml +++ /dev/null @@ -1,241 +0,0 @@ -parameters: - helixSource: 'undefined_defaulted_in_telemetry.yml' - helixType: 'undefined_defaulted_in_telemetry.yml' - buildConfig: '' - runAsPublic: false - maxRetries: 5 - retryDelay: 10 # in seconds - -steps: -- ${{ if and(eq(parameters.runAsPublic, 'false'), not(eq(variables['System.TeamProject'], 'public'))) }}: - - task: AzureKeyVault@1 - inputs: - azureSubscription: 'HelixProd_KeyVault' - KeyVaultName: HelixProdKV - SecretsFilter: 'HelixApiAccessToken' - condition: always() -- bash: | - # create a temporary file - jobInfo=`mktemp` - - # write job info content to temporary file - cat > $jobInfo < /dev/null; then echo "Curl failed; dumping some information about dotnet.microsoft.com for later investigation" - echo | openssl s_client -showcerts -servername dotnet.microsoft.com -connect dotnet.microsoft.com:443 + echo | openssl s_client -showcerts -servername dotnet.microsoft.com -connect dotnet.microsoft.com:443 || true fi echo "Will now retry the same URL with verbose logging." with_retries curl "$install_script_url" -sSL --verbose --retry 10 --create-dirs -o "$install_script" || { @@ -343,20 +341,20 @@ function InitializeBuildTool { _InitializeBuildToolCommand="msbuild" # use override if it exists - commonly set by source-build if [[ "${_OverrideArcadeInitializeBuildToolFramework:-x}" == "x" ]]; then - _InitializeBuildToolFramework="net8.0" + _InitializeBuildToolFramework="net9.0" else _InitializeBuildToolFramework="${_OverrideArcadeInitializeBuildToolFramework}" fi } -# Set RestoreNoCache as a workaround for https://github.com/NuGet/Home/issues/3116 +# Set RestoreNoHttpCache as a workaround for https://github.com/NuGet/Home/issues/3116 function GetNuGetPackageCachePath { if [[ -z ${NUGET_PACKAGES:-} ]]; then if [[ "$use_global_nuget_cache" == true ]]; then - export NUGET_PACKAGES="$HOME/.nuget/packages" + export NUGET_PACKAGES="$HOME/.nuget/packages/" else - export NUGET_PACKAGES="$repo_root/.packages" - export RESTORENOCACHE=true + export NUGET_PACKAGES="$repo_root/.packages/" + export RESTORENOHTTPCACHE=true fi fi @@ -440,7 +438,7 @@ function StopProcesses { } function MSBuild { - local args=$@ + local args=( "$@" ) if [[ "$pipelines_log" == true ]]; then InitializeBuildTool InitializeToolset @@ -458,12 +456,10 @@ function MSBuild { local possiblePaths=() possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.ArcadeLogging.dll" ) possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.Arcade.Sdk.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.ArcadeLogging.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.Arcade.Sdk.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.ArcadeLogging.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.Arcade.Sdk.dll" ) possiblePaths+=( "$toolset_dir/net7.0/Microsoft.DotNet.ArcadeLogging.dll" ) possiblePaths+=( "$toolset_dir/net7.0/Microsoft.DotNet.Arcade.Sdk.dll" ) + possiblePaths+=( "$toolset_dir/net8.0/Microsoft.DotNet.ArcadeLogging.dll" ) + possiblePaths+=( "$toolset_dir/net8.0/Microsoft.DotNet.Arcade.Sdk.dll" ) for path in "${possiblePaths[@]}"; do if [[ -f $path ]]; then selectedPath=$path @@ -477,7 +473,7 @@ function MSBuild { args+=( "-logger:$selectedPath" ) fi - MSBuild-Core ${args[@]} + MSBuild-Core "${args[@]}" } function MSBuild-Core { @@ -510,7 +506,8 @@ function MSBuild-Core { echo "Build failed with exit code $exit_code. Check errors above." # When running on Azure Pipelines, override the returned exit code to avoid double logging. - if [[ "$ci" == "true" && -n ${SYSTEM_TEAMPROJECT:-} ]]; then + # Skip this when the build is a child of the VMR orchestrator build. + if [[ "$ci" == true && -n ${SYSTEM_TEAMPROJECT:-} && "$product_build" != true && "$properties" != *"DotNetBuildRepo=true"* ]]; then Write-PipelineSetResult -result "Failed" -message "msbuild execution failed." # Exiting with an exit code causes the azure pipelines task to log yet another "noise" error # The above Write-PipelineSetResult will cause the task to be marked as failure without adding yet another error diff --git a/eng/devices/android.cake b/eng/devices/android.cake index 8d27db4d6b6b..2fcbadd7ad10 100644 --- a/eng/devices/android.cake +++ b/eng/devices/android.cake @@ -47,6 +47,7 @@ Information("Android SDK Root: {0}", androidSdkRoot); Information("Project File: {0}", projectPath); Information("Build Binary Log (binlog): {0}", binlogDirectory); Information("Build Configuration: {0}", configuration); +Information("Build Target Framework: {0}", targetFramework); var avdSettings = new AndroidAvdManagerToolSettings { SdkRoot = androidSdkRoot }; var adbSettings = new AdbToolSettings { SdkRoot = androidSdkRoot }; @@ -250,6 +251,11 @@ void ExecuteTests(string project, string device, string appPath, string appPacka } finally { + if (testsFailed) + { + // uncomment if you want to copy the test app to the results directory for any reason + // CopyFile(testApp, new DirectoryPath(resultsDir).CombineWithFilePath(new FilePath(testApp).GetFilename())); + } HandleTestResults(resultsDir, testsFailed, false); } diff --git a/eng/devices/catalyst.cake b/eng/devices/catalyst.cake index 734a13eb2547..0cec737d21d1 100644 --- a/eng/devices/catalyst.cake +++ b/eng/devices/catalyst.cake @@ -171,7 +171,6 @@ void ExecuteBuildUITestApp(string appProject, string binDir, string config, stri Framework = tfm, ToolPath = toolPath, ArgumentCustomization = args => args - .Append("/t:Restore;Build") .Append($"/bl:{binlog}") }); diff --git a/eng/devices/devices-shared.cake b/eng/devices/devices-shared.cake index 42c61bffd3ba..1be3ebf34d1a 100644 --- a/eng/devices/devices-shared.cake +++ b/eng/devices/devices-shared.cake @@ -1,6 +1,6 @@ //This assumes that this is always running from a mac with global workloads const string DotnetToolPathDefault = "/usr/local/share/dotnet/dotnet"; -const string DotnetVersion = "net8.0"; +string DotnetVersion = Argument("targetFrameworkVersion", EnvironmentVariable("TARGET_FRAMEWORK_VERSION") ?? "net9.0"); const string TestFramework = "net472"; // Map project types to specific subdirectories under artifacts @@ -208,11 +208,11 @@ string GetDotnetToolPath() if(IsRunningOnWindows()) { - toolPath = isLocalDotnet ? $"{MakeAbsolute(Directory("../../bin/dotnet/")).ToString()}/dotnet" : null; + toolPath = isLocalDotnet ? $"{MakeAbsolute(Directory("../../.dotnet/")).ToString()}/dotnet.exe" : null; } else { - toolPath = isLocalDotnet ? $"{MakeAbsolute(Directory("../../bin/dotnet/")).ToString()}/dotnet" : DotnetToolPathDefault; + toolPath = isLocalDotnet ? $"{MakeAbsolute(Directory("../../.dotnet/")).ToString()}/dotnet" : DotnetToolPathDefault; } Information(isLocalDotnet ? "Using local dotnet" : "Using system dotnet"); diff --git a/eng/devices/ios.cake b/eng/devices/ios.cake index 089017b5089f..c4b2eba3098b 100644 --- a/eng/devices/ios.cake +++ b/eng/devices/ios.cake @@ -1,7 +1,7 @@ #addin nuget:?package=Cake.AppleSimulator&version=0.2.0 #load "./uitests-shared.cake" -const string DefaultVersion = "17.2"; +const string DefaultVersion = "18.0"; const string DefaultTestDevice = $"ios-simulator-64_{DefaultVersion}"; // Required arguments @@ -37,6 +37,7 @@ Information($"Build Runtime Identifier: {runtimeIdentifier}"); Information($"Build Target Framework: {targetFramework}"); Information($"Test Device: {testDevice}"); Information($"Test Results Path: {testResultsPath}"); +Information("Runtime Variant: {0}", RUNTIME_VARIANT); var dotnetToolPath = GetDotnetToolPath(); @@ -139,13 +140,10 @@ void ExecuteBuild(string project, string device, string binDir, string config, s { args .Append("/p:BuildIpa=true") + .Append($"/p:RuntimeIdentifier={rid}") .Append("/bl:" + binlog) .Append("/tl"); - if (device.ToLower().Contains("device")) - { - args.Append("/p:RuntimeIdentifier=ios-arm64"); - } return args; } }); @@ -212,12 +210,14 @@ void ExecuteTests(string project, string device, string resultsDir, string confi void ExecutePrepareUITests(string project, string app, string device, string resultsDir, string binDir, string config, string tfm, string rid, string ver, string toolPath) { Information("Preparing UI Tests..."); - var testApp = GetTestApplications(app, device, config, tfm, rid).FirstOrDefault(); - Information($"Testing Device: {device}"); Information($"Testing App Project: {app}"); - Information($"Testing App: {testApp}"); + Information($"USE_NATIVE_AOT: {USE_NATIVE_AOT}"); + + var testApp = GetTestApplications(app, device, config, tfm, rid).FirstOrDefault(); + Information($"Testing App found: {testApp}"); + if (string.IsNullOrEmpty(testApp)) { throw new Exception("UI Test application path not specified."); @@ -243,6 +243,7 @@ void ExecuteUITests(string project, string app, string device, string resultsDir ToolPath = toolPath, ArgumentCustomization = args => args .Append("/p:ExtraDefineConstants=IOSUITEST") + .Append($"/p:_UseNativeAot={USE_NATIVE_AOT}") .Append("/bl:" + binlog) }); @@ -256,9 +257,19 @@ void ExecuteUITests(string project, string app, string device, string resultsDir void ExecuteBuildUITestApp(string appProject, string device, string binDir, string config, string tfm, string rid, string toolPath) { Information($"Building UI Test app: {appProject}"); + Information($"USE_NATIVE_AOT: {USE_NATIVE_AOT}"); + var projectName = System.IO.Path.GetFileNameWithoutExtension(appProject); var binlog = $"{binDir}/{projectName}-{config}-ios.binlog"; + if (USE_NATIVE_AOT && config.Equals("Debug", StringComparison.OrdinalIgnoreCase)) + { + var errMsg = $"Error: Running UI tests with NativeAOT is only supported in Release configuration"; + Error(errMsg); + throw new Exception(errMsg); + } + + DotNetBuild(appProject, new DotNetBuildSettings { Configuration = config, @@ -268,15 +279,11 @@ void ExecuteBuildUITestApp(string appProject, string device, string binDir, stri { args .Append("/p:BuildIpa=true") + .Append($"/p:_UseNativeAot={USE_NATIVE_AOT}") + .Append($"/p:RuntimeIdentifier={rid}") .Append("/bl:" + binlog) .Append("/tl"); - // if we building for a device - if (device.ToLower().Contains("device")) - { - args.Append("/p:RuntimeIdentifier=ios-arm64"); - } - return args; } }); @@ -291,7 +298,7 @@ void ExecuteCGLegacyUITests(string project, string appProject, string device, st CleanDirectories(resultsDir); Information("Starting Compatibility Gallery UI Tests..."); - + var testApp = GetTestApplications(appProject, device, config, tfm, rid).FirstOrDefault(); Information($"Testing Device: {device}"); @@ -321,7 +328,7 @@ void ExecuteCGLegacyUITests(string project, string appProject, string device, st //set env var for the app path for Xamarin.UITest setup SetEnvironmentVariable("iOS_APP", $"{testApp}"); - var resultName = $"{System.IO.Path.GetFileNameWithoutExtension(project)}-{config}-{DateTime.UtcNow.ToFileTimeUtc()}"; + var resultName = $"{System.IO.Path.GetFileNameWithoutExtension(project)}-{config}-{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}"; Information("Run UITests project {0}", resultName); RunTestWithLocalDotNet( project, @@ -344,6 +351,7 @@ void PerformCleanupIfNeeded(bool cleanupEnabled, bool createDeviceLogs) var sims = ListAppleSimulators().Where(s => s.Name.Contains("XHarness")).ToArray(); foreach (var sim in sims) { + var timestamp = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"); if(createDeviceLogs) { try @@ -353,7 +361,7 @@ void PerformCleanupIfNeeded(bool cleanupEnabled, bool createDeviceLogs) StartProcess("zip", new ProcessSettings { Arguments = new ProcessArgumentBuilder() .Append("-9r") - .AppendQuoted($"{logDirectory}/DiagnosticReports_{sim.UDID}.zip") + .AppendQuoted($"{logDirectory}/DiagnosticReports_{sim.UDID}_{timestamp}.zip") .AppendQuoted($"{homeDirectory}/Library/Logs/DiagnosticReports/"), RedirectStandardOutput = false }); @@ -362,28 +370,28 @@ void PerformCleanupIfNeeded(bool cleanupEnabled, bool createDeviceLogs) StartProcess("zip", new ProcessSettings { Arguments = new ProcessArgumentBuilder() .Append("-9r") - .AppendQuoted($"{logDirectory}/CoreSimulator_{sim.UDID}.zip") + .AppendQuoted($"{logDirectory}/CoreSimulator_{sim.UDID}_{timestamp}.zip") .AppendQuoted($"{homeDirectory}/Library/Logs/CoreSimulator/{sim.UDID}"), RedirectStandardOutput = false }); - StartProcess("xcrun", $"simctl spawn {sim.UDID} log collect --output {homeDirectory}/{sim.UDID}_log.logarchive"); + StartProcess("xcrun", $"simctl spawn {sim.UDID} log collect --output {homeDirectory}/{sim.UDID}_{timestamp}_log.logarchive"); StartProcess("zip", new ProcessSettings { Arguments = new ProcessArgumentBuilder() .Append("-9r") - .AppendQuoted($"{logDirectory}/{sim.UDID}_log.logarchive.zip") - .AppendQuoted($"{homeDirectory}/{sim.UDID}_log.logarchive"), + .AppendQuoted($"{logDirectory}/{sim.UDID}_{timestamp}_log.logarchive.zip") + .AppendQuoted($"{homeDirectory}/{sim.UDID}_{timestamp}_log.logarchive"), RedirectStandardOutput = false }); - var screenshotPath = $"{testResultsPath}/{sim.UDID}_screenshot.png"; + var screenshotPath = $"{testResultsPath}/{sim.UDID}_{timestamp}_screenshot.png"; StartProcess("xcrun", $"simctl io {sim.UDID} screenshot {screenshotPath}"); } catch(Exception ex) { Information($"Failed to collect logs for simulator {sim.Name} ({sim.UDID}): {ex.Message}"); - Information($"Command Executed: simctl spawn {sim.UDID} log collect --output {logDirectory}/{sim.UDID}_log.logarchive"); + Information($"Command Executed: simctl spawn {sim.UDID} log collect --output {logDirectory}/{sim.UDID}_{timestamp}_log.logarchive"); } } diff --git a/eng/devices/windows.cake b/eng/devices/windows.cake index 558b4db01e4a..93b000281274 100644 --- a/eng/devices/windows.cake +++ b/eng/devices/windows.cake @@ -4,7 +4,6 @@ using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; const string defaultVersion = "10.0.19041.0"; -const string dotnetVersion = "net8.0"; // required string DEFAULT_WINDOWS_PROJECT = "../../src/Controls/tests/TestCases.WinUI.Tests/Controls.TestCases.WinUI.Tests.csproj"; @@ -17,7 +16,7 @@ var PACKAGEID = Argument("packageid", EnvironmentVariable("WINDOWS_TEST_PACKAGE_ // optional var DOTNET_PATH = Argument("dotnet-path", EnvironmentVariable("DOTNET_PATH")); var DOTNET_ROOT = Argument("dotnet-root", EnvironmentVariable("DOTNET_ROOT")); -var TARGET_FRAMEWORK = Argument("tfm", EnvironmentVariable("TARGET_FRAMEWORK") ?? $"{dotnetVersion}-windows{defaultVersion}"); +var TARGET_FRAMEWORK = Argument("tfm", EnvironmentVariable("TARGET_FRAMEWORK") ?? $"{DotnetVersion}-windows{defaultVersion}"); var BINLOG_ARG = Argument("binlog", EnvironmentVariable("WINDOWS_TEST_BINLOG") ?? ""); DirectoryPath BINLOG_DIR = string.IsNullOrEmpty(BINLOG_ARG) && !string.IsNullOrEmpty(PROJECT.FullPath) ? PROJECT.GetDirectory() : BINLOG_ARG; var TEST_APP = Argument("app", EnvironmentVariable("WINDOWS_TEST_APP") ?? ""); @@ -29,6 +28,8 @@ string CONFIGURATION = Argument("configuration", "Debug"); var windowsVersion = Argument("apiversion", EnvironmentVariable("WINDOWS_PLATFORM_VERSION") ?? defaultVersion); +var dotnetToolPath = GetDotnetToolPath(); + // other string PLATFORM = "windows"; string DOTNET_PLATFORM = $"win10-x64"; @@ -55,6 +56,7 @@ Information("Build Binary Log (binlog): {0}", BINLOG_DIR); Information("Build Platform: {0}", PLATFORM); Information("Build Configuration: {0}", CONFIGURATION); +Information("Target Framework: {0}", TARGET_FRAMEWORK); Information("Windows version: {0}", windowsVersion); Setup(context => @@ -139,23 +141,19 @@ Task("Build") var name = System.IO.Path.GetFileNameWithoutExtension(PROJECT.FullPath); var binlog = $"{BINLOG_DIR}/{name}-{CONFIGURATION}-windows.binlog"; - var localDotnetRoot = MakeAbsolute(Directory("../../bin/dotnet/")); + var localDotnetRoot = MakeAbsolute(Directory("../../.dotnet/")); Information("new dotnet root: {0}", localDotnetRoot); - DOTNET_ROOT = localDotnetRoot.ToString(); - SetDotNetEnvironmentVariables(DOTNET_ROOT); - - var toolPath = $"{localDotnetRoot}/dotnet.exe"; - - Information("toolPath: {0}", toolPath); + + Information("toolPath: {0}", dotnetToolPath); Information("Building and publishing device test app"); // Build the app in publish mode // Using the certificate thumbprint for the cert we just created var s = new DotNetPublishSettings(); - s.ToolPath = toolPath; + s.ToolPath = dotnetToolPath; s.Configuration = CONFIGURATION; s.Framework = TARGET_FRAMEWORK; s.MSBuildSettings = new DotNetMSBuildSettings(); @@ -203,7 +201,7 @@ Task("Test") .IsDependentOn("SetupTestPaths") .Does(() => { - var waitForResultTimeoutInSeconds = 120; + var waitForResultTimeoutInSeconds = 240; CleanDirectories(TEST_RESULTS); @@ -437,7 +435,7 @@ Task("SetupTestPaths") throw new Exception("If no app was specified, an app must be provided."); } - var winVersion = $"{dotnetVersion}-windows{windowsVersion}"; + var winVersion = $"{DotnetVersion}-windows{windowsVersion}"; var binDir = TEST_APP_PROJECT.GetDirectory().Combine("Controls.TestCases.HostApp").Combine(CONFIGURATION + "/" + winVersion).Combine(DOTNET_PLATFORM); Information("BinDir: {0}", binDir); var apps = GetFiles(binDir + "/*.exe").Where(c => !c.FullPath.EndsWith("createdump.exe")); @@ -523,26 +521,34 @@ Task("uitest") Information("old dotnet root: {0}", DOTNET_ROOT); Information("old dotnet path: {0}", DOTNET_PATH); - var localDotnetRoot = MakeAbsolute(Directory("../../bin/dotnet/")); - Information("new dotnet root: {0}", localDotnetRoot); - - DOTNET_ROOT = localDotnetRoot.ToString(); - - var localToolPath = $"{localDotnetRoot}/dotnet.exe"; - - Information("new dotnet toolPath: {0}", localToolPath); - - SetDotNetEnvironmentVariables(DOTNET_ROOT); - - DotNetBuild(PROJECT.FullPath, new DotNetBuildSettings { + var buildSettings = new DotNetBuildSettings { Configuration = CONFIGURATION, - ToolPath = localToolPath, ArgumentCustomization = args => args .Append("/p:ExtraDefineConstants=WINTEST") .Append("/bl:" + binlog) .Append("/maxcpucount:1") //.Append("/tl") - }); + }; + + string? localToolPath = null; + + if (localDotnet) + { + var localDotnetRoot = MakeAbsolute(Directory("../../.dotnet/")); + Information("new dotnet root: {0}", localDotnetRoot); + + DOTNET_ROOT = localDotnetRoot.ToString(); + + localToolPath = $"{localDotnetRoot}/dotnet.exe"; + + Information("new dotnet toolPath: {0}", localToolPath); + + SetDotNetEnvironmentVariables(DOTNET_ROOT); + + buildSettings.ToolPath = localToolPath; + } + + DotNetBuild(PROJECT.FullPath, buildSettings); SetEnvironmentVariable("WINDOWS_APP_PATH", TEST_APP); SetEnvironmentVariable("APPIUM_LOG_FILE", $"{BINLOG_DIR}/appium_windows.log"); diff --git a/eng/pipelines/azure-pipelines-public.yml b/eng/pipelines/azure-pipelines-public.yml new file mode 100644 index 000000000000..1dca4a6753ec --- /dev/null +++ b/eng/pipelines/azure-pipelines-public.yml @@ -0,0 +1,170 @@ +trigger: + batch: true + branches: + include: + - main + - release/* + paths: + include: + - '*' + exclude: + - '**.md' + - eng/Version.Details.xml + - .github/* + - docs/* + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT + +pr: + branches: + include: + - main + - release/* + - feature/* + paths: + include: + - '*' + exclude: + - '**.md' + - eng/Version.Details.xml + - .github/* + - docs/* + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT + +variables: + - template: /eng/common/templates/variables/pool-providers.yml + + - name: _BuildConfig + value: Release + - name: Build.Arcade.ArtifactsPath + value: $(Build.SourcesDirectory)/artifacts/ + - name: Build.Arcade.LogsPath + value: $(Build.Arcade.ArtifactsPath)log/$(_BuildConfig)/ + - name: Build.Arcade.TestResultsPath + value: $(Build.Arcade.ArtifactsPath)TestResults/$(_BuildConfig)/ + + # needed for darc (dependency flow) publishing + - name: _PublishArgs + value: '' + - name: _OfficialBuildIdArgs + value: '' + # needed for signing + - name: _SignType + value: test + - name: _SignArgs + value: '' + - name: _Sign + value: false + - name: HelixApiAccessToken + value: '' + - name: _InternalBuildArgs + value: '' + + +stages: + +# ---------------------------------------------------------------- +# This stage performs build, test, packaging +# ---------------------------------------------------------------- +- stage: build + displayName: Build + jobs: + - template: /eng/common/templates/jobs/jobs.yml + parameters: + artifacts: + publish: + artifacts: false + logs: + name: 'Logs_Build_$(Agent.JobName)_$(_BuildConfig)' + manifests: true + enableMicrobuild: true + enablePublishUsingPipelines: true + publishAssetsImmediately: true + enablePublishTestResults: true + enableSourceBuild: true + testResultsFormat: vstest + enableSourceIndex: false + workspace: + clean: all + + jobs: + + - ${{ each testVariant in split(',_helix_tests', ',') }}: + - job: Windows${{ testVariant }} + + # timeout accounts for wait times for helix agents up to 30mins + timeoutInMinutes: 90 + + pool: + name: $(DncEngPublicBuildPool) + demands: ImageOverride -equals windows.vs2022preview.amd64.open + + variables: + - name: _buildScript + value: $(Build.SourcesDirectory)/build.cmd -ci + + preSteps: + - checkout: self + fetchDepth: 1 + clean: true + + steps: + - template: /eng/pipelines/common/build-test-pack.yml + parameters: + runAsPublic: true + dotnetScript: $(Build.SourcesDirectory)/dotnet.cmd + buildScript: $(_buildScript) + buildConfig: $(_BuildConfig) + repoArtifactsPath: $(Build.Arcade.ArtifactsPath) + repoLogPath: $(Build.Arcade.LogsPath) + repoTestResultsPath: $(Build.Arcade.TestResultsPath) + isWindows: true + runHelixTests: ${{ contains(testVariant, 'helix') }} + +# ---------------------------------------------------------------- +# This stage performs quality gates checks +# ---------------------------------------------------------------- +- stage: codecoverage + displayName: CodeCoverage + dependsOn: + - build + condition: succeeded('build') + variables: + - template: /eng/common/templates/variables/pool-providers.yml + jobs: + - template: /eng/common/templates/jobs/jobs.yml + parameters: + enableMicrobuild: true + enableTelemetry: true + runAsPublic: false + workspace: + clean: all + + # ---------------------------------------------------------------- + # This stage downloads the code coverage reports from the build jobs, + # merges those and validates the combined test coverage. + # ---------------------------------------------------------------- + jobs: + - job: CodeCoverageReport + timeoutInMinutes: 10 + + pool: + name: $(DncEngPublicBuildPool) + demands: ImageOverride -equals build.ubuntu.2004.amd64.open + + preSteps: + - checkout: self + fetchDepth: 1 + clean: true + + steps: + - script: $(Build.SourcesDirectory)/build.sh --ci --restore + displayName: Init toolset + + - template: /eng/pipelines/templates/VerifyCoverageReport.yml + parameters: + # matches what is used in the conditions for the build/test jobs + testVariants: ',_helix_tests' diff --git a/eng/pipelines/common/build-test-pack.yml b/eng/pipelines/common/build-test-pack.yml new file mode 100644 index 000000000000..60d27cf760e3 --- /dev/null +++ b/eng/pipelines/common/build-test-pack.yml @@ -0,0 +1,158 @@ + +parameters: + - name: runAsPublic + type: boolean + default: false + - name: buildScript + type: string + - name: buildConfig + type: string + - name: repoArtifactsPath + type: string + - name: repoLogPath + type: string + - name: repoTestResultsPath + type: string + - name: isWindows + type: string + default: false + - name: dotnetScript + type: string + - name: runHelixTests + type: boolean + default: false + +steps: + + # - task: UseDotNet@2 + # inputs: + # useGlobalJson: true + + - pwsh: | + if ($env:JAVA_HOME_17_X64) { + $env:JAVA_HOME = $env:JAVA_HOME_17_X64 + } else { + $path = (Get-ChildItem $env:ProgramFiles\Microsoft\jdk-17.*\bin\java.exe) | Select-Object -First 1 + if ($path -and (Test-Path $path)) { + $env:JAVA_HOME = $path.Directory.Parent.FullName + } + } + if ($env:JAVA_HOME) { + echo "##vso[task.setvariable variable=JAVA_HOME]$env:JAVA_HOME" + echo "JAVA_HOME set to '$env:JAVA_HOME'" + } else { + echo "Unable to set JAVA_HOME" + } + displayName: Set JAVA_HOME + + + - ${{ if ne(parameters.isWindows, 'true') }}: + - script: ${{ parameters.buildScript }} + -restore -build + -configuration ${{ parameters.buildConfig }} + /p:ArchiveTests=true + /bl:${{ parameters.repoLogPath }}build.binlog + $(_OfficialBuildIdArgs) + -p:Platform=`uname -m` + displayName: 🛠️ Build + + - ${{ if eq(parameters.isWindows, 'true') }}: + - script: ${{ parameters.buildScript }} + -restore -build + -configuration ${{ parameters.buildConfig }} + /p:ArchiveTests=true + /p:TreatWarningsAsErrors=false + /bl:${{ parameters.repoLogPath }}build.binlog + $(_OfficialBuildIdArgs) + displayName: 🛠️ Build + + # - ${{ if or(ne(parameters.runAsPublic, 'true'), ne(parameters.runHelixTests, 'true')) }}: + # - ${{ if ne(parameters.isWindows, 'true') }}: + # - script: mkdir ${{ parameters.repoArtifactsPath }}/devcert-scripts && + # cd ${{ parameters.repoArtifactsPath }}/devcert-scripts && + # wget https://raw.githubusercontent.com/BorisWilhelms/create-dotnet-devcert/main/scripts/ubuntu-create-dotnet-devcert.sh && + # wget https://raw.githubusercontent.com/BorisWilhelms/create-dotnet-devcert/main/scripts/common.sh && + # chmod +x ubuntu-create-dotnet-devcert.sh && + # ./ubuntu-create-dotnet-devcert.sh + # displayName: Install devcerts + + # - ${{ if eq(parameters.isWindows, 'true') }}: + # - script: dotnet dev-certs https + # displayName: Install dev-certs + + # - ${{ if ne(parameters.isWindows, 'true') }}: + # - script: ${{ parameters.dotnetScript }} dotnet-coverage collect + # --settings $(Build.SourcesDirectory)/eng/CodeCoverage.config + # --output ${{ parameters.repoTestResultsPath }}/NonHelix.cobertura.xml + # "${{ parameters.buildScript }} -testnobuild -test -configuration ${{ parameters.buildConfig }} /bl:${{ parameters.repoLogPath }}tests.binlog $(_OfficialBuildIdArgs) -p:Platform=`uname -m`" + # displayName: Run non-helix tests + + # - ${{ if eq(parameters.runHelixTests, 'true') }}: + # - task: CopyFiles@2 + # inputs: + # Contents: '${{ parameters.repoArtifactsPath }}/helixresults/**/*.trx' + # TargetFolder: '${{ parameters.repoArtifactsPath }}/log/$(_BuildConfig)/TestResults' + # flattenFolders: true + # OverWrite: true + # displayName: Gather helix trx files + # continueOnError: true + # condition: always() + + # - task: CopyFiles@2 + # inputs: + # Contents: '${{ parameters.repoArtifactsPath }}/**/*.cobertura.xml' + # TargetFolder: '${{ parameters.repoArtifactsPath }}/CodeCoverage' + # flattenFolders: true + # displayName: Gather code coverage results + + # - ${{ if eq(parameters.runAsPublic, 'true') }}: + # - task: PublishPipelineArtifact@1 + # displayName: Publish coverage results (cobertura.xml) + # inputs: + # targetPath: '${{ parameters.repoArtifactsPath }}/CodeCoverage' + # artifactName: '$(Agent.JobName)_CodeCoverageResults' + # publishLocation: 'pipeline' + + # - ${{ if ne(parameters.runAsPublic, 'true') }}: + # - task: 1ES.PublishPipelineArtifact@1 + # displayName: Publish code coverage results + # inputs: + # targetPath: '${{ parameters.repoArtifactsPath }}/CodeCoverage' + # artifactName: '$(Agent.JobName)_CodeCoverageResults' + + # Run on windows, for internal pipeline, or public+non-helix-tests job + - ${{ if and(eq(parameters.isWindows, 'true'), or(ne(parameters.runAsPublic, 'true'), ne(parameters.runHelixTests, 'true'))) }}: + + - script: ${{ parameters.buildScript }} + -pack + -sign $(_SignArgs) + -publish $(_PublishArgs) + -configuration $(_BuildConfig) + /bl:${{ parameters.repoLogPath }}/pack.binlog + $(_OfficialBuildIdArgs) + displayName: Pack, Sign & Publish + + # - script: ${{ parameters.buildScript }} + # -restore -build + # -sign $(_SignArgs) + # -publish $(_PublishArgs) + # -configuration $(_BuildConfig) + # /bl:${{ parameters.repoLogPath }}/build-workloads.binlog + # -projects src/Workload/workloads.csproj + # $(_OfficialBuildIdArgs) + # displayName: Build Workloads + + # - ${{ if eq(parameters.runAsPublic, 'true') }}: + # - task: PublishPipelineArtifact@1 + # displayName: Publish VSDrop MSIs + # inputs: + # targetPath: '$(Build.SourcesDirectory)/artifacts/VSSetup/$(_BuildConfig)' + # artifactName: VSDropInsertion + # publishLocation: 'pipeline' + + # - ${{ if ne(parameters.runAsPublic, 'true') }}: + # - task: 1ES.PublishPipelineArtifact@1 + # displayName: Publish VSDrop MSIs + # inputs: + # targetPath: '$(Build.SourcesDirectory)/artifacts/VSSetup/$(_BuildConfig)' + # artifactName: VSDropInsertion \ No newline at end of file diff --git a/eng/pipelines/common/device-tests-steps.yml b/eng/pipelines/common/device-tests-steps.yml index a9ac50cdeecb..854a1e67c078 100644 --- a/eng/pipelines/common/device-tests-steps.yml +++ b/eng/pipelines/common/device-tests-steps.yml @@ -4,6 +4,7 @@ parameters: device: '' # the xharness device to use apiversion: '' # the iOS device api version to use cakeArgs: '' # additional cake args + androidConfiguration: '' # Indicates the configuration to use for Android. We're slowly enabling this for all projects provisionatorChannel: 'latest' agentPoolAccessToken: '' artifactName: 'nuget' @@ -30,8 +31,9 @@ steps: platform: macos skipXcode: ${{ or(eq(parameters.platform, 'android'), eq(parameters.platform, 'windows')) }} skipProvisioning: ${{ eq(parameters.platform, 'windows') }} - skipAndroidImages : ${{ eq(parameters.platform, 'ios') }} - skipAndroidSdks: ${{ eq(parameters.platform, 'ios') }} + skipAndroidImages : ${{ or(eq(parameters.platform, 'ios'), eq(parameters.platform, 'catalyst')) }} + skipAndroidSdks: ${{ or(eq(parameters.platform, 'ios'), eq(parameters.platform, 'catalyst')) }} + installDefaultAndroidApi: ${{ or(eq(parameters.platform, 'ios'), eq(parameters.platform, 'catalyst')) }} provisionatorChannel: ${{ parameters.provisionatorChannel }} - pwsh: ./build.ps1 --target=dotnet --configuration="Release" --verbosity=diagnostic @@ -88,20 +90,41 @@ steps: continueOnError: true timeoutInMinutes: 5 - - pwsh: | - ./build.ps1 -Script eng/devices/${{ parameters.platform }}.cake --project="${{ parameters.path }}" --device=${{ parameters.device }} --apiversion=${{ parameters.apiversion }} --packageid=${{ parameters.windowsPackageId }} --results="$(TestResultsDirectory)" --binlog="$(LogDirectory)" ${{ parameters.cakeArgs }} - displayName: $(Agent.JobName) - workingDirectory: ${{ parameters.checkoutDirectory }} - condition: and(succeeded(), ne(variables['Platform.Name'], 'Mac')) - retryCountOnTaskFailure: 1 - - - bash: | - # Execute the powershell script from a bash shell on Mac to avoid interference between powershell processes that lead to this error: The STDIO streams did not close within 10 seconds of the exit event from process '/usr/local/bin/pwsh'. This may indicate a child process inherited the STDIO streams and has not yet exited. - pwsh ./build.ps1 -Script eng/devices/${{ parameters.platform }}.cake --project="${{ parameters.path }}" --device=${{ parameters.device }} --apiversion=${{ parameters.apiversion }} --packageid=${{ parameters.windowsPackageId }} --results="$(TestResultsDirectory)" --binlog="$(LogDirectory)" ${{ parameters.cakeArgs }} - displayName: $(Agent.JobName) - workingDirectory: ${{ parameters.checkoutDirectory }} - condition: and(succeeded(), eq(variables['Platform.Name'], 'Mac')) - retryCountOnTaskFailure: 1 + # Everything should be release but doing android for now to work around an xharness issue + - ${{ if eq(parameters.platform, 'android')}}: + - pwsh: | + ./build.ps1 -Script eng/devices/${{ parameters.platform }}.cake --project="${{ parameters.path }}" --device=${{ parameters.device }} --apiversion=${{ parameters.apiversion }} --packageid=${{ parameters.windowsPackageId }} --results="$(TestResultsDirectory)" --binlog="$(LogDirectory)" ${{ parameters.cakeArgs }} --configuration=${{ parameters.androidConfiguration }} + displayName: $(Agent.JobName) + workingDirectory: ${{ parameters.checkoutDirectory }} + condition: and(succeeded(), ne(variables['Platform.Name'], 'Mac')) + retryCountOnTaskFailure: 1 + + - ${{ if eq(parameters.platform, 'android')}}: + - bash: | + # Execute the powershell script from a bash shell on Mac to avoid interference between powershell processes that lead to this error: The STDIO streams did not close within 10 seconds of the exit event from process '/usr/local/bin/pwsh'. This may indicate a child process inherited the STDIO streams and has not yet exited. + pwsh ./build.ps1 -Script eng/devices/${{ parameters.platform }}.cake --project="${{ parameters.path }}" --device=${{ parameters.device }} --apiversion=${{ parameters.apiversion }} --packageid=${{ parameters.windowsPackageId }} --results="$(TestResultsDirectory)" --binlog="$(LogDirectory)" ${{ parameters.cakeArgs }} --configuration=${{ parameters.androidConfiguration }} + displayName: $(Agent.JobName) + workingDirectory: ${{ parameters.checkoutDirectory }} + condition: and(succeeded(), eq(variables['Platform.Name'], 'Mac')) + retryCountOnTaskFailure: 1 + + - ${{ if ne(parameters.platform, 'android')}}: + - pwsh: | + ./build.ps1 -Script eng/devices/${{ parameters.platform }}.cake --project="${{ parameters.path }}" --device=${{ parameters.device }} --apiversion=${{ parameters.apiversion }} --packageid=${{ parameters.windowsPackageId }} --results="$(TestResultsDirectory)" --binlog="$(LogDirectory)" ${{ parameters.cakeArgs }} + displayName: $(Agent.JobName) + workingDirectory: ${{ parameters.checkoutDirectory }} + condition: and(succeeded(), ne(variables['Platform.Name'], 'Mac')) + retryCountOnTaskFailure: 1 + + - ${{ if ne(parameters.platform, 'android')}}: + - bash: | + # Execute the powershell script from a bash shell on Mac to avoid interference between powershell processes that lead to this error: The STDIO streams did not close within 10 seconds of the exit event from process '/usr/local/bin/pwsh'. This may indicate a child process inherited the STDIO streams and has not yet exited. + pwsh ./build.ps1 -Script eng/devices/${{ parameters.platform }}.cake --project="${{ parameters.path }}" --device=${{ parameters.device }} --apiversion=${{ parameters.apiversion }} --packageid=${{ parameters.windowsPackageId }} --results="$(TestResultsDirectory)" --binlog="$(LogDirectory)" ${{ parameters.cakeArgs }} + displayName: $(Agent.JobName) + workingDirectory: ${{ parameters.checkoutDirectory }} + condition: and(succeeded(), eq(variables['Platform.Name'], 'Mac')) + retryCountOnTaskFailure: 1 + # Everything should be release but doing android for now to work around an xharness issue - ${{ if eq(parameters.platform, 'ios')}}: - bash: | diff --git a/eng/pipelines/common/device-tests.yml b/eng/pipelines/common/device-tests.yml index 04e3edf5210f..1bac43fff791 100644 --- a/eng/pipelines/common/device-tests.yml +++ b/eng/pipelines/common/device-tests.yml @@ -12,7 +12,11 @@ parameters: artifactName: 'nuget' artifactItemPattern: '**/*.nupkg' checkoutDirectory: $(System.DefaultWorkingDirectory) + androidConfiguration: 'debug' # Indicates the configuration to use for Android. We're slowly enabling this for all projects useArtifacts: false + targetFrameworkVersion: + - tfm: '' + dependsOn: '' projects: - name: name desc: Human Description @@ -21,14 +25,18 @@ parameters: catalyst: /optional/path/to/catalyst.csproj stages: - - stage: android_device_tests - displayName: Android Device Tests - dependsOn: [] + - stage: android_device_tests_${{ replace(parameters.targetFrameworkVersion.tfm, '.', '') }} + displayName: ${{ parameters.targetFrameworkVersion.tfm }} Android Device Tests + ${{ if ne(parameters.targetFrameworkVersion.dependsOn, '') }}: + dependsOn: + - android_device_tests_${{ replace(parameters.targetFrameworkVersion.dependsOn, '.', '') }} + ${{ else }}: + dependsOn: [] jobs: - - job: android_device_tests + - job: android_device_tests_${{ replace(parameters.targetFrameworkVersion.tfm, '.', '') }} workspace: clean: all - displayName: "Android emulator tests" + displayName: "Android" pool: ${{ parameters.androidPool }} timeoutInMinutes: 60 strategy: @@ -41,6 +49,8 @@ stages: ${{ replace(coalesce(project.desc, project.name), ' ', '_') }}_API_${{ api }}: REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) PROJECT_PATH: ${{ project.android }} + ANDROID_CONFIGURATION: ${{ project.androidConfiguration }} + TARGET_FRAMEWORK_VERSION: ${{ parameters.targetFrameworkVersion.tfm }} ${{ if eq(api, 27) }}: DEVICE: android-emulator-32_${{ api }} APIVERSION: ${{ api }} @@ -62,15 +72,20 @@ stages: checkoutDirectory: ${{ parameters.checkoutDirectory }} useArtifacts: ${{ parameters.useArtifacts }} poolName: ${{ parameters.androidPool.name }} + androidConfiguration: $(ANDROID_CONFIGURATION) - - stage: ios_device_tests - displayName: iOS Device Tests - dependsOn: [] + - stage: ios_device_tests_${{ replace(parameters.targetFrameworkVersion.tfm, '.', '') }} + displayName: ${{ parameters.targetFrameworkVersion.tfm }} iOS Device Tests + ${{ if ne(parameters.targetFrameworkVersion.dependsOn, '') }}: + dependsOn: + - ios_device_tests_${{ replace(parameters.targetFrameworkVersion.dependsOn, '.', '') }} + ${{ else }}: + dependsOn: [] jobs: - - job: ios_device_tests + - job: ios_device_tests_${{ replace(parameters.targetFrameworkVersion.tfm, '.', '') }} workspace: clean: all - displayName: "iOS tests" + displayName: "iOS" pool: ${{ parameters.iosPool }} timeoutInMinutes: 120 strategy: @@ -83,6 +98,7 @@ stages: ${{ replace(coalesce(project.desc, project.name), ' ', '_') }}_V_${{ version }}: REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) PROJECT_PATH: ${{ project.ios }} + TARGET_FRAMEWORK_VERSION: ${{ parameters.targetFrameworkVersion.tfm }} ${{ if contains(version, 'device') }}: DEVICE: ios-device APIVERSION: ${{ replace(version, 'device-', '') }} @@ -105,14 +121,18 @@ stages: useArtifacts: ${{ parameters.useArtifacts }} poolName: 'Azure Pipelines' - - stage: catalyst_device_tests - displayName: macOS Device Tests - dependsOn: [] + - stage: catalyst_device_tests_${{ replace(parameters.targetFrameworkVersion.tfm, '.', '') }} + displayName: ${{ parameters.targetFrameworkVersion.tfm }} macOS Device Tests + ${{ if ne(parameters.targetFrameworkVersion.dependsOn, '') }}: + dependsOn: + - catalyst_device_tests_${{ replace(parameters.targetFrameworkVersion.dependsOn, '.', '') }} + ${{ else }}: + dependsOn: [] jobs: - - job: catalyst_device_tests + - job: catalyst_device_tests_${{ replace(parameters.targetFrameworkVersion.tfm, '.', '') }} workspace: clean: all - displayName: "macOS tests" + displayName: "macOS" pool: ${{ parameters.catalystPool }} timeoutInMinutes: 240 strategy: @@ -125,6 +145,7 @@ stages: ${{ replace(coalesce(project.desc, project.name), ' ', '_') }}_V_${{ version }}: REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) PROJECT_PATH: ${{ project.catalyst }} + TARGET_FRAMEWORK_VERSION: ${{ parameters.targetFrameworkVersion.tfm }} ${{ if eq(version, 'latest') }}: DEVICE: maccatalyst ${{ else }}: @@ -146,14 +167,18 @@ stages: poolName: 'Azure Pipelines' - - stage: windows_device_tests - displayName: Windows Device Tests - dependsOn: [] + - stage: windows_device_tests_${{ replace(parameters.targetFrameworkVersion.tfm, '.', '') }} + displayName: ${{ parameters.targetFrameworkVersion.tfm }} Windows Device Tests + ${{ if ne(parameters.targetFrameworkVersion.dependsOn, '') }}: + dependsOn: + - windows_device_tests_${{ replace(parameters.targetFrameworkVersion.dependsOn, '.', '') }} + ${{ else }}: + dependsOn: [] jobs: - - job: windows_device_tests + - job: windows_device_tests_${{ replace(parameters.targetFrameworkVersion.tfm, '.', '') }} workspace: clean: all - displayName: "Windows device tests" + displayName: "Windows" pool: ${{ parameters.windowsPool }} timeoutInMinutes: 240 # how long to run the job before automatically cancelling strategy: @@ -166,6 +191,7 @@ stages: PROJECT_PATH: ${{ project.windows }} PACKAGE_ID: ${{ project.windowsPackageId }} DEVICE: ${{ version }} + TARGET_FRAMEWORK_VERSION: ${{ parameters.targetFrameworkVersion.tfm }} steps: - template: device-tests-steps.yml parameters: diff --git a/eng/pipelines/common/maui-templates.yml b/eng/pipelines/common/maui-templates.yml index e026e70a8afd..6bc2fe51e4f5 100644 --- a/eng/pipelines/common/maui-templates.yml +++ b/eng/pipelines/common/maui-templates.yml @@ -20,109 +20,119 @@ parameters: - name: BuildPlatforms type: object + + - name: BuildCategories + type: object default: - - name: Windows - poolName: $(windowsVmPool) - vmImage: $(windowsVmImage) - artifact: templates-windows - - name: macOS - poolName: $(macOSXVmPool) - vmImage: $(macOSXVmImage) - artifact: templates-macos + - WindowsTemplates + - macOSTemplates + - Build + - Blazor + - MultiProject + - AOT - name: RunPlatforms type: object - default: - - name: $(androidTestsVmPool) - vmImage: $(androidTestsVmImage) - demands: - - macOS.Name -equals Sonoma - - macOS.Architecture -equals x64 - testName: RunOnAndroid - artifact: templates-run-android - - name: $(iosTestsVmPool) - vmImage: $(iosTestsVmImage) - demands: - - macOS.Name -equals Sonoma - - macOS.Architecture -equals x64 - testName: RunOniOS - artifact: templates-run-ios - name: prepareSteps type: stepList default: [] jobs: -- job: build_maui_templates - workspace: - clean: all - displayName: 'Build platform:' - timeoutInMinutes: 240 - condition: ${{ parameters.condition}} - strategy: - matrix: - ${{ each BuildPlatform in parameters.BuildPlatforms }}: - ${{ BuildPlatform.name }}: - POOL_NAME: ${{ BuildPlatform.poolName }} - POOL_VIMAGE: ${{ BuildPlatform.vmImage }} - PLATFORM_NAME: ${{ lower(BuildPlatform.name) }} - - pool: - name: $(POOL_NAME) - vmImage: $(POOL_VIMAGE) - demands: - - macOS.Name -equals Sonoma - - macOS.Architecture -equals x64 - steps: - - - ${{ each step in parameters.prepareSteps }}: - - ${{ each pair in step }}: - ${{ pair.key }}: ${{ pair.value }} - - - template: provision.yml - parameters: - checkoutDirectory: ${{ parameters.checkoutDirectory }} - - - task: DownloadBuildArtifacts@0 - displayName: 'Download Packages' - inputs: - artifactName: ${{ parameters.artifactName }} - itemPattern: ${{ parameters.artifactItemPattern }} - downloadPath: $(System.DefaultWorkingDirectory)/artifacts - - - pwsh: Move-Item -Path artifacts\${{ parameters.artifactName }}\*.nupkg -Destination artifacts -Force - displayName: Move the downloaded artifacts - - - pwsh: ./build.ps1 --target=dotnet-local-workloads --verbosity=diagnostic - displayName: 'Install .NET (Local Workloads)' - retryCountOnTaskFailure: 3 - workingDirectory: ${{ parameters.checkoutDirectory }} - env: - DOTNET_TOKEN: $(dotnetbuilds-internal-container-read-token) - PRIVATE_BUILD: $(PrivateBuild) - - - pwsh: ./build.ps1 --target=dotnet-integration-build --verbosity=diagnostic - displayName: Build Microsoft.Maui.IntegrationTests - workingDirectory: ${{ parameters.checkoutDirectory }} - - - pwsh: ./build.ps1 --target=dotnet-integration-test --filter="FullyQualifiedName=Microsoft.Maui.IntegrationTests.TemplateTests" --resultsfilename="integration-tests" --verbosity=diagnostic - displayName: Run $(PLATFORM_NAME) templates build tests - workingDirectory: ${{ parameters.checkoutDirectory }} - - - task: PublishTestResults@2 - displayName: Publish the $(PLATFORM_NAME) templates build tests - condition: always() - inputs: - testRunner: VSTest - testResultsFiles: '$(build.artifactstagingdirectory)/**/*.trx' - testRunTitle: $(PLATFORM_NAME) templates build tests - - - pwsh: | - Write-Host "Current job status is: $env:AGENT_JOBSTATUS" - if ($env:AGENT_JOBSTATUS -eq "SucceededWithIssues") { - Write-Host "##vso[task.complete result=Failed;]DONE" - } - displayName: Fail if any issues occurred +- ${{ each category in parameters.BuildCategories }}: + - job: build_maui_templates_${{ category }} + workspace: + clean: all + displayName: 'Build ${{ category }}: ' + timeoutInMinutes: 240 + condition: ${{ parameters.condition}} + strategy: + matrix: + ${{ each BuildPlatform in parameters.BuildPlatforms }}: + ${{ BuildPlatform.name }}: + POOL_NAME: ${{ BuildPlatform.poolName }} + POOL_VIMAGE: ${{ BuildPlatform.vmImage }} + PLATFORM_NAME: ${{ lower(BuildPlatform.name) }} + + pool: + name: $(POOL_NAME) + vmImage: $(POOL_VIMAGE) + demands: + - macOS.Name -equals Sonoma + - macOS.Architecture -equals x64 + steps: + + - ${{ each step in parameters.prepareSteps }}: + - ${{ each pair in step }}: + ${{ pair.key }}: ${{ pair.value }} + + - template: provision.yml + parameters: + checkoutDirectory: ${{ parameters.checkoutDirectory }} + + - task: DownloadBuildArtifacts@0 + displayName: 'Download Packages' + inputs: + artifactName: ${{ parameters.artifactName }} + itemPattern: ${{ parameters.artifactItemPattern }} + downloadPath: $(System.DefaultWorkingDirectory)/artifacts + + - pwsh: Move-Item -Path artifacts\${{ parameters.artifactName }}\*.nupkg -Destination artifacts -Force + displayName: Move the downloaded artifacts + + - pwsh: | + Get-ChildItem artifacts -Filter 'Microsoft.Maui.Controls.*.nupkg' | Where-Object { $_.Name -match '^Microsoft\.Maui\.Controls\.([\d\.]+.*)\.nupkg$' } + $version = $Matches.1 + if (!$version) { + Write-Error "Failed to extract the version from the nupkgs" + exit 1 + } + Write-Host "Found .NET MAUI version (MAUI_PACKAGE_VERSION): $version" + Write-Host "##vso[task.setvariable variable=MAUI_PACKAGE_VERSION]$version" + displayName: Read the .NET MAUI version from the nugets + + - pwsh: ./build.ps1 --target=dotnet-local-workloads --verbosity=diagnostic + displayName: 'Install .NET (Local Workloads)' + retryCountOnTaskFailure: 3 + workingDirectory: ${{ parameters.checkoutDirectory }} + env: + DOTNET_TOKEN: $(dotnetbuilds-internal-container-read-token) + PRIVATE_BUILD: $(PrivateBuild) + + - pwsh: ./build.ps1 --target=dotnet-integration-build --verbosity=diagnostic + displayName: Build Microsoft.Maui.IntegrationTests + workingDirectory: ${{ parameters.checkoutDirectory }} + + - pwsh: ./build.ps1 --target=dotnet-integration-test --filter="Category=${{ category }}" --resultsfilename="integration-tests" --verbosity=diagnostic + displayName: Run $(PLATFORM_NAME) templates build tests + workingDirectory: ${{ parameters.checkoutDirectory }} + + - task: CopyFiles@2 + displayName: Copy binlogs + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + **/*.binlog + ../**/*.binlog + ../../**/*.binlog + TargetFolder: '$(Build.StagingDirectory)/IntegrationTestsBuildLogs' + continueOnError: true + condition: succeededOrFailed() + + - task: PublishTestResults@2 + displayName: Publish the $(PLATFORM_NAME) templates build tests + condition: always() + inputs: + testRunner: VSTest + testResultsFiles: '$(build.artifactstagingdirectory)/**/*.trx' + testRunTitle: $(PLATFORM_NAME) templates build tests + + - pwsh: | + Write-Host "Current job status is: $env:AGENT_JOBSTATUS" + if ($env:AGENT_JOBSTATUS -eq "SucceededWithIssues") { + Write-Host "##vso[task.complete result=Failed;]DONE" + } + displayName: Fail if any issues occurred - ${{ each RunPlatform in parameters.RunPlatforms }}: - job: run_${{ RunPlatform.testName }} @@ -150,6 +160,7 @@ jobs: - template: provision.yml parameters: skipXcode: ${{ eq(RunPlatform.testName, 'RunOnAndroid') }} + skipAndroidImages: ${{ ne(RunPlatform.testName, 'RunOnAndroid') }} checkoutDirectory: ${{ parameters.checkoutDirectory }} - task: DownloadBuildArtifacts@0 @@ -162,6 +173,17 @@ jobs: - pwsh: Move-Item -Path artifacts\${{ parameters.artifactName }}\*.nupkg -Destination artifacts -Force displayName: Move the downloaded artifacts + - pwsh: | + Get-ChildItem artifacts -Filter 'Microsoft.Maui.Controls.*.nupkg' | Where-Object { $_.Name -match '^Microsoft\.Maui\.Controls\.([\d\.]+.*)\.nupkg$' } + $version = $Matches.1 + if (!$version) { + Write-Error "Failed to extract the version from the nupkgs" + exit 1 + } + Write-Host "Found .NET MAUI version (MAUI_PACKAGE_VERSION): $version" + Write-Host "##vso[task.setvariable variable=MAUI_PACKAGE_VERSION]$version" + displayName: Read the .NET MAUI version from the nugets + - pwsh: ./build.ps1 --target=dotnet-local-workloads --verbosity=diagnostic displayName: 'Install .NET (Local Workloads)' retryCountOnTaskFailure: 3 @@ -183,7 +205,7 @@ jobs: - pwsh: ./build.ps1 --target=dotnet-integration-build --verbosity=diagnostic displayName: Build Microsoft.Maui.IntegrationTests - - pwsh: ./build.ps1 --target=dotnet-integration-test --filter="Name=${{ RunPlatform.testName }}" --resultsfilename="integration-run-${{ RunPlatform.testName }}" --verbosity=diagnostic + - pwsh: ./build.ps1 --target=dotnet-integration-test --filter="Category=${{ RunPlatform.testName }}" --resultsfilename="integration-run-${{ RunPlatform.testName }}" --verbosity=diagnostic displayName: Run $(PLATFORM_NAME) templates run tests continueOnError: true # TODO: pass properly device type/version from top-level yml diff --git a/eng/pipelines/common/pack.yml b/eng/pipelines/common/pack.yml index c82597446880..eb3cb7da5aad 100644 --- a/eng/pipelines/common/pack.yml +++ b/eng/pipelines/common/pack.yml @@ -150,7 +150,7 @@ steps: condition: succeeded() inputs: Contents: | - ${{ parameters.checkoutDirectory }}/artifacts/bin/Controls.Nuget/${{ parameters.buildConfiguration }}/**/*.dll + ${{ parameters.checkoutDirectory }}/artifacts/bin/Controls.Nuget/${{ parameters.buildConfiguration }}/**/Microsoft.Maui*.dll TargetFolder: ${{ parameters.checkoutDirectory }}/artifacts/binaries flattenFolders: false diff --git a/eng/pipelines/common/provision.yml b/eng/pipelines/common/provision.yml index 6b3cdd86b498..13302d8e0025 100644 --- a/eng/pipelines/common/provision.yml +++ b/eng/pipelines/common/provision.yml @@ -5,6 +5,7 @@ parameters: skipProvisioning: $(skipProvisionator) skipAndroidSdks: false skipAndroidImages: false + installDefaultAndroidApi: false checkoutDirectory: $(System.DefaultWorkingDirectory) provisionatorPath: $(provisionator.path) provisionatorXCodePath: $(provisionator.xcode) @@ -12,6 +13,10 @@ parameters: provisionatorExtraArguments: $(provisionator.extraArguments) gitHubToken: $(github--pat--vs-mobiletools-engineering-service2) certPass: $(pass--components-mac-ios-certificate-p12) + federatedServiceConnection: 'dotnetbuilds-internal-read' + outputVariableName: 'dotnetbuilds-internal-container-read-token' + expiryInHours: 1 + base64Encode: false steps: # Prepare macOS @@ -54,23 +59,26 @@ steps: SKIP_ANDROID_API_SDKS: 'true' ${{ if eq(parameters.skipAndroidImages, true) }}: SKIP_ANDROID_API_IMAGES: 'true' + ${{ if eq(parameters.installDefaultAndroidApi, true) }}: + INSTALL_DEFAULT_ANDROID_API: 'true' # Setup JDK Paths (gradle needs it) - bash: | - echo "##vso[task.setvariable variable=JI_JAVA_HOME]$(JAVA_HOME_11_X64)" - echo "##vso[task.setvariable variable=JAVA_HOME]$(JAVA_HOME_11_X64)" + echo "##vso[task.setvariable variable=JI_JAVA_HOME]$(JAVA_HOME_17_X64)" + echo "##vso[task.setvariable variable=JAVA_HOME]$(JAVA_HOME_17_X64)" + # brew install --cask microsoft-openjdk@17 displayName: 'Setup JDK Paths' condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) # Configure VS Mac for Xcode # This seems to be needed or else it will pick other xcode for example on xharness - - bash: | - set -x - mkdir -p ~/Library/Preferences/Xamarin - rm -f ~/Library/Preferences/Xamarin/Settings.plist - /usr/libexec/PlistBuddy -c "add :AppleSdkRoot string $(dirname $(dirname $(xcode-select -p)))" ~/Library/Preferences/Xamarin/Settings.plist || true - cat ~/Library/Preferences/Xamarin/Settings.plist || true - displayName: 'Configure Visual Studio' - condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) + # - bash: | + # set -x + # mkdir -p ~/Library/Preferences/Xamarin + # rm -f ~/Library/Preferences/Xamarin/Settings.plist + # /usr/libexec/PlistBuddy -c "add :AppleSdkRoot string $(dirname $(dirname $(xcode-select -p)))" ~/Library/Preferences/Xamarin/Settings.plist || true + # cat ~/Library/Preferences/Xamarin/Settings.plist || true + # displayName: 'Configure Visual Studio' + # condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) # Prepare Windows # Provision Additional Software @@ -88,12 +96,14 @@ steps: SKIP_ANDROID_API_SDKS: 'true' ${{ if eq(parameters.skipAndroidImages, true) }}: SKIP_ANDROID_API_IMAGES: 'true' + ${{ if eq(parameters.installDefaultAndroidApi, true) }}: + INSTALL_DEFAULT_ANDROID_API: 'true' - pwsh: | - if ($env:JAVA_HOME_11_X64) { - $env:JAVA_HOME = $env:JAVA_HOME_11_X64 + if ($env:JAVA_HOME_17_X64) { + $env:JAVA_HOME = $env:JAVA_HOME_17_X64 } else { - $path = (Get-ChildItem $env:ProgramFiles\Microsoft\jdk-11.*\bin\java.exe) | Select-Object -First 1 + $path = (Get-ChildItem $env:ProgramFiles\Microsoft\jdk-17.*\bin\java.exe) | Select-Object -First 1 if ($path -and (Test-Path $path)) { $env:JAVA_HOME = $path.Directory.Parent.FullName } @@ -130,6 +140,7 @@ steps: inputs: packageType: sdk version: $(DOTNET_VERSION) + includePreviewVersions: true - pwsh: | dotnet --version @@ -141,11 +152,11 @@ steps: displayName: 'Clear all NuGet caches' - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: - - task: PowerShell@2 - condition: eq(variables['PrivateBuild'], 'true') - displayName: Setup Private Feeds Credentials - inputs: - filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1 - arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $Env:Token - env: - Token: $(dn-bot-dnceng-artifact-feeds-rw) \ No newline at end of file + - template: ../../common/templates-official/steps/enable-internal-sources.yml + + - template: ../../common/templates-official/steps/enable-internal-runtimes.yml + parameters: + federatedServiceConnection: ${{ parameters.federatedServiceConnection }} + outputVariableName: ${{ parameters.outputVariableName }} + expiryInHours: ${{ parameters.expiryInHours }} + base64Encode: ${{ parameters.base64Encode }} diff --git a/eng/pipelines/common/sdk-insertion.yml b/eng/pipelines/common/sdk-insertion.yml index 70b21ec58fa6..fea5695cc9ef 100644 --- a/eng/pipelines/common/sdk-insertion.yml +++ b/eng/pipelines/common/sdk-insertion.yml @@ -57,10 +57,11 @@ jobs: buildNumber: $(ReleaseDropPrefix)/nugets destinationPath: ${{ parameters.nugetArtifactPath }} - - task: UseDotNet@2 - displayName: Install .NET 9.x + - task: UseDotNet@2 # https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/tool/dotnet-core-tool-installer?view=azure-devops + displayName: 'Use .NET SDK $(DOTNET_VERSION)' inputs: - version: 9.x + packageType: sdk + version: $(DOTNET_VERSION) includePreviewVersions: true - task: AzureCLI@2 @@ -70,13 +71,11 @@ jobs: scriptType: ps scriptLocation: inlineScript inlineScript: >- - & dotnet build $(Build.SourcesDirectory)\src\Workload\Microsoft.Maui.Sdk\Microsoft.Maui.Sdk.csproj + dotnet build $(Build.SourcesDirectory)\src\Workload\Microsoft.Maui.Sdk\Microsoft.Maui.Sdk.csproj -t:PushManifestToBuildAssetRegistry -p:OfficialBuildId=$(_BuildOfficalId) -p:OutputPath=${{ parameters.nugetArtifactPath }} -v:n -bl:$(Build.StagingDirectory)\binlogs\push-bar-manifest.binlog - # Execute outside of the source directory to avoid any conflicting global.json file - workingDirectory: $(Build.SourcesDirectory)\.. condition: and(succeeded(), eq('${{ parameters.pushMauiPackagesToMaestro }}', 'true')) - task: AzureCLI@2 @@ -90,7 +89,5 @@ jobs: $arcadeServicesSource = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' & dotnet tool update microsoft.dotnet.darc --version "$darcVersion" --add-source "$arcadeServicesSource" --tool-path $(Agent.ToolsDirectory)\darc -v n & $(Agent.ToolsDirectory)\darc\darc add-build-to-channel --default-channels --id $(BARBuildId) --ci --publishing-infra-version 3 --azdev-pat $(System.AccessToken) - # Execute outside of the source directory to avoid any conflicting global.json file - workingDirectory: $(Build.SourcesDirectory)\.. displayName: Add build to default darc channel condition: and(succeeded(), eq('${{ parameters.pushMauiPackagesToMaestro }}', 'true')) diff --git a/eng/pipelines/common/ui-tests-build-sample.yml b/eng/pipelines/common/ui-tests-build-sample.yml index 9d359ee2f87e..c133355d3e32 100644 --- a/eng/pipelines/common/ui-tests-build-sample.yml +++ b/eng/pipelines/common/ui-tests-build-sample.yml @@ -9,6 +9,7 @@ parameters: agentPoolAccessToken: '' configuration : "Release" testFilter: '' + runtimeVariant: 'Mono' steps: - ${{ if eq(parameters.platform, 'ios')}}: @@ -22,7 +23,8 @@ steps: - template: provision.yml parameters: skipProvisioning: ${{ eq(parameters.platform, 'windows') }} - skipAndroidSdks: ${{ ne(parameters.platform, 'android') }} + # FIXME: 'Build the MSBuild Tasks' step fails for net9.0-android35 without API 35 + skipAndroidSdks: false skipXcode: ${{ or(eq(parameters.platform, 'android'), eq(parameters.platform, 'windows')) }} provisionatorChannel: ${{ parameters.provisionatorChannel }} @@ -47,7 +49,7 @@ steps: - pwsh: echo "##vso[task.prependpath]$(DotNet.Dir)" displayName: 'Add .NET to PATH' - - pwsh: ./build.ps1 --target=uitests-apphost --configuration="${{ parameters.configuration }}" --${{ parameters.platform }} --verbosity=diagnostic --usenuget=false + - pwsh: ./build.ps1 --target=uitests-apphost --configuration="${{ parameters.configuration }}" --${{ parameters.platform }} --verbosity=diagnostic --usenuget=false --runtimevariant="${{ parameters.runtimeVariant }}" displayName: 'Build the samples' - bash: | @@ -58,17 +60,31 @@ steps: continueOnError: true - publish: $(System.DefaultWorkingDirectory)/artifacts/bin - condition: and(ne('${{ parameters.platform }}' , 'windows'), succeeded()) + condition: and(ne('${{ parameters.platform }}' , 'windows'), ne('${{ parameters.runtimeVariant }}' , 'NativeAOT'), succeeded()) artifact: ui-tests-samples + + - publish: $(System.DefaultWorkingDirectory)/artifacts/bin + condition: and(ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'NativeAOT'), succeeded()) + artifact: ui-tests-samples-nativeaot - publish: $(System.DefaultWorkingDirectory)/artifacts/bin condition: and(eq('${{ parameters.platform }}' , 'windows'), succeeded()) artifact: ui-tests-samples-windows - publish: $(System.DefaultWorkingDirectory)/artifacts/bin - condition: and(ne('${{ parameters.platform }}' , 'windows'), failed()) + condition: and(ne('${{ parameters.platform }}' , 'windows'), ne('${{ parameters.runtimeVariant }}' , 'NativeAOT'), failed()) artifact: ui-tests-samples_failed_$(System.JobAttempt) + - publish: $(System.DefaultWorkingDirectory)/artifacts/bin + condition: and(ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'NativeAOT'), failed()) + artifact: ui-tests-samples-nativeaot_failed_$(System.JobAttempt) + - publish: $(System.DefaultWorkingDirectory)/artifacts/bin condition: and(eq('${{ parameters.platform }}' , 'windows'), failed()) - artifact: ui-tests-samples-windows_failed_$(System.JobAttempt) \ No newline at end of file + artifact: ui-tests-samples-windows_failed_$(System.JobAttempt) + + - task: PublishBuildArtifacts@1 + displayName: Publish Artifacts + condition: always() + inputs: + artifactName: '$(Agent.JobName) (attempt $(System.JobAttempt))' diff --git a/eng/pipelines/common/ui-tests-steps.yml b/eng/pipelines/common/ui-tests-steps.yml index 86ab2bd5c7c3..095103432667 100644 --- a/eng/pipelines/common/ui-tests-steps.yml +++ b/eng/pipelines/common/ui-tests-steps.yml @@ -8,13 +8,19 @@ parameters: provisionatorChannel: 'latest' agentPoolAccessToken: '' configuration : "Release" + runtimeVariant : "Mono" testFilter: '' steps: - task: DownloadPipelineArtifact@2 - condition: ne('${{ parameters.platform }}' , 'windows') + condition: and(ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'Mono')) inputs: artifact: ui-tests-samples + + - task: DownloadPipelineArtifact@2 + condition: and(ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'NativeAOT')) + inputs: + artifact: ui-tests-samples-nativeaot - task: DownloadPipelineArtifact@2 condition: eq('${{ parameters.platform }}' , 'windows') @@ -84,6 +90,7 @@ steps: - pwsh: | $command = "./build.ps1 -Script eng/devices/${{ parameters.platform }}.cake --target=uitest --project=""${{ parameters.path }}""" $command += " --appproject=""${{ parameters.app }}"" --device=""${{ parameters.device }}"" --apiversion=""${{ parameters.version }}"" --configuration=""${{ parameters.configuration }}""" + $command += " --runtimevariant=""${{ parameters.runtimeVariant }}""" $command += " --results=""$(TestResultsDirectory)"" --binlog=""$(LogDirectory)"" ${{ parameters.cakeArgs }} --verbosity=diagnostic" $testFilter = "" @@ -128,4 +135,4 @@ steps: # This must always be placed as the last step in the job - template: agent-rebooter/mac.v1.yml@yaml-templates parameters: - AgentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} + AgentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} \ No newline at end of file diff --git a/eng/pipelines/common/ui-tests.yml b/eng/pipelines/common/ui-tests.yml index 2cc19a42d6ac..16d1ab574bfc 100644 --- a/eng/pipelines/common/ui-tests.yml +++ b/eng/pipelines/common/ui-tests.yml @@ -53,6 +53,24 @@ stages: APPIUM_HOME: $(System.DefaultWorkingDirectory)/.appium/ steps: - template: ui-tests-build-sample.yml + parameters: + runtimeVariant: "Mono" + + - stage: build_ui_tests_nativeaot + displayName: Build UITests Sample App NativeAOT + dependsOn: [] + jobs: + - job: build_ui_tests + displayName: Build Sample App + pool: ${{ parameters.androidPool }} + variables: + REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) + APPIUM_HOME: $(System.DefaultWorkingDirectory)/.appium/ + steps: + - template: ui-tests-build-sample.yml + parameters: + runtimeVariant: "NativeAOT" + platform: ios - stage: build_ui_tests_windows displayName: Build UITests Windows Sample App @@ -106,15 +124,15 @@ stages: agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} testFilter: $(CATEGORYGROUP) - - stage: ios_ui_tests - displayName: iOS UITests + - stage: ios_ui_tests_mono + displayName: iOS UITests Mono dependsOn: build_ui_tests jobs: - ${{ each project in parameters.projects }}: - ${{ if ne(project.ios, '') }}: - ${{ each version in parameters.iosVersions }}: - ${{ if not(containsValue(project.iosVersionsExclude, version)) }}: - - job: ios_ui_tests_${{ project.name }}_${{ replace(version, '.', '_') }} + - job: ios_ui_tests_mono_${{ project.name }}_${{ replace(version, '.', '_') }} strategy: matrix: ${{ each categoryGroup in parameters.categoryGroupsToTest }}: @@ -144,6 +162,49 @@ stages: device: ios-simulator-64_${{ version }} provisionatorChannel: ${{ parameters.provisionatorChannel }} agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} + runtimeVariant : "Mono" + testFilter: $(CATEGORYGROUP) + + + - stage: ios_ui_tests_nativeaot + displayName: iOS UITests NativeAOT + dependsOn: build_ui_tests_nativeaot + jobs: + - ${{ each project in parameters.projects }}: + - ${{ if ne(project.ios, '') }}: + - ${{ each version in parameters.iosVersions }}: + - ${{ if not(containsValue(project.iosVersionsExclude, version)) }}: + - job: ios_ui_tests_nativeaot_${{ project.name }}_${{ replace(version, '.', '_') }} + strategy: + matrix: + ${{ each categoryGroup in parameters.categoryGroupsToTest }}: + ${{ categoryGroup }}: + CATEGORYGROUP: ${{ categoryGroup }} + timeoutInMinutes: 240 # how long to run the job before automatically cancelling + workspace: + clean: all + displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) + pool: ${{ parameters.iosPool }} + variables: + REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) + APPIUM_HOME: $(System.DefaultWorkingDirectory)/.appium/ + steps: + - template: ui-tests-steps.yml + parameters: + platform: ios + ${{ if eq(version, 'latest') }}: + version: 17.2 + ${{ if ne(version, 'latest') }}: + version: ${{ version }} + path: ${{ project.ios }} + app: ${{ project.app }} + ${{ if eq(version, 'latest') }}: + device: ios-simulator-64 + ${{ if ne(version, 'latest') }}: + device: ios-simulator-64_${{ version }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} + runtimeVariant : "NativeAOT" testFilter: $(CATEGORYGROUP) - stage: winui_ui_tests diff --git a/eng/pipelines/common/variables.yml b/eng/pipelines/common/variables.yml index 663378cf41fd..1f29c6c8278d 100644 --- a/eng/pipelines/common/variables.yml +++ b/eng/pipelines/common/variables.yml @@ -8,11 +8,11 @@ variables: - name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE value: true - name: DOTNET_VERSION - value: 8.0.300 + value: 9.0.100-preview.4.24267.66 - name: REQUIRED_XCODE - value: 15.4.0 + value: 16.0.0 - name: DEVICETESTS_REQUIRED_XCODE - value: 15.4.0 + value: 16.0.0 - name: LocBranchPrefix value: 'loc-hb' - name: isMainBranch @@ -48,9 +48,9 @@ variables: - name: provisionator.extraArguments value: '-vvvv' - name: DotNet.Dir - value: $(System.DefaultWorkingDirectory)/bin/dotnet + value: $(System.DefaultWorkingDirectory)/.dotnet - name: DotNet.Path - value: $(System.DefaultWorkingDirectory)/bin/dotnet/dotnet + value: $(System.DefaultWorkingDirectory)/.dotnet/dotnet - name: TeamName value: Maui - name: POWERSHELL_VERSION @@ -58,11 +58,33 @@ variables: - name: Codeql.Enabled value: false - group: Xamarin-Secrets + # Variable groups required for private builds -# - ${{ if or(eq(variables['System.TeamProject'], 'DevDiv'), eq(variables['Build.DefinitionName'], 'dotnet-maui')) }}: -# - name: PrivateBuild -# value: true -# # For eng/common/SetupNugetSources.ps1 -# - group: DotNetBuilds storage account read tokens -# - group: AzureDevOps-Artifact-Feeds-Pats +- ${{ if or(eq(variables['System.TeamProject'], 'DevDiv'), eq(variables['Build.DefinitionName'], 'dotnet-maui')) }}: + - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}: + - name: PrivateBuild + value: false + - name: _RunAsPublic + value: False + - name: _RunAsInternal + value: True + - name: _SignType + value: real + # - name: PostBuildSign + # value: true + # For eng/common/SetupNugetSources.ps1 + - group: DotNetBuilds storage account read tokens + - group: AzureDevOps-Artifact-Feeds-Pats + - name: _InternalBuildArgs + value: /p:DotNetSignType=$(_SignType) + /p:TeamName=$(_TeamName) + /p:DotNetPublishUsingPipelines=true + /p:OfficialBuildId=$(BUILD.BUILDNUMBER) +- ${{ if eq(variables['Build.DefinitionName'], 'dotnet-maui') }}: + - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}: + # Publish-Build-Assets provides: MaestroAccessToken, BotAccount-dotnet-maestro-bot-PAT + # DotNet-HelixApi-Access provides: HelixApiAccessToken + - group: Publish-Build-Assets + - group: DotNet-HelixApi-Access + - group: SDL_Settings \ No newline at end of file diff --git a/eng/pipelines/device-tests.yml b/eng/pipelines/device-tests.yml index 3ecf40a1ff71..f863a35c56e8 100644 --- a/eng/pipelines/device-tests.yml +++ b/eng/pipelines/device-tests.yml @@ -72,17 +72,17 @@ parameters: - name: iosPool type: object default: - name: $(iosTestsVmPool) - vmImage: $(iosTestsVmImage) + name: $(iosDeviceTestsVmPool) + vmImage: $(iosDeviceTestsVmImage) demands: - - macOS.Name -equals Sonoma - - macOS.Architecture -equals x64 - + - Agent.OSVersion -equals 14.5 + - Agent.OSArchitecture -equals ARM64 + - name: catalystPool type: object default: - name: $(iosTestsVmPool) - vmImage: $(iosTestsVmImage) + name: $(androidTestsVmPool) + vmImage: $(androidTestsVmImage) demands: - macOS.Name -equals Sonoma - macOS.Architecture -equals x64 @@ -93,6 +93,11 @@ parameters: name: $(windowsTestsVmPool) vmImage: $(windowsTestsVmImage) + - name: targetFrameworkVersions + type: object + default: + - tfm: net9.0 + resources: repositories: - repository: yaml-templates @@ -102,7 +107,7 @@ resources: ref: refs/heads/main stages: - +- ${{ each targetFrameworkVersion in parameters.targetFrameworkVersions }}: - template: common/device-tests.yml parameters: androidPool: ${{ parameters.androidPool }} @@ -110,15 +115,16 @@ stages: catalystPool: ${{ parameters.catalystPool }} windowsPool: ${{ parameters.windowsPool }} agentPoolAccessToken: $(AgentPoolAccessToken) + targetFrameworkVersion: ${{ targetFrameworkVersion }} ${{ if or(parameters.BuildEverything, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv'))) }}: androidApiLevels: [ 33, 30, 29, 28, 27, 26, 25, 24, 23 ] - iosVersions: [ 'simulator-17.2'] + iosVersions: [ 'simulator-18.0'] catalystVersions: [ 'latest' ] windowsVersions: ['packaged', 'unpackaged'] provisionatorChannel: ${{ parameters.provisionatorChannel }} - ${{ if not(or(parameters.BuildEverything, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv')))) }}: + ${{ else }}: androidApiLevels: [ 33, 23 ] - iosVersions: [ 'simulator-17.2' ] + iosVersions: [ 'simulator-18.0' ] catalystVersions: [ 'latest' ] windowsVersions: ['packaged', 'unpackaged'] provisionatorChannel: ${{ parameters.provisionatorChannel }} @@ -126,6 +132,7 @@ stages: - name: essentials desc: Essentials androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable + androidConfiguration: 'Release' windowsPackageId: 'com.microsoft.maui.essentials.devicetests' android: $(System.DefaultWorkingDirectory)/src/Essentials/test/DeviceTests/Essentials.DeviceTests.csproj ios: $(System.DefaultWorkingDirectory)/src/Essentials/test/DeviceTests/Essentials.DeviceTests.csproj @@ -134,6 +141,7 @@ stages: - name: graphics desc: Graphics androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable + androidConfiguration: 'Release' windowsPackageId: 'com.microsoft.maui.graphics.devicetests' android: $(System.DefaultWorkingDirectory)/src/Graphics/tests/DeviceTests/Graphics.DeviceTests.csproj ios: $(System.DefaultWorkingDirectory)/src/Graphics/tests/DeviceTests/Graphics.DeviceTests.csproj @@ -142,6 +150,7 @@ stages: - name: core desc: Core androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable + androidConfiguration: 'Release' windowsPackageId: 'com.microsoft.maui.core.devicetests' android: $(System.DefaultWorkingDirectory)/src/Core/tests/DeviceTests/Core.DeviceTests.csproj ios: $(System.DefaultWorkingDirectory)/src/Core/tests/DeviceTests/Core.DeviceTests.csproj @@ -150,6 +159,7 @@ stages: - name: controls desc: Controls androidApiLevelsExclude: [27, 25] # Ignore for now API25 since the runs's are not stable + androidConfiguration: 'Debug' windowsPackageId: 'com.microsoft.maui.controls.devicetests' android: $(System.DefaultWorkingDirectory)/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj ios: $(System.DefaultWorkingDirectory)/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj @@ -157,7 +167,8 @@ stages: windows: $(System.DefaultWorkingDirectory)/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj - name: blazorwebview desc: BlazorWebView - androidApiLevelsExclude: [ 27, 26, 25, 24, 23, 22, 21 ] # BlazorWebView requires a recent version of Chrome + androidApiLevelsExclude: [ 30, 29, 28, 27, 26, 25, 24, 23, 22, 21 ] # BlazorWebView requires a recent version of Chrome + androidConfiguration: 'Release' windowsPackageId: 'Microsoft.Maui.MauiBlazorWebView.DeviceTests' android: $(System.DefaultWorkingDirectory)/src/BlazorWebView/tests/MauiDeviceTests/MauiBlazorWebView.DeviceTests.csproj ios: $(System.DefaultWorkingDirectory)/src/BlazorWebView/tests/MauiDeviceTests/MauiBlazorWebView.DeviceTests.csproj diff --git a/eng/pipelines/handlers.yml b/eng/pipelines/handlers.yml index 6a804080dedf..ad1740cba0e3 100644 --- a/eng/pipelines/handlers.yml +++ b/eng/pipelines/handlers.yml @@ -29,6 +29,7 @@ pr: - release/* - net9.0 - net8.0 + - net9.0 paths: include: - '*' @@ -87,7 +88,7 @@ parameters: vmImage: $(macOSXVmImage) artifact: nuget-macos - - name: BuilTemplatePlatforms + - name: BuildTemplatePlatforms type: object default: - name: Windows @@ -122,8 +123,8 @@ parameters: default: - name: default tfm: default - - name: net8 - tfm: net8.0 + - name: net9 + tfm: net9.0 resources: repositories: @@ -166,6 +167,9 @@ stages: parameters: poolName: ${{ BuildPlatform.poolName }} gitHubToken: $(github--pat--vs-mobiletools-engineering-service2) + skipAndroidSdks: true + skipAndroidImages: true + installDefaultAndroidApi: false - pwsh: ./build.ps1 --target=dotnet --configuration="${{ BuildConfiguration }}" --verbosity=diagnostic displayName: 'Install .NET' retryCountOnTaskFailure: 3 @@ -233,7 +237,9 @@ stages: checkoutDirectory: '$(System.DefaultWorkingDirectory)' provisionatorChannel: ${{ parameters.provisionatorChannel }} gitHubToken: $(github--pat--vs-mobiletools-engineering-service2) + skipAndroidSdks: true skipAndroidImages: true + installDefaultAndroidApi: true - stage: samples_net displayName: Test .NET MAUI Samples @@ -255,6 +261,9 @@ stages: - template: common/provision.yml parameters: poolName: ${{ BuildPlatform.poolName }} + skipAndroidSdks: true + skipAndroidImages: true + installDefaultAndroidApi: true - task: DownloadBuildArtifacts@0 displayName: 'Download Packages' @@ -272,7 +281,7 @@ stages: PRIVATE_BUILD: $(PrivateBuild) - pwsh: ./build.ps1 --target=dotnet-integration-build --verbosity=diagnostic displayName: Build Microsoft.Maui.IntegrationTests - - pwsh: ./build.ps1 --target=dotnet-integration-test --filter="FullyQualifiedName=Microsoft.Maui.IntegrationTests.SampleTests" --resultsfilename="integration-samples" --verbosity=diagnostic + - pwsh: ./build.ps1 --target=dotnet-integration-test --filter="Category=Samples" --resultsfilename="integration-samples" --verbosity=diagnostic displayName: Run ${{ BuildPlatform.name }} sample build tests - task: PublishTestResults@2 displayName: Publish the ${{ BuildPlatform.name }} sample build tests @@ -281,6 +290,11 @@ stages: testRunner: VSTest testResultsFiles: '$(build.artifactstagingdirectory)/**/*.trx' testRunTitle: ${{ BuildPlatform.name }} sample build tests + - task: PublishBuildArtifacts@1 + condition: always() + displayName: publish artifacts + inputs: + ArtifactName: build_net_${{ BuildPlatform.name }}_samples - stage: templates_net displayName: Test Templates @@ -289,7 +303,7 @@ stages: - template: common/maui-templates.yml parameters: RunPlatforms: ${{ parameters.RunTemplatePlatforms }} - BuildPlatforms: ${{ parameters.BuilTemplatePlatforms }} + BuildPlatforms: ${{ parameters.BuildTemplatePlatforms }} - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: - template: common/localization-handoff.yml # Process outgoing strings [Localization Handoff] diff --git a/eng/pipelines/maui-release-internal.yml b/eng/pipelines/maui-release-internal.yml index 0c4dd4e3883b..246a45c62ecb 100644 --- a/eng/pipelines/maui-release-internal.yml +++ b/eng/pipelines/maui-release-internal.yml @@ -2,6 +2,7 @@ trigger: branches: include: - main + - net9.0 - release/* tags: include: @@ -30,11 +31,11 @@ schedules: variables: - template: /eng/pipelines/common/variables.yml@self + - template: /eng/common/templates-official/variables/pool-providers.yml@self + - group: DotNetBuilds storage account read tokens - group: AzureDevOps-Artifact-Feeds-Pats - - name: _InternalRuntimeDownloadArgs - value: /p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal - /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) + # needed for darc (dependency flow) publishing - name: _BuildConfig value: Release @@ -44,18 +45,38 @@ variables: value: $(Build.Arcade.ArtifactsPath)log/$(_BuildConfig)/ - name: Build.Arcade.TestResultsPath value: $(Build.Arcade.ArtifactsPath)TestResults/$(_BuildConfig)/ - - name: _PublishArgs - value: >- - /p:DotNetPublishUsingPipelines=true - - name: _OfficialBuildIdArgs - value: /p:OfficialBuildId=$(BUILD.BUILDNUMBER) - # needed for signing - - name: _SignType - value: real - - name: _SignArgs - value: /p:DotNetSignType=$(_SignType) /p:TeamName=$(_TeamName) /p:Sign=$(_Sign) - - name: _Sign - value: true + + # Produce test-signed build for PR and Public builds + - ${{ if or(eq(variables['_RunAsPublic'], 'true'), eq(variables['Build.Reason'], 'PullRequest')) }}: + # needed for darc (dependency flow) publishing + - name: _PublishArgs + value: '' + - name: _OfficialBuildIdArgs + value: '' + # needed for signing + - name: _SignType + value: test + - name: _SignArgs + value: '' + - name: _Sign + value: false + + # Set up non-PR build from internal project + - ${{ if and(ne(variables['_RunAsPublic'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) }}: + # needed for darc (dependency flow) publishing + - name: _PublishArgs + value: >- + /p:DotNetPublishUsingPipelines=true + # - name: _OfficialBuildIdArgs + # value: /p:OfficialBuildId=$(BUILD.BUILDNUMBER) + # needed for signing + - name: _SignType + value: real + - name: _SignArgs + value: /p:DotNetSignType=$(_SignType) /p:TeamName=$(TeamName) /p:Sign=$(_Sign) /p:DotNetPublishUsingPipelines=true + - name: _Sign + value: true + parameters: - name: pushMauiPackagesToMaestro @@ -116,115 +137,98 @@ extends: suppression: suppressionFile: $(Build.SourcesDirectory)\eng\automation\guardian\source.gdnsuppress stages: - - stage: pack_net + - stage: Pack displayName: Pack .NET MAUI dependsOn: [] jobs: - template: /eng/common/templates-official/jobs/jobs.yml@self parameters: + enableMicrobuild: true helixRepo: dotnet/maui pool: ${{ parameters.VM_IMAGE_HOST }} enablePublishUsingPipelines: true enablePublishBuildAssets: true enableTelemetry: true + enableSourceBuild: false enableSourceIndex: false - # Publish build logs + publishAssetsImmediately: true + # Publish build logs enablePublishBuildArtifacts: true # Publish test logs - enablePublishTestResults: false + enablePublishTestResults: true workspace: clean: all jobs: - job: pack_net_${{ parameters.PackPlatform.name }} displayName: ${{ parameters.PackPlatform.name }} + timeoutInMinutes: 240 - templateContext: - outputs: - - output: pipelineArtifact - displayName: 'Publish the ${{ parameters.PackPlatform.artifact }} artifacts' - artifactName: ${{ parameters.PackPlatform.artifact }} - targetPath: '${{ parameters.PackPlatform.artifactsPath }}/nuget' + # templateContext: + # outputs: + # - output: pipelineArtifact + # displayName: 'Publish the ${{ parameters.PackPlatform.artifact }} artifacts' + # artifactName: ${{ parameters.PackPlatform.artifact }} + # targetPath: '${{ parameters.PackPlatform.artifactsPath }}/nuget' - - output: pipelineArtifact - displayName: 'Publish the ${{ parameters.PackPlatform.binariesArtifact }} artifacts' - artifactName: ${{ parameters.PackPlatform.binariesArtifact }} - targetPath: '$(System.DefaultWorkingDirectory)/artifacts/binaries' - - - output: pipelineArtifact - displayName: 'Publish the ${{ parameters.PackPlatform.docsArtifact }} artifacts' - artifactName: ${{ parameters.PackPlatform.docsArtifact }} - targetPath: '$(System.DefaultWorkingDirectory)/artifacts/docs-packs' - - - output: pipelineArtifact - displayName: 'Publish the ${{ parameters.PackPlatform.metadataArtifact }} artifacts' - artifactName: ${{ parameters.PackPlatform.metadataArtifact }} - targetPath: '${{ parameters.PackPlatform.artifactsPath }}/metadata' - - - output: pipelineArtifact - displayName: 'Publish the ${{ parameters.PackPlatform.logsArtifact }} artifacts' - artifactName: ${{ parameters.PackPlatform.logsArtifact }} - targetPath: '${{ parameters.PackPlatform.artifactsPath }}/logs' + # - output: pipelineArtifact + # displayName: 'Publish the ${{ parameters.PackPlatform.binariesArtifact }} artifacts' + # artifactName: ${{ parameters.PackPlatform.binariesArtifact }} + # targetPath: '$(System.DefaultWorkingDirectory)/artifacts/binaries' + + # - output: pipelineArtifact + # displayName: 'Publish the ${{ parameters.PackPlatform.docsArtifact }} artifacts' + # artifactName: ${{ parameters.PackPlatform.docsArtifact }} + # targetPath: '$(System.DefaultWorkingDirectory)/artifacts/docs-packs' + + # - output: pipelineArtifact + # displayName: 'Publish the ${{ parameters.PackPlatform.metadataArtifact }} artifacts' + # artifactName: ${{ parameters.PackPlatform.metadataArtifact }} + # targetPath: '${{ parameters.PackPlatform.artifactsPath }}/metadata' + + # - output: pipelineArtifact + # displayName: 'Publish the ${{ parameters.PackPlatform.logsArtifact }} artifacts' + # artifactName: ${{ parameters.PackPlatform.logsArtifact }} + # targetPath: '${{ parameters.PackPlatform.artifactsPath }}/logs' variables: - name: _buildScript value: $(Build.SourcesDirectory)/build.cmd -ci - - name: _BuildConfig - value: Release - name: _BuildOfficalId value: $[ format('{0}.{1}', format('{0:yyyyMMdd}', pipeline.startTime), counter(format('{0:yyyyMMdd}', pipeline.startTime), 1) )] - + - name: TreatWarningsAsErrors + value: false + - name: _OfficialBuildIdArgs + value: /p:OfficialBuildId=$(_BuildOfficalId) /p:_SkipUpdateBuildNumber=true + preSteps: - checkout: self fetchDepth: 1 clean: true steps: - - template: /eng/pipelines/common/pack.yml@self + - template: /eng/pipelines/common/build-test-pack.yml@self parameters: - publishArtifacts: false - platform: ${{ parameters.PackPlatform.name }} - provisionatorChannel: ${{ parameters.provisionatorChannel }} - artifact: ${{ parameters.PackPlatform.artifact }} - artifactBinaries: ${{ parameters.PackPlatform.binariesArtifact }} - artifactsPath: ${{ parameters.PackPlatform.artifactsPath }} - buildConfiguration: $(_BuildConfig) dotnetScript: $(Build.SourcesDirectory)/dotnet.cmd buildScript: $(_buildScript) + buildConfig: $(_BuildConfig) repoArtifactsPath: $(Build.Arcade.ArtifactsPath) repoLogPath: $(Build.Arcade.LogsPath) repoTestResultsPath: $(Build.Arcade.TestResultsPath) - officialBuildId: $(_BuildOfficalId) - # prepareSteps: - # - template: /eng/pipelines/common/provision.yml@self - # parameters: - # checkoutDirectory: '$(System.DefaultWorkingDirectory)' - # provisionatorChannel: ${{ parameters.provisionatorChannel }} - # gitHubToken: $(github--pat--vs-mobiletools-engineering-service2) - # skipAndroidImages: true - - # - task: DotNetCoreCLI@2 - # displayName: Generate and publish BAR manifest - # inputs: - # projects: $(Build.SourcesDirectory)\src\Workload\Microsoft.Maui.Sdk\Microsoft.Maui.Sdk.csproj - # arguments: >- - # -t:PushManifestToBuildAssetRegistry - # -p:BuildAssetRegistryToken=$(MaestroAccessToken) - # -p:OutputPath=$(Build.StagingDirectory)\nuget\ - # -v:n -bl:$(Build.StagingDirectory)\binlogs\push-bar-manifest.binlog - # condition: and(succeeded(), eq('${{ parameters.pushMauiPackagesToMaestro }}', 'true')) - - # - powershell: | - # $versionEndpoint = 'https://maestro-prod.westus2.cloudapp.azure.com/api/assets/darc-version?api-version=2019-01-16' - # $darcVersion = $(Invoke-WebRequest -Uri $versionEndpoint -UseBasicParsing).Content - # $arcadeServicesSource = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - # & dotnet tool update microsoft.dotnet.darc --version "$darcVersion" --add-source "$arcadeServicesSource" --tool-path $(Agent.ToolsDirectory)\darc -v n - # & $(Agent.ToolsDirectory)\darc\darc add-build-to-channel --default-channels --id $(BARBuildId) --publishing-infra-version 3 --skip-assets-publishing --password $(MaestroAccessToken) --azdev-pat $(publishing-dnceng-devdiv-code-r-build-re) + isWindows: true # Publish and validation steps. Only run in official builds - template: /eng/common/templates-official/post-build/post-build.yml@self parameters: publishingInfraVersion: 3 + enableSymbolValidation: true + enableSigningValidation: true + # Disable for now as we test the new signing process + enableSourceLinkValidation: false validateDependsOn: - - pack_net - enableSourceLinkValidation: true \ No newline at end of file + - Pack + publishDependsOn: + - Validate + # This is to enable SDL runs part of Post-Build Validation Stage + SDLValidationParameters: + enable: false \ No newline at end of file diff --git a/eng/pipelines/maui-release.yml b/eng/pipelines/maui-release.yml index 962a9ce682f6..c25664848a36 100644 --- a/eng/pipelines/maui-release.yml +++ b/eng/pipelines/maui-release.yml @@ -2,6 +2,7 @@ trigger: branches: include: - main + - net9.0 - release/* tags: include: @@ -26,7 +27,6 @@ schedules: branches: include: - main - - net9.0 variables: - template: /eng/pipelines/common/variables.yml@self @@ -171,6 +171,8 @@ extends: provisionatorChannel: ${{ parameters.provisionatorChannel }} gitHubToken: $(github--pat--vs-mobiletools-engineering-service2) skipAndroidImages: true + skipAndroidSdks: true + installDefaultAndroidApi: true - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: # Sign only using the private server - template: /eng/pipelines/common/sign.yml@self @@ -199,6 +201,7 @@ extends: tsaUploadEnabled: true tsaConfigFile: '$(Build.SourcesDirectory)\eng\automation\guardian\tsaoptions-v2.json' scanArtifacts: ['${{ parameters.PackPlatform.binariesArtifact }}'] + softwareVersion: 9.0 - ${{ if eq(variables['Build.Reason'], 'Schedule') }}: - template: /eng/pipelines/common/push-nightly.yml@self diff --git a/eng/pipelines/ui-tests.yml b/eng/pipelines/ui-tests.yml index d6ea2bd6b565..d6d44bc4be41 100644 --- a/eng/pipelines/ui-tests.yml +++ b/eng/pipelines/ui-tests.yml @@ -130,11 +130,11 @@ stages: agentPoolAccessToken: $(AgentPoolAccessToken) ${{ if or(parameters.BuildEverything, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv'))) }}: androidApiLevels: [ 30 ] - iosVersions: [ '17.2' ] + iosVersions: [ '18.0' ] provisionatorChannel: ${{ parameters.provisionatorChannel }} ${{ if not(or(parameters.BuildEverything, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv')))) }}: androidApiLevels: [ 30 ] - iosVersions: [ '17.2' ] + iosVersions: [ '18.0' ] provisionatorChannel: ${{ parameters.provisionatorChannel }} ${{ if parameters.CompatibilityTests }}: runCompatibilityTests: true diff --git a/eng/provisioning/provisioning.csx b/eng/provisioning/provisioning.csx index 1e753b9fb5aa..565ecc5adfda 100644 --- a/eng/provisioning/provisioning.csx +++ b/eng/provisioning/provisioning.csx @@ -1,7 +1,7 @@ if (IsMac) { ForceJavaCleanup(); - MicrosoftOpenJdk ("11.0.13.8.1"); + MicrosoftOpenJdk ("17.0.12"); //this is needed for tools on macos like for nuget pack additional target and for classic xamarin projects Item("https://download.mono-project.com/archive/6.12.0/macos-10-universal/MonoFramework-MDK-6.12.0.206.macos10.xamarin.universal.pkg"); @@ -15,11 +15,15 @@ string ANDROID_API_SDKS = Environment.GetEnvironmentVariable ("ANDROID_API_SDKS" string SKIP_ANDROID_API_SDKS = Environment.GetEnvironmentVariable ("SKIP_ANDROID_API_SDKS"); string SKIP_ANDROID_API_IMAGES = Environment.GetEnvironmentVariable ("SKIP_ANDROID_API_IMAGES"); +string INSTALL_DEFAULT_ANDROID_API = Environment.GetEnvironmentVariable ("INSTALL_DEFAULT_ANDROID_API"); + Console.WriteLine($"LOGGING:"); Console.WriteLine($"ANDROID_API_SDKS: {ANDROID_API_SDKS}"); Console.WriteLine($"SKIP_ANDROID_API_SDKS: {SKIP_ANDROID_API_SDKS}"); Console.WriteLine($"SKIP_ANDROID_API_IMAGES: {SKIP_ANDROID_API_IMAGES}"); +Console.WriteLine($"INSTALL_DEFAULT_ANDROID_API: {INSTALL_DEFAULT_ANDROID_API}"); + if(String.IsNullOrWhiteSpace(ANDROID_API_SDKS) && String.IsNullOrWhiteSpace(SKIP_ANDROID_API_SDKS)) { AndroidSdk() @@ -34,7 +38,8 @@ if(String.IsNullOrWhiteSpace(ANDROID_API_SDKS) && String.IsNullOrWhiteSpace(SKIP .ApiLevel((AndroidApiLevel)31) .ApiLevel((AndroidApiLevel)32) .ApiLevel((AndroidApiLevel)33) - .ApiLevel((AndroidApiLevel)34); + .ApiLevel((AndroidApiLevel)34) + .ApiLevel((AndroidApiLevel)35); if(string.IsNullOrWhiteSpace(SKIP_ANDROID_API_IMAGES)) { @@ -70,9 +75,15 @@ if(String.IsNullOrWhiteSpace(ANDROID_API_SDKS) && String.IsNullOrWhiteSpace(SKIP } } - AndroidSdk().SdkManagerPackage ("build-tools;33.0.0"); + AndroidSdk().SdkManagerPackage ("build-tools;35.0.0"); } +if(!string.IsNullOrEmpty(INSTALL_DEFAULT_ANDROID_API)) +{ + AndroidSdk() + .ApiLevel((AndroidApiLevel)35) + .SdkManagerPackage ("build-tools;35.0.0");; +} else if(!String.IsNullOrWhiteSpace(ANDROID_API_SDKS)) { diff --git a/global.json b/global.json index 0efe559da047..d34c468d1c5c 100644 --- a/global.json +++ b/global.json @@ -1,13 +1,13 @@ { "tools": { - "dotnet": "9.0.100-rc.1.24452.12" + "dotnet": "9.0.100-rtm.24509.30" }, "msbuild-sdks": { "MSBuild.Sdk.Extras": "3.0.44", "Microsoft.Build.NoTargets": "3.7.0", - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24310.5" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24509.3" }, "sdk": { - "allowPrerelease": false + "allowPrerelease": true } } diff --git a/loc/cs/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/cs/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index bdebe13a998c..6a114998aa44 100644 --- a/loc/cs/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/cs/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/cs/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/cs/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..1cd08b96a732 --- /dev/null +++ b/loc/cs/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/cs/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/cs/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index 40cd7f5cdfcf..52919557f7dd 100644 --- a/loc/cs/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/cs/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/cs/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/cs/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index d62e1a505960..41b6001d9711 100644 --- a/loc/cs/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/cs/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/cs/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/cs/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index b6d4b054371e..647557da0809 100644 --- a/loc/cs/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/cs/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/cs/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/cs/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index 23f8084b6d9b..e914f0a3d39a 100644 --- a/loc/cs/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/cs/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/cs/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/cs/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index 485babe793ef..63cfed2949ca 100644 --- a/loc/cs/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/cs/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/cs/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/cs/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index 4f9c2ef2e9e0..284f7350c8c3 100644 --- a/loc/cs/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/cs/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/de/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/de/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index 07eea9a3b04f..4787624f9cd8 100644 --- a/loc/de/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/de/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/de/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/de/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..19bf555da0af --- /dev/null +++ b/loc/de/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/de/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/de/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index 5200b2f0f369..252ed6beaf91 100644 --- a/loc/de/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/de/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/de/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/de/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index 0aa0223dfdf6..d548188adec8 100644 --- a/loc/de/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/de/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/de/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/de/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index 9be2a38c2299..49fefad5c302 100644 --- a/loc/de/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/de/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/de/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/de/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index 6aceca0438fd..79e83f024cb3 100644 --- a/loc/de/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/de/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/de/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/de/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index fe3e9a63c188..c23b879bc81e 100644 --- a/loc/de/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/de/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/de/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/de/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index 5dce31ee71af..15a0adff77bb 100644 --- a/loc/de/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/de/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/es/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/es/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index 135ce54205f4..8e73ce83c34c 100644 --- a/loc/es/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/es/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/es/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/es/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..c135e88c9053 --- /dev/null +++ b/loc/es/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/es/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/es/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index 764caada0c10..705baad630f6 100644 --- a/loc/es/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/es/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/es/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/es/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index 038de6667f66..3962504cd2d4 100644 --- a/loc/es/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/es/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/es/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/es/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index bbb5192bc452..b4f5b0f19e11 100644 --- a/loc/es/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/es/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/es/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/es/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index e127029487ee..c7a6ce1cacb3 100644 --- a/loc/es/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/es/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/es/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/es/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index ae519da60cee..fd271d55e732 100644 --- a/loc/es/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/es/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/es/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/es/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index dc4d705a21bd..bcfd468122ad 100644 --- a/loc/es/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/es/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/fr/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/fr/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index 31c104308722..eff229f027e2 100644 --- a/loc/fr/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/fr/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/fr/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/fr/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..0fdb710c89f1 --- /dev/null +++ b/loc/fr/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/fr/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/fr/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index 110f09be1048..60d3c8022fd0 100644 --- a/loc/fr/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/fr/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/fr/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/fr/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index dcbc49f9c9ec..d061d7c14e6c 100644 --- a/loc/fr/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/fr/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/fr/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/fr/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index 65799104c4c1..222690913be4 100644 --- a/loc/fr/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/fr/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/fr/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/fr/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index 6b66d110aee4..623f306c07f9 100644 --- a/loc/fr/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/fr/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/fr/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/fr/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index 0a0ffd9328a3..865c351301bf 100644 --- a/loc/fr/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/fr/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/fr/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/fr/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index 70e012b7e204..d38fdcdd76fa 100644 --- a/loc/fr/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/fr/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/it/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/it/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index 7d72c6e44055..947e21de8d3f 100644 --- a/loc/it/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/it/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/it/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/it/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..59c0f4b8e879 --- /dev/null +++ b/loc/it/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/it/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/it/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index d82b060bb47e..a128ca1e9c82 100644 --- a/loc/it/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/it/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/it/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/it/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index 5cce1c0fde9a..42a07611305a 100644 --- a/loc/it/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/it/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/it/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/it/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index d9352d930cc3..b74297518109 100644 --- a/loc/it/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/it/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/it/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/it/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index 34a1958cdfd7..c2726aa87482 100644 --- a/loc/it/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/it/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/it/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/it/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index ec2c9a7b6062..62211c454683 100644 --- a/loc/it/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/it/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/it/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/it/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index 23a5abee2211..96765feb7107 100644 --- a/loc/it/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/it/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ja/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/ja/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index c1640efeb062..770f5d074bb3 100644 --- a/loc/ja/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/ja/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ja/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/ja/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..2d0c2fd3bab4 --- /dev/null +++ b/loc/ja/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/ja/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/ja/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index b65f1948b812..bac7c9ba1ef1 100644 --- a/loc/ja/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/ja/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ja/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/ja/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index fbf9ea4950bd..722a8c60bd06 100644 --- a/loc/ja/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/ja/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ja/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/ja/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index bc3676551184..14ba90da4f0d 100644 --- a/loc/ja/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/ja/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ja/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/ja/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index a5c7feccc40e..45834fc2e375 100644 --- a/loc/ja/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/ja/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ja/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/ja/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index fca976483332..a6268920de11 100644 --- a/loc/ja/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/ja/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ja/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/ja/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index 48898616cdb0..2f4d47f4df23 100644 --- a/loc/ja/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/ja/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ko/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/ko/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index 4f54a09f93d0..e5d394953b40 100644 --- a/loc/ko/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/ko/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ko/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/ko/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..560c40fcf479 --- /dev/null +++ b/loc/ko/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/ko/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/ko/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index 8c411dbb172f..4335403e253b 100644 --- a/loc/ko/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/ko/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ko/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/ko/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index efba932b4303..5f902a15ee09 100644 --- a/loc/ko/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/ko/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ko/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/ko/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index 7c7a35823ca8..5943236f24b2 100644 --- a/loc/ko/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/ko/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ko/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/ko/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index afb4963b6ccc..c84020523a9c 100644 --- a/loc/ko/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/ko/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ko/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/ko/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index 1a7a6c107675..004bb236b257 100644 --- a/loc/ko/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/ko/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ko/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/ko/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index 7d231b46ad21..46dd790f0734 100644 --- a/loc/ko/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/ko/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pl/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/pl/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index 18afd8e3d256..a9f23a58d559 100644 --- a/loc/pl/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/pl/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pl/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/pl/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..57e4c0b6e874 --- /dev/null +++ b/loc/pl/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/pl/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/pl/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index d675020bbac0..2f74fd8ff85e 100644 --- a/loc/pl/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/pl/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pl/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/pl/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index 327a1b2ca3e9..1e8cea1699aa 100644 --- a/loc/pl/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/pl/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pl/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/pl/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index 4436126cfe78..12a0ec119096 100644 --- a/loc/pl/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/pl/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pl/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/pl/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index ede86bb1aa56..e7ea2425de49 100644 --- a/loc/pl/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/pl/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pl/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/pl/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index 424b525ab4e6..d9ed37741d52 100644 --- a/loc/pl/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/pl/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pl/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/pl/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index eec8e6be5426..b80ac3d150ac 100644 --- a/loc/pl/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/pl/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pt-BR/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/pt-BR/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index 32fb63bd50dd..51c9c3af62fc 100644 --- a/loc/pt-BR/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/pt-BR/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pt-BR/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/pt-BR/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..36cbe32fd8b8 --- /dev/null +++ b/loc/pt-BR/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/pt-BR/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/pt-BR/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index 1ec51eef7064..a32b18fac49e 100644 --- a/loc/pt-BR/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/pt-BR/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pt-BR/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/pt-BR/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index ce9dfb988e5e..5743d86778b3 100644 --- a/loc/pt-BR/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/pt-BR/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pt-BR/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/pt-BR/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index a28e9a35aa97..19784cf53ced 100644 --- a/loc/pt-BR/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/pt-BR/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pt-BR/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/pt-BR/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index b2ca63417ccf..df254f39564b 100644 --- a/loc/pt-BR/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/pt-BR/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pt-BR/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/pt-BR/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index d236b4dfde0f..dd42e797c2c2 100644 --- a/loc/pt-BR/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/pt-BR/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/pt-BR/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/pt-BR/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index b6bbfea39457..a754c54dc818 100644 --- a/loc/pt-BR/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/pt-BR/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ru/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/ru/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index 5bb8a14f7d64..b2dd6de69de7 100644 --- a/loc/ru/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/ru/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ru/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/ru/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..f5111c4dd1d9 --- /dev/null +++ b/loc/ru/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/ru/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/ru/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index fd7bad8481ff..815c5a2427f0 100644 --- a/loc/ru/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/ru/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ru/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/ru/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index ac15532d4be2..0c2b4564f8aa 100644 --- a/loc/ru/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/ru/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ru/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/ru/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index 266a1954a0f9..33ca41b977e1 100644 --- a/loc/ru/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/ru/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ru/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/ru/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index 010d6db6af34..e4da66d29b84 100644 --- a/loc/ru/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/ru/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ru/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/ru/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index ac63f835ea5a..c57ba5b20c83 100644 --- a/loc/ru/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/ru/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/ru/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/ru/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index 367e78213968..2dab8e53a81a 100644 --- a/loc/ru/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/ru/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/tr/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/tr/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index d9bc6f8f571b..7bd53d150d2a 100644 --- a/loc/tr/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/tr/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/tr/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/tr/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..a98c54738ebb --- /dev/null +++ b/loc/tr/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/tr/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/tr/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index 8f11d9d4f358..741c02a6d1c2 100644 --- a/loc/tr/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/tr/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/tr/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/tr/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index ae67d7f7b6ea..4a0cc21752a4 100644 --- a/loc/tr/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/tr/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/tr/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/tr/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index d69ed7b0278e..7ce7ac08cc9e 100644 --- a/loc/tr/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/tr/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/tr/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/tr/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index a866a55bbf12..a526c255b556 100644 --- a/loc/tr/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/tr/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/tr/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/tr/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index ca2588dda0e0..b67e6a661bfb 100644 --- a/loc/tr/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/tr/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/tr/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/tr/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index 7c19b2c10ebc..14051446db74 100644 --- a/loc/tr/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/tr/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hans/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/zh-Hans/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index 653eb1fc9f94..f85976cc2b3d 100644 --- a/loc/zh-Hans/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/zh-Hans/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hans/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hans/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..76bc2ce76ee2 --- /dev/null +++ b/loc/zh-Hans/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/zh-Hans/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hans/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index 13b5e4a95521..189c780f0768 100644 --- a/loc/zh-Hans/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hans/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hans/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hans/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index 89996008e9ff..a340bbefbf31 100644 --- a/loc/zh-Hans/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hans/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hans/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hans/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index 60dd7679e3e9..021759e14756 100644 --- a/loc/zh-Hans/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hans/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hans/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hans/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index 90a70c856472..4eaabf6d2bba 100644 --- a/loc/zh-Hans/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hans/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hans/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hans/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index 0ba83fb61eb4..1cec5f796252 100644 --- a/loc/zh-Hans/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hans/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hans/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hans/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index 8537756b6ce0..36b6ad6ea62a 100644 --- a/loc/zh-Hans/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hans/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hant/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl b/loc/zh-Hant/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl index d89acaef8944..08fa1e0ebb32 100644 --- a/loc/zh-Hant/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl +++ b/loc/zh-Hant/src/Controls/src/Build.Tasks/ErrorMessages.resx.lcl @@ -1,10 +1,11 @@  - + + @@ -12,288 +13,375 @@ + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + true in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information.]]> + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hant/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hant/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl new file mode 100644 index 000000000000..887fd539200e --- /dev/null +++ b/loc/zh-Hant/src/Templates/src/templates/maui-blazor-solution/.template.config/localize/templatestrings.json.lcl @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/loc/zh-Hant/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hant/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl index eab593fc9b8c..ace76b3d1fcf 100644 --- a/loc/zh-Hant/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hant/src/Templates/src/templates/maui-blazor/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,45 +13,93 @@ + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hant/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hant/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl index e5f68cb3a2f5..d514a55c5fa2 100644 --- a/loc/zh-Hant/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hant/src/Templates/src/templates/maui-contentpage-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hant/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hant/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl index 7de66552db80..9068f5fe88b1 100644 --- a/loc/zh-Hant/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hant/src/Templates/src/templates/maui-contentpage-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hant/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hant/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl index 7743f8b99bad..53a5ff662536 100644 --- a/loc/zh-Hant/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hant/src/Templates/src/templates/maui-contentview-csharp/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hant/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hant/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl index 691c70ef4199..c6df3dfcea7b 100644 --- a/loc/zh-Hant/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hant/src/Templates/src/templates/maui-contentview-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/loc/zh-Hant/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl b/loc/zh-Hant/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl index b915e679c454..422c76195516 100644 --- a/loc/zh-Hant/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl +++ b/loc/zh-Hant/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/localize/templatestrings.json.lcl @@ -1,10 +1,11 @@  - + + @@ -12,27 +13,48 @@ + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/maui.code-workspace b/maui.code-workspace index 876a1499c09d..bccea6924a3c 100644 --- a/maui.code-workspace +++ b/maui.code-workspace @@ -4,5 +4,9 @@ "path": "." } ], - "settings": {} + "settings": { + "files.associations": { + "*.yaml": "home-assistant" + } + } } \ No newline at end of file diff --git a/src/BlazorWebView/samples/BlazorWinFormsApp/Form1.cs b/src/BlazorWebView/samples/BlazorWinFormsApp/Form1.cs index 3f41c849e7d0..ccb8ef4bd0c2 100644 --- a/src/BlazorWebView/samples/BlazorWinFormsApp/Form1.cs +++ b/src/BlazorWebView/samples/BlazorWinFormsApp/Form1.cs @@ -60,10 +60,10 @@ public Form1() private void button1_Click(object sender, EventArgs e) { - MessageBox.Show( - owner: this, - text: $"Current counter value is: {_appState.Counter}", - caption: "Counter"); + //MessageBox.Show( + // owner: this, + // text: $"Current counter value is: {_appState.Counter}", + // caption: "Counter"); } private void _webViewActionButton_Click(object sender, EventArgs e) @@ -100,7 +100,7 @@ private async void _useServicesButton_Click(object sender, EventArgs e) if (!called) { - MessageBox.Show(this, "Couldn't call TryDispatchAsync!"); + //s MessageBox.Show(this, "Couldn't call TryDispatchAsync!"); } } } diff --git a/src/BlazorWebView/samples/MauiRazorClassLibrarySample/MauiRazorClassLibrarySample.csproj b/src/BlazorWebView/samples/MauiRazorClassLibrarySample/MauiRazorClassLibrarySample.csproj index 24648effda0e..4f6d21573020 100644 --- a/src/BlazorWebView/samples/MauiRazorClassLibrarySample/MauiRazorClassLibrarySample.csproj +++ b/src/BlazorWebView/samples/MauiRazorClassLibrarySample/MauiRazorClassLibrarySample.csproj @@ -1,7 +1,8 @@ - $(_MauiDotNetTfm) + $(_MauiDotNetTfm) + $(TargetFrameworks);$(_MauiPreviousDotNetTfm) false diff --git a/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj b/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj index 060a2c43cb4e..5a530b48d967 100644 --- a/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj +++ b/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj @@ -2,11 +2,18 @@ $(_MauiDotNetTfm);$(MauiPlatforms) + $(TargetFrameworks);$(_MauiPreviousDotNetTfm);$(MauiPreviousPlatforms) enable $(DefineConstants);WEBVIEW2_MAUI true + + true + true + true + + true diff --git a/src/BlazorWebView/src/Maui/iOS/IOSWebViewManager.cs b/src/BlazorWebView/src/Maui/iOS/IOSWebViewManager.cs index 8576dff08f0b..527e58c2d714 100644 --- a/src/BlazorWebView/src/Maui/iOS/IOSWebViewManager.cs +++ b/src/BlazorWebView/src/Maui/iOS/IOSWebViewManager.cs @@ -40,8 +40,8 @@ internal class IOSWebViewManager : WebViewManager public IOSWebViewManager(BlazorWebViewHandler blazorMauiWebViewHandler, WKWebView webview, IServiceProvider provider, Dispatcher dispatcher, IFileProvider fileProvider, JSComponentConfigurationStore jsComponents, string contentRootRelativeToAppRoot, string hostPageRelativePath, ILogger logger) : base(provider, dispatcher, BlazorWebViewHandler.AppOriginUri, fileProvider, jsComponents, hostPageRelativePath) { - ArgumentNullException.ThrowIfNull(nameof(blazorMauiWebViewHandler)); - ArgumentNullException.ThrowIfNull(nameof(webview)); + ArgumentNullException.ThrowIfNull(blazorMauiWebViewHandler); + ArgumentNullException.ThrowIfNull(webview); if (provider.GetService() is null) { diff --git a/src/BlazorWebView/src/WindowsForms/BlazorWebView.cs b/src/BlazorWebView/src/WindowsForms/BlazorWebView.cs index 5a54464ce022..061e96cd3857 100644 --- a/src/BlazorWebView/src/WindowsForms/BlazorWebView.cs +++ b/src/BlazorWebView/src/WindowsForms/BlazorWebView.cs @@ -71,6 +71,7 @@ protected override void OnCreateControl() /// This property must be set to a valid value for the Razor components to start. /// [Category("Behavior")] + [DefaultValue(null)] [Description(@"Path to the host page within the application's static files. Example: wwwroot\index.html.")] public string? HostPage { @@ -86,6 +87,7 @@ public string? HostPage /// Path for initial Blazor navigation when the Blazor component is finished loading. /// [Category("Behavior")] + [DefaultValue("/")] [Description(@"Path for initial Blazor navigation when the Blazor component is finished loading.")] public string StartPath { get; set; } = "/"; @@ -170,7 +172,9 @@ private void StartWebViewCoreIfPossible() // We assume the host page is always in the root of the content directory, because it's // unclear there's any other use case. We can add more options later if so. string appRootDir; +#pragma warning disable IL3000 // 'System.Reflection.Assembly.Location.get' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'. var entryAssemblyLocation = Assembly.GetEntryAssembly()?.Location; +#pragma warning restore IL3000 if (!string.IsNullOrEmpty(entryAssemblyLocation)) { appRootDir = Path.GetDirectoryName(entryAssemblyLocation)!; diff --git a/src/BlazorWebView/src/WindowsForms/Microsoft.AspNetCore.Components.WebView.WindowsForms.csproj b/src/BlazorWebView/src/WindowsForms/Microsoft.AspNetCore.Components.WebView.WindowsForms.csproj index 0e8d16a7f252..3877c5eaa307 100644 --- a/src/BlazorWebView/src/WindowsForms/Microsoft.AspNetCore.Components.WebView.WindowsForms.csproj +++ b/src/BlazorWebView/src/WindowsForms/Microsoft.AspNetCore.Components.WebView.WindowsForms.csproj @@ -12,6 +12,12 @@ true + + true + true + true + + true diff --git a/src/BlazorWebView/src/Wpf/BlazorWebView.cs b/src/BlazorWebView/src/Wpf/BlazorWebView.cs index af673607a2de..bebcc9ce6ff5 100644 --- a/src/BlazorWebView/src/Wpf/BlazorWebView.cs +++ b/src/BlazorWebView/src/Wpf/BlazorWebView.cs @@ -255,7 +255,9 @@ private void StartWebViewCoreIfPossible() // We assume the host page is always in the root of the content directory, because it's // unclear there's any other use case. We can add more options later if so. string appRootDir; +#pragma warning disable IL3000 // 'System.Reflection.Assembly.Location.get' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'. var entryAssemblyLocation = Assembly.GetEntryAssembly()?.Location; +#pragma warning restore IL3000 if (!string.IsNullOrEmpty(entryAssemblyLocation)) { appRootDir = Path.GetDirectoryName(entryAssemblyLocation)!; diff --git a/src/BlazorWebView/src/Wpf/Microsoft.AspNetCore.Components.WebView.Wpf.csproj b/src/BlazorWebView/src/Wpf/Microsoft.AspNetCore.Components.WebView.Wpf.csproj index 15efc75f0653..85901e18a68f 100644 --- a/src/BlazorWebView/src/Wpf/Microsoft.AspNetCore.Components.WebView.Wpf.csproj +++ b/src/BlazorWebView/src/Wpf/Microsoft.AspNetCore.Components.WebView.Wpf.csproj @@ -12,6 +12,12 @@ true + + true + true + true + + true diff --git a/src/BlazorWebView/tests/MauiDeviceTests/MauiAppNewWindowStub.Windows.cs b/src/BlazorWebView/tests/MauiDeviceTests/MauiAppNewWindowStub.Windows.cs index f0fb73bf4516..34ed68addcd1 100644 --- a/src/BlazorWebView/tests/MauiDeviceTests/MauiAppNewWindowStub.Windows.cs +++ b/src/BlazorWebView/tests/MauiDeviceTests/MauiAppNewWindowStub.Windows.cs @@ -106,6 +106,11 @@ public void OpenWindow(IWindow window) throw new NotImplementedException(); } + public void ActivateWindow(IWindow window) + { + throw new NotImplementedException(); + } + public void ThemeChanged() { throw new NotImplementedException(); diff --git a/src/Compatibility/Android.AppLinks/src/Compatibility.Android.AppLinks.csproj b/src/Compatibility/Android.AppLinks/src/Compatibility.Android.AppLinks.csproj index 6291f18b2528..80335f991d0a 100644 --- a/src/Compatibility/Android.AppLinks/src/Compatibility.Android.AppLinks.csproj +++ b/src/Compatibility/Android.AppLinks/src/Compatibility.Android.AppLinks.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/src/Compatibility/ControlGallery/src/Android/Compatibility.ControlGallery.Android.csproj b/src/Compatibility/ControlGallery/src/Android/Compatibility.ControlGallery.Android.csproj index 90c11c47e82d..f4cd1dabf33c 100644 --- a/src/Compatibility/ControlGallery/src/Android/Compatibility.ControlGallery.Android.csproj +++ b/src/Compatibility/ControlGallery/src/Android/Compatibility.ControlGallery.Android.csproj @@ -9,7 +9,7 @@ false disable - IL2036;0618;0612 + IL2036;0618;0612;CS0672;CS0618 - 0612 + 0612;CS0672;CS0618 diff --git a/src/Compatibility/ControlGallery/src/WinUI/BrokenNativeControl.cs b/src/Compatibility/ControlGallery/src/WinUI/BrokenNativeControl.cs index 24c4c3d50b3b..2a14186edb76 100644 --- a/src/Compatibility/ControlGallery/src/WinUI/BrokenNativeControl.cs +++ b/src/Compatibility/ControlGallery/src/WinUI/BrokenNativeControl.cs @@ -27,7 +27,7 @@ public BrokenNativeControl() Background = new Microsoft.UI.Xaml.Media.LinearGradientBrush( - new Microsoft.UI.Xaml.Media.GradientStopCollection { new Microsoft.UI.Xaml.Media.GradientStop { Color = Colors.Green, Offset = 0.5 }, new Microsoft.UI.Xaml.Media.GradientStop { Color = Colors.Blue, Offset = 1 } }, 0); + new Microsoft.UI.Xaml.Media.GradientStopCollection { new Microsoft.UI.Xaml.Media.GradientStop { Color = global::Microsoft.UI.Colors.Green, Offset = 0.5 }, new Microsoft.UI.Xaml.Media.GradientStop { Color = global::Microsoft.UI.Colors.Blue, Offset = 1 } }, 0); } public static readonly DependencyProperty TextProperty = DependencyProperty.Register( @@ -66,4 +66,4 @@ public string Text return new global::Windows.Foundation.Size(size.Width, _textBlock.DesiredSize.Height); } } -} \ No newline at end of file +} diff --git a/src/Compatibility/ControlGallery/src/WinUI/Compatibility.ControlGallery.WinUI.csproj b/src/Compatibility/ControlGallery/src/WinUI/Compatibility.ControlGallery.WinUI.csproj index 75c82319dc84..242f283cf36e 100644 --- a/src/Compatibility/ControlGallery/src/WinUI/Compatibility.ControlGallery.WinUI.csproj +++ b/src/Compatibility/ControlGallery/src/WinUI/Compatibility.ControlGallery.WinUI.csproj @@ -4,19 +4,23 @@ WinExe - $(_MauiDotNetTfm)-windows10.0.19041.0 + $(_MauiDotNetTfm)-windows$(WindowsTargetFrameworkVersion) 10.0.17134.0 Microsoft.Maui.Controls.Compatibility.ControlGallery.WinUI app.manifest - 1701;1702;CS8305;8305;CA1416;0612 + 1701;1702;CS8305;8305;CA1416;0612;CS0672;CS0618 true false - + false true MSIX win10-x64 + + + + @@ -32,6 +36,10 @@ + + + + @@ -103,7 +111,7 @@ - + diff --git a/src/Compatibility/ControlGallery/src/iOS/AppDelegate.cs b/src/Compatibility/ControlGallery/src/iOS/AppDelegate.cs index 5a4d415ac351..f5de87919a98 100644 --- a/src/Compatibility/ControlGallery/src/iOS/AppDelegate.cs +++ b/src/Compatibility/ControlGallery/src/iOS/AppDelegate.cs @@ -162,7 +162,7 @@ public void StartPressed40911() button.TouchUpInside += (sender, e) => { - Maui.Controls.Application.Current.MainPage = new ContentPage { Content = new Label { Text = "40911 Success" } }; + Maui.Controls.Application.Current.Windows[0].Page = new ContentPage { Content = new Label { Text = "40911 Success" } }; loginViewController.DismissViewController(true, null); }; diff --git a/src/Compatibility/ControlGallery/src/iOS/Compatibility.ControlGallery.iOS.csproj b/src/Compatibility/ControlGallery/src/iOS/Compatibility.ControlGallery.iOS.csproj index 802f11b97c5a..0e61c3c61132 100644 --- a/src/Compatibility/ControlGallery/src/iOS/Compatibility.ControlGallery.iOS.csproj +++ b/src/Compatibility/ControlGallery/src/iOS/Compatibility.ControlGallery.iOS.csproj @@ -9,9 +9,9 @@ disable - 0612 - 11.0 - 11.0 + 0612;CS0672;CS0618 + 15.0 + 15.0 @@ -56,4 +56,3 @@ - diff --git a/src/Compatibility/ControlGallery/test/Android.UITests/Compatibility.ControlGallery.Android.UITests.csproj b/src/Compatibility/ControlGallery/test/Android.UITests/Compatibility.ControlGallery.Android.UITests.csproj index 12e89688c362..509b95814821 100644 --- a/src/Compatibility/ControlGallery/test/Android.UITests/Compatibility.ControlGallery.Android.UITests.csproj +++ b/src/Compatibility/ControlGallery/test/Android.UITests/Compatibility.ControlGallery.Android.UITests.csproj @@ -1,4 +1,4 @@ - + net472 @@ -7,7 +7,7 @@ false disable $(DefineConstants);__ANDROID__;UITEST;__SHELL__;ANDROID - 1701;1702;0618;0612;CA1307;CA1309 + 1701;1702;0618;0612;CA1307;CA1309;CS0672;CS0618 true @@ -17,6 +17,7 @@ + diff --git a/src/Compatibility/ControlGallery/test/WinUI.UITests/WinUI.UITests.csproj b/src/Compatibility/ControlGallery/test/WinUI.UITests/WinUI.UITests.csproj index d3f92c002a91..ec9e195bb301 100644 --- a/src/Compatibility/ControlGallery/test/WinUI.UITests/WinUI.UITests.csproj +++ b/src/Compatibility/ControlGallery/test/WinUI.UITests/WinUI.UITests.csproj @@ -7,7 +7,7 @@ false disable $(DefineConstants);WINDOWS;UITEST - 0114;0108;4014;0649;0169;0168;0219;0618;0612;CA1307;CA1309 + 0114;0108;4014;0649;0169;0168;0219;0618;0612;CA1307;CA1309;CS0672;CS0618 diff --git a/src/Compatibility/ControlGallery/test/iOS.UITests/Compatibility.ControlGallery.iOS.UITests.csproj b/src/Compatibility/ControlGallery/test/iOS.UITests/Compatibility.ControlGallery.iOS.UITests.csproj index b76a900ce507..8db27a53d51c 100644 --- a/src/Compatibility/ControlGallery/test/iOS.UITests/Compatibility.ControlGallery.iOS.UITests.csproj +++ b/src/Compatibility/ControlGallery/test/iOS.UITests/Compatibility.ControlGallery.iOS.UITests.csproj @@ -7,7 +7,7 @@ false disable $(DefineConstants);__IOS__;UITEST;__SHELL__;IOS;iOS - 1701;1702;0618;0612;CA1307;CA1309 + 1701;1702;0618;0612;CA1307;CA1309;CS0672;CS0618 true diff --git a/src/Compatibility/Core/src/Android/AppCompat/FormsAppCompatActivity.cs b/src/Compatibility/Core/src/Android/AppCompat/FormsAppCompatActivity.cs index 030490cae7a5..05317f6d23de 100644 --- a/src/Compatibility/Core/src/Android/AppCompat/FormsAppCompatActivity.cs +++ b/src/Compatibility/Core/src/Android/AppCompat/FormsAppCompatActivity.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using Android.App; @@ -101,10 +102,12 @@ public override bool OnOptionsItemSelected(IMenuItem item) public void SetStatusBarColor(AColor color) { +#pragma warning disable CA1422 // Obsolete in API 35 https://developer.android.com/reference/android/view/Window#setStatusBarColor(int) Window.SetStatusBarColor(color); +#pragma warning restore CA1422 // Obsolete in API 35 } - static void RegisterHandler(Type target, Type handler, Type filter) + static void RegisterHandler(Type target, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type handler, Type filter) { Profile.FrameBegin(); @@ -459,7 +462,7 @@ void OnStateChanged() } // This is currently being used by the previewer please do not change or remove this - void RegisterHandlerForDefaultRenderer(Type target, Type handler, Type filter) + void RegisterHandlerForDefaultRenderer(Type target, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type handler, Type filter) { RegisterHandler(target, handler, filter); } diff --git a/src/Compatibility/Core/src/Android/AppCompat/FormsFragmentPagerAdapter.cs b/src/Compatibility/Core/src/Android/AppCompat/FormsFragmentPagerAdapter.cs index 992b18c70a8c..3d94df67b881 100644 --- a/src/Compatibility/Core/src/Android/AppCompat/FormsFragmentPagerAdapter.cs +++ b/src/Compatibility/Core/src/Android/AppCompat/FormsFragmentPagerAdapter.cs @@ -12,7 +12,11 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android.AppCompat { [System.Obsolete] - internal class FormsFragmentPagerAdapter<[DynamicallyAccessedMembers(BindableProperty.DeclaringTypeMembers)] T> : FragmentPagerAdapter where T : Page + internal class FormsFragmentPagerAdapter<[DynamicallyAccessedMembers(BindableProperty.DeclaringTypeMembers + #if NET8_0 // IL2091 + | BindableProperty.ReturnTypeMembers + #endif + )] T> : FragmentPagerAdapter where T : Page { MultiPage _page; FragmentManager _fragmentManager; diff --git a/src/Compatibility/Core/src/Android/AppCompat/Platform.cs b/src/Compatibility/Core/src/Android/AppCompat/Platform.cs index 9705ebbf6a47..d738a737eee4 100644 --- a/src/Compatibility/Core/src/Android/AppCompat/Platform.cs +++ b/src/Compatibility/Core/src/Android/AppCompat/Platform.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Android.Content; @@ -16,6 +17,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { [Obsolete] + [TypeConverter(typeof(PlatformTypeConverter))] public class Platform : BindableObject, IPlatformLayout, INavigation { readonly Context _context; @@ -720,6 +722,20 @@ public static implicit operator ViewGroup(Platform canvas) #endregion + private sealed class PlatformTypeConverter : TypeConverter + { + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => destinationType == typeof(ViewGroup); + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + => value switch + { + Platform platformValue when destinationType == typeof(ViewGroup) => (ViewGroup)platformValue, + _ => throw new NotSupportedException(), + }; + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) => false; + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) => throw new NotSupportedException(); + } + #pragma warning disable CS0618 // Type or member is obsolete internal class DefaultRenderer : VisualElementRenderer, ILayoutChanges #pragma warning restore CS0618 // Type or member is obsolete diff --git a/src/Compatibility/Core/src/Android/ButtonLayoutManager.cs b/src/Compatibility/Core/src/Android/ButtonLayoutManager.cs index 48871171dcea..caeefa454d2a 100644 --- a/src/Compatibility/Core/src/Android/ButtonLayoutManager.cs +++ b/src/Compatibility/Core/src/Android/ButtonLayoutManager.cs @@ -154,12 +154,16 @@ public void OnLayout(bool changed, int left, int top, int right, int bottom) var measuredTextWidth = view.Paint.MeasureText(buttonText, 0, buttonText.Length()); var textWidth = Math.Min((int)measuredTextWidth, view.Layout.Width); +#pragma warning disable CS0618 // Obsolete var contentsWidth = ViewCompat.GetPaddingStart(view) + iconWidth + view.CompoundDrawablePadding + textWidth + ViewCompat.GetPaddingEnd(view); +#pragma warning restore CS0618 // Obsolete var newLeft = (view.MeasuredWidth - contentsWidth) / 2; if (_element.ContentLayout.Position == Button.ButtonContentLayout.ImagePosition.Right) newLeft = -newLeft; +#pragma warning disable CS0618 // Obsolete if (ViewCompat.GetLayoutDirection(view) == ViewCompat.LayoutDirectionRtl) +#pragma warning restore CS0618 // Obsolete newLeft = -newLeft; _drawableBounds.Set(newLeft, _drawableBounds.Top, newLeft + iconWidth, _drawableBounds.Bottom); diff --git a/src/Compatibility/Core/src/Android/Extensions/NativeBindingExtensions.cs b/src/Compatibility/Core/src/Android/Extensions/NativeBindingExtensions.cs index 1cce4eff3e42..54dca7b49c2f 100644 --- a/src/Compatibility/Core/src/Android/Extensions/NativeBindingExtensions.cs +++ b/src/Compatibility/Core/src/Android/Extensions/NativeBindingExtensions.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { public static class NativeBindingExtensions { + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public static void SetBinding(this global::Android.Views.View view, string propertyName, BindingBase binding, string updateSourceEventName = null) { PlatformBindingHelpers.SetBinding(view, propertyName, binding, updateSourceEventName); diff --git a/src/Compatibility/Core/src/Android/FastRenderers/ImageElementManager.cs b/src/Compatibility/Core/src/Android/FastRenderers/ImageElementManager.cs index fc77f7c38a40..15ae12b64739 100644 --- a/src/Compatibility/Core/src/Android/FastRenderers/ImageElementManager.cs +++ b/src/Compatibility/Core/src/Android/FastRenderers/ImageElementManager.cs @@ -25,7 +25,10 @@ public static void Init(IVisualElementRenderer renderer) static void OnLayoutChange(object sender, global::Android.Views.View.LayoutChangeEventArgs e) { if (sender is IVisualElementRenderer renderer && renderer.View is ImageView imageView) +#pragma warning disable CS0618 // Obsolete AViewCompat.SetClipBounds(imageView, imageView.GetScaleType() == AScaleType.CenterCrop ? new ARect(0, 0, e.Right - e.Left, e.Bottom - e.Top) : null); +#pragma warning restore CS0618 // Obsolete + } public static void Dispose(IVisualElementRenderer renderer) diff --git a/src/Compatibility/Core/src/Android/HandlerToRendererShim.cs b/src/Compatibility/Core/src/Android/HandlerToRendererShim.cs index ef0285104148..8914227dc165 100644 --- a/src/Compatibility/Core/src/Android/HandlerToRendererShim.cs +++ b/src/Compatibility/Core/src/Android/HandlerToRendererShim.cs @@ -82,10 +82,14 @@ public void SetLabelFor(int? id) { if (_defaultLabelFor == null) { +#pragma warning disable CS0618 // Obsolete _defaultLabelFor = ViewCompat.GetLabelFor(View); +#pragma warning restore CS0618 // Obsolete } +#pragma warning disable CS0618 // Obsolete ViewCompat.SetLabelFor(View, (int)(id ?? _defaultLabelFor)); +#pragma warning restore CS0618 // Obsolete } public void UpdateLayout() diff --git a/src/Compatibility/Core/src/Android/NativeBindingservice.cs b/src/Compatibility/Core/src/Android/NativeBindingservice.cs index 5b7b9fad8b10..5fa34009a928 100644 --- a/src/Compatibility/Core/src/Android/NativeBindingservice.cs +++ b/src/Compatibility/Core/src/Android/NativeBindingservice.cs @@ -9,7 +9,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { class NativeBindingService : INativeBindingService { - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = TrimmerConstants.NativeBindingService)] + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public bool TrySetBinding(object target, string propertyName, BindingBase binding) { var view = target as AView; diff --git a/src/Compatibility/Core/src/Android/Renderers/ListViewAdapter.cs b/src/Compatibility/Core/src/Android/Renderers/ListViewAdapter.cs index 738b7da01ee7..8336909f2134 100644 --- a/src/Compatibility/Core/src/Android/Renderers/ListViewAdapter.cs +++ b/src/Compatibility/Core/src/Android/Renderers/ListViewAdapter.cs @@ -736,7 +736,9 @@ Cell GetNewGroupHeaderCell(ITemplatedItemsList group) else { groupHeaderCell = new TextCell(); - groupHeaderCell.SetBinding(TextCell.TextProperty, nameof(group.Name)); + groupHeaderCell.SetBinding( + TextCell.TextProperty, + static (ITemplatedItemsList g) => g.Name); groupHeaderCell.BindingContext = group; } diff --git a/src/Compatibility/Core/src/Android/Shapes/ShapeRenderer.cs b/src/Compatibility/Core/src/Android/Shapes/ShapeRenderer.cs index 22e26a639359..5bff243e9df8 100644 --- a/src/Compatibility/Core/src/Android/Shapes/ShapeRenderer.cs +++ b/src/Compatibility/Core/src/Android/Shapes/ShapeRenderer.cs @@ -423,7 +423,9 @@ protected void UpdatePathShape() _drawable.Paint.StrokeWidth = 0.01f; _drawable.Paint.SetStyle(Paint.Style.Stroke); _drawable.Paint.GetFillPath(_path, fillPath); +#pragma warning disable CA1422 // Obsolete in API 35 https://developer.android.com/reference/android/graphics/Path#computeBounds(android.graphics.RectF,%20boolean) fillPath.ComputeBounds(_pathFillBounds, false); +#pragma warning restore CA1422 _drawable.Paint.StrokeWidth = _strokeWidth; } } @@ -480,7 +482,9 @@ void UpdatePathStrokeBounds() { _drawable.Paint.SetStyle(Paint.Style.Stroke); _drawable.Paint.GetFillPath(_path, strokePath); +#pragma warning disable CA1422 // Obsolete in API 35 https://developer.android.com/reference/android/graphics/Path#computeBounds(android.graphics.RectF,%20boolean) strokePath.ComputeBounds(_pathStrokeBounds, false); +#pragma warning restore CA1422 // Obsolete in API 35 } } else diff --git a/src/Compatibility/Core/src/Compatibility.csproj b/src/Compatibility/Core/src/Compatibility.csproj index bdec21c355e0..87c2bf3b13fb 100644 --- a/src/Compatibility/Core/src/Compatibility.csproj +++ b/src/Compatibility/Core/src/Compatibility.csproj @@ -1,6 +1,7 @@  netstandard2.1;netstandard2.0;$(_MauiDotNetTfm);$(MauiPlatforms) + $(TargetFrameworks);$(_MauiPreviousDotNetTfm);$(MauiPreviousPlatforms) Microsoft.Maui.Controls.Compatibility Microsoft.Maui.Controls.Compatibility disable @@ -8,15 +9,15 @@ iOS\ Windows\ Tizen\ - true + true true true - $(NoWarn);CS1591 + $(NoWarn);CS1591;CS0672;CS0618 $(DefineConstants);COMPATIBILITY - $(NoWarn);CA1416;CS8305 + $(NoWarn);CA1416;CS8305;IL2059 $(DefineConstants);WINDOWS @@ -49,7 +50,16 @@ Windows\BootstrapHelper.cs - + + $(InterceptorsPreviewNamespaces);Microsoft.Maui.Controls.Generated + + $(CompilerResponseFile);WorkaroundXamlPreCompilePreviewFeatures.rsp + + + diff --git a/src/Compatibility/Core/src/ExportRendererAttribute.cs b/src/Compatibility/Core/src/ExportRendererAttribute.cs index 212130be8af0..acb5f89d160d 100644 --- a/src/Compatibility/Core/src/ExportRendererAttribute.cs +++ b/src/Compatibility/Core/src/ExportRendererAttribute.cs @@ -1,15 +1,16 @@ using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls.Compatibility { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class ExportRendererAttribute : HandlerAttribute { - public ExportRendererAttribute(Type handler, Type target) : this(handler, target, null) + public ExportRendererAttribute(Type handler, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type target) : this(handler, target, null) { } - public ExportRendererAttribute(Type handler, Type target, Type[] supportedVisuals) : base(handler, target, supportedVisuals) + public ExportRendererAttribute(Type handler, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type target, Type[] supportedVisuals) : base(handler, target, supportedVisuals) { } } @@ -17,7 +18,7 @@ public ExportRendererAttribute(Type handler, Type target, Type[] supportedVisual [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class ExportCellAttribute : HandlerAttribute { - public ExportCellAttribute(Type handler, Type target) : base(handler, target) + public ExportCellAttribute(Type handler, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type target) : base(handler, target) { } } @@ -25,7 +26,7 @@ public ExportCellAttribute(Type handler, Type target) : base(handler, target) [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class ExportImageSourceHandlerAttribute : HandlerAttribute { - public ExportImageSourceHandlerAttribute(Type handler, Type target) : base(handler, target) + public ExportImageSourceHandlerAttribute(Type handler, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type target) : base(handler, target) { } } diff --git a/src/Compatibility/Core/src/MauiHandlersCollectionExtensions.cs b/src/Compatibility/Core/src/MauiHandlersCollectionExtensions.cs index df004cad2fc7..507321e6c571 100644 --- a/src/Compatibility/Core/src/MauiHandlersCollectionExtensions.cs +++ b/src/Compatibility/Core/src/MauiHandlersCollectionExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.Maui.Controls.Hosting; using Microsoft.Maui.Hosting; @@ -6,7 +7,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Hosting { public static class MauiHandlersCollectionExtensions { - public static IMauiHandlersCollection TryAddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection, Type controlType, Type rendererType) + public static IMauiHandlersCollection TryAddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection, Type controlType, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type rendererType) { Internals.Registrar.CheckIfRendererIsCompatibilityRenderer(rendererType); Hosting.MauiAppBuilderExtensions.CheckForCompatibility(); @@ -21,7 +22,7 @@ public static IMauiHandlersCollection TryAddCompatibilityRenderer(this IMauiHand return handlersCollection; } - public static IMauiHandlersCollection AddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection, Type controlType, Type rendererType) + public static IMauiHandlersCollection AddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection, Type controlType, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type rendererType) { Internals.Registrar.CheckIfRendererIsCompatibilityRenderer(rendererType); Hosting.MauiAppBuilderExtensions.CheckForCompatibility(); @@ -36,7 +37,7 @@ public static IMauiHandlersCollection AddCompatibilityRenderer(this IMauiHandler return handlersCollection; } - public static IMauiHandlersCollection AddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection) + public static IMauiHandlersCollection AddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection) where TMauiType : IView { Internals.Registrar.CheckIfRendererIsCompatibilityRenderer(typeof(TRenderer)); @@ -51,7 +52,7 @@ public static IMauiHandlersCollection AddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection) + public static IMauiHandlersCollection AddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection) where TControlType : IView { Internals.Registrar.CheckIfRendererIsCompatibilityRenderer(typeof(TRenderer)); diff --git a/src/Compatibility/Core/src/Properties/AssemblyInfo.cs b/src/Compatibility/Core/src/Properties/AssemblyInfo.cs index 8ee7328de170..34a0a0078b89 100644 --- a/src/Compatibility/Core/src/Properties/AssemblyInfo.cs +++ b/src/Compatibility/Core/src/Properties/AssemblyInfo.cs @@ -2,6 +2,7 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.StyleSheets; +#pragma warning disable CS0618 // Type or member is obsolete using CFlexLayout = Microsoft.Maui.Controls.Compatibility.FlexLayout; using CGrid = Microsoft.Maui.Controls.Compatibility.Grid; using CStackLayout = Microsoft.Maui.Controls.Compatibility.StackLayout; @@ -29,4 +30,5 @@ //xf specific [assembly: StyleProperty("-maui-spacing", typeof(CStackLayout), nameof(CStackLayout.SpacingProperty))] -[assembly: StyleProperty("-maui-orientation", typeof(CStackLayout), nameof(CStackLayout.OrientationProperty))] \ No newline at end of file +[assembly: StyleProperty("-maui-orientation", typeof(CStackLayout), nameof(CStackLayout.OrientationProperty))] +#pragma warning restore CS0618 // Type or member is obsolete \ No newline at end of file diff --git a/src/Compatibility/Core/src/Tizen/Extensions/NativeBindingExtensions.cs b/src/Compatibility/Core/src/Tizen/Extensions/NativeBindingExtensions.cs index 5cbb35f62b12..0286d6911cf6 100644 --- a/src/Compatibility/Core/src/Tizen/Extensions/NativeBindingExtensions.cs +++ b/src/Compatibility/Core/src/Tizen/Extensions/NativeBindingExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Microsoft.Maui.Controls.Internals; using NView = Tizen.NUI.BaseComponents.View; @@ -7,6 +8,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Tizen { public static class NativeBindingExtensions { + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public static void SetBinding(this NView view, string propertyName, BindingBase binding, string updateSourceEventName = null) { PlatformBindingHelpers.SetBinding(view, propertyName, binding, updateSourceEventName); diff --git a/src/Compatibility/Core/src/Tizen/NativeBindingService.cs b/src/Compatibility/Core/src/Tizen/NativeBindingService.cs index d575dbf30615..e377576f703e 100644 --- a/src/Compatibility/Core/src/Tizen/NativeBindingService.cs +++ b/src/Compatibility/Core/src/Tizen/NativeBindingService.cs @@ -7,7 +7,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Tizen { class NativeBindingService : INativeBindingService { - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = TrimmerConstants.NativeBindingService)] + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public bool TrySetBinding(object target, string propertyName, BindingBase binding) { Hosting.MauiAppBuilderExtensions.CheckForCompatibility(); diff --git a/src/Compatibility/Core/src/Tizen/Renderers/VisualElementRenderer.cs b/src/Compatibility/Core/src/Tizen/Renderers/VisualElementRenderer.cs index 21b7d6d6eb30..f590927fc7d0 100644 --- a/src/Compatibility/Core/src/Tizen/Renderers/VisualElementRenderer.cs +++ b/src/Compatibility/Core/src/Tizen/Renderers/VisualElementRenderer.cs @@ -260,7 +260,7 @@ protected virtual void Dispose(bool disposing) { // This is the reason why I call SendDisappearing() here. // When OnChildRemove is called first like how it is called in Navigation.PopToRootAsync(), - // you can not controll using SendDisappearing() on the lower class. + // you cannot control using SendDisappearing() on the lower class. (Element as IPageController)?.SendDisappearing(); if (Element != null) diff --git a/src/Compatibility/Core/src/Tizen/ResourcePath.cs b/src/Compatibility/Core/src/Tizen/ResourcePath.cs index 47671abfd080..b1fee46baf59 100644 --- a/src/Compatibility/Core/src/Tizen/ResourcePath.cs +++ b/src/Compatibility/Core/src/Tizen/ResourcePath.cs @@ -14,7 +14,7 @@ public static string GetPath(string res) return res; } - foreach (AppFW.ResourceManager.Category category in Enum.GetValues(typeof(AppFW.ResourceManager.Category))) + foreach (AppFW.ResourceManager.Category category in Enum.GetValues()) { var path = AppFW.ResourceManager.TryGetPath(category, res); diff --git a/src/Compatibility/Core/src/WPF/Microsoft.Windows.Shell/Standard/Verify.cs b/src/Compatibility/Core/src/WPF/Microsoft.Windows.Shell/Standard/Verify.cs index 18e64534505a..19a1440a40c1 100644 --- a/src/Compatibility/Core/src/WPF/Microsoft.Windows.Shell/Standard/Verify.cs +++ b/src/Compatibility/Core/src/WPF/Microsoft.Windows.Shell/Standard/Verify.cs @@ -55,7 +55,7 @@ public static void IsNeitherNullNorEmpty(string value, string name) Assert.IsNeitherNullNorEmpty(name); // Notice that ArgumentNullException and ArgumentException take the parameters in opposite order :P - const string errorMessage = "The parameter can not be either null or empty."; + const string errorMessage = "The parameter cannot be either null or empty."; if (null == value) { Assert.Fail(); @@ -82,7 +82,7 @@ public static void IsNeitherNullNorWhitespace(string value, string name) Assert.IsNeitherNullNorEmpty(name); // Notice that ArgumentNullException and ArgumentException take the parameters in opposite order :P - const string errorMessage = "The parameter can not be either null or empty or consist only of white space characters."; + const string errorMessage = "The parameter cannot be either null or empty or consist only of white space characters."; if (null == value) { Assert.Fail(); diff --git a/src/Compatibility/Core/src/Windows/FrameworkElementExtensions.cs b/src/Compatibility/Core/src/Windows/FrameworkElementExtensions.cs index 8a49258a0241..a3b41d1bf9d6 100644 --- a/src/Compatibility/Core/src/Windows/FrameworkElementExtensions.cs +++ b/src/Compatibility/Core/src/Windows/FrameworkElementExtensions.cs @@ -82,7 +82,9 @@ static DependencyProperty GetForegroundProperty(FrameworkElement element) DependencyProperty foregroundProperty; if (!ForegroundProperties.Value.TryGetValue(type, out foregroundProperty)) { - FieldInfo field = ReflectionExtensions.GetFields(type).FirstOrDefault(f => f.Name == "ForegroundProperty"); +#pragma warning disable IL2075 // The Compatibility assembly is not trimmable + FieldInfo field = type.GetField("ForegroundProperty", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); +#pragma warning restore IL2075 if (field == null) throw new ArgumentException("type is not a Foregroundable type"); diff --git a/src/Compatibility/Core/src/Windows/NativeBindingExtensions.cs b/src/Compatibility/Core/src/Windows/NativeBindingExtensions.cs index 00de36ce7264..938df2a83e75 100644 --- a/src/Compatibility/Core/src/Windows/NativeBindingExtensions.cs +++ b/src/Compatibility/Core/src/Windows/NativeBindingExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Microsoft.Maui.Controls.Internals; using Microsoft.UI.Xaml; using static System.String; @@ -9,6 +10,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { public static class NativeBindingExtensions { + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public static void SetBinding(this FrameworkElement view, string propertyName, BindingBase bindingBase, string updateSourceEventName = null) { var binding = bindingBase as Binding; diff --git a/src/Compatibility/Core/src/Windows/NativeBindingService.cs b/src/Compatibility/Core/src/Windows/NativeBindingService.cs index 794e91db2e33..53cf9aa35b27 100644 --- a/src/Compatibility/Core/src/Windows/NativeBindingService.cs +++ b/src/Compatibility/Core/src/Windows/NativeBindingService.cs @@ -9,7 +9,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP { public class NativeBindingService : INativeBindingService { - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = TrimmerConstants.NativeBindingService)] + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public bool TrySetBinding(object target, string propertyName, BindingBase binding) { var view = target as FrameworkElement; diff --git a/src/Compatibility/Core/src/Windows/NativeEventWrapper.cs b/src/Compatibility/Core/src/Windows/NativeEventWrapper.cs index 8c49cd00da43..82a157455077 100644 --- a/src/Compatibility/Core/src/Windows/NativeEventWrapper.cs +++ b/src/Compatibility/Core/src/Windows/NativeEventWrapper.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.InteropServices.WindowsRuntime; @@ -20,7 +21,10 @@ public NativeEventWrapper(object target, string targetProperty, string updateSou TargetProperty = targetProperty; try { + +#pragma warning disable IL2072 // Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations. var updateSourceEvent = target.GetType().GetRuntimeEvent(updateSourceEventName); +#pragma warning restore IL2072 // Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations. MethodInfo addMethod = updateSourceEvent.AddMethod; MethodInfo removeMethod = updateSourceEvent.RemoveMethod; ParameterInfo[] addParameters = addMethod.GetParameters(); @@ -34,7 +38,7 @@ public NativeEventWrapper(object target, string targetProperty, string updateSou } catch (Exception) { - Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning("Can not attach NativeEventWrapper."); + Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning("Cannot attach NativeEventWrapper."); } } diff --git a/src/Compatibility/Core/src/WorkaroundXamlPreCompilePreviewFeatures.rsp b/src/Compatibility/Core/src/WorkaroundXamlPreCompilePreviewFeatures.rsp new file mode 100644 index 000000000000..e60a129bbc68 --- /dev/null +++ b/src/Compatibility/Core/src/WorkaroundXamlPreCompilePreviewFeatures.rsp @@ -0,0 +1 @@ +/features:"InterceptorsPreviewNamespaces=Microsoft.Maui.Controls.Generated" \ No newline at end of file diff --git a/src/Compatibility/Core/src/iOS/NativeBindingService.cs b/src/Compatibility/Core/src/iOS/NativeBindingService.cs index 0fd914b78845..6fe5fb746c07 100644 --- a/src/Compatibility/Core/src/iOS/NativeBindingService.cs +++ b/src/Compatibility/Core/src/iOS/NativeBindingService.cs @@ -8,10 +8,9 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS { - [Preserve(AllMembers = true)] class NativeBindingService : INativeBindingService { - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = TrimmerConstants.NativeBindingService)] + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public bool TrySetBinding(object target, string propertyName, BindingBase binding) { Hosting.MauiAppBuilderExtensions.CheckForCompatibility(); diff --git a/src/Compatibility/Core/src/iOS/Renderers/SwipeViewRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/SwipeViewRenderer.cs index 78dcfabec40c..9ee778516ba9 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/SwipeViewRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/SwipeViewRenderer.cs @@ -706,7 +706,7 @@ async void UpdateSwipeItemIconImage(UIButton swipeButton, SwipeItem swipeItem) catch (Exception) { // UIImage ctor throws on file not found if MonoTouch.ObjCRuntime.Class.ThrowOnInitFailure is true; - Forms.MauiContext?.CreateLogger()?.LogWarning("Can not load SwipeItem Icon"); + Forms.MauiContext?.CreateLogger()?.LogWarning("Cannot load SwipeItem Icon"); } } } diff --git a/src/Compatibility/Core/tests/Compatibility.UnitTests/ApplicationStub.cs b/src/Compatibility/Core/tests/Compatibility.UnitTests/ApplicationStub.cs index ed89efcc164e..112bfec84381 100644 --- a/src/Compatibility/Core/tests/Compatibility.UnitTests/ApplicationStub.cs +++ b/src/Compatibility/Core/tests/Compatibility.UnitTests/ApplicationStub.cs @@ -32,6 +32,8 @@ public void CloseWindow(IWindow window) _windows.Remove(window); } + public void ActivateWindow(IWindow window) { } + public void ThemeChanged() { } } } \ No newline at end of file diff --git a/src/Compatibility/Core/tests/Compatibility.UnitTests/BaseTestFixture.cs b/src/Compatibility/Core/tests/Compatibility.UnitTests/BaseTestFixture.cs new file mode 100644 index 000000000000..6df23fa7410e --- /dev/null +++ b/src/Compatibility/Core/tests/Compatibility.UnitTests/BaseTestFixture.cs @@ -0,0 +1,66 @@ +using System; +using System.Globalization; +using System.Threading; +using Microsoft.Maui.ApplicationModel; +using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Devices; +using Microsoft.Maui.Dispatching; +using Microsoft.Maui.UnitTests; +using Xunit; + +// By default, xUnit will run test collections (the tests in each class) in parallel +// with other test collections. Unfortunately, a _ton_ of the Controls legacy tests +// interact with properties on static classes (e.g., Application.Current), and if we +// let them run in parallel they'll step on one another. So we tell xUnit to consider +// the whole assembly as a single collection for now, so all the tests run in sequence. +// (Hopefully in the future we can untangle some of the singletons and run these in parallel, +// because it'll be a lot faster.) +[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)] + +namespace Microsoft.Maui.Controls.Core.UnitTests +{ + public class BaseTestFixture : IDisposable + { + CultureInfo _defaultCulture; + CultureInfo _defaultUICulture; + + public BaseTestFixture() + { + Microsoft.Maui.Controls.Hosting.CompatibilityCheck.UseCompatibility(); + _defaultCulture = System.Threading.Thread.CurrentThread.CurrentCulture; + _defaultUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + DispatcherProvider.SetCurrent(new DispatcherProviderStub()); + DeviceDisplay.SetCurrent(null); + DeviceInfo.SetCurrent(null); + AppInfo.SetCurrent(null); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + bool _disposed; + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + AppInfo.SetCurrent(null); + DeviceDisplay.SetCurrent(null); + DeviceInfo.SetCurrent(null); + System.Threading.Thread.CurrentThread.CurrentCulture = _defaultCulture; + System.Threading.Thread.CurrentThread.CurrentUICulture = _defaultUICulture; + DispatcherProvider.SetCurrent(null); + } + + _disposed = true; + } + } +} diff --git a/src/Controls/tests/Core.UnitTests/FlexLayoutAlignContentTests.cs b/src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutAlignContentTests.cs similarity index 74% rename from src/Controls/tests/Core.UnitTests/FlexLayoutAlignContentTests.cs rename to src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutAlignContentTests.cs index 66aa292d46b4..556ae6265fbb 100644 --- a/src/Controls/tests/Core.UnitTests/FlexLayoutAlignContentTests.cs +++ b/src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutAlignContentTests.cs @@ -13,7 +13,7 @@ public class FlexLayoutAlignContentTests : BaseTestFixture [Fact] public void TestAlignContentFlexStart() { - MockPlatformSizeService.Current.GetPlatformSizeFunc = (visual, width, height) => new SizeRequest(new Size(50, 10)); + static SizeRequest GetPlatformSize(VisualElement v, double w, double h) => new(new Size(50, 10)); var layout = new FlexLayout { @@ -27,19 +27,19 @@ public void TestAlignContentFlexStart() Wrap = FlexWrap.Wrap, }; - var view0 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view0 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view1 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view2 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view3 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view4 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view4); layout.Layout(new Rect(0, 0, 130, 100)); @@ -55,7 +55,7 @@ public void TestAlignContentFlexStart() [Fact] public void TestAlignContentFlexStartWithoutHeightOnChildren() { - MockPlatformSizeService.Current.GetPlatformSizeFunc = (visual, width, height) => new SizeRequest(new Size(50, 10)); + static SizeRequest GetPlatformSize(VisualElement v, double w, double h) => new(new Size(50, 10)); var layout = new FlexLayout { @@ -67,19 +67,19 @@ public void TestAlignContentFlexStartWithoutHeightOnChildren() Direction = FlexDirection.Column, Wrap = FlexWrap.Wrap, }; - var view0 = new View { IsPlatformEnabled = true, WidthRequest = 50, }; + var view0 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50); layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view1 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true, WidthRequest = 50, }; + var view2 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50); layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view3 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view4 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view4); layout.Layout(new Rect(0, 0, 100, 100)); @@ -94,7 +94,7 @@ public void TestAlignContentFlexStartWithoutHeightOnChildren() [Fact] public void TestAlignContentFlexStartWithFlex() { - MockPlatformSizeService.Current.GetPlatformSizeFunc = (visual, width, height) => new SizeRequest(new Size(0, 0)); + static SizeRequest GetPlatformSize(VisualElement v, double w, double h) => new(new Size(0, 0)); var layout = new FlexLayout { @@ -107,31 +107,31 @@ public void TestAlignContentFlexStartWithFlex() AlignItems = FlexAlignItems.Start, }; - var view0 = new View { IsPlatformEnabled = true }; + var view0 = MockPlatformSizeService.Sub(GetPlatformSize); FlexLayout.SetGrow(view0, 1); FlexLayout.SetBasis(view0, 0); view0.WidthRequest = 50; layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true }; + var view1 = MockPlatformSizeService.Sub(GetPlatformSize); FlexLayout.SetGrow(view1, 1); FlexLayout.SetBasis(view1, 0); view1.WidthRequest = 50; view1.HeightRequest = 10; layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true }; + var view2 = MockPlatformSizeService.Sub(GetPlatformSize); view2.WidthRequest = 50; layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true }; + var view3 = MockPlatformSizeService.Sub(GetPlatformSize); FlexLayout.SetGrow(view3, 1); FlexLayout.SetShrink(view3, 1); FlexLayout.SetBasis(view3, 0); view3.WidthRequest = 50; layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true }; + var view4 = MockPlatformSizeService.Sub(GetPlatformSize); view4.WidthRequest = 50; layout.Children.Add(view4); @@ -148,7 +148,7 @@ public void TestAlignContentFlexStartWithFlex() [Fact] public void TestAlignContentFlexEnd() { - MockPlatformSizeService.Current.GetPlatformSizeFunc = (visual, width, height) => new SizeRequest(new Size(50, 10)); + static SizeRequest GetPlatformSize(VisualElement v, double w, double h) => new(new Size(50, 10)); var layout = new FlexLayout { @@ -162,12 +162,7 @@ public void TestAlignContentFlexEnd() Wrap = FlexWrap.Wrap, }; - Func createView = () => new View - { - IsPlatformEnabled = true, - WidthRequest = 50, - HeightRequest = 10, - }; + Func createView = () => MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); var view0 = createView(); layout.Children.Add(view0); @@ -198,7 +193,7 @@ public void TestAlignContentFlexEnd() [Fact] public void TestAlignContentStretch() { - MockPlatformSizeService.Current.GetPlatformSizeFunc = (visual, width, height) => new SizeRequest(new Size(0, 0)); + static SizeRequest GetPlatformSize(VisualElement v, double w, double h) => new(new Size(0, 0)); var layout = new FlexLayout { @@ -210,23 +205,23 @@ public void TestAlignContentStretch() WidthRequest = 150, HeightRequest = 100 }; - var view0 = new View { IsPlatformEnabled = true }; + var view0 = MockPlatformSizeService.Sub(GetPlatformSize); view0.WidthRequest = 50; layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true }; + var view1 = MockPlatformSizeService.Sub(GetPlatformSize); view1.WidthRequest = 50; layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true }; + var view2 = MockPlatformSizeService.Sub(GetPlatformSize); view2.WidthRequest = 50; layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true }; + var view3 = MockPlatformSizeService.Sub(GetPlatformSize); view3.WidthRequest = 50; layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true }; + var view4 = MockPlatformSizeService.Sub(GetPlatformSize); view4.WidthRequest = 50; layout.Children.Add(view4); @@ -266,7 +261,7 @@ public void TestAlignContentStretch() [Fact] public void TestAlignContentSpaceBetween() { - MockPlatformSizeService.Current.GetPlatformSizeFunc = (visual, width, height) => new SizeRequest(new Size(50, 10)); + static SizeRequest GetPlatformSize(VisualElement v, double w, double h) => new(new Size(50, 10)); var layout = new FlexLayout { @@ -279,19 +274,19 @@ public void TestAlignContentSpaceBetween() Wrap = FlexWrap.Wrap, }; - var view0 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10 }; + var view0 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10 }; + var view1 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10 }; + var view2 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10 }; + var view3 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10 }; + var view4 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view4); layout.Layout(new Rect(0, 0, 130, 100)); @@ -307,7 +302,7 @@ public void TestAlignContentSpaceBetween() [Fact] public void TestAlignContentSpaceAround() { - MockPlatformSizeService.Current.GetPlatformSizeFunc = (visual, width, height) => new SizeRequest(new Size(50, 10)); + static SizeRequest GetPlatformSize(VisualElement v, double w, double h) => new(new Size(50, 10)); var layout = new FlexLayout { @@ -319,19 +314,19 @@ public void TestAlignContentSpaceAround() AlignContent = FlexAlignContent.SpaceAround, Wrap = FlexWrap.Wrap, }; - var view0 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view0 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view1 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view2 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view3 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true, WidthRequest = 50, HeightRequest = 10, }; + var view4 = MockPlatformSizeService.Sub(GetPlatformSize, width: 50, height: 10); layout.Children.Add(view4); layout.Layout(new Rect(0, 0, 140, 120)); @@ -357,23 +352,23 @@ public void TestAlignContentStretchRow() WidthRequest = 150, HeightRequest = 100 }; - var view0 = new View { IsPlatformEnabled = true }; + var view0 = MockPlatformSizeService.Sub(); view0.WidthRequest = 50; layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true }; + var view1 = MockPlatformSizeService.Sub(); view1.WidthRequest = 50; layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true }; + var view2 = MockPlatformSizeService.Sub(); view2.WidthRequest = 50; layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true }; + var view3 = MockPlatformSizeService.Sub(); view3.WidthRequest = 50; layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true }; + var view4 = MockPlatformSizeService.Sub(); view4.WidthRequest = 50; layout.Children.Add(view4); @@ -426,22 +421,22 @@ public void TestAlignContentStretchRowWithChildren() var view0 = new FlexLayout { IsPlatformEnabled = true, WidthRequest = 50, }; layout.Children.Add(view0); - //var view0_child0 = new View { IsPlatformEnabled = true }; + //var view0_child0 = MockPlatformSizeService.Sub(); //FlexLayout.SetGrow(view0_child0, 1); //FlexLayout.SetShrink(view0_child0, 1); //FlexLayout.SetBasis(view0_child0, 0); //view0.Children.Add(view0_child0); - var view1 = new View { IsPlatformEnabled = true, WidthRequest = 50, }; + var view1 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true, WidthRequest = 50, }; + var view2 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true, WidthRequest = 50, }; + var view3 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true, WidthRequest = 50, }; + var view4 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view4); layout.Layout(new Rect(0, 0, 150, 100)); @@ -490,25 +485,25 @@ public void TestAlignContentStretchRowWithFlex() Direction = FlexDirection.Row, Wrap = FlexWrap.Wrap, }; - var view0 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view0 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view1 = MockPlatformSizeService.Sub(width: 50); FlexLayout.SetGrow(view1, 1); FlexLayout.SetShrink(view1, 1); FlexLayout.SetBasis(view1, 0); layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view2 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view3 = MockPlatformSizeService.Sub(width: 50); FlexLayout.SetGrow(view3, 1); FlexLayout.SetShrink(view3, 1); FlexLayout.SetBasis(view3, 0); layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view4 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view4); layout.Layout(new Rect(0, 0, 150, 100)); @@ -533,24 +528,24 @@ public void TestAlignContentStretchRowWithFlexNoShrink() WidthRequest = 150, HeightRequest = 100 }; - var view0 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view0 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view1 = MockPlatformSizeService.Sub(width: 50); FlexLayout.SetGrow(view1, 1); FlexLayout.SetShrink(view1, 1); FlexLayout.SetBasis(view1, 0); layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view2 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view3 = MockPlatformSizeService.Sub(width: 50); FlexLayout.SetGrow(view3, 1); FlexLayout.SetBasis(view3, 0); layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true, WidthRequest = 50 }; + var view4 = MockPlatformSizeService.Sub(width: 50); layout.Children.Add(view4); layout.Layout(new Rect(0, 0, 150, 100)); @@ -608,38 +603,16 @@ public void TestAlignContentStretchRowWithMargin() layout.Children.Add(view0); - var view1 = new View - { - IsPlatformEnabled = true, - Margin = 10, - WidthRequest = 50, - HeightRequest = 20, - }; + var view1 = MockPlatformSizeService.Sub(width: 50, height: 20, margin: 10); layout.Children.Add(view1); - var view2 = new View - { - IsPlatformEnabled = true, - WidthRequest = 50, - HeightRequest = 20, - }; + var view2 = MockPlatformSizeService.Sub(width: 50, height: 20); layout.Children.Add(view2); - var view3 = new View - { - IsPlatformEnabled = true, - Margin = new Thickness(10), - WidthRequest = 50, - HeightRequest = 20, - }; + var view3 = MockPlatformSizeService.Sub(width: 50, height: 20, margin: 10); layout.Children.Add(view3); - var view4 = new View - { - IsPlatformEnabled = true, - WidthRequest = 50, - HeightRequest = 20, - }; + var view4 = MockPlatformSizeService.Sub(width: 50, height: 20); layout.Children.Add(view4); layout.Layout(new Rect(0, 0, 150, 100)); @@ -664,11 +637,11 @@ public void TestAlignContentStretchRowWithSingleRow() WidthRequest = 150, HeightRequest = 100 }; - var view0 = new View { IsPlatformEnabled = true }; + var view0 = MockPlatformSizeService.Sub(); view0.WidthRequest = 50; layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true }; + var view1 = MockPlatformSizeService.Sub(); view1.WidthRequest = 50; layout.Children.Add(view1); @@ -693,7 +666,7 @@ public void TestAlignContentStretchRowWithSingleRow() [Fact] public void TestAlignContentStretchRowWithFixedHeight() { - MockPlatformSizeService.Current.GetPlatformSizeFunc = (visual, width, height) => new SizeRequest(new Size(0, 0)); + static SizeRequest GetPlatformSize(VisualElement v, double w, double h) => new(new Size(0, 0)); var layout = new FlexLayout { @@ -705,24 +678,24 @@ public void TestAlignContentStretchRowWithFixedHeight() WidthRequest = 150, HeightRequest = 100 }; - var view0 = new View { IsPlatformEnabled = true }; + var view0 = MockPlatformSizeService.Sub(GetPlatformSize); view0.WidthRequest = 50; layout.Children.Add(view0); - var view1 = new View { IsPlatformEnabled = true }; + var view1 = MockPlatformSizeService.Sub(GetPlatformSize); view1.WidthRequest = 50; view1.HeightRequest = 60; layout.Children.Add(view1); - var view2 = new View { IsPlatformEnabled = true }; + var view2 = MockPlatformSizeService.Sub(GetPlatformSize); view2.WidthRequest = 50; layout.Children.Add(view2); - var view3 = new View { IsPlatformEnabled = true }; + var view3 = MockPlatformSizeService.Sub(GetPlatformSize); view3.WidthRequest = 50; layout.Children.Add(view3); - var view4 = new View { IsPlatformEnabled = true }; + var view4 = MockPlatformSizeService.Sub(GetPlatformSize); view4.WidthRequest = 50; layout.Children.Add(view4); diff --git a/src/Controls/tests/Core.UnitTests/FlexLayoutAlignItemsTests.cs b/src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutAlignItemsTests.cs similarity index 100% rename from src/Controls/tests/Core.UnitTests/FlexLayoutAlignItemsTests.cs rename to src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutAlignItemsTests.cs diff --git a/src/Controls/tests/Core.UnitTests/FlexLayoutAlignSelfTests.cs b/src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutAlignSelfTests.cs similarity index 100% rename from src/Controls/tests/Core.UnitTests/FlexLayoutAlignSelfTests.cs rename to src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutAlignSelfTests.cs diff --git a/src/Controls/tests/Core.UnitTests/FlexLayoutFlexDirectionTests.cs b/src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutFlexDirectionTests.cs similarity index 97% rename from src/Controls/tests/Core.UnitTests/FlexLayoutFlexDirectionTests.cs rename to src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutFlexDirectionTests.cs index 4fd0c39e2341..83ca15f64c88 100644 --- a/src/Controls/tests/Core.UnitTests/FlexLayoutFlexDirectionTests.cs +++ b/src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutFlexDirectionTests.cs @@ -29,7 +29,7 @@ public void TestFlexDirectionColumnWithoutHeight() Direction = FlexDirection.Column, }; - var sizeRequest = layout.Measure(100, double.PositiveInfinity); + var sizeRequest = layout.Measure(100, double.PositiveInfinity, MeasureFlags.None); layout.Layout(new Rect(0, 0, sizeRequest.Request.Width, sizeRequest.Request.Height)); Assert.Equal(layout.Bounds, new Rect(0, 0, 100, 30)); Assert.Equal(view0.Bounds, new Rect(0, 0, 100, 10)); @@ -56,7 +56,7 @@ public void TestFlexDirectionRowNoWidth() }; - var measure = layout.Measure(double.PositiveInfinity, 100); + var measure = layout.Measure(double.PositiveInfinity, 100, MeasureFlags.None); layout.Layout(new Rect(0, 0, measure.Request.Width, measure.Request.Height)); Assert.Equal(layout.Bounds, new Rect(0, 0, 30, 100)); Assert.Equal(view0.Bounds, new Rect(0, 0, 10, 100)); diff --git a/src/Controls/tests/Core.UnitTests/FlexLayoutTests.cs b/src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutTests.cs similarity index 80% rename from src/Controls/tests/Core.UnitTests/FlexLayoutTests.cs rename to src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutTests.cs index be2584e2750f..9b7710112043 100644 --- a/src/Controls/tests/Core.UnitTests/FlexLayoutTests.cs +++ b/src/Compatibility/Core/tests/Compatibility.UnitTests/FlexLayoutTests.cs @@ -16,8 +16,8 @@ public class FlexLayoutTests : BaseTestFixture [Fact] public void TestBasicLayout() { - var label1 = new Label { IsPlatformEnabled = true }; - var label2 = new Label { IsPlatformEnabled = true }; + var label1 = MockPlatformSizeService.Sub + \ No newline at end of file diff --git a/src/Controls/src/BindingSourceGen/AccessExpressionBuilder.cs b/src/Controls/src/BindingSourceGen/AccessExpressionBuilder.cs new file mode 100644 index 000000000000..f5bf992f72af --- /dev/null +++ b/src/Controls/src/BindingSourceGen/AccessExpressionBuilder.cs @@ -0,0 +1,23 @@ +namespace Microsoft.Maui.Controls.BindingSourceGen; +using static Microsoft.Maui.Controls.BindingSourceGen.UnsafeAccessorsMethodName; + + +public static class AccessExpressionBuilder +{ + public static string ExtendExpression(string previousExpression, IPathPart nextPart, uint bindingId, bool shouldUseUnsafePropertySetter = false) + => nextPart switch + { + Cast { TargetType: var targetType } => $"({previousExpression} as {CastTargetName(targetType)})", + ConditionalAccess conditionalAccess => ExtendExpression(previousExpression: $"{previousExpression}?", conditionalAccess.Part, bindingId: bindingId), + IndexAccess { Index: int numericIndex } => $"{previousExpression}[{numericIndex}]", + IndexAccess { Index: string stringIndex } => $"{previousExpression}[\"{stringIndex}\"]", + MemberAccess memberAccess => $"{previousExpression}.{memberAccess.MemberName}", + InaccessibleMemberAccess inaccessibleMemberAccess when inaccessibleMemberAccess.Kind == AccessorKind.Field => $"{CreateUnsafeFieldAccessorMethodName(bindingId, inaccessibleMemberAccess.MemberName)}({previousExpression})", + InaccessibleMemberAccess inaccessibleMemberAccess when inaccessibleMemberAccess.Kind == AccessorKind.Property && !shouldUseUnsafePropertySetter => $"{CreateUnsafePropertyAccessorGetMethodName(bindingId, inaccessibleMemberAccess.MemberName)}({previousExpression})", + InaccessibleMemberAccess inaccessibleMemberAccess when inaccessibleMemberAccess.Kind == AccessorKind.Property => previousExpression, // This case is handled by the caller + _ => throw new NotSupportedException($"Unsupported path part type: {nextPart.GetType()}"), + }; + + private static string CastTargetName(TypeDescription targetType) + => targetType.IsValueType ? $"{targetType.GlobalName}?" : targetType.GlobalName; +} diff --git a/src/Controls/src/BindingSourceGen/BindingCodeWriter.cs b/src/Controls/src/BindingSourceGen/BindingCodeWriter.cs new file mode 100644 index 000000000000..39ba1f2d546a --- /dev/null +++ b/src/Controls/src/BindingSourceGen/BindingCodeWriter.cs @@ -0,0 +1,456 @@ +using System.CodeDom.Compiler; +using System.Globalization; +using System.Runtime.InteropServices; + +using static Microsoft.Maui.Controls.BindingSourceGen.UnsafeAccessorsMethodName; + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +public static class BindingCodeWriter +{ + private static readonly string NewLine = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "\r\n" : "\n"; + + public static string GeneratedCodeAttribute => $"[GeneratedCodeAttribute(\"{typeof(BindingCodeWriter).Assembly.FullName}\", \"{typeof(BindingCodeWriter).Assembly.GetName().Version}\")]"; + + public static string GenerateCommonCode() => $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace Microsoft.Maui.Controls.Generated + { + using System.CodeDom.Compiler; + + {{GeneratedCodeAttribute}} + internal static partial class GeneratedBindingInterceptors + { + private static bool ShouldUseSetter(BindingMode mode, BindableProperty bindableProperty) + => mode == BindingMode.OneWayToSource + || mode == BindingMode.TwoWay + || (mode == BindingMode.Default + && (bindableProperty.DefaultBindingMode == BindingMode.OneWayToSource + || bindableProperty.DefaultBindingMode == BindingMode.TwoWay)); + + private static bool ShouldUseSetter(BindingMode mode) + => mode == BindingMode.OneWayToSource + || mode == BindingMode.TwoWay + || mode == BindingMode.Default; + } + } + """; + + private static string GenerateUnsafeFieldAccessor(string fieldName, string memberType, string containingType, uint id) => $$""" + [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "{{fieldName}}")] + private static extern ref {{memberType}} {{CreateUnsafeFieldAccessorMethodName(id, fieldName)}}({{containingType}} source); + """; + + private static string GenerateUnsafePropertyAccessors(string propertyName, string memberType, string containingType, uint id, bool generateSetter) + { + var propertyAccessors = new List + { + GenerateUnsafePropertyGetAccessors(propertyName, memberType, containingType, id) + }; + + if (generateSetter) + { + propertyAccessors.Add(GenerateUnsafePropertySetAccessors(propertyName, memberType, containingType, id)); + } + + return string.Join(NewLine, propertyAccessors); + } + + private static string GenerateUnsafePropertyGetAccessors(string propertyName, string memberType, string containingType, uint id) => $$""" + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_{{propertyName}}")] + private static extern {{memberType}} {{CreateUnsafePropertyAccessorGetMethodName(id, propertyName)}}({{containingType}} source); + """; + + private static string GenerateUnsafePropertySetAccessors(string propertyName, string memberType, string containingType, uint id) => $$""" + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "set_{{propertyName}}")] + private static extern void {{CreateUnsafePropertyAccessorSetMethodName(id, propertyName)}}({{containingType}} source, {{memberType}} value); + """; + + private static string GenerateBindingCode(string bindingMethodBody, IEnumerable unsafeAccessors) => $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + {{bindingMethodBody}} + {{string.Join(NewLine, unsafeAccessors)}} + } + } + """; + + public static string GenerateBinding(BindingInvocationDescription binding, uint id) + { + if (!binding.NullableContextEnabled) + { + var referenceTypesConditionalAccessTransformer = new ReferenceTypesConditionalAccessTransformer(); + binding = referenceTypesConditionalAccessTransformer.Transform(binding); + } + + var unsafeAccessors = binding.Path + .OfType(); + var bindingMethod = GenerateBindingMethod(binding, id); + + var unsafeAccessorsStrings = new List(); + + foreach (var unsafeAccessor in unsafeAccessors) + { + var accessor = unsafeAccessor.Kind switch + { + AccessorKind.Field => GenerateUnsafeFieldAccessor(unsafeAccessor.MemberName, unsafeAccessor.memberType.GlobalName, unsafeAccessor.ContainingType.GlobalName, id), + AccessorKind.Property => GenerateUnsafePropertyAccessors(unsafeAccessor.MemberName, unsafeAccessor.memberType.GlobalName, unsafeAccessor.ContainingType.GlobalName, id, binding.SetterOptions.IsWritable), + _ => throw new ArgumentException(nameof(unsafeAccessor.Kind)) + }; + unsafeAccessorsStrings.Add(accessor); + } + return GenerateBindingCode(bindingMethod, unsafeAccessorsStrings); + } + + private static string GenerateBindingMethod(BindingInvocationDescription binding, uint id) + { + using var builder = new BindingInterceptorCodeBuilder(indent: 2); + builder.AppendSetBindingInterceptor(id: id, binding: binding); + return builder.ToString(); + } + + public sealed class BindingInterceptorCodeBuilder : IDisposable + { + private StringWriter _stringWriter; + private IndentedTextWriter _indentedTextWriter; + + public override string ToString() + { + _indentedTextWriter.Flush(); + return _stringWriter.ToString(); + } + + public BindingInterceptorCodeBuilder(int indent = 0) + { + _stringWriter = new StringWriter(CultureInfo.InvariantCulture); + _indentedTextWriter = new IndentedTextWriter(_stringWriter, "\t") { Indent = indent }; + } + + public void AppendSetBindingInterceptor(uint id, BindingInvocationDescription binding) + { + AppendLine(GeneratedCodeAttribute); + AppendInterceptorAttribute(binding.Location); + AppendMethodName(binding, id); + if (binding.SourceType.IsGenericParameter && binding.PropertyType.IsGenericParameter) + { + Append($"<{binding.SourceType}, {binding.PropertyType}>"); + } + else if (binding.SourceType.IsGenericParameter) + { + Append($"<{binding.SourceType}>"); + } + else if (binding.PropertyType.IsGenericParameter) + { + Append($"<{binding.PropertyType}>"); + } + AppendLine('('); + + AppendFunctionArguments(binding); + + AppendLines($$""" + { + Action<{{binding.SourceType}}, {{binding.PropertyType}}>? setter = null; + if ({{GetShouldUseSetterCall(binding.MethodType)}}) + { + """); + + Indent(); + Indent(); + + if (binding.SetterOptions.IsWritable) + { + AppendLines(""" + setter = static (source, value) => + { + """); + Indent(); + + AppendSetterAction(binding, id); + + Unindent(); + AppendLine("};"); + } + else + { + AppendLine("throw new InvalidOperationException(\"Cannot set value on the source object.\");"); + } + + Unindent(); + Unindent(); + + AppendLines($$""" + } + + var binding = new TypedBinding<{{binding.SourceType}}, {{binding.PropertyType}}>( + getter: source => (getter(source), true), + setter, + """); + + + Indent(); + Indent(); + + Append("handlers: "); + AppendHandlersArray(binding, id); + AppendLine(")"); + + Unindent(); + Unindent(); + + AppendLines($$""" + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + {{GetEpilog(binding.MethodType)}} + } + """); + } + + private void AppendFunctionArguments(BindingInvocationDescription binding) + { + if (binding.MethodType == InterceptedMethodType.SetBinding) + { + AppendLines($$""" + this BindableObject bindableObject, + BindableProperty bindableProperty, + """); + + } + AppendLines($$""" + Func<{{binding.SourceType}}, {{binding.PropertyType}}> getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + """); + } + + private static string GetEpilog(InterceptedMethodType interceptedMethodType) => + interceptedMethodType switch + { + InterceptedMethodType.SetBinding => "bindableObject.SetBinding(bindableProperty, binding);", + InterceptedMethodType.Create => "return binding;", + _ => throw new ArgumentOutOfRangeException(nameof(interceptedMethodType)) + }; + + private static string GetShouldUseSetterCall(InterceptedMethodType interceptedMethodType) => + interceptedMethodType switch + { + InterceptedMethodType.SetBinding => "ShouldUseSetter(mode, bindableProperty)", + InterceptedMethodType.Create => "ShouldUseSetter(mode)", + _ => throw new ArgumentOutOfRangeException(nameof(interceptedMethodType)) + }; + + + private void AppendMethodName(BindingInvocationDescription binding, uint id) + { + Append(binding.MethodType switch + { + InterceptedMethodType.SetBinding => $"public static void SetBinding{id}", + InterceptedMethodType.Create => $"public static BindingBase Create{id}", + _ => throw new ArgumentOutOfRangeException(nameof(binding.MethodType)) + }); + } + + private void AppendInterceptorAttribute(InterceptorLocation location) + { + AppendLine($"[InterceptsLocationAttribute(@\"{location.FilePath}\", {location.Line}, {location.Column})]"); + } + + private void AppendSetterAction(BindingInvocationDescription binding, uint id, string sourceVariableName = "source", string valueVariableName = "value") + { + var assignedValueExpression = valueVariableName; + + // early return for nullable values if the setter doesn't accept them + if (binding.PropertyType.IsNullable && !binding.SetterOptions.AcceptsNullValue) + { + if (binding.PropertyType.IsValueType) + { + AppendLine($"if (!{valueVariableName}.HasValue)"); + assignedValueExpression = $"{valueVariableName}.Value"; + } + else + { + AppendLine($"if ({valueVariableName} is null)"); + } + AppendLine('{'); + Indent(); + AppendLine("return;"); + Unindent(); + AppendLine('}'); + } + + var setter = Setter.From(binding.Path, id, sourceVariableName, assignedValueExpression); + if (setter.PatternMatchingExpressions.Length > 0) + { + Append("if ("); + + for (int i = 0; i < setter.PatternMatchingExpressions.Length; i++) + { + if (i == 1) + { + Indent(); + } + + if (i > 0) + { + AppendBlankLine(); + Append("&& "); + } + + Append(setter.PatternMatchingExpressions[i]); + } + + AppendLine(')'); + if (setter.PatternMatchingExpressions.Length > 1) + { + Unindent(); + } + + AppendLine('{'); + Indent(); + } + + AppendLine(setter.AssignmentStatement); + + if (setter.PatternMatchingExpressions.Length > 0) + { + Unindent(); + AppendLine('}'); + } + } + + private void AppendHandlersArray(BindingInvocationDescription binding, uint id) + { + AppendLine($"new Tuple, string>[]"); + AppendLine('{'); + + Indent(); + + string nextExpression = "source"; + bool forceConditonalAccessToNextPart = false; + foreach (var part in binding.Path) + { + var previousExpression = nextExpression; + nextExpression = AccessExpressionBuilder.ExtendExpression(previousExpression, MaybeWrapInConditionalAccess(part, forceConditonalAccessToNextPart), id); + forceConditonalAccessToNextPart = part is Cast; + + // Make binding react for PropertyChanged events on indexer itself + if (part is IndexAccess indexAccess) + { + AppendLine($"new(static source => {previousExpression}, \"{indexAccess.DefaultMemberName}\"),"); + } + else if (part is ConditionalAccess conditionalAccess && conditionalAccess.Part is IndexAccess innerIndexAccess) + { + AppendLine($"new(static source => {previousExpression}, \"{innerIndexAccess.DefaultMemberName}\"),"); + } + + // Some parts don't have a property name, so we can't generate a handler for them (for example casts) + if (part.PropertyName is string propertyName) + { + AppendLine($"new(static source => {previousExpression}, \"{propertyName}\"),"); + } + } + Unindent(); + + Append('}'); + + static IPathPart MaybeWrapInConditionalAccess(IPathPart part, bool forceConditonalAccess) + { + if (!forceConditonalAccess) + { + return part; + } + + return part switch + { + MemberAccess memberAccess => new ConditionalAccess(memberAccess), + IndexAccess indexAccess => new ConditionalAccess(indexAccess), + _ => part, + }; + } + } + + public void Dispose() + { + _indentedTextWriter.Dispose(); + _stringWriter.Dispose(); + } + + private void AppendBlankLine() => _indentedTextWriter.WriteLine(); + private void AppendLine(string line) => _indentedTextWriter.WriteLine(line); + private void AppendLine(char character) => _indentedTextWriter.WriteLine(character); + private void Append(string str) => _indentedTextWriter.Write(str); + private void Append(char character) => _indentedTextWriter.Write(character); + + private readonly char[] LineSeparators = ['\n', '\r']; + private void AppendLines(string lines) + { + foreach (var line in lines.Split(LineSeparators, StringSplitOptions.RemoveEmptyEntries)) + { + AppendLine(line); + } + } + + private void Indent() => _indentedTextWriter.Indent++; + private void Unindent() => _indentedTextWriter.Indent--; + } +} diff --git a/src/Controls/src/BindingSourceGen/BindingInvocationDescription.cs b/src/Controls/src/BindingSourceGen/BindingInvocationDescription.cs new file mode 100644 index 000000000000..c2e04cd7e56c --- /dev/null +++ b/src/Controls/src/BindingSourceGen/BindingInvocationDescription.cs @@ -0,0 +1,53 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +public sealed record BindingInvocationDescription( + InterceptorLocation Location, + TypeDescription SourceType, + TypeDescription PropertyType, + EquatableArray Path, + SetterOptions SetterOptions, + bool NullableContextEnabled, + InterceptedMethodType MethodType); + +public sealed record SourceCodeLocation(string FilePath, TextSpan TextSpan, LinePositionSpan LineSpan) +{ + public static SourceCodeLocation? CreateFrom(Location location) + => location.SourceTree is null + ? null + : new SourceCodeLocation(location.SourceTree.FilePath, location.SourceSpan, location.GetLineSpan().Span); + + public Location ToLocation() + { + return Location.Create(FilePath, TextSpan, LineSpan); + } + + public InterceptorLocation ToInterceptorLocation() + { + return new InterceptorLocation(FilePath, LineSpan.Start.Line + 1, LineSpan.Start.Character + 1); + } +} + +public sealed record InterceptorLocation(string FilePath, int Line, int Column); + +public sealed record TypeDescription( + string GlobalName, + bool IsValueType = false, + bool IsNullable = false, + bool IsGenericParameter = false) +{ + public override string ToString() + => IsNullable + ? $"{GlobalName}?" + : GlobalName; +} + +public enum InterceptedMethodType +{ + SetBinding, + Create +} + +public sealed record SetterOptions(bool IsWritable, bool AcceptsNullValue = false); diff --git a/src/Controls/src/BindingSourceGen/BindingSourceGenerator.cs b/src/Controls/src/BindingSourceGen/BindingSourceGenerator.cs new file mode 100644 index 000000000000..e9c1a3664331 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/BindingSourceGenerator.cs @@ -0,0 +1,247 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +public class TrackingNames +{ + public const string BindingsWithDiagnostics = nameof(BindingsWithDiagnostics); + public const string Bindings = nameof(Bindings); +} + +[Generator(LanguageNames.CSharp)] +public class BindingSourceGenerator : IIncrementalGenerator +{ + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var bindingsWithDiagnostics = context.SyntaxProvider.CreateSyntaxProvider( + predicate: static (node, _) => IsSetBindingMethod(node) || IsCreateMethod(node), + transform: static (ctx, t) => GetBindingForGeneration(ctx, t) + ) + .WithTrackingName(TrackingNames.BindingsWithDiagnostics); + + context.RegisterSourceOutput(bindingsWithDiagnostics, (spc, bindingWithDiagnostic) => + { + foreach (var diagnostic in bindingWithDiagnostic.Diagnostics) + { + spc.ReportDiagnostic(Diagnostic.Create(diagnostic.Descriptor, diagnostic.Location?.ToLocation())); + } + }); + + var bindings = bindingsWithDiagnostics + .Where(static binding => !binding.HasDiagnostics) + .Select(static (binding, t) => binding.Value) + .WithTrackingName(TrackingNames.Bindings); + + context.RegisterPostInitializationOutput(spc => + { + spc.AddSource("GeneratedBindingInterceptorsCommon.g.cs", BindingCodeWriter.GenerateCommonCode()); + }); + + context.RegisterImplementationSourceOutput(bindings, (spc, binding) => + { + var fileName = $"{binding.Location.FilePath}-GeneratedBindingInterceptors-{binding.Location.Line}-{binding.Location.Column}.g.cs"; + var sanitizedFileName = fileName.Replace('/', '-').Replace('\\', '-').Replace(':', '-'); + var code = BindingCodeWriter.GenerateBinding(binding, (uint)Math.Abs(binding.Location.GetHashCode())); + spc.AddSource(sanitizedFileName, code); + }); + } + + private static bool IsSetBindingMethod(SyntaxNode node) + { + return node is InvocationExpressionSyntax invocation + && invocation.Expression is MemberAccessExpressionSyntax method + && method.Name.Identifier.Text == "SetBinding" + && invocation.ArgumentList.Arguments.Count >= 2 + && invocation.ArgumentList.Arguments[1].Expression is not LiteralExpressionSyntax + && invocation.ArgumentList.Arguments[1].Expression is not ObjectCreationExpressionSyntax; + } + + private static bool IsCreateMethod(SyntaxNode node) + { + return node is InvocationExpressionSyntax invocation + && invocation.Expression is MemberAccessExpressionSyntax method + && method.Name.Identifier.Text == "Create" + && invocation.ArgumentList.Arguments.Count >= 1 + && invocation.ArgumentList.Arguments[0].Expression is not LiteralExpressionSyntax + && invocation.ArgumentList.Arguments[0].Expression is not ObjectCreationExpressionSyntax; + } + + private static Result GetBindingForGeneration(GeneratorSyntaxContext context, CancellationToken t) + { + var enabledNullable = IsNullableContextEnabled(context); + + var invocation = (InvocationExpressionSyntax)context.Node; + var method = (MemberAccessExpressionSyntax)invocation.Expression; + + var invocationParser = new InvocationParser(context); + var interceptedMethodTypeResult = invocationParser.ParseInvocation(invocation, t); + + if (interceptedMethodTypeResult.HasDiagnostics) + { + return Result.Failure(interceptedMethodTypeResult.Diagnostics); + } + + var sourceCodeLocation = SourceCodeLocation.CreateFrom(method.Name.GetLocation()); + if (sourceCodeLocation == null) + { + return Result.Failure(DiagnosticsFactory.UnableToResolvePath(invocation.GetLocation())); + } + + var lambdaResult = GetLambda(invocation, interceptedMethodTypeResult.Value); + if (lambdaResult.HasDiagnostics) + { + return Result.Failure(lambdaResult.Diagnostics); + } + + var lambdaParamTypeResult = GetLambdaParameterType(lambdaResult.Value, context.SemanticModel, t); + if (lambdaParamTypeResult.HasDiagnostics) + { + return Result.Failure(lambdaParamTypeResult.Diagnostics); + } + + var lambdaReturnTypeResult = GetLambdaReturnType(lambdaResult.Value, context.SemanticModel, t); + if (lambdaReturnTypeResult.HasDiagnostics) + { + return Result.Failure(lambdaReturnTypeResult.Diagnostics); + } + + var pathParser = new PathParser(context, enabledNullable); + var pathParseResult = pathParser.ParsePath(lambdaResult.Value.ExpressionBody); + if (pathParseResult.HasDiagnostics) + { + return Result.Failure(pathParseResult.Diagnostics); + } + + var binding = new BindingInvocationDescription( + Location: sourceCodeLocation.ToInterceptorLocation(), + SourceType: lambdaParamTypeResult.Value.CreateTypeDescription(enabledNullable), + PropertyType: lambdaReturnTypeResult.Value.CreateTypeDescription(enabledNullable), + Path: new EquatableArray([.. pathParseResult.Value]), + SetterOptions: DeriveSetterOptions(lambdaResult.Value.ExpressionBody, context.SemanticModel, enabledNullable), + NullableContextEnabled: enabledNullable, + MethodType: interceptedMethodTypeResult.Value); + return Result.Success(binding); + } + + private static bool IsNullableContextEnabled(GeneratorSyntaxContext context) + { + NullableContext nullableContext = context.SemanticModel.GetNullableContext(context.Node.Span.Start); + return (nullableContext & NullableContext.Enabled) == NullableContext.Enabled; + } + + private static Result GetLambda(InvocationExpressionSyntax invocation, InterceptedMethodType methodType) + { + var argumentList = invocation.ArgumentList.Arguments; + var expression = methodType switch + { + InterceptedMethodType.SetBinding => argumentList[1].Expression, + InterceptedMethodType.Create => argumentList[0].Expression, + _ => throw new NotSupportedException() + }; + + if (expression is not LambdaExpressionSyntax lambda) + { + return Result.Failure(DiagnosticsFactory.GetterIsNotLambda(expression.GetLocation())); + } + + // We only support static lambdas + if (!lambda.Modifiers.Any(SyntaxKind.StaticKeyword)) + { + return Result.Failure(DiagnosticsFactory.LambdaIsNotStatic(lambda.GetLocation())); + } + + return Result.Success(lambda); + } + + private static Result GetLambdaReturnType(LambdaExpressionSyntax lambda, SemanticModel semanticModel, CancellationToken t) + { + if (lambda.Body is not ExpressionSyntax lambdaBody) + { + return Result.Failure(DiagnosticsFactory.GetterLambdaBodyIsNotExpression(lambda.Body.GetLocation())); + } + + var lambdaResultType = semanticModel.GetTypeInfo(lambdaBody, t).Type; + if (lambdaResultType == null || lambdaResultType is IErrorTypeSymbol) + { + return Result.Failure(DiagnosticsFactory.LambdaResultCannotBeResolved(lambdaBody.GetLocation())); + } + + return Result.Success(lambdaResultType); + } + + private static Result GetLambdaParameterType(LambdaExpressionSyntax lambda, SemanticModel semanticModel, CancellationToken t) + { + if (semanticModel.GetSymbolInfo(lambda, t).Symbol is not IMethodSymbol lambdaSymbol) + { + return Result.Failure(DiagnosticsFactory.GetterIsNotLambda(lambda.GetLocation())); + } + + var parameters = lambdaSymbol.Parameters; + if (parameters.Length == 0 || parameters[0].Type is IErrorTypeSymbol) + { + return Result.Failure(DiagnosticsFactory.LambdaParameterCannotBeResolved(lambda.GetLocation())); + } + + var lambdaParamType = parameters[0].Type; + if (!lambdaParamType.IsAccessible()) + { + return Result.Failure(DiagnosticsFactory.UnaccessibleTypeUsedAsLambdaParameter(lambda.GetLocation())); + } + + return Result.Success(lambdaParamType); + } + + private static SetterOptions DeriveSetterOptions(ExpressionSyntax? lambdaBodyExpression, SemanticModel semanticModel, bool enabledNullable) + { + if (lambdaBodyExpression is null) + { + return new SetterOptions(IsWritable: false, AcceptsNullValue: false); + } + else if (lambdaBodyExpression is IdentifierNameSyntax identifier) + { + var symbol = semanticModel.GetSymbolInfo(identifier).Symbol; + return new SetterOptions(IsWritable(symbol), AcceptsNullValue(symbol, enabledNullable)); + } + else if (lambdaBodyExpression is ElementAccessExpressionSyntax elementAccess) + { + var symbol = semanticModel.GetSymbolInfo(elementAccess).Symbol; + return new SetterOptions(IsWritable(symbol), AcceptsNullValue(symbol, enabledNullable)); + } + else if (lambdaBodyExpression is ElementBindingExpressionSyntax elementBinding) + { + var symbol = semanticModel.GetSymbolInfo(elementBinding).Symbol; + return new SetterOptions(IsWritable(symbol), AcceptsNullValue(symbol, enabledNullable)); + } + + var nestedExpression = lambdaBodyExpression switch + { + MemberAccessExpressionSyntax memberAccess => memberAccess.Name, + ConditionalAccessExpressionSyntax conditionalAccess => conditionalAccess.WhenNotNull, + MemberBindingExpressionSyntax memberBinding => memberBinding.Name, + BinaryExpressionSyntax binary when binary.Kind() == SyntaxKind.AsExpression => binary.Left, + CastExpressionSyntax cast => cast.Expression, + ParenthesizedExpressionSyntax parenthesized => parenthesized.Expression, + _ => null, + }; + + return DeriveSetterOptions(nestedExpression, semanticModel, enabledNullable); + + static bool IsWritable(ISymbol? symbol) + => symbol switch + { + IPropertySymbol propertySymbol => propertySymbol.SetMethod != null, + IFieldSymbol fieldSymbol => !fieldSymbol.IsReadOnly, + _ => true, + }; + + static bool AcceptsNullValue(ISymbol? symbol, bool enabledNullable) + => symbol switch + { + IPropertySymbol propertySymbol => propertySymbol.Type.IsTypeNullable(enabledNullable), + IFieldSymbol fieldSymbol => fieldSymbol.Type.IsTypeNullable(enabledNullable), + _ => false, + }; + } +} diff --git a/src/Controls/src/BindingSourceGen/BindingTransformer.cs b/src/Controls/src/BindingSourceGen/BindingTransformer.cs new file mode 100644 index 000000000000..6abeebdb0617 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/BindingTransformer.cs @@ -0,0 +1,50 @@ + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +public interface IBindingInvocationTransformer +{ + BindingInvocationDescription Transform(BindingInvocationDescription BindingInvocationDescription); +} + +public class ReferenceTypesConditionalAccessTransformer : IBindingInvocationTransformer +{ + public BindingInvocationDescription Transform(BindingInvocationDescription BindingInvocationDescription) + { + var path = TransformPath(BindingInvocationDescription); + return BindingInvocationDescription with { Path = path }; + } + + private static EquatableArray TransformPath(BindingInvocationDescription BindingInvocationDescription) + { + var newPath = new List(); + foreach (var pathPart in BindingInvocationDescription.Path) + { + var sourceIsReferenceType = newPath.Count == 0 && !BindingInvocationDescription.SourceType.IsValueType; + var previousPartIsReferenceType = newPath.Count > 0 && PreviousPartIsReferenceType(newPath.Last()); + + if (pathPart is not MemberAccess && pathPart is not IndexAccess) + { + newPath.Add(pathPart); + } + else if (sourceIsReferenceType || previousPartIsReferenceType) + { + newPath.Add(new ConditionalAccess(pathPart)); + } + else + { + newPath.Add(pathPart); + } + } + + return new EquatableArray(newPath.ToArray()); + + static bool PreviousPartIsReferenceType(IPathPart previousPathPart) => + previousPathPart switch + { + MemberAccess memberAccess => !memberAccess.IsValueType, + IndexAccess indexAccess => !indexAccess.IsValueType, + ConditionalAccess { Part: var inner } => PreviousPartIsReferenceType(inner), + _ => false, + }; + } +} diff --git a/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj b/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj new file mode 100644 index 000000000000..d7df9f008760 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj @@ -0,0 +1,32 @@ + + + netstandard2.0 + enable + true + Latest + Microsoft.Maui.Controls.BindingSourceGen + Microsoft.Maui.Controls.BindingSourceGen + Microsoft.Maui.Controls.BindingSourceGen + false + + + + false + true + true + true + + + + + + + + + + <_CopyItems Include="$(TargetDir)*.dll" Exclude="$(TargetDir)System.*.dll" /> + <_CopyItems Include="$(TargetDir)*.pdb" Exclude="$(TargetDir)System.*.pdb" /> + + + + \ No newline at end of file diff --git a/src/Controls/src/BindingSourceGen/DiagnosticsFactory.cs b/src/Controls/src/BindingSourceGen/DiagnosticsFactory.cs new file mode 100644 index 000000000000..5bd89c923bd2 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/DiagnosticsFactory.cs @@ -0,0 +1,128 @@ +using Microsoft.CodeAnalysis; + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +public sealed record DiagnosticInfo +{ + public DiagnosticInfo(DiagnosticDescriptor descriptor, Location? location) + { + Descriptor = descriptor; + Location = location is not null ? SourceCodeLocation.CreateFrom(location) : null; + } + + public DiagnosticDescriptor Descriptor { get; } + public SourceCodeLocation? Location { get; } +} + +internal static class DiagnosticsFactory +{ + public static DiagnosticInfo UnableToResolvePath(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0001", + title: "Invalid getter method", + messageFormat: "The getter expression is not valid. The expression can only consist of property access, index access, and type casts.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true), + location); + + public static DiagnosticInfo GetterIsNotLambda(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0002", + title: "Getter method is not a lambda", + messageFormat: "The getter must be a lambda expression.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true), + location); + + public static DiagnosticInfo GetterLambdaBodyIsNotExpression(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0003", + title: "Getter method body is not an expression", + messageFormat: "The getter lambda's body must be an expression.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true), + location); + + public static DiagnosticInfo SuboptimalSetBindingOverload(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0004", + title: "Using SetBinding with a string path", + messageFormat: "Consider using SetBinding with a lambda expression for improved performance.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Hidden, + isEnabledByDefault: false), + location); + + public static DiagnosticInfo LambdaParameterCannotBeResolved(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0005", + title: "Lambda parameter cannot be resolved", + messageFormat: "The lambda parameter cannot be resolved. Make sure that it is not source generated.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true), + location); + + public static DiagnosticInfo LambdaResultCannotBeResolved(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0006", + title: "Lambda result type cannot be resolved", + messageFormat: "The lambda result type cannot be resolved. Make sure that soruce generated fields / properties are not used in the path.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true), + location); + + public static DiagnosticInfo UnaccessibleTypeUsedAsLambdaParameter(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0007", + title: "Unaccessible type used as lambda parameter", + messageFormat: "The lambda parameter type has to be declared as public, internal or protected internal.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true), + location); + + public static DiagnosticInfo UnaccessibleFieldInPath(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0008", + title: "Unaccessible field in path", + messageFormat: "The path can contain only public, internal and protected internal fields.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true), + location); + + public static DiagnosticInfo UnaccessiblePropertyInPath(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0009", + title: "Unaccessible property in path", + messageFormat: "The path can contain only public, internal and protected internal properties.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true), + location); + + public static DiagnosticInfo LambdaIsNotStatic(Location location) + => new DiagnosticInfo( + new DiagnosticDescriptor( + id: "BSG0010", + title: "Lambda is not static", + messageFormat: "The lambda must be static.", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true), + location); +} diff --git a/src/Controls/src/BindingSourceGen/EquatableArray.cs b/src/Controls/src/BindingSourceGen/EquatableArray.cs new file mode 100644 index 000000000000..46b15c10ec92 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/EquatableArray.cs @@ -0,0 +1,102 @@ +using System.Collections; +using System.Collections.Immutable; +using System.Runtime.CompilerServices; + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +// Original source: +// https://github.com/CommunityToolkit/dotnet/blob/main/src/CommunityToolkit.Mvvm.SourceGenerators/Helpers/EquatableArray%7BT%7D.cs + +public readonly struct EquatableArray : IEquatable>, IEnumerable + where T : IEquatable +{ + private readonly T[]? array; + + private EquatableArray(ImmutableArray array) + { + this.array = Unsafe.As, T[]?>(ref array); + } + + public EquatableArray(T[] array) : this(array.ToImmutableArray()) + { + } + + public ref readonly T this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => ref AsImmutableArray().ItemRef(index); + } + + public int Length + { + get => array?.Length ?? 0; + } + + public bool Equals(EquatableArray array) + { + return AsSpan().SequenceEqual(array.AsSpan()); + } + + public override bool Equals(object? obj) + { + return obj is EquatableArray array && Equals(this, array); + } + + public override int GetHashCode() + { + if (this.array is not T[] array) + { + return 0; + } + + HashCode hashCode = default; + + foreach (T item in array) + { + hashCode.Add(item); + } + + return hashCode.ToHashCode(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ImmutableArray AsImmutableArray() + { + return Unsafe.As>(ref Unsafe.AsRef(in this.array)); + } + + public ReadOnlySpan AsSpan() + { + return AsImmutableArray().AsSpan(); + } + + public T[] ToArray() + { + return AsImmutableArray().ToArray(); + } + + public ImmutableArray.Enumerator GetEnumerator() + { + return AsImmutableArray().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)AsImmutableArray()).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)AsImmutableArray()).GetEnumerator(); + } + + public static bool operator ==(EquatableArray left, EquatableArray right) + { + return left.Equals(right); + } + + public static bool operator !=(EquatableArray left, EquatableArray right) + { + return !left.Equals(right); + } +} diff --git a/src/Controls/src/BindingSourceGen/HashCode.cs b/src/Controls/src/BindingSourceGen/HashCode.cs new file mode 100644 index 000000000000..82273a724371 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/HashCode.cs @@ -0,0 +1,157 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +// Original source: +// https://github.com/dotnet/BenchmarkDotNet/blob/master/src/BenchmarkDotNet/Helpers/HashCode.cs + +// Mimics System.HashCode, which is missing in NetStandard2.0. +// Placed in root namespace to avoid ambiguous reference with System.HashCode + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +internal struct HashCode +{ + private int hashCode; + + public void Add(T value) + { + hashCode = Hash(hashCode, value); + } + + public void Add(T value, IEqualityComparer comparer) + { + hashCode = Hash(hashCode, value, comparer); + } + + public readonly int ToHashCode() => hashCode; + + public static int Combine(T1 value1) + { + int hashCode = 0; + hashCode = Hash(hashCode, value1); + return hashCode; + } + + public static int Combine(T1 value1, T2 value2) + { + int hashCode = 0; + hashCode = Hash(hashCode, value1); + hashCode = Hash(hashCode, value2); + return hashCode; + } + + public static int Combine(T1 value1, T2 value2, T3 value3) + { + int hashCode = 0; + hashCode = Hash(hashCode, value1); + hashCode = Hash(hashCode, value2); + hashCode = Hash(hashCode, value3); + return hashCode; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4) + { + int hashCode = 0; + hashCode = Hash(hashCode, value1); + hashCode = Hash(hashCode, value2); + hashCode = Hash(hashCode, value3); + hashCode = Hash(hashCode, value4); + return hashCode; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) + { + int hashCode = 0; + hashCode = Hash(hashCode, value1); + hashCode = Hash(hashCode, value2); + hashCode = Hash(hashCode, value3); + hashCode = Hash(hashCode, value4); + hashCode = Hash(hashCode, value5); + return hashCode; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) + { + int hashCode = 0; + hashCode = Hash(hashCode, value1); + hashCode = Hash(hashCode, value2); + hashCode = Hash(hashCode, value3); + hashCode = Hash(hashCode, value4); + hashCode = Hash(hashCode, value5); + hashCode = Hash(hashCode, value6); + return hashCode; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) + { + int hashCode = 0; + hashCode = Hash(hashCode, value1); + hashCode = Hash(hashCode, value2); + hashCode = Hash(hashCode, value3); + hashCode = Hash(hashCode, value4); + hashCode = Hash(hashCode, value5); + hashCode = Hash(hashCode, value6); + hashCode = Hash(hashCode, value7); + return hashCode; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8) + { + int hashCode = 0; + hashCode = Hash(hashCode, value1); + hashCode = Hash(hashCode, value2); + hashCode = Hash(hashCode, value3); + hashCode = Hash(hashCode, value4); + hashCode = Hash(hashCode, value5); + hashCode = Hash(hashCode, value6); + hashCode = Hash(hashCode, value7); + hashCode = Hash(hashCode, value8); + return hashCode; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, + T8 value8, T9 value9, T10 value10) + { + int hashCode = 0; + hashCode = Hash(hashCode, value1); + hashCode = Hash(hashCode, value2); + hashCode = Hash(hashCode, value3); + hashCode = Hash(hashCode, value4); + hashCode = Hash(hashCode, value5); + hashCode = Hash(hashCode, value6); + hashCode = Hash(hashCode, value7); + hashCode = Hash(hashCode, value8); + hashCode = Hash(hashCode, value9); + hashCode = Hash(hashCode, value10); + return hashCode; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int Hash(int hashCode, T value) + { + unchecked + { + return (hashCode * 397) ^ (value?.GetHashCode() ?? 0); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int Hash(int hashCode, T value, IEqualityComparer comparer) + { + unchecked + { + return (hashCode * 397) ^ (value is null ? 0 : (comparer?.GetHashCode(value) ?? value.GetHashCode())); + } + } + +#pragma warning disable CS0809 // Obsolete member 'HashCode.GetHashCode()' overrides non-obsolete member 'object.GetHashCode()' + [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", + error: true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => throw new NotSupportedException(); + + [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => throw new NotSupportedException(); +#pragma warning restore CS0809 // Obsolete member 'HashCode.GetHashCode()' overrides non-obsolete member 'object.GetHashCode()' +} diff --git a/src/Controls/src/BindingSourceGen/ISymbolExtensions.cs b/src/Controls/src/BindingSourceGen/ISymbolExtensions.cs new file mode 100644 index 000000000000..31436ffed748 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/ISymbolExtensions.cs @@ -0,0 +1,67 @@ +using Microsoft.CodeAnalysis; + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +internal static class ISymbolExtensions +{ + internal static bool IsAccessible(this ISymbol symbol) => + symbol.DeclaredAccessibility == Accessibility.Public + || symbol.DeclaredAccessibility == Accessibility.Internal + || symbol.DeclaredAccessibility == Accessibility.ProtectedOrInternal; + + internal static AccessorKind ToAccessorKind(this ISymbol symbol) + { + return symbol switch + { + IFieldSymbol _ => AccessorKind.Field, + IPropertySymbol _ => AccessorKind.Property, + _ => throw new ArgumentException("Symbol is not a field or property.", nameof(symbol)) + }; + } + + internal static string GetIndexerName(this ISymbol? elementAccessSymbol) + { + const string defaultName = "Item"; + + if (elementAccessSymbol is not IPropertySymbol propertySymbol) + { + return defaultName; + } + + var containgType = propertySymbol.ContainingType; + if (containgType == null) + { + return defaultName; + } + + var defaultMemberAttribute = GetAttribute(containgType, "DefaultMemberAttribute"); + if (defaultMemberAttribute != null) + { + return GetAttributeValue(defaultMemberAttribute); + } + + var indexerNameAttr = GetAttribute(propertySymbol, "IndexerNameAttribute"); + if (indexerNameAttr != null) + { + return GetAttributeValue(indexerNameAttr); + } + + return defaultName; + + AttributeData? GetAttribute(ISymbol symbol, string attributeName) + { + return symbol.GetAttributes().FirstOrDefault(attr => attr.AttributeClass?.Name == attributeName); + } + + string GetAttributeValue(AttributeData attribute) + { + return (attribute.ConstructorArguments.Length > 0 ? attribute.ConstructorArguments[0].Value as string : null) ?? defaultName; + } + } +} + +public enum AccessorKind +{ + Field, + Property, +} diff --git a/src/Controls/src/BindingSourceGen/ITypeSymbolExtensions.cs b/src/Controls/src/BindingSourceGen/ITypeSymbolExtensions.cs new file mode 100644 index 000000000000..ec4a13b2cc30 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/ITypeSymbolExtensions.cs @@ -0,0 +1,46 @@ +using Microsoft.CodeAnalysis; + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +internal static class ITypeSymbolExtensions +{ + internal static bool IsTypeNullable(this ITypeSymbol typeInfo, bool enabledNullable) + { + if (!enabledNullable && typeInfo.IsReferenceType) + { + return true; + } + + return typeInfo.IsNullableValueType() || typeInfo.IsNullableReferenceType(); + } + + internal static TypeDescription CreateTypeDescription(this ITypeSymbol typeSymbol, bool enabledNullable) + { + var isNullable = IsTypeNullable(typeSymbol, enabledNullable); + return new TypeDescription( + GlobalName: GetGlobalName(typeSymbol, isNullable, typeSymbol.IsValueType), + IsNullable: isNullable, + IsGenericParameter: typeSymbol.Kind == SymbolKind.TypeParameter, //TODO: Add support for generic parameters + IsValueType: typeSymbol.IsValueType); + } + + private static bool IsNullableValueType(this ITypeSymbol typeInfo) => + typeInfo is INamedTypeSymbol namedTypeSymbol + && namedTypeSymbol.IsGenericType + && namedTypeSymbol.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T; + + private static bool IsNullableReferenceType(this ITypeSymbol typeInfo) => + typeInfo.IsReferenceType && typeInfo.NullableAnnotation == NullableAnnotation.Annotated; + + + private static string GetGlobalName(this ITypeSymbol typeSymbol, bool isNullable, bool isValueType) + { + if (isNullable && isValueType) + { + // Strips the "?" from the type name + return ((INamedTypeSymbol)typeSymbol).TypeArguments[0].ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + } + + return typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + } +} diff --git a/src/Controls/src/BindingSourceGen/InvocationParser.cs b/src/Controls/src/BindingSourceGen/InvocationParser.cs new file mode 100644 index 000000000000..bba633ce3f3d --- /dev/null +++ b/src/Controls/src/BindingSourceGen/InvocationParser.cs @@ -0,0 +1,109 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +internal class InvocationParser +{ + private readonly GeneratorSyntaxContext _context; + + internal InvocationParser(GeneratorSyntaxContext context) + { + _context = context; + } + + private class InterceptedMethodsNames + { + internal const string SetBinding = nameof(SetBinding); + internal const string Create = nameof(Create); + } + + internal Result ParseInvocation(InvocationExpressionSyntax invocationSyntax, CancellationToken t) + { + return ((MemberAccessExpressionSyntax)invocationSyntax.Expression).Name.Identifier.Text switch + { + InterceptedMethodsNames.SetBinding => VerifyCorrectOverloadSetBinding(invocationSyntax, t), + InterceptedMethodsNames.Create => VerifyCorrectOverloadBindingCreate(invocationSyntax, t), + _ => throw new NotSupportedException() + }; + } + + private Result VerifyCorrectOverloadBindingCreate(InvocationExpressionSyntax invocation, CancellationToken t) + { + var argumentList = invocation.ArgumentList.Arguments; + + var symbol = _context.SemanticModel.GetSymbolInfo(invocation.Expression).Symbol; + if ((symbol?.ContainingType?.Name != "Binding" && symbol?.ContainingType?.Name != "BindingBase") + || symbol?.ContainingType?.ContainingNamespace.ToDisplayString() is not "Microsoft.Maui.Controls") + { + return Result.Failure(DiagnosticsFactory.SuboptimalSetBindingOverload(invocation.GetLocation())); + } + + if (argumentList.Count == 0) + { + throw new ArgumentOutOfRangeException(nameof(invocation)); + } + + var firstArgument = argumentList[0].Expression; + if (firstArgument is IdentifierNameSyntax) + { + var type = _context.SemanticModel.GetTypeInfo(firstArgument, cancellationToken: t).Type; + if (type != null && type.Name == "Func") + { + return Result.Failure(DiagnosticsFactory.GetterIsNotLambda(firstArgument.GetLocation())); + } + else // String and Binding + { + return Result.Failure(DiagnosticsFactory.SuboptimalSetBindingOverload(firstArgument.GetLocation())); + } + } + + return Result.Success(InterceptedMethodType.Create); + } + + private Result VerifyCorrectOverloadSetBinding(InvocationExpressionSyntax invocation, CancellationToken t) + { + var symbol = _context.SemanticModel.GetSymbolInfo(invocation.Expression).Symbol; + if (symbol is not null) + { + if (symbol is not IMethodSymbol methodSymbol + || methodSymbol.Kind != SymbolKind.Method + || methodSymbol.Name != "SetBinding" + || !methodSymbol.IsGenericMethod + || methodSymbol.TypeParameters.Length != 2 + || methodSymbol.Parameters.Length != 9 + || methodSymbol.ContainingType?.Name != "BindableObjectExtensions" + || methodSymbol.ContainingType?.ContainingNamespace.ToDisplayString() is not "Microsoft.Maui.Controls") + { + // ignore this method invocation + return Result.Failure(DiagnosticsFactory.SuboptimalSetBindingOverload(invocation.GetLocation())); + } + } + else + { + // It is not possible to resolve the method symbol when the bindable object (the first argument or the object that the extension method + // is called on) is referenced by a field that will be generated via XamlG based on the x:Name attributes. In that case, this source generator + // cannot see the outputs of the other source generator and we have incomplete information about the method invocation and we can only work with + // the syntax tree and not the semantic model. + + var argumentsList = invocation.ArgumentList.Arguments; + if (argumentsList.Count < 2) + { + return Result.Failure(DiagnosticsFactory.SuboptimalSetBindingOverload(invocation.GetLocation())); + } + + var secondArgument = argumentsList[1].Expression; + if (secondArgument is not LambdaExpressionSyntax) + { + var secondArgumentType = _context.SemanticModel.GetTypeInfo(secondArgument, cancellationToken: t).Type; + return secondArgumentType switch + { + { Name: "Func", ContainingNamespace.Name: "System" } => Result.Failure(DiagnosticsFactory.GetterIsNotLambda(secondArgument.GetLocation())), + _ => Result.Failure(DiagnosticsFactory.SuboptimalSetBindingOverload(secondArgument.GetLocation())), + }; + } + } + + return Result.Success(InterceptedMethodType.SetBinding); + } +} diff --git a/src/Controls/src/BindingSourceGen/IsExternalInitCompat.cs b/src/Controls/src/BindingSourceGen/IsExternalInitCompat.cs new file mode 100644 index 000000000000..97b7ffc4ecae --- /dev/null +++ b/src/Controls/src/BindingSourceGen/IsExternalInitCompat.cs @@ -0,0 +1,11 @@ +using System.ComponentModel; + +namespace System.Runtime.CompilerServices; + +/// +/// This dummy class is required to compile records when targeting .NET Standard +/// +[EditorBrowsable(EditorBrowsableState.Never)] +public static class IsExternalInit +{ +} diff --git a/src/Controls/src/BindingSourceGen/PathParser.cs b/src/Controls/src/BindingSourceGen/PathParser.cs new file mode 100644 index 000000000000..99bf47af109c --- /dev/null +++ b/src/Controls/src/BindingSourceGen/PathParser.cs @@ -0,0 +1,196 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Maui.Controls.BindingSourceGen; + +internal class PathParser +{ + private readonly GeneratorSyntaxContext _context; + private readonly bool _enabledNullable; + + internal PathParser(GeneratorSyntaxContext context, bool enabledNullable) + { + _context = context; + _enabledNullable = enabledNullable; + } + + internal Result> ParsePath(CSharpSyntaxNode? expressionSyntax) + { + return expressionSyntax switch + { + IdentifierNameSyntax _ => Result>.Success(new List()), + MemberAccessExpressionSyntax memberAccess => HandleMemberAccessExpression(memberAccess), + ElementAccessExpressionSyntax elementAccess => HandleElementAccessExpression(elementAccess), + ElementBindingExpressionSyntax elementBinding => HandleElementBindingExpression(elementBinding), + ConditionalAccessExpressionSyntax conditionalAccess => HandleConditionalAccessExpression(conditionalAccess), + MemberBindingExpressionSyntax memberBinding => HandleMemberBindingExpression(memberBinding), + ParenthesizedExpressionSyntax parenthesized => ParsePath(parenthesized.Expression), + BinaryExpressionSyntax asExpression when asExpression.Kind() == SyntaxKind.AsExpression => HandleBinaryExpression(asExpression), + CastExpressionSyntax castExpression => HandleCastExpression(castExpression), + _ => HandleDefaultCase(), + }; + } + + private Result> HandleMemberAccessExpression(MemberAccessExpressionSyntax memberAccess) + { + var result = ParsePath(memberAccess.Expression); + if (result.HasDiagnostics) + { + return result; + } + + var member = memberAccess.Name.Identifier.Text; + var typeInfo = _context.SemanticModel.GetTypeInfo(memberAccess).Type; + var symbol = _context.SemanticModel.GetSymbolInfo(memberAccess).Symbol; + + if (symbol == null || typeInfo == null) + { + return Result>.Failure(DiagnosticsFactory.UnableToResolvePath(memberAccess.GetLocation())); + } + + var isReferenceType = typeInfo.IsReferenceType; + var accessorKind = symbol.ToAccessorKind(); + var memberType = typeInfo.CreateTypeDescription(_enabledNullable); + var containgType = symbol.ContainingType.CreateTypeDescription(_enabledNullable); + + IPathPart part = symbol.IsAccessible() + ? new MemberAccess(member, !isReferenceType) + : new InaccessibleMemberAccess(containgType, memberType, accessorKind, member, !isReferenceType); + + result.Value.Add(part); + return Result>.Success(result.Value); + } + + private Result> HandleElementAccessExpression(ElementAccessExpressionSyntax elementAccess) + { + var result = ParsePath(elementAccess.Expression); + if (result.HasDiagnostics) + { + return result; + } + + var elementAccessSymbol = _context.SemanticModel.GetSymbolInfo(elementAccess).Symbol; + var elementType = _context.SemanticModel.GetTypeInfo(elementAccess).Type; + + var elementAccessResult = CreateIndexAccess(elementAccessSymbol, elementType, elementAccess.ArgumentList.Arguments, elementAccess.GetLocation()); + if (elementAccessResult.HasDiagnostics) + { + return elementAccessResult; + } + result.Value.AddRange(elementAccessResult.Value); + + return Result>.Success(result.Value); + } + + private Result> HandleConditionalAccessExpression(ConditionalAccessExpressionSyntax conditionalAccess) + { + var expressionResult = ParsePath(conditionalAccess.Expression); + if (expressionResult.HasDiagnostics) + { + return expressionResult; + } + + var whenNotNullResult = ParsePath(conditionalAccess.WhenNotNull); + if (whenNotNullResult.HasDiagnostics) + { + return whenNotNullResult; + } + + expressionResult.Value.AddRange(whenNotNullResult.Value); + + return Result>.Success(expressionResult.Value); + } + + private Result> HandleMemberBindingExpression(MemberBindingExpressionSyntax memberBinding) + { + var member = memberBinding.Name.Identifier.Text; + var typeInfo = _context.SemanticModel.GetTypeInfo(memberBinding).Type; + var isReferenceType = typeInfo?.IsReferenceType ?? false; + IPathPart part = new MemberAccess(member, !isReferenceType); + part = new ConditionalAccess(part); + + return Result>.Success(new List([part])); + } + + private Result> HandleElementBindingExpression(ElementBindingExpressionSyntax elementBinding) + { + var elementAccessSymbol = _context.SemanticModel.GetSymbolInfo(elementBinding).Symbol; + var elementType = _context.SemanticModel.GetTypeInfo(elementBinding).Type; + + var elementAccessResult = CreateIndexAccess(elementAccessSymbol, elementType, elementBinding.ArgumentList.Arguments, elementBinding.GetLocation()); + if (elementAccessResult.HasDiagnostics) + { + return elementAccessResult; + } + + elementAccessResult.Value[0] = new ConditionalAccess(elementAccessResult.Value[0]); + + return Result>.Success(elementAccessResult.Value); + } + + private Result> HandleBinaryExpression(BinaryExpressionSyntax asExpression) + { + var leftResult = ParsePath(asExpression.Left); + if (leftResult.HasDiagnostics) + { + return leftResult; + } + + var castTo = asExpression.Right; + var typeInfo = _context.SemanticModel.GetTypeInfo(castTo).Type; + if (typeInfo == null) + { + return Result>.Failure(DiagnosticsFactory.UnableToResolvePath(castTo.GetLocation())); + }; + + leftResult.Value.Add(new Cast(typeInfo.CreateTypeDescription(_enabledNullable))); + + return Result>.Success(leftResult.Value); + } + + private Result> HandleCastExpression(CastExpressionSyntax castExpression) + { + var result = ParsePath(castExpression.Expression); + if (result.HasDiagnostics) + { + return result; + } + + var typeInfo = _context.SemanticModel.GetTypeInfo(castExpression.Type).Type; + if (typeInfo == null) + { + return Result>.Failure(DiagnosticsFactory.UnableToResolvePath(castExpression.GetLocation())); + }; + + result.Value.Add(new Cast(typeInfo.CreateTypeDescription(_enabledNullable))); + + return Result>.Success(result.Value); + } + + private Result> HandleDefaultCase() + { + return Result>.Failure(DiagnosticsFactory.UnableToResolvePath(_context.Node.GetLocation())); + } + + private Result> CreateIndexAccess(ISymbol? elementAccessSymbol, ITypeSymbol? typeSymbol, SeparatedSyntaxList argumentList, Location location) + { + if (argumentList.Count != 1) + { + return Result>.Failure(DiagnosticsFactory.UnableToResolvePath(location)); + } + + var indexExpression = argumentList[0].Expression; + object? indexValue = _context.SemanticModel.GetConstantValue(indexExpression).Value; + if (indexValue is null) + { + return Result>.Failure(DiagnosticsFactory.UnableToResolvePath(indexExpression.GetLocation())); + } + + var name = elementAccessSymbol.GetIndexerName(); + var isReferenceType = typeSymbol?.IsReferenceType ?? false; + IPathPart part = new IndexAccess(name, indexValue, !isReferenceType); + + return Result>.Success(new List([part])); + } +} diff --git a/src/Controls/src/BindingSourceGen/PathPart.cs b/src/Controls/src/BindingSourceGen/PathPart.cs new file mode 100644 index 000000000000..59b0a7e61181 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/PathPart.cs @@ -0,0 +1,64 @@ +namespace Microsoft.Maui.Controls.BindingSourceGen; + +public interface IPathPart : IEquatable +{ + public string? PropertyName { get; } +} + +public sealed record InaccessibleMemberAccess(TypeDescription ContainingType, TypeDescription memberType, AccessorKind Kind, string MemberName, bool IsValueType = false) : IPathPart +{ + public string PropertyName => MemberName; + + public bool Equals(IPathPart other) + { + return other is InaccessibleMemberAccess memberAccess + && ContainingType == memberAccess.ContainingType + && Kind == memberAccess.Kind + && MemberName == memberAccess.MemberName + && IsValueType == memberAccess.IsValueType; + } +} + +public record MemberAccess(string MemberName, bool IsValueType = false) : IPathPart +{ + public string PropertyName => MemberName; + public bool Equals(IPathPart other) + { + return other is MemberAccess memberAccess + && MemberName == memberAccess.MemberName + && IsValueType == memberAccess.IsValueType; + } +} + +public sealed record IndexAccess(string DefaultMemberName, object Index, bool IsValueType = false) : IPathPart +{ + public string? PropertyName => $"{DefaultMemberName}[{Index}]"; + + public bool Equals(IPathPart other) + { + return other is IndexAccess indexAccess + && DefaultMemberName == indexAccess.DefaultMemberName + && Index.Equals(indexAccess.Index) + && IsValueType == indexAccess.IsValueType; + } +} + +public sealed record ConditionalAccess(IPathPart Part) : IPathPart +{ + public string? PropertyName => Part.PropertyName; + + public bool Equals(IPathPart other) + { + return other is ConditionalAccess conditionalAccess && Part.Equals(conditionalAccess.Part); + } +} + +public sealed record Cast(TypeDescription TargetType) : IPathPart +{ + public string? PropertyName => null; + + public bool Equals(IPathPart other) + { + return other is Cast cast && TargetType.Equals(cast.TargetType); + } +} diff --git a/src/Controls/src/BindingSourceGen/Result.cs b/src/Controls/src/BindingSourceGen/Result.cs new file mode 100644 index 000000000000..79b3fda2029a --- /dev/null +++ b/src/Controls/src/BindingSourceGen/Result.cs @@ -0,0 +1,23 @@ +namespace Microsoft.Maui.Controls.BindingSourceGen; + +public sealed record Result(T? OptionalValue, EquatableArray Diagnostics) +{ + public bool HasDiagnostics => Diagnostics.Length > 0; + + public T Value => OptionalValue ?? throw new InvalidOperationException("Result does not contain a value."); + + public static Result Success(T value) + { + return new Result(value, new EquatableArray(Array.Empty())); + } + + public static Result Failure(EquatableArray diagnostics) + { + return new Result(default, diagnostics); + } + + public static Result Failure(DiagnosticInfo diagnostic) + { + return new Result(default, new EquatableArray(new[] { diagnostic })); + } +} diff --git a/src/Controls/src/BindingSourceGen/Setter.cs b/src/Controls/src/BindingSourceGen/Setter.cs new file mode 100644 index 000000000000..42d58feeff03 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/Setter.cs @@ -0,0 +1,62 @@ +namespace Microsoft.Maui.Controls.BindingSourceGen; +using static Microsoft.Maui.Controls.BindingSourceGen.UnsafeAccessorsMethodName; + +public sealed record Setter(string[] PatternMatchingExpressions, string AssignmentStatement) +{ + public static Setter From( + IEnumerable path, + uint bindingId, + string sourceVariableName = "source", + string assignedValueExpression = "value") + { + string accessAccumulator = sourceVariableName; + List patternMatchingExpressions = new(); + bool skipNextConditionalAccess = false; + + void AddPatternMatchingExpression(string pattern) + { + var tmpVariableName = $"p{patternMatchingExpressions.Count}"; + patternMatchingExpressions.Add($"{accessAccumulator} is {pattern} {tmpVariableName}"); + accessAccumulator = tmpVariableName; + } + + foreach (var part in path) + { + var skipConditionalAccess = skipNextConditionalAccess; + skipNextConditionalAccess = false; + + if (part is Cast { TargetType: var targetType }) + { + AddPatternMatchingExpression(targetType.GlobalName); + + // the current `is T` expression makes sure that the value is not null + // so if a conditional access to a member/indexer follows, we can skip the next null check + skipNextConditionalAccess = true; + } + else if (part is ConditionalAccess { Part: var innerPart }) + { + if (!skipConditionalAccess) + { + AddPatternMatchingExpression("{}"); + } + + accessAccumulator = AccessExpressionBuilder.ExtendExpression(accessAccumulator, innerPart, bindingId); + } + else + { + accessAccumulator = AccessExpressionBuilder.ExtendExpression(accessAccumulator, part, bindingId, part == path.Last()); + } + } + + return new Setter( + patternMatchingExpressions.ToArray(), + AssignmentStatement: BuildAssignmentStatement(accessAccumulator, path.Any() ? path.Last() : null, bindingId, assignedValueExpression)); + } + + public static string BuildAssignmentStatement(string accessAccumulator, IPathPart? lastPart, uint bindingId, string assignedValueExpression = "value") => + lastPart switch + { + InaccessibleMemberAccess inaccessibleMemberAccess when inaccessibleMemberAccess.Kind == AccessorKind.Property => $"{CreateUnsafePropertyAccessorSetMethodName(bindingId, inaccessibleMemberAccess.MemberName)}({accessAccumulator}, {assignedValueExpression});", + _ => $"{accessAccumulator} = {assignedValueExpression};", + }; +} diff --git a/src/Controls/src/BindingSourceGen/UnsafeAccessorsMethodName.cs b/src/Controls/src/BindingSourceGen/UnsafeAccessorsMethodName.cs new file mode 100644 index 000000000000..49258da0f6c8 --- /dev/null +++ b/src/Controls/src/BindingSourceGen/UnsafeAccessorsMethodName.cs @@ -0,0 +1,8 @@ +namespace Microsoft.Maui.Controls.BindingSourceGen; + +internal static class UnsafeAccessorsMethodName +{ + internal static string CreateUnsafeFieldAccessorMethodName(uint bindingId, string fieldName) => $"GetUnsafeField{bindingId}{fieldName}"; + internal static string CreateUnsafePropertyAccessorGetMethodName(uint bindingId, string propertyName) => $"GetUnsafeProperty{bindingId}{propertyName}"; + internal static string CreateUnsafePropertyAccessorSetMethodName(uint bindingId, string propertyName) => $"SetUnsafeProperty{bindingId}{propertyName}"; +} diff --git a/src/Controls/src/Build.Tasks/BuildException.cs b/src/Controls/src/Build.Tasks/BuildException.cs index f506850d8c14..d64773afebdf 100644 --- a/src/Controls/src/Build.Tasks/BuildException.cs +++ b/src/Controls/src/Build.Tasks/BuildException.cs @@ -30,7 +30,12 @@ protected BuildException(System.Runtime.Serialization.SerializationInfo info, Sy static string FormatMessage(BuildExceptionCode code, IXmlLineInfo xmlinfo, object[] args) { - var message = string.Format(ErrorMessages.ResourceManager.GetString(code.ErrorMessageKey), args); + var message = ErrorMessages.ResourceManager.GetString(code.ErrorMessageKey); + if (args is not null) + { + message = string.Format(message, args); + } + var ecode = code.Code; var position = xmlinfo == null || !xmlinfo.HasLineInfo() ? "" : $"({xmlinfo.LineNumber},{xmlinfo.LinePosition})"; @@ -41,55 +46,58 @@ static string FormatMessage(BuildExceptionCode code, IXmlLineInfo xmlinfo, objec class BuildExceptionCode { //Assemblies, Types, Members - public static BuildExceptionCode TypeResolution = new BuildExceptionCode("XFC", 0000, nameof(TypeResolution), ""); - public static BuildExceptionCode PropertyResolution = new BuildExceptionCode("XFC", 0001, nameof(PropertyResolution), ""); - public static BuildExceptionCode MissingEventHandler = new BuildExceptionCode("XFC", 0002, nameof(MissingEventHandler), ""); - public static BuildExceptionCode PropertyMissing = new BuildExceptionCode("XFC", 0003, nameof(PropertyMissing), ""); - public static BuildExceptionCode ConstructorDefaultMissing = new BuildExceptionCode("XFC", 0004, nameof(ConstructorDefaultMissing), ""); - public static BuildExceptionCode ConstructorXArgsMissing = new BuildExceptionCode("XFC", 0005, nameof(ConstructorXArgsMissing), ""); - public static BuildExceptionCode MethodStaticMissing = new BuildExceptionCode("XFC", 0006, nameof(MethodStaticMissing), ""); - public static BuildExceptionCode EnumValueMissing = new BuildExceptionCode("XFC", 0007, nameof(EnumValueMissing), ""); - public static BuildExceptionCode AdderMissing = new BuildExceptionCode("XFC", 0008, nameof(AdderMissing), ""); - public static BuildExceptionCode MemberResolution = new BuildExceptionCode("XFC", 0009, nameof(MemberResolution), ""); + public static BuildExceptionCode TypeResolution = new BuildExceptionCode("XC", 0000, nameof(TypeResolution), ""); + public static BuildExceptionCode PropertyResolution = new BuildExceptionCode("XC", 0001, nameof(PropertyResolution), ""); + public static BuildExceptionCode MissingEventHandler = new BuildExceptionCode("XC", 0002, nameof(MissingEventHandler), ""); + public static BuildExceptionCode PropertyMissing = new BuildExceptionCode("XC", 0003, nameof(PropertyMissing), ""); + public static BuildExceptionCode ConstructorDefaultMissing = new BuildExceptionCode("XC", 0004, nameof(ConstructorDefaultMissing), ""); + public static BuildExceptionCode ConstructorXArgsMissing = new BuildExceptionCode("XC", 0005, nameof(ConstructorXArgsMissing), ""); + public static BuildExceptionCode MethodStaticMissing = new BuildExceptionCode("XC", 0006, nameof(MethodStaticMissing), ""); + public static BuildExceptionCode EnumValueMissing = new BuildExceptionCode("XC", 0007, nameof(EnumValueMissing), ""); + public static BuildExceptionCode AdderMissing = new BuildExceptionCode("XC", 0008, nameof(AdderMissing), ""); + public static BuildExceptionCode MemberResolution = new BuildExceptionCode("XC", 0009, nameof(MemberResolution), ""); //BP,BO - public static BuildExceptionCode BPName = new BuildExceptionCode("XFC", 0020, nameof(BPName), ""); - public static BuildExceptionCode BPMissingGetter = new BuildExceptionCode("XFC", 0021, nameof(BPMissingGetter), ""); + public static BuildExceptionCode BPName = new BuildExceptionCode("XC", 0020, nameof(BPName), ""); + public static BuildExceptionCode BPMissingGetter = new BuildExceptionCode("XC", 0021, nameof(BPMissingGetter), ""); public static BuildExceptionCode BindingWithoutDataType = new BuildExceptionCode("XC", 0022, nameof(BindingWithoutDataType), "https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings"); //warning public static BuildExceptionCode BindingWithNullDataType = new BuildExceptionCode("XC", 0023, nameof(BindingWithNullDataType), "https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings"); //warning + public static BuildExceptionCode BindingWithXDataTypeFromOuterScope = new BuildExceptionCode("XC", 0024, nameof(BindingWithXDataTypeFromOuterScope), "https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings"); + public static BuildExceptionCode BindingWithSourceCompilationSkipped = new BuildExceptionCode("XC", 0025, nameof(BindingWithSourceCompilationSkipped), "https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings"); //warning //Bindings, conversions - public static BuildExceptionCode Conversion = new BuildExceptionCode("XFC", 0040, nameof(Conversion), ""); - public static BuildExceptionCode BindingIndexerNotClosed = new BuildExceptionCode("XFC", 0041, nameof(BindingIndexerNotClosed), ""); - public static BuildExceptionCode BindingIndexerEmpty = new BuildExceptionCode("XFC", 0042, nameof(BindingIndexerEmpty), ""); - public static BuildExceptionCode BindingIndexerTypeUnsupported = new BuildExceptionCode("XFC", 0043, nameof(BindingIndexerTypeUnsupported), ""); - public static BuildExceptionCode BindingIndexerParse = new BuildExceptionCode("XFC", 0044, nameof(BindingIndexerParse), ""); - public static BuildExceptionCode BindingPropertyNotFound = new BuildExceptionCode("XFC", 0045, nameof(BindingPropertyNotFound), ""); + public static BuildExceptionCode Conversion = new BuildExceptionCode("XC", 0040, nameof(Conversion), ""); + public static BuildExceptionCode BindingIndexerNotClosed = new BuildExceptionCode("XC", 0041, nameof(BindingIndexerNotClosed), ""); + public static BuildExceptionCode BindingIndexerEmpty = new BuildExceptionCode("XC", 0042, nameof(BindingIndexerEmpty), ""); + public static BuildExceptionCode BindingIndexerTypeUnsupported = new BuildExceptionCode("XC", 0043, nameof(BindingIndexerTypeUnsupported), ""); + public static BuildExceptionCode BindingIndexerParse = new BuildExceptionCode("XC", 0044, nameof(BindingIndexerParse), ""); + public static BuildExceptionCode BindingPropertyNotFound = new BuildExceptionCode("XC", 0045, nameof(BindingPropertyNotFound), ""); //XAML issues - public static BuildExceptionCode MarkupNotClosed = new BuildExceptionCode("XFC", 0060, nameof(MarkupNotClosed), ""); - public static BuildExceptionCode MarkupParsingFailed = new BuildExceptionCode("XFC", 0061, nameof(MarkupParsingFailed), ""); - public static BuildExceptionCode XmlnsUndeclared = new BuildExceptionCode("XFC", 0062, nameof(XmlnsUndeclared), ""); - public static BuildExceptionCode SByteEnums = new BuildExceptionCode("XFC", 0063, nameof(SByteEnums), ""); - public static BuildExceptionCode NamescopeDuplicate = new BuildExceptionCode("XFC", 0064, nameof(NamescopeDuplicate), ""); - public static BuildExceptionCode ContentPropertyAttributeMissing = new BuildExceptionCode("XFC", 0065, nameof(ContentPropertyAttributeMissing), ""); - public static BuildExceptionCode InvalidXaml = new BuildExceptionCode("XFC", 0066, nameof(InvalidXaml), ""); + public static BuildExceptionCode MarkupNotClosed = new BuildExceptionCode("XC", 0060, nameof(MarkupNotClosed), ""); + public static BuildExceptionCode MarkupParsingFailed = new BuildExceptionCode("XC", 0061, nameof(MarkupParsingFailed), ""); + public static BuildExceptionCode XmlnsUndeclared = new BuildExceptionCode("XC", 0062, nameof(XmlnsUndeclared), ""); + public static BuildExceptionCode SByteEnums = new BuildExceptionCode("XC", 0063, nameof(SByteEnums), ""); + public static BuildExceptionCode NamescopeDuplicate = new BuildExceptionCode("XC", 0064, nameof(NamescopeDuplicate), ""); + public static BuildExceptionCode ContentPropertyAttributeMissing = new BuildExceptionCode("XC", 0065, nameof(ContentPropertyAttributeMissing), ""); + public static BuildExceptionCode InvalidXaml = new BuildExceptionCode("XC", 0066, nameof(InvalidXaml), ""); //Extensions - public static BuildExceptionCode XStaticSyntax = new BuildExceptionCode("XFC", 0100, nameof(XStaticSyntax), ""); - public static BuildExceptionCode XStaticResolution = new BuildExceptionCode("XFC", 0101, nameof(XStaticResolution), ""); - public static BuildExceptionCode XDataTypeSyntax = new BuildExceptionCode("XFC", 0102, nameof(XDataTypeSyntax), ""); + public static BuildExceptionCode XStaticSyntax = new BuildExceptionCode("XC", 0100, nameof(XStaticSyntax), ""); + public static BuildExceptionCode XStaticResolution = new BuildExceptionCode("XC", 0101, nameof(XStaticResolution), ""); + public static BuildExceptionCode XDataTypeSyntax = new BuildExceptionCode("XC", 0102, nameof(XDataTypeSyntax), ""); + public static BuildExceptionCode UnattributedMarkupType = new BuildExceptionCode("XC", 0103, nameof(UnattributedMarkupType), ""); //warning //Style, StyleSheets, Resources - public static BuildExceptionCode StyleSheetSourceOrContent = new BuildExceptionCode("XFC", 0120, nameof(StyleSheetSourceOrContent), ""); - public static BuildExceptionCode StyleSheetNoSourceOrContent = new BuildExceptionCode("XFC", 0121, nameof(StyleSheetNoSourceOrContent), ""); - public static BuildExceptionCode StyleSheetStyleNotALiteral = new BuildExceptionCode("XFC", 0122, nameof(StyleSheetStyleNotALiteral), ""); - public static BuildExceptionCode StyleSheetSourceNotALiteral = new BuildExceptionCode("XFC", 0123, nameof(StyleSheetSourceNotALiteral), ""); - public static BuildExceptionCode ResourceMissing = new BuildExceptionCode("XFC", 0124, nameof(ResourceMissing), ""); - public static BuildExceptionCode ResourceDictDuplicateKey = new BuildExceptionCode("XFC", 0125, nameof(ResourceDictDuplicateKey), ""); - public static BuildExceptionCode ResourceDictMissingKey = new BuildExceptionCode("XFC", 0126, nameof(ResourceDictMissingKey), ""); - public static BuildExceptionCode XKeyNotLiteral = new BuildExceptionCode("XFC", 0127, nameof(XKeyNotLiteral), ""); + public static BuildExceptionCode StyleSheetSourceOrContent = new BuildExceptionCode("XC", 0120, nameof(StyleSheetSourceOrContent), ""); + public static BuildExceptionCode StyleSheetNoSourceOrContent = new BuildExceptionCode("XC", 0121, nameof(StyleSheetNoSourceOrContent), ""); + public static BuildExceptionCode StyleSheetStyleNotALiteral = new BuildExceptionCode("XC", 0122, nameof(StyleSheetStyleNotALiteral), ""); + public static BuildExceptionCode StyleSheetSourceNotALiteral = new BuildExceptionCode("XC", 0123, nameof(StyleSheetSourceNotALiteral), ""); + public static BuildExceptionCode ResourceMissing = new BuildExceptionCode("XC", 0124, nameof(ResourceMissing), ""); + public static BuildExceptionCode ResourceDictDuplicateKey = new BuildExceptionCode("XC", 0125, nameof(ResourceDictDuplicateKey), ""); + public static BuildExceptionCode ResourceDictMissingKey = new BuildExceptionCode("XC", 0126, nameof(ResourceDictMissingKey), ""); + public static BuildExceptionCode XKeyNotLiteral = new BuildExceptionCode("XC", 0127, nameof(XKeyNotLiteral), ""); public static BuildExceptionCode StaticResourceSyntax = new BuildExceptionCode("XC", 0128, nameof(StaticResourceSyntax), ""); //CSC equivalents diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs index e8876ea4761c..aaeb4f497065 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs @@ -44,31 +44,95 @@ public IEnumerable ConvertFromString(string value, ILContext contex var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath); - //fail early - var resourceId = XamlCTask.GetResourceIdForPath(context.Cache, module, resourcePath); - if (resourceId == null) - throw new BuildException(BuildExceptionCode.ResourceMissing, node, null, value); + foreach (var instruction in CreateUri(context, (ILRootNode)rootNode, value, node, asmName)) + yield return instruction; - var resourceDictionaryType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"); + var uriVarDef = new VariableDefinition(currentModule.ImportReference(context.Cache, ("System", "System", "Uri"))); + body.Variables.Add(uriVarDef); + yield return Create(Stloc, uriVarDef); - //abuse the converter, produce some side effect, but leave the stack untouched - //public void SetAndLoadSource(Uri value, string resourceID, Assembly assembly, System.Xml.IXmlLineInfo lineInfo) - foreach (var instruction in context.Variables[rdNode].LoadAs(context.Cache, currentModule.GetTypeDefinition(context.Cache, resourceDictionaryType), currentModule)) - yield return instruction; + var resourceTypeRef = GetTypeForPath(context.Cache, module, resourcePath); + if (resourceTypeRef is not null) + { + foreach (var instruction in CreateResourceDictionaryType(context, currentModule, module, node, rdNode, resourceTypeRef, uriVarDef)) + yield return instruction; + } + else + { + // It is possible that this resource exists but it is not compiled and it doesn't have a resource type associated with it (e.g., using ) + // we can still generate code that will load the XAML from the resource file at runtime. This code won't be trimming safe and the generated code + // will produce trimming warnings when compiled. + var resourceId = XamlCTask.GetResourceIdForPath(context.Cache, module, resourcePath); + if (resourceId is null) + { + throw new BuildException(BuildExceptionCode.ResourceMissing, node, null, value); + } + + foreach (var instruction in LoadResourceDictionaryFromSource(context, currentModule, (ILRootNode)rootNode, node, rdNode, uriVarDef, resourcePath, asmName)) + yield return instruction; + } + + yield return Create(Ldloc, uriVarDef); + } + + private static IEnumerable CreateUri(ILContext context, ILRootNode rootNode, string value, BaseNode node, string asmName) + { //reappend assembly= in all cases, see other RD converter if (!string.IsNullOrEmpty(asmName)) value = $"{value};assembly={asmName}"; else - value = $"{value};assembly={((ILRootNode)rootNode).TypeReference.Module.Assembly.Name.Name}"; + value = $"{value};assembly={rootNode.TypeReference.Module.Assembly.Name.Name}"; foreach (var instruction in (new UriTypeConverter()).ConvertFromString(value, context, node)) yield return instruction; //the Uri + } - //keep the Uri for later - yield return Create(Dup); - var uriVarDef = new VariableDefinition(currentModule.ImportReference(context.Cache, ("System", "System", "Uri"))); - body.Variables.Add(uriVarDef); - yield return Create(Stloc, uriVarDef); - yield return Create(Ldstr, resourcePath); //resourcePath + private static IEnumerable CreateResourceDictionaryType( + ILContext context, + ModuleDefinition currentModule, + ModuleDefinition module, + BaseNode node, + IElementNode rdNode, + TypeReference resourceTypeRef, + VariableDefinition uriVarDef) + { + var resourceType = module.ImportReference(resourceTypeRef).Resolve(); + + // validate that the resourceType has a default ctor + var hasDefaultCtor = resourceType.Methods.Any(md => md.IsConstructor && !md.HasParameters); + if (!hasDefaultCtor) + throw new BuildException(BuildExceptionCode.ConstructorDefaultMissing, node, null, resourceType); + + var method = module.ImportMethodReference( + context.Cache, + ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"), + methodName: "SetAndCreateSource", + parameterTypes: new[] { ("System", "System", "Uri") }); + + var genericInstanceMethod = new GenericInstanceMethod(method); + genericInstanceMethod.GenericArguments.Add(resourceType); + + // public void rd.SetAndCreateSource(Uri value) + foreach (var instruction in context.Variables[rdNode].LoadAs(context.Cache, currentModule.GetTypeDefinition(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary")), currentModule)) + yield return instruction; + yield return Create(Ldloc, uriVarDef); + yield return Create(Callvirt, currentModule.ImportReference(genericInstanceMethod)); + } + + private static IEnumerable LoadResourceDictionaryFromSource( + ILContext context, + ModuleDefinition currentModule, + ILRootNode rootNode, + BaseNode node, + IElementNode rdNode, + VariableDefinition uriVarDef, + string resourcePath, + string asmName) + { + // public void static ResourceDictionaryHelpers.LoadFromSource(ResourceDictionary rd, Uri source, string resourcePath, Assembly assembly, IXmlLineInfo lineInfo) + foreach (var instruction in context.Variables[rdNode].LoadAs(context.Cache, currentModule.GetTypeDefinition(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary")), currentModule)) + yield return instruction; + yield return Create(Ldloc, uriVarDef); + yield return Create(Ldstr, resourcePath); if (!string.IsNullOrEmpty(asmName)) { @@ -77,18 +141,25 @@ public IEnumerable ConvertFromString(string value, ILContext contex } else //we could use assembly.Load in the 'else' part too, but I don't want to change working code right now { - yield return Create(Ldtoken, currentModule.ImportReference(((ILRootNode)rootNode).TypeReference)); + yield return Create(Ldtoken, currentModule.ImportReference(rootNode.TypeReference)); yield return Create(Call, currentModule.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); yield return Create(Callvirt, currentModule.ImportPropertyGetterReference(context.Cache, ("mscorlib", "System", "Type"), propertyName: "Assembly", flatten: true)); } + foreach (var instruction in node.PushXmlLineInfo(context)) - yield return instruction; //lineinfo - yield return Create(Callvirt, currentModule.ImportMethodReference(context.Cache, - resourceDictionaryType, - methodName: "SetAndLoadSource", - parameterTypes: new[] { ("System", "System", "Uri"), ("mscorlib", "System", "String"), ("mscorlib", "System.Reflection", "Assembly"), ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") })); - //ldloc the stored uri as return value - yield return Create(Ldloc, uriVarDef); + yield return instruction; + + yield return Create(Call, currentModule.ImportMethodReference( + context.Cache, + ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml", "ResourceDictionaryHelpers"), + methodName: "LoadFromSource", + parameterTypes: new[] { + ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"), + ("System", "System", "Uri"), + ("mscorlib", "System", "String"), + ("mscorlib", "System.Reflection", "Assembly"), + ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") }, + isStatic: true)); } internal static string GetPathForType(ILContext context, ModuleDefinition module, TypeReference type) @@ -103,5 +174,18 @@ internal static string GetPathForType(ILContext context, ModuleDefinition module } return null; } + + private static TypeReference GetTypeForPath(XamlCache cache, ModuleDefinition module, string path) + { + foreach (var ca in module.GetCustomAttributes()) + { + if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute")))) + continue; + if (ca.ConstructorArguments[1].Value as string != path) + continue; + return ca.ConstructorArguments[2].Value as TypeReference; + } + return null; + } } } \ No newline at end of file diff --git a/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/StaticResourceExtension.cs b/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/StaticResourceExtension.cs index 0df3af12a6ea..a78664dd4997 100644 --- a/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/StaticResourceExtension.cs +++ b/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/StaticResourceExtension.cs @@ -113,7 +113,7 @@ public static IEnumerable TryConvert(ValueNode stringResourceNode, if (bpRef != null) { var targetTypeRef = module.ImportReference(bpRef.GetBindablePropertyType(context.Cache, node as IXmlLineInfo, module)); - foreach (var instruction in stringResourceNode.PushConvertedValue(context, bpRef, stringResourceNode.PushServiceProvider(context, bpRef: bpRef), true, false)) + foreach (var instruction in stringResourceNode.PushConvertedValue(context, bpRef, requiredServices => stringResourceNode.PushServiceProvider(context, requiredServices, bpRef: bpRef), true, false)) yield return instruction; var vardef = new VariableDefinition(targetTypeRef); yield return Create(Stloc, vardef); @@ -124,7 +124,7 @@ public static IEnumerable TryConvert(ValueNode stringResourceNode, var propertyRef = parentType.GetProperty(context.Cache, pd => pd.Name == localName, out var declaringTypeReference); if (propertyRef != null) { - foreach (var instruction in stringResourceNode.PushConvertedValue(context, propertyRef.PropertyType, new ICustomAttributeProvider[] { propertyRef, propertyRef.PropertyType.ResolveCached(context.Cache) }, stringResourceNode.PushServiceProvider(context, propertyRef: propertyRef), true, false)) + foreach (var instruction in stringResourceNode.PushConvertedValue(context, propertyRef.PropertyType, new ICustomAttributeProvider[] { propertyRef, propertyRef.PropertyType.ResolveCached(context.Cache) }, requiredServices => stringResourceNode.PushServiceProvider(context, requiredServices, propertyRef: propertyRef), true, false)) yield return instruction; var vardef = new VariableDefinition(propertyRef.PropertyType); yield return Create(Stloc, vardef); @@ -167,7 +167,9 @@ public static IEnumerable FallBack(string key, IElementNode node, M propertyRef = parentType.GetProperty(context.Cache, pd => pd.Name == localName, out declaringTypeReference); } - foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, declaringTypeReference)) + + var requiredServices = staticResourceExtensionType.GetRequiredServices(context.Cache, module); + foreach (var instruction in node.PushServiceProvider(context, requiredServices, bpRef, propertyRef, declaringTypeReference)) yield return instruction; yield return Create(Callvirt, module.ImportMethodReference(context.Cache, diff --git a/src/Controls/src/Build.Tasks/CompiledValueProviders/SetterValueProvider.cs b/src/Controls/src/Build.Tasks/CompiledValueProviders/SetterValueProvider.cs index c44eb9e61e18..09c764c4a0f6 100644 --- a/src/Controls/src/Build.Tasks/CompiledValueProviders/SetterValueProvider.cs +++ b/src/Controls/src/Build.Tasks/CompiledValueProviders/SetterValueProvider.cs @@ -39,7 +39,7 @@ public IEnumerable ProvideValue(VariableDefinitionReference vardefr yield return instruction; //push the value - foreach (var instruction in ((ValueNode)valueNode).PushConvertedValue(context, bpRef, valueNode.PushServiceProvider(context, bpRef: bpRef), boxValueTypes: true, unboxValueTypes: false)) + foreach (var instruction in ((ValueNode)valueNode).PushConvertedValue(context, bpRef, (requiredServices) => valueNode.PushServiceProvider(context, requiredServices, bpRef: bpRef), boxValueTypes: true, unboxValueTypes: false)) yield return instruction; //set the value diff --git a/src/Controls/src/Build.Tasks/Controls.Build.Tasks.csproj b/src/Controls/src/Build.Tasks/Controls.Build.Tasks.csproj index 7da07333deaa..913661fc3d10 100644 --- a/src/Controls/src/Build.Tasks/Controls.Build.Tasks.csproj +++ b/src/Controls/src/Build.Tasks/Controls.Build.Tasks.csproj @@ -25,16 +25,17 @@ - - - - + + + + + @@ -49,6 +50,8 @@ + + diff --git a/src/Controls/src/Build.Tasks/CreateObjectVisitor.cs b/src/Controls/src/Build.Tasks/CreateObjectVisitor.cs index 1244530e390e..4e58dbf878a9 100644 --- a/src/Controls/src/Build.Tasks/CreateObjectVisitor.cs +++ b/src/Controls/src/Build.Tasks/CreateObjectVisitor.cs @@ -124,6 +124,17 @@ public void Visit(ElementNode node, INode parentNode) return; } + if (IsXaml2009LanguagePrimitive(node)) + { + var vardef = new VariableDefinition(typeref); + Context.Variables[node] = vardef; + Context.Body.Variables.Add(vardef); + + Context.IL.Append(PushValueFromLanguagePrimitive(typedef, node)); + Context.IL.Emit(Stloc, vardef); + return; + } + MethodDefinition factoryCtorInfo = null; MethodDefinition factoryMethodInfo = null; MethodDefinition parameterizedCtorInfo = null; @@ -204,7 +215,8 @@ public void Visit(ElementNode node, INode parentNode) { //Purple Context.IL.Append(vnode.PushConvertedValue(Context, typeref, new ICustomAttributeProvider[] { typedef }, - node.PushServiceProvider(Context), false, true)); + (requiredServices) => node.PushServiceProvider(Context, requiredServices), + false, true)); Context.IL.Emit(OpCodes.Stloc, vardef); } else if (node.CollectionItems.Count == 1 && (vnode = node.CollectionItems.First() as ValueNode) != null && @@ -313,7 +325,8 @@ IEnumerable PushCtorArguments(MethodReference ctorinfo, ElementNode foreach (var instruction in vnode.PushConvertedValue(Context, parameter.ParameterType, new ICustomAttributeProvider[] { parameter, parameter.ParameterType.ResolveCached(Context.Cache) }, - enode.PushServiceProvider(Context), false, true)) + (requiredServices) => enode.PushServiceProvider(Context, requiredServices), + false, true)) yield return instruction; } } @@ -350,7 +363,8 @@ IEnumerable PushCtorXArguments(MethodReference factoryCtorInfo, Ele foreach (var instruction in vnode.PushConvertedValue(Context, parameter.ParameterType, new ICustomAttributeProvider[] { parameter, parameter.ParameterType.ResolveCached(Context.Cache) }, - enode.PushServiceProvider(Context), false, true)) + (requiredServices) => enode.PushServiceProvider(Context, requiredServices), + false, true)) yield return instruction; } } diff --git a/src/Controls/src/Build.Tasks/ErrorMessages.Designer.cs b/src/Controls/src/Build.Tasks/ErrorMessages.Designer.cs index e3316e659b3f..9d958e40a2a5 100644 --- a/src/Controls/src/Build.Tasks/ErrorMessages.Designer.cs +++ b/src/Controls/src/Build.Tasks/ErrorMessages.Designer.cs @@ -313,7 +313,7 @@ internal static string StyleSheetSourceNotALiteral { } /// - /// Looks up a localized string similar to StyleSheet can not have both a Source and a content.. + /// Looks up a localized string similar to StyleSheet cannot have both a Source and a content.. /// internal static string StyleSheetSourceOrContent { get { @@ -340,7 +340,7 @@ internal static string TypeResolution { } /// - /// Looks up a localized string similar to x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}.. + /// Looks up a localized string similar to x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}.. /// internal static string XDataTypeSyntax { get { @@ -382,6 +382,15 @@ internal static string XStaticSyntax { get { return ResourceManager.GetString("XStaticSyntax", resourceCulture); } + } + + /// + /// Looks up a localized string similar to Consider attributing the markup extension with [AcceptEmptyServiceProvider] or [RequireService].. + /// + internal static string UnattributedMarkupType { + get { + return ResourceManager.GetString("UnattributedMarkupType", resourceCulture); + } } /// diff --git a/src/Controls/src/Build.Tasks/ErrorMessages.resx b/src/Controls/src/Build.Tasks/ErrorMessages.resx index 869fd764d172..39907273d5d0 100644 --- a/src/Controls/src/Build.Tasks/ErrorMessages.resx +++ b/src/Controls/src/Build.Tasks/ErrorMessages.resx @@ -137,10 +137,16 @@ Binding could be compiled to improve runtime performance if x:DataType is specified. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information. - + Binding could be compiled to improve runtime performance if x:DataType is not explicitly null. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information. - + + + Binding might be compiled incorrectly since the x:DataType annotation comes from an outer scope. Make sure you annotate all DataTemplate XAML elements with the correct x:DataType. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information. + + + Binding was not compiled because it has an explicitly set Source property and compilation of bindings with Source is not enabled. Consider enabling this optimization by setting the <MauiEnableXamlCBindingWithSourceCompilation>true</MauiEnableXamlCBindingWithSourceCompilation> in your project file and make sure the correct x:DataType is specified for this binding. See https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/compiled-bindings for more information. + Binding: Property "{0}" not found on "{1}". 0 is property name, 1 is type name @@ -231,7 +237,7 @@ Source property is not a string literal. - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. Style property or Content is not a string literal. @@ -241,8 +247,13 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + + + Consider attributing the markup extension "{0}" with [RequireService] or [AcceptEmptyServiceProvider] if it doesn't require any. + 0 is type name + Undeclared xmlns prefix "{0}". 0 is the xmlns prefix diff --git a/src/Controls/src/Build.Tasks/ILContext.cs b/src/Controls/src/Build.Tasks/ILContext.cs index 3a0f8cac3686..56630b15f561 100644 --- a/src/Controls/src/Build.Tasks/ILContext.cs +++ b/src/Controls/src/Build.Tasks/ILContext.cs @@ -20,6 +20,7 @@ public ILContext(ILProcessor il, MethodBody body, ModuleDefinition module, XamlC ParentContextValues = parentContextValues; Module = module; Cache = cache; + CompileBindingsWithSource = false; } public XamlCache Cache { get; private set; } @@ -46,5 +47,7 @@ public ILContext(ILProcessor il, MethodBody body, ModuleDefinition module, XamlC public TaskLoggingHelper LoggingHelper { get; internal set; } public bool ValidateOnly { get; set; } + + public bool CompileBindingsWithSource { get; set; } } } diff --git a/src/Controls/src/Build.Tasks/NodeILExtensions.cs b/src/Controls/src/Build.Tasks/NodeILExtensions.cs index c804f1070384..2e68a52c2e17 100644 --- a/src/Controls/src/Build.Tasks/NodeILExtensions.cs +++ b/src/Controls/src/Build.Tasks/NodeILExtensions.cs @@ -98,7 +98,7 @@ public static bool CanConvertValue(this ValueNode node, ILContext context, TypeR public static IEnumerable PushConvertedValue(this ValueNode node, ILContext context, TypeReference targetTypeRef, IEnumerable attributeProviders, - IEnumerable pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) + Func> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { TypeReference typeConverter = null; foreach (var attributeProvider in attributeProviders) @@ -119,7 +119,7 @@ public static IEnumerable PushConvertedValue(this ValueNode node, I } public static IEnumerable PushConvertedValue(this ValueNode node, ILContext context, FieldReference bpRef, - IEnumerable pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) + Func> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { var module = context.Body.Method.Module; var targetTypeRef = bpRef.GetBindablePropertyType(context.Cache, node, module); @@ -142,7 +142,7 @@ static T TryFormat(Func func, IXmlLineInfo lineInfo, string str) } public static IEnumerable PushConvertedValue(this ValueNode node, ILContext context, - TypeReference targetTypeRef, TypeReference typeConverter, IEnumerable pushServiceProvider, + TypeReference targetTypeRef, TypeReference typeConverter, Func> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { var module = context.Body.Method.Module; @@ -197,7 +197,8 @@ public static IEnumerable PushConvertedValue(this ValueNode node, I if (isExtendedConverter) { - foreach (var instruction in pushServiceProvider) + var requiredServiceType = typeConverter.GetRequiredServices(context.Cache, module); + foreach (var instruction in pushServiceProvider(requiredServiceType)) yield return instruction; } @@ -326,6 +327,12 @@ public static IEnumerable PushConvertedValue(this ValueNode node, I yield return Create(Box, module.ImportReference(originalTypeRef)); } + public static TypeReference[] GetRequiredServices(this TypeReference type, XamlCache cache, ModuleDefinition module) + { + var requireServiceAttribute = type.GetCustomAttribute(cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "RequireServiceAttribute")); + return (requireServiceAttribute?.ConstructorArguments[0].Value as CustomAttributeArgument[])?.Select(ca => ca.Value as TypeReference).ToArray(); + } + static Instruction PushParsedEnum(XamlCache cache, TypeReference enumRef, string value, IXmlLineInfo lineInfo) { var enumDef = enumRef.ResolveCached(cache); @@ -591,7 +598,7 @@ static IEnumerable PushNamescopes(INode node, ILContext context, Mo } } - public static IEnumerable PushServiceProvider(this INode node, ILContext context, FieldReference bpRef = null, PropertyReference propertyRef = null, TypeReference declaringTypeReference = null) + public static IEnumerable PushServiceProvider(this INode node, ILContext context, TypeReference[] requiredServices, FieldReference bpRef = null, PropertyReference propertyRef = null, TypeReference declaringTypeReference = null) { if (context.ValidateOnly) { @@ -599,10 +606,8 @@ public static IEnumerable PushServiceProvider(this INode node, ILCo } var module = context.Body.Method.Module; -#if NOSERVICEPROVIDER - yield return Instruction.Create (OpCodes.Ldnull); - yield break; -#endif + var createAllServices = requiredServices is null; + var alreadyContainsProvideValueTarget = false; var addService = module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XamlServiceProvider"), methodName: "Add", @@ -613,43 +618,76 @@ public static IEnumerable PushServiceProvider(this INode node, ILCo yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XamlServiceProvider"), parameterTypes: null)); - //Add a SimpleValueTargetProvider and register it as IProvideValueTarget and IReferenceProvider - var pushParentIl = node.PushParentObjectsArray(context).ToList(); - if (pushParentIl[pushParentIl.Count - 1].OpCode != Ldnull) + //Add a SimpleValueTargetProvider and register it as IProvideValueTarget, IReferenceProvider and IProvideParentValues + if ( createAllServices + || requiredServices.Contains(module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IProvideParentValues")), TypeRefComparer.Default) + || requiredServices.Contains(module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IReferenceProvider")), TypeRefComparer.Default)) + { + alreadyContainsProvideValueTarget = true; + var pushParentIl = node.PushParentObjectsArray(context).ToList(); + if (pushParentIl[pushParentIl.Count - 1].OpCode != Ldnull) + { + yield return Create(Dup); //Keep the serviceProvider on the stack + yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IProvideValueTarget"))); + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + + foreach (var instruction in pushParentIl) + yield return instruction; + + foreach (var instruction in PushTargetProperty(context, bpRef, propertyRef, declaringTypeReference, module)) + yield return instruction; + + foreach (var instruction in PushNamescopes(node, context, module)) + yield return instruction; + + yield return Create(Ldc_I4_0); //don't ask + yield return Create(Newobj, module.ImportCtorReference(context.Cache, + ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "SimpleValueTargetProvider"), paramCount: 4)); + + //store the provider so we can register it again with a different key + yield return Create(Dup); + var refProvider = new VariableDefinition(module.ImportReference(context.Cache, ("mscorlib", "System", "Object"))); + context.Body.Variables.Add(refProvider); + yield return Create(Stloc, refProvider); + yield return Create(Callvirt, addService); + + yield return Create(Dup); //Keep the serviceProvider on the stack + yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IReferenceProvider"))); + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + yield return Create(Ldloc, refProvider); + yield return Create(Callvirt, addService); + } + } + + //Add an even simpler ValueTargetProvider and register it as IProvideValueTarget + if (!alreadyContainsProvideValueTarget && requiredServices.Contains(module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IProvideValueTarget")), TypeRefComparer.Default)) { yield return Create(Dup); //Keep the serviceProvider on the stack yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IProvideValueTarget"))); yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); - foreach (var instruction in pushParentIl) - yield return instruction; + if (node.Parent is IElementNode elementNode && + context.Variables.TryGetValue(elementNode, out VariableDefinition variableDefinition)) + { + foreach (var instruction in variableDefinition.LoadAs(context.Cache, module.TypeSystem.Object, module)) + { + yield return instruction; + } + } + else + { + yield return Create(Ldnull); + } foreach (var instruction in PushTargetProperty(context, bpRef, propertyRef, declaringTypeReference, module)) yield return instruction; - foreach (var instruction in PushNamescopes(node, context, module)) - yield return instruction; - - yield return Create(Ldc_I4_0); //don't ask - yield return Create(Newobj, module.ImportCtorReference(context.Cache, - ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "SimpleValueTargetProvider"), paramCount: 4)); - - //store the provider so we can register it again with a different key - yield return Create(Dup); - var refProvider = new VariableDefinition(module.ImportReference(context.Cache, ("mscorlib", "System", "Object"))); - context.Body.Variables.Add(refProvider); - yield return Create(Stloc, refProvider); - yield return Create(Callvirt, addService); - - yield return Create(Dup); //Keep the serviceProvider on the stack - yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IReferenceProvider"))); - yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); - yield return Create(Ldloc, refProvider); + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "ValueTargetProvider"), paramCount: 2)); yield return Create(Callvirt, addService); } - //Add a XamlTypeResolver - if (node.NamespaceResolver != null) + //Add a IXamlTypeResolver + if (node.NamespaceResolver != null && createAllServices || requiredServices.Contains(module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IXamlTypeResolver")), TypeRefComparer.Default)) { yield return Create(Dup); //Duplicate the serviceProvider yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IXamlTypeResolver"))); @@ -674,7 +712,7 @@ public static IEnumerable PushServiceProvider(this INode node, ILCo yield return Create(Callvirt, addService); } - if (node is IXmlLineInfo) + if (node is IXmlLineInfo && createAllServices || requiredServices.Contains(module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IXmlLineInfoProvider")), TypeRefComparer.Default)) { yield return Create(Dup); //Duplicate the serviceProvider yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IXmlLineInfoProvider"))); @@ -684,6 +722,8 @@ public static IEnumerable PushServiceProvider(this INode node, ILCo yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XmlLineInfoProvider"), parameterTypes: new[] { ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") })); yield return Create(Callvirt, addService); } + + //and... we end up with the serviceProvider on the stack, as expected } } -} +} \ No newline at end of file diff --git a/src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs b/src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs index 1e5094d8d6a6..6a34134afa25 100644 --- a/src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs +++ b/src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs @@ -15,15 +15,15 @@ namespace Microsoft.Maui.Controls.Build.Tasks { class SetPropertiesVisitor : IXamlNodeVisitor { - static readonly IList skips = new List - { + static readonly IList skips = + [ XmlName.xKey, XmlName.xTypeArguments, XmlName.xArguments, XmlName.xFactoryMethod, XmlName.xName, XmlName.xDataType - }; + ]; public SetPropertiesVisitor(ILContext context, bool stopOnResourceDictionary = false) { @@ -51,8 +51,7 @@ public bool IsResourceDictionary(ElementNode node) public void Visit(ValueNode node, INode parentNode) { //TODO support Label text as element - XmlName propertyName; - if (!TryGetPropertyName(node, parentNode, out propertyName)) + if (!TryGetPropertyName(node, parentNode, out XmlName propertyName)) { if (!IsCollectionItem(node, parentNode)) return; @@ -275,8 +274,7 @@ public static IEnumerable ProvideValue(VariableDefinitionReference vardefref.VariableDefinition = new VariableDefinition(module.ImportReference(genericArguments.First())); foreach (var instruction in context.Variables[node].LoadAs(context.Cache, markupExtension, module)) yield return instruction; - foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef)) - yield return instruction; + yield return Instruction.Create(OpCodes.Ldnull); //ArrayExtension does not require ServiceProvider yield return Instruction.Create(OpCodes.Callvirt, provideValue); if (arrayTypeRef != null) @@ -287,12 +285,37 @@ public static IEnumerable ProvideValue(VariableDefinitionReference out markupExtension, out genericArguments)) { var acceptEmptyServiceProvider = vardefref.VariableDefinition.VariableType.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "AcceptEmptyServiceProviderAttribute")) != null; - if (vardefref.VariableDefinition.VariableType.FullName == "Microsoft.Maui.Controls.Xaml.BindingExtension" - && (node.Properties == null || !node.Properties.ContainsKey(new XmlName("", "Source"))) //do not compile bindings if Source is set - && bpRef != null //do not compile bindings if we're not gonna SetBinding - ) - foreach (var instruction in CompileBindingPath(node, context, vardefref.VariableDefinition)) - yield return instruction; + var requiredServiceType = vardefref.VariableDefinition.VariableType.GetRequiredServices(context.Cache, module); + + if (!acceptEmptyServiceProvider && requiredServiceType is null) + context.LoggingHelper.LogWarningOrError(BuildExceptionCode.UnattributedMarkupType, context.XamlFilePath, node.LineNumber, node.LinePosition, 0, 0, vardefref.VariableDefinition.VariableType); + + (string, string, string)? bindingExtensionType = vardefref.VariableDefinition.VariableType.FullName switch + { + "Microsoft.Maui.Controls.Xaml.BindingExtension" => ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml", "BindingExtension"), + "Microsoft.Maui.Controls.Xaml.TemplateBindingExtension" => ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml", "TemplateBindingExtension"), + _ => null, + }; + + if (bindingExtensionType.HasValue) + { + // for backwards compatibility, it is possible to disable compilation of bindings with the `Source` property via a feature switch + // this feature switch is enabled by default only for NativeAOT and full trimming mode + bool hasSource = node.Properties.ContainsKey(new XmlName("", "Source")); + bool skipBindingCompilation = hasSource && !context.CompileBindingsWithSource; + if (!skipBindingCompilation) + { + if (TryCompileBindingPath(node, context, vardefref.VariableDefinition, bindingExtensionType.Value, out var instructions)) + { + foreach (var instruction in instructions) + yield return instruction; + } + } + else + { + context.LoggingHelper.LogWarningOrError(BuildExceptionCode.BindingWithSourceCompilationSkipped, context.XamlFilePath, node.LineNumber, node.LinePosition, 0, 0, null); + } + } var markExt = markupExtension.ResolveCached(context.Cache); var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue"); @@ -304,9 +327,9 @@ public static IEnumerable ProvideValue(VariableDefinitionReference foreach (var instruction in context.Variables[node].LoadAs(context.Cache, markupExtension, module)) yield return instruction; if (acceptEmptyServiceProvider) - yield return Instruction.Create(OpCodes.Ldnull); + yield return Create(Ldnull); else - foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef)) + foreach (var instruction in node.PushServiceProvider(context, requiredServiceType, bpRef, propertyRef, propertyDeclaringTypeRef)) yield return instruction; yield return Instruction.Create(OpCodes.Callvirt, provideValue); yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition); @@ -314,6 +337,11 @@ public static IEnumerable ProvideValue(VariableDefinitionReference else if (context.Variables[node].VariableType.ImplementsInterface(context.Cache, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IMarkupExtension")))) { var acceptEmptyServiceProvider = context.Variables[node].VariableType.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "AcceptEmptyServiceProviderAttribute")) != null; + var requiredServiceType = vardefref.VariableDefinition.VariableType.GetRequiredServices(context.Cache, module); + + if (!acceptEmptyServiceProvider && requiredServiceType is null) + context.LoggingHelper.LogWarningOrError(BuildExceptionCode.UnattributedMarkupType, context.XamlFilePath, node.LineNumber, node.LinePosition, 0, 0, vardefref.VariableDefinition.VariableType); + var markupExtensionType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IMarkupExtension"); //some markup extensions weren't compiled earlier (on purpose), so we need to compile them now var compiledValueProviderName = context.Variables[node].VariableType.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?[0].Value as string; @@ -341,7 +369,7 @@ public static IEnumerable ProvideValue(VariableDefinitionReference if (acceptEmptyServiceProvider) yield return Create(Ldnull); else - foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef)) + foreach (var instruction in node.PushServiceProvider(context, requiredServiceType, bpRef, propertyRef, propertyDeclaringTypeRef)) yield return instruction; yield return Create(Callvirt, module.ImportMethodReference(context.Cache, markupExtensionType, @@ -352,6 +380,11 @@ public static IEnumerable ProvideValue(VariableDefinitionReference else if (context.Variables[node].VariableType.ImplementsInterface(context.Cache, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IValueProvider")))) { var acceptEmptyServiceProvider = context.Variables[node].VariableType.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "AcceptEmptyServiceProviderAttribute")) != null; + var requiredServiceType = vardefref.VariableDefinition.VariableType.GetRequiredServices(context.Cache, module); + + if (!acceptEmptyServiceProvider && requiredServiceType is null) + context.LoggingHelper.LogWarningOrError(BuildExceptionCode.UnattributedMarkupType, context.XamlFilePath, node.LineNumber, node.LinePosition, 0, 0, vardefref.VariableDefinition.VariableType); + var valueProviderType = context.Variables[node].VariableType; //If the IValueProvider has a ProvideCompiledAttribute that can be resolved, shortcut this var compiledValueProviderName = valueProviderType?.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?[0].Value as string; @@ -377,7 +410,7 @@ public static IEnumerable ProvideValue(VariableDefinitionReference if (acceptEmptyServiceProvider) yield return Create(Ldnull); else - foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef)) + foreach (var instruction in node.PushServiceProvider(context, requiredServiceType, bpRef, propertyRef, propertyDeclaringTypeRef)) yield return instruction; yield return Create(Callvirt, module.ImportMethodReference(context.Cache, valueProviderInterface, @@ -388,8 +421,10 @@ public static IEnumerable ProvideValue(VariableDefinitionReference } //Once we get compiled IValueProvider, this will move to the BindingExpression - static IEnumerable CompileBindingPath(ElementNode node, ILContext context, VariableDefinition bindingExt) + static bool TryCompileBindingPath(ElementNode node, ILContext context, VariableDefinition bindingExt, (string, string, string) bindingExtensionType, out IEnumerable instructions) { + instructions = null; + //TODO support casting operators var module = context.Module; @@ -414,6 +449,7 @@ static IEnumerable CompileBindingPath(ElementNode node, ILContext c skipNode = GetParent(node); } + bool xDataTypeIsInOuterScope = false; while (n != null) { if (n != skipNode && n.Properties.TryGetValue(XmlName.xDataType, out dataTypeNode)) @@ -421,6 +457,12 @@ static IEnumerable CompileBindingPath(ElementNode node, ILContext c break; } + if (n.XmlType.Name == nameof(Microsoft.Maui.Controls.DataTemplate) + && n.XmlType.NamespaceUri == XamlParser.MauiUri) + { + xDataTypeIsInOuterScope = true; + } + n = GetParent(n); } @@ -428,7 +470,13 @@ static IEnumerable CompileBindingPath(ElementNode node, ILContext c { context.LoggingHelper.LogWarningOrError(BuildExceptionCode.BindingWithoutDataType, context.XamlFilePath, node.LineNumber, node.LinePosition, 0, 0, null); - yield break; + return false; + } + + if (xDataTypeIsInOuterScope) + { + context.LoggingHelper.LogWarningOrError(BuildExceptionCode.BindingWithXDataTypeFromOuterScope, context.XamlFilePath, node.LineNumber, node.LinePosition, 0, 0, null); + // continue compilation } if (dataTypeNode is ElementNode enode @@ -436,7 +484,7 @@ static IEnumerable CompileBindingPath(ElementNode node, ILContext c && enode.XmlType.Name == nameof(Microsoft.Maui.Controls.Xaml.NullExtension)) { context.LoggingHelper.LogWarningOrError(BuildExceptionCode.BindingWithNullDataType, context.XamlFilePath, node.LineNumber, node.LinePosition, 0, 0, null); - yield break; + return false; } string dataType = (dataTypeNode as ValueNode)?.Value as string; @@ -457,56 +505,64 @@ static IEnumerable CompileBindingPath(ElementNode node, ILContext c var tSourceRef = dtXType.GetTypeReference(context.Cache, module, (IXmlLineInfo)node); if (tSourceRef == null) - yield break; //throw + return false; //throw - var properties = ParsePath(context, path, tSourceRef, node as IXmlLineInfo, module); - TypeReference tPropertyRef = tSourceRef; - if (properties != null && properties.Count > 0) + if (!TryParsePath(context, path, tSourceRef, node as IXmlLineInfo, module, out var properties)) { - var lastProp = properties[properties.Count - 1]; - if (lastProp.property != null) - tPropertyRef = lastProp.property.PropertyType.ResolveGenericParameters(lastProp.propDeclTypeRef); - else //array type - tPropertyRef = lastProp.propDeclTypeRef.ResolveCached(context.Cache); + return false; } - tPropertyRef = module.ImportReference(tPropertyRef); - var valuetupleRef = context.Module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "ValueTuple`2")).MakeGenericInstanceType(new[] { tPropertyRef, module.TypeSystem.Boolean })); - var funcRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, valuetupleRef })); - var actionRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Action`2")).MakeGenericInstanceType(new[] { tSourceRef, tPropertyRef })); - var funcObjRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, module.TypeSystem.Object })); - var tupleRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Tuple`2")).MakeGenericInstanceType(new[] { funcObjRef, module.TypeSystem.String })); - var typedBindingRef = module.ImportReference(module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "TypedBinding`2")).MakeGenericInstanceType(new[] { tSourceRef, tPropertyRef })); - - //FIXME: make sure the non-deprecated one is used - var ctorInfo = module.ImportReference(typedBindingRef.ResolveCached(context.Cache).Methods.FirstOrDefault(md => - md.IsConstructor - && !md.IsStatic - && md.Parameters.Count == 3 - && !md.HasCustomAttributes(module.ImportReference(context.Cache, ("mscorlib", "System", "ObsoleteAttribute"))))); - var ctorinforef = ctorInfo.MakeGeneric(typedBindingRef, funcRef, actionRef, tupleRef); - - var bindingExtensionType = ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml", "BindingExtension"); - - foreach (var instruction in bindingExt.LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, bindingExtensionType), module)) - yield return instruction; - foreach (var instruction in CompiledBindingGetGetter(tSourceRef, tPropertyRef, properties, node, context)) - yield return instruction; - if (declaredmode != BindingMode.OneTime && declaredmode != BindingMode.OneWay) - { //if the mode is explicitly 1w, or 1t, no need for setters - foreach (var instruction in CompiledBindingGetSetter(tSourceRef, tPropertyRef, properties, node, context)) + + instructions = GenerateInstructions(); + return true; + + IEnumerable GenerateInstructions() + { + TypeReference tPropertyRef = tSourceRef; + if (properties != null && properties.Count > 0) + { + var lastProp = properties[properties.Count - 1]; + if (lastProp.property != null) + tPropertyRef = lastProp.property.PropertyType.ResolveGenericParameters(lastProp.propDeclTypeRef); + else //array type + tPropertyRef = lastProp.propDeclTypeRef.ResolveCached(context.Cache); + } + tPropertyRef = module.ImportReference(tPropertyRef); + var valuetupleRef = context.Module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "ValueTuple`2")).MakeGenericInstanceType(new[] { tPropertyRef, module.TypeSystem.Boolean })); + var funcRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, valuetupleRef })); + var actionRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Action`2")).MakeGenericInstanceType(new[] { tSourceRef, tPropertyRef })); + var funcObjRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, module.TypeSystem.Object })); + var tupleRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Tuple`2")).MakeGenericInstanceType(new[] { funcObjRef, module.TypeSystem.String })); + var typedBindingRef = module.ImportReference(module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "TypedBinding`2")).MakeGenericInstanceType(new[] { tSourceRef, tPropertyRef })); + + //FIXME: make sure the non-deprecated one is used + var ctorInfo = module.ImportReference(typedBindingRef.ResolveCached(context.Cache).Methods.FirstOrDefault(md => + md.IsConstructor + && !md.IsStatic + && md.Parameters.Count == 3 + && !md.HasCustomAttributes(module.ImportReference(context.Cache, ("mscorlib", "System", "ObsoleteAttribute"))))); + var ctorinforef = ctorInfo.MakeGeneric(typedBindingRef, funcRef, actionRef, tupleRef); + + foreach (var instruction in bindingExt.LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, bindingExtensionType), module)) yield return instruction; - } - else - yield return Create(Ldnull); - if (declaredmode != BindingMode.OneTime) - { //if the mode is explicitly 1t, no need for handlers - foreach (var instruction in CompiledBindingGetHandlers(tSourceRef, tPropertyRef, properties, node, context)) + foreach (var instruction in CompiledBindingGetGetter(tSourceRef, tPropertyRef, properties, node, context)) yield return instruction; + if (declaredmode != BindingMode.OneTime && declaredmode != BindingMode.OneWay) + { //if the mode is explicitly 1w, or 1t, no need for setters + foreach (var instruction in CompiledBindingGetSetter(tSourceRef, tPropertyRef, properties, node, context)) + yield return instruction; + } + else + yield return Create(Ldnull); + if (declaredmode != BindingMode.OneTime) + { //if the mode is explicitly 1t, no need for handlers + foreach (var instruction in CompiledBindingGetHandlers(tSourceRef, tPropertyRef, properties, node, context)) + yield return instruction; + } + else + yield return Create(Ldnull); + yield return Create(Newobj, module.ImportReference(ctorinforef)); + yield return Create(Callvirt, module.ImportPropertySetterReference(context.Cache, bindingExtensionType, propertyName: "TypedBinding")); } - else - yield return Create(Ldnull); - yield return Create(Newobj, module.ImportReference(ctorinforef)); - yield return Create(Callvirt, module.ImportPropertySetterReference(context.Cache, bindingExtensionType, propertyName: "TypedBinding")); static IElementNode GetParent(IElementNode node) { @@ -522,16 +578,19 @@ static bool IsBindingContextBinding(ElementNode node) { // looking for BindingContext="{Binding ...}" return GetParent(node) is IElementNode parentNode - && ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out var propertyName) + && node.TryGetPropertyName(parentNode, out var propertyName) && propertyName.NamespaceURI == "" && propertyName.LocalName == nameof(BindableObject.BindingContext); } } - static IList<(PropertyDefinition property, TypeReference propDeclTypeRef, string indexArg)> ParsePath(ILContext context, string path, TypeReference tSourceRef, IXmlLineInfo lineInfo, ModuleDefinition module) + static bool TryParsePath(ILContext context, string path, TypeReference tSourceRef, IXmlLineInfo lineInfo, ModuleDefinition module, out IList<(PropertyDefinition property, TypeReference propDeclTypeRef, string indexArg)> pathProperties) { + pathProperties = null; + if (string.IsNullOrWhiteSpace(path)) - return null; + return true; + path = path.Trim(' ', '.'); //trim leading or trailing dots var parts = path.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); var properties = new List<(PropertyDefinition property, TypeReference propDeclTypeRef, string indexArg)>(); @@ -562,8 +621,13 @@ static bool IsBindingContextBinding(ElementNode node) if (p.Length > 0) { - var property = previousPartTypeRef.GetProperty(context.Cache, pd => pd.Name == p && pd.GetMethod != null && pd.GetMethod.IsPublic, out var propDeclTypeRef) - ?? throw new BuildException(BuildExceptionCode.BindingPropertyNotFound, lineInfo, null, p, previousPartTypeRef); + var property = previousPartTypeRef.GetProperty(context.Cache, pd => pd.Name == p && pd.GetMethod != null && pd.GetMethod.IsPublic && !pd.GetMethod.IsStatic, out var propDeclTypeRef); + if (property is null) + { + context.LoggingHelper.LogWarningOrError(BuildExceptionCode.BindingPropertyNotFound, context.XamlFilePath, lineInfo.LineNumber, lineInfo.LinePosition, 0, 0, p, previousPartTypeRef); + return false; + } + properties.Add((property, propDeclTypeRef, null)); previousPartTypeRef = property.PropertyType.ResolveGenericParameters(propDeclTypeRef); } @@ -603,7 +667,8 @@ static bool IsBindingContextBinding(ElementNode node) } } - return properties; + pathProperties = properties; + return true; } static IEnumerable DigProperties(IEnumerable<(PropertyDefinition property, TypeReference propDeclTypeRef, string indexArg)> properties, Dictionary locs, Func fallback, IXmlLineInfo lineInfo, ModuleDefinition module) @@ -1321,7 +1386,8 @@ static IEnumerable SetValue(VariableDefinition parent, FieldReferen if (valueNode != null) { - foreach (var instruction in valueNode.PushConvertedValue(context, bpRef, valueNode.PushServiceProvider(context, bpRef: bpRef), true, false)) + //FIXME which services are required here ? + foreach (var instruction in valueNode.PushConvertedValue(context, bpRef, (requiredServices) => valueNode.PushServiceProvider(context, requiredServices, bpRef: bpRef), true, false)) yield return instruction; } else if (elementNode != null) @@ -1478,7 +1544,8 @@ static IEnumerable Set(VariableDefinition parent, string localName, if (valueNode != null) { - foreach (var instruction in valueNode.PushConvertedValue(context, propertyType, new ICustomAttributeProvider[] { property, propertyType.ResolveCached(context.Cache) }, valueNode.PushServiceProvider(context, propertyRef: property), false, true)) + //FIXME which services are required here ? + foreach (var instruction in valueNode.PushConvertedValue(context, propertyType, new ICustomAttributeProvider[] { property, propertyType.ResolveCached(context.Cache) }, (requiredServices) => valueNode.PushServiceProvider(context, requiredServices, propertyRef: property), false, true)) yield return instruction; if (parent.VariableType.IsValueType) yield return Instruction.Create(OpCodes.Call, propertySetterRef); @@ -1717,6 +1784,7 @@ static void SetDataTemplate(IElementNode parentNode, ElementNode node, ILContext XamlFilePath = parentContext.XamlFilePath, LoggingHelper = parentContext.LoggingHelper, ValidateOnly = parentContext.ValidateOnly, + CompileBindingsWithSource = parentContext.CompileBindingsWithSource, }; //Instanciate nested class diff --git a/src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs b/src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs index 1989c825b1a6..44c060a9b028 100644 --- a/src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs +++ b/src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs @@ -9,12 +9,12 @@ namespace Microsoft.Maui.Controls.Build.Tasks { class TypeRefComparer : IEqualityComparer { - static string GetAssembly(TypeReference typeRef) + static string GetAssemblyName(TypeReference typeRef) { if (typeRef.Scope is ModuleDefinition md) - return md.Assembly.FullName; + return md.Assembly.Name.Name; if (typeRef.Scope is AssemblyNameReference anr) - return anr.FullName; + return anr.Name; throw new ArgumentOutOfRangeException(nameof(typeRef)); } @@ -30,8 +30,8 @@ public bool Equals(TypeReference x, TypeReference y) var yname = y.FullName.EndsWith("&", StringComparison.InvariantCulture) ? y.FullName.Substring(0, y.FullName.Length - 1) : y.FullName; if (xname != yname) return false; - var xasm = GetAssembly(x); - var yasm = GetAssembly(y); + var xasm = GetAssemblyName(x); + var yasm = GetAssemblyName(y); //standard types comes from either mscorlib. System.Runtime or netstandard. Assume they are equivalent if ((xasm.StartsWith("System.Runtime", StringComparison.Ordinal) @@ -50,7 +50,7 @@ public bool Equals(TypeReference x, TypeReference y) public int GetHashCode(TypeReference obj) { - return $"{GetAssembly(obj)}//{obj.FullName}".GetHashCode(); + return $"{GetAssemblyName(obj)}//{obj.FullName}".GetHashCode(); } static TypeRefComparer s_default; diff --git a/src/Controls/src/Build.Tasks/XamlCTask.cs b/src/Controls/src/Build.Tasks/XamlCTask.cs index c8fad9033484..829d675b0399 100644 --- a/src/Controls/src/Build.Tasks/XamlCTask.cs +++ b/src/Controls/src/Build.Tasks/XamlCTask.cs @@ -26,16 +26,26 @@ class LoggingHelperContext public IList WarningsAsErrors { get; set; } public IList WarningsNotAsErrors { get; set; } public IList NoWarn { get; set; } + public string PathPrefix { get; set; } } static LoggingHelperContext Context { get; set; } - - public static void SetContext(this TaskLoggingHelper loggingHelper, int warningLevel, bool treatWarningsAsErrors, string noWarn, string warningsAsErrors, string warningsNotAsErrors) + internal static List LoggedErrors { get; set; } + + public static void SetContext( + this TaskLoggingHelper loggingHelper, + int warningLevel, + bool treatWarningsAsErrors, + string noWarn, + string warningsAsErrors, + string warningsNotAsErrors, + string pathPrefix) { if (Context == null) Context = new LoggingHelperContext(); Context.WarningLevel = warningLevel; Context.TreatWarningsAsErrors = treatWarningsAsErrors; + Context.PathPrefix = pathPrefix; Context.NoWarn = noWarn?.Split([';', ','], StringSplitOptions.RemoveEmptyEntries).Select(s => { @@ -83,11 +93,30 @@ public static void LogWarningOrError(this TaskLoggingHelper loggingHelper, Build Context = new LoggingHelperContext(); if (Context.NoWarn != null && Context.NoWarn.Contains(code.CodeCode)) return; + xamlFilePath = loggingHelper.GetXamlFilePath(xamlFilePath); if ((Context.TreatWarningsAsErrors && (Context.WarningsNotAsErrors == null || !Context.WarningsNotAsErrors.Contains(code.CodeCode))) || (Context.WarningsAsErrors != null && Context.WarningsAsErrors.Contains(code.CodeCode))) - loggingHelper.LogError($"XamlC {code.CodePrefix}{code.CodeCode:0000}", null, null, xamlFilePath, lineNumber, linePosition, endLineNumber, endLinePosition, ErrorMessages.ResourceManager.GetString(code.ErrorMessageKey), messageArgs); + { + loggingHelper.LogError("XamlC", $"{code.CodePrefix}{code.CodeCode:0000}", code.HelpLink, xamlFilePath, lineNumber, linePosition, endLineNumber, endLinePosition, ErrorMessages.ResourceManager.GetString(code.ErrorMessageKey), messageArgs); + LoggedErrors ??= new(); + LoggedErrors.Add(new BuildException(code, new XmlLineInfo(lineNumber, linePosition), innerException: null, messageArgs)); + } else - loggingHelper.LogWarning($"XamlC {code.CodePrefix}{code.CodeCode:0000}", null, null, xamlFilePath, lineNumber, linePosition, endLineNumber, endLinePosition, ErrorMessages.ResourceManager.GetString(code.ErrorMessageKey), messageArgs); + { + loggingHelper.LogWarning("XamlC", $"{code.CodePrefix}{code.CodeCode:0000}", code.HelpLink, xamlFilePath, lineNumber, linePosition, endLineNumber, endLinePosition, ErrorMessages.ResourceManager.GetString(code.ErrorMessageKey), messageArgs); + } + } + + public static string GetXamlFilePath(this TaskLoggingHelper loggingHelper, string xamlFilePath) + { + Context ??= new LoggingHelperContext(); + + if (Context.PathPrefix is string prefix) + { + xamlFilePath = IOPath.Combine(prefix, xamlFilePath); + } + + return xamlFilePath; } } @@ -99,6 +128,7 @@ public class XamlCTask : XamlTask public bool OptimizeIL { get; set; } = true; public bool DefaultCompile { get; set; } public bool ForceCompile { get; set; } + public bool CompileBindingsWithSource { get; set; } public string TargetFramework { get; set; } public int WarningLevel { get; set; } = 4; //unused so far @@ -107,6 +137,8 @@ public class XamlCTask : XamlTask public string WarningsNotAsErrors { get; set; } public string NoWarn { get; set; } + public bool GenerateFullPaths { get; set; } + public string FullPathPrefix { get; set; } public IAssemblyResolver DefaultAssemblyResolver { get; set; } @@ -122,7 +154,7 @@ public class XamlCTask : XamlTask public override bool Execute(out IList thrownExceptions) { thrownExceptions = null; - LoggingHelper.SetContext(WarningLevel, TreatWarningsAsErrors, NoWarn, WarningsAsErrors, WarningsNotAsErrors); + LoggingHelper.SetContext(WarningLevel, TreatWarningsAsErrors, NoWarn, WarningsAsErrors, WarningsNotAsErrors, GenerateFullPaths ? FullPathPrefix : null); LoggingHelper.LogMessage(Normal, $"{new string(' ', 0)}Compiling Xaml, assembly: {Assembly}"); var skipassembly = !DefaultCompile; bool success = true; @@ -133,6 +165,11 @@ public override bool Execute(out IList thrownExceptions) return true; } + if (GenerateFullPaths && string.IsNullOrEmpty(FullPathPrefix)) + { + LoggingHelper.LogMessage(Low, " GenerateFullPaths is enabled but FullPathPrefix is missing or empty."); + } + using (var fallbackResolver = DefaultAssemblyResolver == null ? new XamlCAssemblyResolver() : null) { var resolver = DefaultAssemblyResolver ?? fallbackResolver; @@ -260,6 +297,7 @@ public override bool Execute(out IList thrownExceptions) success = false; LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}failed."); (thrownExceptions = thrownExceptions ?? new List()).Add(e); + xamlFilePath = LoggingHelper.GetXamlFilePath(xamlFilePath); if (e is BuildException be) LoggingHelper.LogError("XamlC", be.Code.Code, be.HelpLink, xamlFilePath, be.XmlInfo?.LineNumber ?? 0, be.XmlInfo?.LinePosition ?? 0, 0, 0, ErrorMessages.ResourceManager.GetString(be.Code.ErrorMessageKey), be.MessageArgs); else if (e is XamlParseException xpe) //shouldn't happen anymore @@ -271,6 +309,29 @@ public override bool Execute(out IList thrownExceptions) LoggingHelper.LogMessage(Low, e.StackTrace); continue; } + else + { + if (LoggingHelperExtensions.LoggedErrors is List errors) + { + foreach (var error in errors) + { + success = false; + (thrownExceptions = thrownExceptions ?? new List()).Add(error); + } + + LoggingHelperExtensions.LoggedErrors = null; + } + } + + if (initComp.HasCustomAttributes) + { + var suppressMessageAttribute = initComp.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute"); + if (suppressMessageAttribute != null) + { + LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Removing UnconditionalSuppressMessageAttribute from InitializeComponent()"); + initComp.CustomAttributes.Remove(suppressMessageAttribute); + } + } if (Type != null) InitCompForType = initComp; @@ -355,6 +416,7 @@ bool TryCoreCompile(MethodDefinition initComp, ILRootNode rootnode, string xamlF XamlFilePath = xamlFilePath, LoggingHelper = loggingHelper, ValidateOnly = ValidateOnly, + CompileBindingsWithSource = CompileBindingsWithSource, }; diff --git a/src/Controls/src/Build.Tasks/XamlTask.cs b/src/Controls/src/Build.Tasks/XamlTask.cs index 31b3f7073709..032588eef344 100644 --- a/src/Controls/src/Build.Tasks/XamlTask.cs +++ b/src/Controls/src/Build.Tasks/XamlTask.cs @@ -42,7 +42,6 @@ public bool Execute() internal static ILRootNode ParseXaml(Stream stream, TypeReference typeReference) { - ILRootNode rootnode = null; using (var reader = XmlReader.Create(stream)) { while (reader.Read()) @@ -56,12 +55,13 @@ internal static ILRootNode ParseXaml(Stream stream, TypeReference typeReference) continue; } - XamlParser.ParseXaml( - rootnode = new ILRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), typeReference, reader as IXmlNamespaceResolver, ((IXmlLineInfo)reader).LineNumber, ((IXmlLineInfo)reader).LinePosition), reader); - break; + var xmlType = new XmlType(reader.NamespaceURI, reader.Name, XamlParser.GetTypeArguments(reader)); + var rootnode = new ILRootNode(xmlType, typeReference, reader as IXmlNamespaceResolver, ((IXmlLineInfo)reader).LineNumber, ((IXmlLineInfo)reader).LinePosition); + XamlParser.ParseXaml(rootnode, reader); + return rootnode; } } - return rootnode; + return null; } } diff --git a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets index 9bdc3525eaf1..08769eef8da7 100644 --- a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets +++ b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets @@ -21,6 +21,15 @@ + + + <_MauiBindingInterceptorsSupport Condition=" '$(_MauiBindingInterceptorsSupport)' == '' and '$(DisableMauiAnalyzers)' != 'true' ">true + $(InterceptorsPreviewNamespaces);Microsoft.Maui.Controls.Generated + + + + + @@ -151,9 +160,13 @@ <_MauiXamlCValidateOnly Condition="'$(Configuration)' == 'Debug' AND '$(_MauiForceXamlCForDebug)' != 'True'">True <_MauiXamlCValidateOnly Condition="'$(BuildingForLiveUnitTesting)' == 'True' ">True - true - <_MauiXamlCNoWarn>$(NoWarn) - <_MauiXamlCNoWarn Condition="'$(MauiStrictXamlCompilation)' != 'true'">$(_MauiXamlCNoWarn);XC0022;XC0023 + true + <_MauiXamlCWarningsNotAsErrors>$(WarningsNotAsErrors) + <_MauiXamlCWarningsNotAsErrors Condition="'$(MauiStrictXamlCompilation)' != 'true'">$(_MauiXamlCWarningsNotAsErrors);XC0022;XC0023;XC0025 + + <_MauiXamlCGenerateFullPaths Condition="'$(_MauiXamlCGenerateFullPaths)' == '' and '$(GenerateFullPaths)' == 'true'">true + <_MauiXamlCGenerateFullPaths Condition="'$(_MauiXamlCGenerateFullPaths)' == ''">false + <_MauiXamlCFullPathPrefix Condition="'$(_MauiXamlCFullPathPrefix)' == '' and '$(_MauiXamlCGenerateFullPaths)' == 'true'">$(MSBuildProjectDirectory) + WarningsNotAsErrors = "$(_MauiXamlCWarningsNotAsErrors)" + GenerateFullPaths = "$(_MauiXamlCGenerateFullPaths)" + FullPathPrefix = "$(_MauiXamlCFullPathPrefix)" /> @@ -210,4 +226,42 @@ Text="The %24(TargetFrameworkVersion) for $(ProjectName) ($(TargetFrameworkVersion)) is less than the minimum required %24(TargetFrameworkVersion) for Microsoft.Maui ($(MinTargetFrameworkVersionForMaui)). You need to increase the %24(TargetFrameworkVersion) for $(ProjectName)." /> + + + false + + + false + false + false + true + + + + + + + + + + + diff --git a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui-blazor.aotprofile b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui-blazor.aotprofile index 0c23834056fa..79f0849306e0 100644 Binary files a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui-blazor.aotprofile and b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui-blazor.aotprofile differ diff --git a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui-blazor.aotprofile.txt b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui-blazor.aotprofile.txt index 617ae72943e9..34126450a9d7 100644 --- a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui-blazor.aotprofile.txt +++ b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui-blazor.aotprofile.txt @@ -33,7 +33,6 @@ Methods: Android.Graphics.Color Android.Graphics.Color:Argb (int,int,int,int) Android.Graphics.Color Microsoft.Maui.Graphics.Platform.GraphicsExtensions:AsColor (Microsoft.Maui.Graphics.Color) Android.Graphics.Color Microsoft.Maui.Platform.ColorExtensions:ToPlatform (Microsoft.Maui.Graphics.Color) - Android.Graphics.Drawables.Drawable Android.Views.View:get_Background () Android.Graphics.Paint Microsoft.Maui.Graphics.Platform.PlatformCanvasState:get_StrokePaint () Android.Graphics.Paint/Style Android.Graphics.Paint/Style:get_Fill () Android.Graphics.Paint/Style Android.Graphics.Paint/Style:get_Stroke () @@ -122,13 +121,12 @@ Methods: bool Android.Runtime.InputStreamInvoker:get_CanSeek () bool Android.Runtime.InputStreamInvoker:get_CanWrite () bool Android.Runtime.JavaArray`1/d__13:MoveNext () - bool Android.Runtime.JavaDictionary:b__36_0 (intptr) + bool Android.Runtime.JavaDictionary:b__37_0 (intptr) bool Android.Runtime.JavaDictionary:Contains (object) bool Android.Runtime.JavaDictionary`2:b__15_0 (intptr) bool Android.Runtime.JavaDictionary`2:ContainsKey (string) bool Android.Runtime.JNIEnv:CallBooleanMethod (intptr,intptr,Android.Runtime.JValue[]) bool Android.Runtime.JNIEnv:CallBooleanMethod (intptr,intptr,Android.Runtime.JValue*) - bool Android.Runtime.JNIEnv:CallBooleanMethod (intptr,intptr) bool Android.Runtime.JNIEnv:IsAssignableFrom (intptr,intptr) bool Android.Runtime.JNIEnv:IsGCUserPeer (intptr) bool Android.Runtime.JNIEnv:IsInstanceOf (intptr,intptr) @@ -141,7 +139,6 @@ Methods: bool Java.Interop.JavaConvert:WithLocalJniHandle (object,System.Func`2) bool Java.Interop.JavaConvert:WithLocalJniHandle (string,System.Func`2) bool Java.Interop.JniEnvironment/InstanceMethods:CallBooleanMethod (Java.Interop.JniObjectReference,Java.Interop.JniMethodInfo,Java.Interop.JniArgumentValue*) - bool Java.Interop.JniEnvironment/InstanceMethods:CallBooleanMethod (Java.Interop.JniObjectReference,Java.Interop.JniMethodInfo) bool Java.Interop.JniEnvironment/InstanceMethods:CallNonvirtualBooleanMethod (Java.Interop.JniObjectReference,Java.Interop.JniObjectReference,Java.Interop.JniMethodInfo,Java.Interop.JniArgumentValue*) bool Java.Interop.JniEnvironment/Types:IsAssignableFrom (Java.Interop.JniObjectReference,Java.Interop.JniObjectReference) bool Java.Interop.JniEnvironment/Types:IsInstanceOf (Java.Interop.JniObjectReference,Java.Interop.JniObjectReference) @@ -155,9 +152,9 @@ Methods: bool Java.Interop.JniPeerMembers/JniInstanceMethods:TryInvokeInt32StaticRedirect (Java.Interop.JniMethodInfo,Java.Interop.IJavaPeerable,Java.Interop.JniArgumentValue*,int&) bool Java.Interop.JniPeerMembers/JniInstanceMethods:TryInvokeObjectStaticRedirect (Java.Interop.JniMethodInfo,Java.Interop.IJavaPeerable,Java.Interop.JniArgumentValue*,Java.Interop.JniObjectReference&) bool Java.Interop.JniPeerMembers/JniInstanceMethods:TryInvokeVoidStaticRedirect (Java.Interop.JniMethodInfo,Java.Interop.IJavaPeerable,Java.Interop.JniArgumentValue*) - bool Java.Interop.JniRuntime:GetBuiltInTypeArraySignature (System.Type,Java.Interop.JniTypeSignature&) bool Java.Interop.JniRuntime:GetBuiltInTypeSignature (System.Type,Java.Interop.JniTypeSignature&) bool Java.Interop.JniRuntime/JniObjectReferenceManager:get_LogGlobalReferenceMessages () + bool Java.Interop.JniRuntime/JniTypeManager:GetBuiltInTypeArraySignature (System.Type,Java.Interop.JniTypeSignature&) bool Java.Interop.JniType:TryGetStaticMethod (string,string,Java.Interop.JniMethodInfo&) bool Java.Interop.Runtime:IsGCUserPeer (intptr) bool Java.Interop.TypeManager:get_ActivationEnabled () @@ -165,7 +162,6 @@ Methods: bool Java.Lang.Object:Java.Interop.IJavaObjectEx.get_NeedsActivation () bool Java.Net.URLConnection:get_DoOutput () bool Java.Util.IIteratorInvoker:get_HasNext () - bool Microsoft.AspNetCore.Components.EventCallback`1:get_HasDelegate () bool Microsoft.AspNetCore.Components.NavigationManager:TryGetLengthOfBaseUriPrefix (System.Uri,string,int&) bool Microsoft.AspNetCore.Components.ParameterView/CascadingParameterEnumerator:MoveNext () bool Microsoft.AspNetCore.Components.ParameterView/Enumerator:MoveNext () @@ -175,7 +171,6 @@ Methods: bool Microsoft.AspNetCore.Components.Reflection.PropertySetter:get_AcceptsCascadingParameters () bool Microsoft.AspNetCore.Components.Reflection.PropertySetter:get_AcceptsDirectParameters () bool Microsoft.AspNetCore.Components.Rendering.SimplifiedStringHashComparer:Equals (string,string) - bool Microsoft.AspNetCore.Components.RouteTableFactory:CompareSegments (Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry,Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry) bool Microsoft.AspNetCore.Components.Routing.NavLink:EqualsHrefExactlyOrIfTrailingSlashAdded (string) bool Microsoft.AspNetCore.Components.Routing.NavLink:IsStrictlyPrefixWithSeparator (string,string) bool Microsoft.AspNetCore.Components.Routing.NavLink:ShouldMatch (string) @@ -183,6 +178,7 @@ Methods: bool Microsoft.AspNetCore.Components.Routing.RouteValueDictionary/Enumerator:MoveNextRare () bool Microsoft.AspNetCore.Components.WebView.ArrayBuilderMemoryStream:get_CanWrite () bool Microsoft.AspNetCore.Components.WebView.FileExtensionContentTypeProvider:TryGetContentType (string,string&) + bool Microsoft.AspNetCore.Components.WebView.HostAddressHelper:get_IsAppHostAddressAlways0000Enabled () bool Microsoft.AspNetCore.Components.WebView.IpcCommon:TryDeserialize (string,Microsoft.AspNetCore.Components.WebView.IpcCommon/IncomingMessageType&,System.ArraySegment`1&) bool Microsoft.AspNetCore.Components.WebView.IpcCommon:TryDeserializeIncoming (string,Microsoft.AspNetCore.Components.WebView.IpcCommon/IncomingMessageType&,System.ArraySegment`1&) bool Microsoft.AspNetCore.Components.WebView.Maui.AndroidMauiAssetFileProvider/AndroidMauiAssetFileInfo:<.ctor>b__4_0 () @@ -208,6 +204,9 @@ Methods: bool Microsoft.AspNetCore.Routing.RouteConstraintMatcher:Match (System.Collections.Generic.IDictionary`2,Microsoft.AspNetCore.Components.Routing.RouteValueDictionary) bool Microsoft.AspNetCore.Routing.RoutePatternMatcher:TryMatch (Microsoft.AspNetCore.Components.Routing.PathString,Microsoft.AspNetCore.Components.Routing.RouteValueDictionary) bool Microsoft.AspNetCore.Routing.Tree.TreeEnumerator:MoveNext () + bool Microsoft.Extensions.DependencyInjection.ActivatorUtilities:TryCreateParameterMap (System.Reflection.ParameterInfo[],System.Type[],System.Nullable`1[]&) + bool Microsoft.Extensions.DependencyInjection.ActivatorUtilities:TryFindMatchingConstructor (System.Type,System.Type[],System.Reflection.ConstructorInfo&,System.Nullable`1[]&) + bool Microsoft.Extensions.DependencyInjection.ActivatorUtilities:TryFindPreferredConstructor (System.Type,System.Type[],Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorInfoEx[],System.Reflection.ConstructorInfo&,System.Nullable`1[]&) bool Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory:KeysMatch (object,object) bool Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey:Equals (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey) bool Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceDescriptorExtensions:HasImplementationInstance (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) @@ -242,25 +241,21 @@ Methods: bool Microsoft.Maui.Controls.ControlsColorExtensions:IsNotDefault (Microsoft.Maui.Graphics.Color) bool Microsoft.Maui.Controls.DependencyService/<>c__DisplayClass10_0:b__0 (Microsoft.Maui.Controls.DependencyService/DependencyType) bool Microsoft.Maui.Controls.DependencyService/<>c__DisplayClass11_0:b__0 (Microsoft.Maui.Controls.DependencyService/DependencyType) - bool Microsoft.Maui.Controls.Element/d__101`1:MoveNext () + bool Microsoft.Maui.Controls.Element/d__103`1:MoveNext () bool Microsoft.Maui.Controls.ImageSource:IsNullOrEmpty (Microsoft.Maui.Controls.ImageSource) bool Microsoft.Maui.Controls.Label:IsLabelSizeable (Microsoft.Maui.Controls.Label) bool Microsoft.Maui.Controls.Label:TextChangedShouldInvalidateMeasure (Microsoft.Maui.Controls.Label) bool Microsoft.Maui.Controls.MenuItemTracker`1/d__7:MoveNext () bool Microsoft.Maui.Controls.Page:get_IsBusy () - bool Microsoft.Maui.Controls.Page:ShouldLayoutChildren () bool Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_IsModalPlatformReady () bool Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_IsModalReady () + bool Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_IsWindowReadyForModals () bool Microsoft.Maui.Controls.Platform.SemanticExtensions:ControlsAccessibilityDelegateNeeded (Microsoft.Maui.Controls.View) bool Microsoft.Maui.Controls.Platform.SemanticExtensions:TapGestureRecognizerNeedsDelegate (Microsoft.Maui.Controls.View) - bool Microsoft.Maui.Controls.ResourceDictionary:ContainsKey (string) bool Microsoft.Maui.Controls.ResourceDictionary:TryGetValue (string,object&) bool Microsoft.Maui.Controls.ResourceDictionary:TryGetValueAndSource (string,object&,Microsoft.Maui.Controls.ResourceDictionary&) - bool Microsoft.Maui.Controls.ResourceDictionary/d__42:MoveNext () + bool Microsoft.Maui.Controls.ResourceDictionary/d__46:MoveNext () bool Microsoft.Maui.Controls.ResourcesExtensions:TryGetResource (Microsoft.Maui.Controls.IElementDefinition,string,object&) - bool Microsoft.Maui.Controls.SetterSpecificity:Equals (Microsoft.Maui.Controls.SetterSpecificity) - bool Microsoft.Maui.Controls.SetterSpecificity:op_Equality (Microsoft.Maui.Controls.SetterSpecificity,Microsoft.Maui.Controls.SetterSpecificity) - bool Microsoft.Maui.Controls.SetterSpecificity:op_Inequality (Microsoft.Maui.Controls.SetterSpecificity,Microsoft.Maui.Controls.SetterSpecificity) bool Microsoft.Maui.Controls.SolidColorBrush:get_IsEmpty () bool Microsoft.Maui.Controls.StyleSheets.StyleSheetExtensions/d__0:MoveNext () bool Microsoft.Maui.Controls.ViewExtensions/d__22:MoveNext () @@ -269,8 +264,6 @@ Methods: bool Microsoft.Maui.Controls.VisualElement:get_IsEnabled () bool Microsoft.Maui.Controls.VisualElement:get_IsEnabledCore () bool Microsoft.Maui.Controls.VisualElement:get_IsVisible () - bool Microsoft.Maui.Controls.VisualElement:IsMocked () - bool Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.Controls.IFlowDirectionController.get_ApplyEffectiveFlowDirectionToChildContainer () bool Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.Controls.IResourcesProvider.get_IsResourcesCreated () bool Microsoft.Maui.Controls.VisualStateGroupListExtensions:HasVisualState (Microsoft.Maui.Controls.VisualElement,string) bool Microsoft.Maui.Controls.VisualStateManager:HasVisualStateGroups (Microsoft.Maui.Controls.VisualElement) @@ -290,12 +283,11 @@ Methods: bool Microsoft.Maui.Graphics.PaintExtensions:IsNullOrEmpty (Microsoft.Maui.Graphics.Paint) bool Microsoft.Maui.Graphics.Rect:Equals (Microsoft.Maui.Graphics.Rect) bool Microsoft.Maui.Graphics.Rect:op_Equality (Microsoft.Maui.Graphics.Rect,Microsoft.Maui.Graphics.Rect) - bool Microsoft.Maui.Graphics.Rect:op_Inequality (Microsoft.Maui.Graphics.Rect,Microsoft.Maui.Graphics.Rect) bool Microsoft.Maui.Handlers.AndroidBatchPropertyMapper`2/d__2:MoveNext () bool Microsoft.Maui.Handlers.ViewHandler:get_HasContainer () bool Microsoft.Maui.Handlers.ViewHandler:get_NeedsContainer () - bool Microsoft.Maui.Hosting.Internal.MauiFactory:TryGetServiceDescriptors (System.Type&,Microsoft.Extensions.DependencyInjection.ServiceDescriptor&,System.Collections.Generic.IEnumerable`1&) bool Microsoft.Maui.Hosting.Internal.MauiServiceCollection:TryGetService (System.Type,Microsoft.Extensions.DependencyInjection.ServiceDescriptor&) + bool Microsoft.Maui.HotReload.MauiHotReloadHelper:get_IsSupported () bool Microsoft.Maui.JavaObjectExtensions:IsAlive (Java.Lang.Object) bool Microsoft.Maui.JavaObjectExtensions:IsDisposed (Java.Lang.Object) bool Microsoft.Maui.Layouts.GridLayoutManager/GridStructure:AnyAuto (Microsoft.Maui.Layouts.GridLayoutManager/Definition[]) @@ -310,6 +302,8 @@ Methods: bool Microsoft.Maui.Platform.ViewExtensions:IsLoadedOnPlatform (Microsoft.Maui.IElement) bool Microsoft.Maui.PropertyMapper/d__17:MoveNext () bool Microsoft.Maui.ViewExtensions:NeedsContainer (Microsoft.Maui.IView) + bool Microsoft.Maui.VisualDiagnostics:get_IsEnabled () + bool Microsoft.Maui.VisualDiagnostics/<>c:<.cctor>b__18_0 () bool Microsoft.Maui.WindowOverlay:get_IsPlatformViewInitialized () bool Microsoft.Maui.WindowOverlay:Initialize () bool Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid:get_IsInvalid () @@ -326,9 +320,13 @@ Methods: bool System.Boolean:IsTrueStringIgnoreCase (System.ReadOnlySpan`1) bool System.Boolean:TryParse (string,bool&) bool System.Boolean:TryParse (System.ReadOnlySpan`1,bool&) - bool System.Buffers.ReadOnlySequence`1:get_IsEmpty () + bool System.Buffers.ProbabilisticMapState:g__TestModulus|13_0 (System.ReadOnlySpan`1,int) + bool System.Buffers.SearchValues:g__ShouldUseProbabilisticMap|1_0 (int,int) bool System.Buffers.SearchValues:TryGetSingleRange (System.ReadOnlySpan`1,byte&,byte&) bool System.Buffers.SearchValues:TryGetSingleRange (System.ReadOnlySpan`1,char&,char&) + bool System.Buffers.SearchValues`1:ContainsAny (System.ReadOnlySpan`1) + bool System.Buffers.SearchValues`1:ContainsAnyExcept (System.ReadOnlySpan`1) + bool System.Buffers.SharedArrayPoolStatics:TryGetInt32EnvironmentVariable (string,int&) bool System.Buffers.Text.Utf8Parser:TryParse (System.ReadOnlySpan`1,long&,int&,char) bool System.Buffers.Text.Utf8Parser:TryParseInt64D (System.ReadOnlySpan`1,long&,int&) bool System.Char:IsLatin1 (char) @@ -347,6 +345,8 @@ Methods: bool System.Collections.Concurrent.ConcurrentDictionary`2:TryGetValueInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,int,Microsoft.Extensions.DependencyInjection.ServiceProvider/ServiceAccessor&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,System.Nullable`1,object,bool,bool,object&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryGetValueInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,int,object&) + bool System.Collections.Concurrent.ConcurrentDictionary`2:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,Microsoft.Maui.Hosting.IMauiHandlersCollection,System.Nullable`1,Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet,bool,bool,Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet&) + bool System.Collections.Concurrent.ConcurrentDictionary`2:TryGetValueInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,Microsoft.Maui.Hosting.IMauiHandlersCollection,int,Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,long,System.Nullable`1,Microsoft.JSInterop.Infrastructure.IDotNetObjectReference,bool,bool,Microsoft.JSInterop.Infrastructure.IDotNetObjectReference&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,long,System.Nullable`1,object,bool,bool,object&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryRemove (long,object&) @@ -354,8 +354,8 @@ Methods: bool System.Collections.Concurrent.ConcurrentDictionary`2:TryRemove (long,System.Threading.CancellationTokenRegistration&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryRemoveInternal (long,System.Threading.CancellationTokenRegistration&,bool,System.Threading.CancellationTokenRegistration) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryGetValue (string,Microsoft.Extensions.Logging.Logger&) - bool System.Collections.Concurrent.ConcurrentDictionary`2>:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables>,string,System.Nullable`1,System.Lazy`1,bool,bool,System.Lazy`1&) - bool System.Collections.Concurrent.ConcurrentDictionary`2>:TryGetValueInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables>,string,int,System.Lazy`1&) + bool System.Collections.Concurrent.ConcurrentDictionary`2:TryAdd (string,ulong) + bool System.Collections.Concurrent.ConcurrentDictionary`2:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,string,System.Nullable`1,ulong,bool,bool,ulong&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryAdd (System.Type,Microsoft.AspNetCore.Components.ComponentFactory/ComponentTypeInfoCacheEntry) bool System.Collections.Concurrent.ConcurrentDictionary`2>>:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables>>,System.Type,System.Nullable`1,System.ValueTuple`2>,bool,bool,System.ValueTuple`2>&) bool System.Collections.Concurrent.ConcurrentDictionary`2>>:TryGetValue (System.Type,System.ValueTuple`2>&) @@ -365,11 +365,14 @@ Methods: bool System.Collections.Concurrent.ConcurrentDictionary`2, System.Text.Json.Cache`1/CacheEntry>>:TryGetValueInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables, System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>>,System.ValueTuple`3,int,System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>&) bool System.Collections.Concurrent.ConcurrentDictionaryTypeProps`1:IsWriteAtomicPrivate () bool System.Collections.Concurrent.ConcurrentDictionaryTypeProps`1:IsWriteAtomicPrivate () + bool System.Collections.Concurrent.ConcurrentDictionaryTypeProps`1:IsWriteAtomicPrivate () bool System.Collections.Concurrent.ConcurrentDictionaryTypeProps`1>>:IsWriteAtomicPrivate () bool System.Collections.Concurrent.ConcurrentQueue`1:TryDequeue (object&) bool System.Collections.Concurrent.ConcurrentQueueSegment`1:TryDequeue (object&) bool System.Collections.Concurrent.ConcurrentQueueSegment`1:TryEnqueue (object) bool System.Collections.Generic.Dictionary`2/Enumerator>:MoveNext () + bool System.Collections.Generic.Dictionary`2/Enumerator:MoveNext () + bool System.Collections.Generic.Dictionary`2/Enumerator:MoveNext () bool System.Collections.Generic.Dictionary`2/Enumerator:MoveNext () bool System.Collections.Generic.Dictionary`2/Enumerator:MoveNext () bool System.Collections.Generic.Dictionary`2:TryGetValue (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey,object&) @@ -379,6 +382,7 @@ Methods: bool System.Collections.Generic.Dictionary`2:TryInsert (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain/ChainItemInfo,System.Collections.Generic.InsertionBehavior) bool System.Collections.Generic.Dictionary`2:TryGetValue (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/ServiceDescriptorCacheItem&) bool System.Collections.Generic.Dictionary`2:TryInsert (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/ServiceDescriptorCacheItem,System.Collections.Generic.InsertionBehavior) + bool System.Collections.Generic.Dictionary`2>:TryGetValue (Microsoft.Maui.Controls.BindableProperty,System.ValueTuple`2&) bool System.Collections.Generic.Dictionary`2>:TryInsert (Microsoft.Maui.Controls.BindableProperty,System.ValueTuple`2,System.Collections.Generic.InsertionBehavior) bool System.Collections.Generic.Dictionary`2:TryGetValue (int,Microsoft.AspNetCore.Components.Rendering.ComponentState&) bool System.Collections.Generic.Dictionary`2:TryInsert (int,Microsoft.AspNetCore.Components.Rendering.ComponentState,System.Collections.Generic.InsertionBehavior) @@ -393,6 +397,18 @@ Methods: bool System.Collections.Generic.Dictionary`2:TryInsert (intptr,Java.Interop.JniRuntime,System.Collections.Generic.InsertionBehavior) bool System.Collections.Generic.Dictionary`2:ContainsKey (intptr) bool System.Collections.Generic.Dictionary`2:TryInsert (intptr,System.IDisposable,System.Collections.Generic.InsertionBehavior) + bool System.Collections.Generic.Dictionary`2:TryGetValue (System.Linq.Expressions.Compiler.BoundConstants/TypedConstant,int&) + bool System.Collections.Generic.Dictionary`2:TryInsert (System.Linq.Expressions.Compiler.BoundConstants/TypedConstant,int,System.Collections.Generic.InsertionBehavior) + bool System.Collections.Generic.Dictionary`2:TryGetValue (System.Linq.Expressions.Compiler.BoundConstants/TypedConstant,System.Reflection.Emit.LocalBuilder&) + bool System.Collections.Generic.Dictionary`2:TryGetValue (System.Linq.Expressions.ParameterExpression,int&) + bool System.Collections.Generic.Dictionary`2:TryInsert (System.Linq.Expressions.ParameterExpression,int,System.Collections.Generic.InsertionBehavior) + bool System.Collections.Generic.Dictionary`2:ContainsKey (System.Linq.Expressions.ParameterExpression) + bool System.Collections.Generic.Dictionary`2:TryInsert (System.Linq.Expressions.ParameterExpression,System.Linq.Expressions.Compiler.VariableStorageKind,System.Collections.Generic.InsertionBehavior) + bool System.Collections.Generic.Dictionary`2:TryAdd (object,int) + bool System.Collections.Generic.Dictionary`2:TryGetValue (object,int&) + bool System.Collections.Generic.Dictionary`2:TryInsert (object,int,System.Collections.Generic.InsertionBehavior) + bool System.Collections.Generic.Dictionary`2:TryGetValue (System.Reflection.MemberInfo,System.Reflection.NullabilityState&) + bool System.Collections.Generic.Dictionary`2:TryInsert (System.Reflection.MemberInfo,System.Reflection.NullabilityState,System.Collections.Generic.InsertionBehavior) bool System.Collections.Generic.Dictionary`2:TryAdd (string,Microsoft.AspNetCore.Components.WebView.WebViewManager/RootComponent) bool System.Collections.Generic.Dictionary`2:TryAdd (string,int) bool System.Collections.Generic.Dictionary`2:TryGetValue (string,int&) @@ -409,19 +425,13 @@ Methods: bool System.Collections.Generic.Dictionary`2>:TryInsert (string,System.ValueTuple`2,System.Collections.Generic.InsertionBehavior) bool System.Collections.Generic.Dictionary`2:TryGetValue (System.Type,int&) bool System.Collections.Generic.Dictionary`2:TryInsert (System.Type,int,System.Collections.Generic.InsertionBehavior) - bool System.Collections.Generic.GenericEqualityComparer`1:Equals (string,string) - bool System.Collections.Generic.HashSet`1/Enumerator:MoveNext () + bool System.Collections.Generic.HashSet`1/Enumerator:MoveNext () bool System.Collections.Generic.HashSet`1:Add (string) bool System.Collections.Generic.HashSet`1:AddIfNotPresent (string,int&) - bool System.Collections.Generic.HashSet`1:Contains (System.Type) - bool System.Collections.Generic.List`1/Enumerator:MoveNext () - bool System.Collections.Generic.List`1/Enumerator:MoveNextRare () + bool System.Collections.Generic.HashSet`1:Contains (string) + bool System.Collections.Generic.HashSet`1:Remove (string) bool System.Collections.Generic.List`1/Enumerator:MoveNext () bool System.Collections.Generic.List`1/Enumerator:MoveNextRare () - bool System.Collections.Generic.List`1/Enumerator>:MoveNext () - bool System.Collections.Generic.List`1/Enumerator>:MoveNextRare () - bool System.Collections.Generic.List`1/Enumerator>:MoveNext () - bool System.Collections.Generic.List`1/Enumerator>:MoveNextRare () bool System.Collections.Generic.List`1/Enumerator>:MoveNext () bool System.Collections.Generic.List`1/Enumerator>:MoveNextRare () bool System.Collections.Generic.List`1:System.Collections.Generic.ICollection.get_IsReadOnly () @@ -430,10 +440,12 @@ Methods: bool System.Collections.Generic.NonRandomizedStringEqualityComparer/OrdinalIgnoreCaseComparer:Equals (string,string) bool System.Collections.Generic.ObjectEqualityComparer`1:Equals (System.Type,System.Type) bool System.Collections.Generic.ReferenceEqualityComparer:Equals (object,object) + bool System.Collections.Generic.Stack`1/Enumerator:MoveNext () + bool System.Collections.Generic.StringEqualityComparer:Equals (string,string) bool System.Collections.Hashtable:ContainsKey (object) bool System.Collections.Hashtable:KeyEquals (object,object) bool System.Collections.Specialized.SingleItemReadOnlyList/d__15:MoveNext () - bool System.Decimal:op_Inequality (System.Decimal,System.Decimal) + bool System.DefaultBinder:CompareMethodSig (System.Reflection.MethodBase,System.Reflection.MethodBase) bool System.Delegate:Equals (object) bool System.Delegate:IsArgumentTypeMatch (System.Type,System.Type) bool System.Delegate:IsArgumentTypeMatchWithThis (System.Type,System.Type,bool) @@ -441,20 +453,30 @@ Methods: bool System.Delegate:IsReturnTypeMatch (System.Type,System.Type) bool System.Diagnostics.Debugger:get_IsAttached () bool System.Diagnostics.Debugger:IsAttached_internal () + bool System.Diagnostics.Metrics.InstrumentAdvice`1:IsSortedAndDistinct (System.Collections.Generic.List`1) bool System.Diagnostics.Metrics.Meter:InitializeIsSupported () - bool System.Diagnostics.Tracing.EventSource:InitializeIsSupported () bool System.DomainNameHelper:IsValid (System.ReadOnlySpan`1,bool,bool,int&) bool System.Double:Equals (double) bool System.Double:Equals (object) + bool System.Dynamic.Utils.TypeExtensions:MatchesArgumentTypes (System.Reflection.MethodInfo,System.Type[]) + bool System.Dynamic.Utils.TypeUtils:AreEquivalent (System.Type,System.Type) + bool System.Dynamic.Utils.TypeUtils:AreReferenceAssignable (System.Type,System.Type) + bool System.Dynamic.Utils.TypeUtils:HasBuiltInEqualityOperator (System.Type,System.Type) + bool System.Dynamic.Utils.TypeUtils:IsNullableType (System.Type) + bool System.Dynamic.Utils.TypeUtils:ValidateType (System.Type,string,int) + bool System.Dynamic.Utils.TypeUtils/<>c:<.cctor>b__54_0 (System.Type) bool System.Enum:AreSequentialFromZero (uint[]) bool System.Enum:AreSequentialFromZero (uint16[]) bool System.Enum:AreSorted (uint[]) bool System.Enum:AreSorted (uint16[]) bool System.Enum:Equals (object) + bool System.Enum:IsDefined (System.Type,object) + bool System.Enum:IsDefinedPrimitive (System.RuntimeType,uint) bool System.Enum:TryFormatPrimitiveDefault (System.RuntimeType,int16,System.Span`1,int&) bool System.Enum:TryParse (System.Type,System.ReadOnlySpan`1,bool,bool,object&) bool System.Enum:TryParseByName (System.RuntimeType,System.ReadOnlySpan`1,bool,bool,uint&) bool System.Enum:TryParseByValueOrName (System.RuntimeType,System.ReadOnlySpan`1,bool,bool,int&) + bool System.Environment:get_IsSingleProcessor () bool System.GenericEmptyEnumeratorBase:MoveNext () bool System.Globalization.CompareInfo:GetIsAsciiEqualityOrdinal (string) bool System.Globalization.CompareInfo:IcuStartsWith (System.ReadOnlySpan`1,System.ReadOnlySpan`1,System.Globalization.CompareOptions,int*) @@ -470,12 +492,15 @@ Methods: bool System.Globalization.CultureInfo:get_HasInvariantCultureName () bool System.Globalization.CultureInfo:VerifyCultureName (string,bool) bool System.Globalization.GlobalizationMode:get_Invariant () + bool System.Globalization.GlobalizationMode:get_InvariantNoLoad () bool System.Globalization.GlobalizationMode:TryGetAppLocalIcuSwitchValue (string&) bool System.Globalization.GlobalizationMode:TryGetStringValue (string,string,string&) bool System.Globalization.GlobalizationMode/Settings:get_Invariant () bool System.Globalization.Ordinal:EqualsIgnoreCase_Scalar (char&,char&,int) - bool System.Globalization.Ordinal:EqualsIgnoreCase_Vector128 (char&,char&,int) + bool System.Globalization.Ordinal:EqualsIgnoreCase_Vector (char&,char&,int) bool System.Guid:TryWriteBytes (System.Span`1) + bool System.Int128:op_GreaterThan (System.Int128,System.Int128) + bool System.Int128:op_LessThan (System.Int128,System.Int128) bool System.Int32:TryFormat (System.Span`1,int&,System.ReadOnlySpan`1,System.IFormatProvider) bool System.Int64:TryParse (System.ReadOnlySpan`1,System.Globalization.NumberStyles,System.IFormatProvider,long&) bool System.IO.BufferedStream:get_CanSeek () @@ -487,8 +512,6 @@ Methods: bool System.IO.Path:EndsInDirectorySeparator (System.ReadOnlySpan`1) bool System.IO.Path:HasExtension (string) bool System.IO.Path:HasExtension (System.ReadOnlySpan`1) - bool System.IO.Path:IsPathRooted (string) - bool System.IO.Path:IsPathRooted (System.ReadOnlySpan`1) bool System.IO.PathInternal:AreRootsEqual (string,string,System.StringComparison) bool System.IO.PathInternal:EndsInDirectorySeparator (System.ReadOnlySpan`1) bool System.IO.PathInternal:RemoveRelativeSegments (System.ReadOnlySpan`1,int,System.Text.ValueStringBuilder&) @@ -499,18 +522,37 @@ Methods: bool System.IPv4AddressHelper:Parse (string,byte*,int,int) bool System.Lazy`1:CreateValue () bool System.Lazy`1:get_Value () - bool System.Linq.Enumerable:g__WithEnumerator|8_0 (System.Collections.Generic.IEnumerable`1) bool System.Linq.Enumerable:Any (System.Collections.Generic.IEnumerable`1,System.Func`2) bool System.Linq.Enumerable:Any (System.Collections.Generic.IEnumerable`1) bool System.Linq.Enumerable:Any (System.Collections.Generic.IEnumerable`1,System.Func`2) - bool System.Linq.Enumerable:TryGetNonEnumeratedCount (System.Collections.Generic.IEnumerable`1,int&) - bool System.Linq.Enumerable/d__41`1:MoveNext () bool System.Linq.Enumerable/AppendPrepend1Iterator`1:MoveNext () bool System.Linq.Enumerable/AppendPrependIterator`1:LoadFromEnumerator () - bool System.Linq.Enumerable/WhereArrayIterator`1:MoveNext () - bool System.Linq.Enumerable/WhereListIterator`1:MoveNext () - bool System.Linq.Extensions/d__5`1:MoveNext () - bool System.Linq.OrderedEnumerable`1/d__4:MoveNext () + bool System.Linq.Enumerable/ArrayWhereIterator`1:MoveNext () + bool System.Linq.Enumerable/ArrayWhereSelectIterator`2:MoveNext () + bool System.Linq.Enumerable/IEnumerableWhereIterator`1:MoveNext () + bool System.Linq.Enumerable/ListWhereIterator`1:MoveNext () + bool System.Linq.Enumerable/OfTypeIterator`1:MoveNext () + bool System.Linq.Enumerable/OrderedIterator`2:MoveNext () + bool System.Linq.Expressions.Compiler.CompilerScope:b__22_0 (System.Linq.Expressions.ParameterExpression) + bool System.Linq.Expressions.Compiler.CompilerScope:ShouldCache (System.Linq.Expressions.ParameterExpression,int) + bool System.Linq.Expressions.Compiler.ILGen:CanEmitConstant (object,System.Type) + bool System.Linq.Expressions.Compiler.ILGen:CanEmitILConstant (System.Type) + bool System.Linq.Expressions.Compiler.ILGen:TryEmitConstant (System.Reflection.Emit.ILGenerator,object,System.Type,System.Linq.Expressions.Compiler.ILocalCache) + bool System.Linq.Expressions.Compiler.ILGen:TryEmitILConstant (System.Reflection.Emit.ILGenerator,object,System.Type) + bool System.Linq.Expressions.Compiler.LambdaCompiler:HasVariables (object) + bool System.Linq.Expressions.Compiler.LambdaCompiler:NotEmpty (System.Linq.Expressions.Expression) + bool System.Linq.Expressions.Compiler.LambdaCompiler:Significant (System.Linq.Expressions.Expression) + bool System.Linq.Expressions.Compiler.LambdaCompiler:TryPushLabelBlock (System.Linq.Expressions.Expression) + bool System.Linq.Expressions.Compiler.ParameterList/d__6:MoveNext () + bool System.Linq.Expressions.Compiler.ParameterProviderExtensions:Contains (System.Linq.Expressions.IParameterProvider,System.Linq.Expressions.ParameterExpression) + bool System.Linq.Expressions.ConstantCheck:IsNull (System.Linq.Expressions.Expression) + bool System.Linq.Expressions.Expression:IsLiftingConditionalLogicalOperator (System.Type,System.Type,System.Reflection.MethodInfo,System.Linq.Expressions.ExpressionType) + bool System.Linq.Expressions.LambdaExpression:get_TailCall () + bool System.Linq.Expressions.LambdaExpression:get_TailCallCore () + bool System.Linq.Expressions.ParameterExpression:get_IsByRef () + bool System.Linq.Expressions.ParameterExpression:GetIsByRef () + bool System.Linq.Expressions.StackGuard:TryEnterOnCurrentStack () + bool System.Linq.Extensions/d__6`1:MoveNext () bool System.LocalAppContextSwitches:GetCachedSwitchValueInternal (string,int&) bool System.LocalAppContextSwitches:GetSwitchDefaultValue (string) bool System.MemoryExtensions:Equals (System.ReadOnlySpan`1,System.ReadOnlySpan`1,System.StringComparison) @@ -523,7 +565,6 @@ Methods: bool System.Net.Http.Headers.HeaderDescriptor:TryGet (string,System.Net.Http.Headers.HeaderDescriptor&) bool System.Net.Http.Headers.HeaderUtilities:TryParseInt64 (string,int,int,long&) bool System.Net.Http.Headers.HttpHeaders:TryAddWithoutValidation (string,System.Collections.Generic.IEnumerable`1) - bool System.Net.Http.Headers.HttpHeaders:TryAddWithoutValidation (System.Net.Http.Headers.HeaderDescriptor,string) bool System.Net.Http.Headers.HttpHeaders:TryAddWithoutValidation (System.Net.Http.Headers.HeaderDescriptor,System.Collections.Generic.IEnumerable`1) bool System.Net.Http.Headers.HttpHeaders:TryGetAndParseHeaderInfo (System.Net.Http.Headers.HeaderDescriptor,System.Net.Http.Headers.HttpHeaders/HeaderStoreItemInfo&) bool System.Net.Http.Headers.HttpHeaders:TryGetHeaderDescriptor (string,System.Net.Http.Headers.HeaderDescriptor&) @@ -543,7 +584,7 @@ Methods: bool System.Net.Http.HttpResponseMessage:get_IsSuccessStatusCode () bool System.Net.Http.HttpRuleParser:ContainsNewLine (string,int) bool System.Net.Http.QPack.QPackEncoder:EncodeNameString (string,System.Span`1,int&) - bool System.Number:g__TryFormatInt32Slow|42_0 (int,int,System.ReadOnlySpan`1,System.IFormatProvider,System.Span`1,int&) + bool System.Number:g__TryFormatInt32Slow|19_0 (int,int,System.ReadOnlySpan`1,System.IFormatProvider,System.Span`1,int&) bool System.Number:TryInt32ToHexStr (int,char,int,System.Span`1,int&) bool System.Number:TryUInt32ToDecStr (uint,System.Span`1,int&) bool System.Number:TryUInt64ToDecStr (ulong,System.Span`1,int&) @@ -564,7 +605,13 @@ Methods: bool System.ReadOnlySpan`1:TryCopyTo (System.Span`1) bool System.Reflection.Assembly:Equals (object) bool System.Reflection.Assembly:op_Inequality (System.Reflection.Assembly,System.Reflection.Assembly) + bool System.Reflection.AssemblyNameParser:IsAttribute (string,string) bool System.Reflection.AssemblyNameParser:IsWhiteSpace (char) + bool System.Reflection.AssemblyNameParser:TryGetNextToken (string&,System.Reflection.AssemblyNameParser/Token&) + bool System.Reflection.AssemblyNameParser:TryParse (System.Reflection.AssemblyNameParser/AssemblyNameParts&) + bool System.Reflection.AssemblyNameParser:TryParseCulture (string,string&) + bool System.Reflection.AssemblyNameParser:TryParsePKT (string,bool,byte[]&) + bool System.Reflection.AssemblyNameParser:TryParseVersion (string,System.Version&) bool System.Reflection.ConstructorInfo:Equals (object) bool System.Reflection.ConstructorInfo:op_Inequality (System.Reflection.ConstructorInfo,System.Reflection.ConstructorInfo) bool System.Reflection.CustomAttribute:AttrTypeMatches (System.Type,System.Type) @@ -572,15 +619,31 @@ Methods: bool System.Reflection.CustomAttribute:IsDefinedInternal (System.Reflection.ICustomAttributeProvider,System.Type) bool System.Reflection.CustomAttribute:IsUserCattrProvider (object) bool System.Reflection.CustomAttributeExtensions:IsDefined (System.Reflection.MemberInfo,System.Type) + bool System.Reflection.Emit.RuntimeTypeBuilder:get_ContainsGenericParameters () + bool System.Reflection.Emit.RuntimeTypeBuilder:get_IsGenericParameter () + bool System.Reflection.Emit.RuntimeTypeBuilder:get_IsGenericType () + bool System.Reflection.Emit.RuntimeTypeBuilder:get_IsGenericTypeDefinition () + bool System.Reflection.Emit.RuntimeTypeBuilder:HasElementTypeImpl () + bool System.Reflection.Emit.RuntimeTypeBuilder:IsValueTypeImpl () + bool System.Reflection.Emit.TypeNameBuilder:ContainsReservedChar (string) + bool System.Reflection.Emit.TypeNameBuilder:IsTypeNameReservedChar (char) bool System.Reflection.FieldInfo:get_IsNotSerialized () bool System.Reflection.FieldInfo:get_IsPublic () + bool System.Reflection.MemberInfo:get_IsCollectible () + bool System.Reflection.MethodBase:get_IsAssembly () + bool System.Reflection.MethodBase:get_IsFamilyAndAssembly () + bool System.Reflection.MethodBase:get_IsPrivate () bool System.Reflection.MethodBase:get_IsPublic () bool System.Reflection.MethodBase:get_IsStatic () bool System.Reflection.MethodBase:get_IsVirtual () bool System.Reflection.MethodBaseInvoker:TryByRefFastPath (System.RuntimeType,object&) + bool System.Reflection.NullabilityInfoContext:IsPrivateOrInternalMethodAndAnnotationDisabled (System.Reflection.MethodBase) + bool System.Reflection.NullabilityInfoContext/NullableAttributeStateParser:ParseNullableState (int,System.Reflection.NullabilityState&) bool System.Reflection.ParameterInfo:get_IsIn () bool System.Reflection.ParameterInfo:get_IsOptional () bool System.Reflection.ParameterInfo:get_IsOut () + bool System.Reflection.RuntimeAssembly:get_IsCollectible () + bool System.Reflection.RuntimeConstructorInfo:IsDefined (System.Type,bool) bool System.Reflection.RuntimeMethodInfo:g__IsDisallowedByRefType|79_0 (System.Type) bool System.Reflection.RuntimeMethodInfo:get_ContainsGenericParameters () bool System.Reflection.RuntimeMethodInfo:get_IsGenericMethod () @@ -599,8 +662,6 @@ Methods: bool System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1/ConfiguredTaskAwaiter:get_IsCompleted () bool System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1/ConfiguredTaskAwaiter:GetResult () bool System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1/ConfiguredTaskAwaiter:get_IsCompleted () - bool System.Runtime.CompilerServices.RuntimeFeature:get_IsDynamicCodeCompiled () - bool System.Runtime.CompilerServices.RuntimeFeature:get_IsDynamicCodeSupported () bool System.Runtime.CompilerServices.RuntimeHelpers:SufficientExecutionStack () bool System.Runtime.CompilerServices.RuntimeHelpers:TryEnsureSufficientExecutionStack () bool System.Runtime.InteropServices.MemoryMarshal:TryGetArray (System.ReadOnlyMemory`1,System.ArraySegment`1&) @@ -611,6 +672,7 @@ Methods: bool System.RuntimeType:FilterApplyMethodInfo (System.Reflection.RuntimeMethodInfo,System.Reflection.BindingFlags,System.Reflection.CallingConventions,System.Type[]) bool System.RuntimeType:get_ContainsGenericParameters () bool System.RuntimeType:get_IsActualEnum () + bool System.RuntimeType:get_IsActualValueType () bool System.RuntimeType:get_IsByRefLike () bool System.RuntimeType:get_IsConstructedGenericType () bool System.RuntimeType:get_IsEnum () @@ -626,6 +688,7 @@ Methods: bool System.RuntimeType:IsByRefImpl () bool System.RuntimeType:IsDefined (System.Type,bool) bool System.RuntimeType:IsDelegate () + bool System.RuntimeType:IsEnumDefined (object) bool System.RuntimeType:IsEquivalentTo (System.Type) bool System.RuntimeType:IsInstanceOfType (object) bool System.RuntimeType:IsPointerImpl () @@ -647,7 +710,6 @@ Methods: bool System.RuntimeTypeHandle:IsGenericVariable (System.RuntimeType) bool System.RuntimeTypeHandle:IsInstanceOfType (System.Runtime.CompilerServices.QCallTypeHandle,object) bool System.RuntimeTypeHandle:IsInstanceOfType (System.RuntimeType,object) - bool System.RuntimeTypeHandle:IsInterface (System.RuntimeType) bool System.RuntimeTypeHandle:IsPointer (System.RuntimeType) bool System.RuntimeTypeHandle:IsPrimitive (System.RuntimeType) bool System.RuntimeTypeHandle:IsSubclassOf (System.RuntimeType,System.RuntimeType) @@ -676,11 +738,11 @@ Methods: bool System.Text.Ascii:IsValidCore (uint16&,int) bool System.Text.CompositeFormat:TryParseLiterals (System.ReadOnlySpan`1,System.Collections.Generic.List`1>,int&,System.ExceptionResource&) bool System.Text.Encoding:get_IsUTF8CodePage () + bool System.Text.Json.AppContextSwitchHelper:get_RespectNullableAnnotationsDefault () + bool System.Text.Json.AppContextSwitchHelper:get_RespectRequiredConstructorParametersDefault () bool System.Text.Json.JsonDocument:TryGetValue (int,long&) bool System.Text.Json.JsonDocument:TryParseValue (System.Text.Json.Utf8JsonReader&,System.Text.Json.JsonDocument&,bool,bool) bool System.Text.Json.JsonElement:TryGetInt64 (long&) - bool System.Text.Json.JsonPropertyDictionary`1:ContainsProperty (string) - bool System.Text.Json.JsonPropertyDictionary`1:TryAddValue (string,System.Text.Json.Serialization.Metadata.JsonPropertyInfo) bool System.Text.Json.JsonSerializerOptions:get_CanUseFastPathSerializationLogic () bool System.Text.Json.JsonSerializerOptions:TryGetTypeInfoCached (System.Type,System.Text.Json.Serialization.Metadata.JsonTypeInfo&) bool System.Text.Json.JsonSerializerOptions/CachingContext:TryGetTypeInfo (System.Type,System.Text.Json.Serialization.Metadata.JsonTypeInfo&) @@ -689,7 +751,6 @@ Methods: bool System.Text.Json.Reflection.ReflectionExtensions:HasCustomAttributeWithName (System.Reflection.MemberInfo,string,bool) bool System.Text.Json.Reflection.ReflectionExtensions:HasJsonConstructorAttribute (System.Reflection.ConstructorInfo) bool System.Text.Json.Reflection.ReflectionExtensions:HasRequiredMemberAttribute (System.Reflection.MemberInfo) - bool System.Text.Json.Reflection.ReflectionExtensions:HasSetsRequiredMembersAttribute (System.Reflection.MemberInfo) bool System.Text.Json.Reflection.ReflectionExtensions:IsAssignableFromInternal (System.Type,System.Type) bool System.Text.Json.Reflection.ReflectionExtensions:IsImmutableDictionaryType (System.Type) bool System.Text.Json.Reflection.ReflectionExtensions:IsImmutableEnumerableType (System.Type) @@ -699,14 +760,16 @@ Methods: bool System.Text.Json.Reflection.ReflectionExtensions:TryGetDeserializationConstructor (System.Type,bool,System.Reflection.ConstructorInfo&) bool System.Text.Json.Serialization.Converters.EnumConverterFactory:CanConvert (System.Type) bool System.Text.Json.Serialization.Converters.FSharpTypeConverterFactory:CanConvert (System.Type) - bool System.Text.Json.Serialization.Converters.IEnumerableConverter`1:get_SupportsCreateObjectDelegate () + bool System.Text.Json.Serialization.Converters.IEnumerableConverter`1:get_SupportsCreateObjectDelegate () bool System.Text.Json.Serialization.Converters.IEnumerableConverterFactory:CanConvert (System.Type) bool System.Text.Json.Serialization.Converters.IEnumerableDefaultConverter`2, System.Object>:OnWriteResume (System.Text.Json.Utf8JsonWriter,System.Collections.Generic.IEnumerable`1,System.Text.Json.JsonSerializerOptions,System.Text.Json.WriteStack&) bool System.Text.Json.Serialization.Converters.IEnumerableOfTConverter`2, System.Char>:get_SupportsCreateObjectDelegate () bool System.Text.Json.Serialization.Converters.IEnumerableOfTConverter`2>>, System.Collections.Generic.KeyValuePair`2>>:get_SupportsCreateObjectDelegate () bool System.Text.Json.Serialization.Converters.IEnumerableOfTConverter`2, System.Object>:get_SupportsCreateObjectDelegate () bool System.Text.Json.Serialization.Converters.IEnumerableOfTConverter`2>>, System.Collections.Generic.KeyValuePair`2>>:get_SupportsCreateObjectDelegate () + bool System.Text.Json.Serialization.Converters.JsonDocumentConverter:get_HandleNull () bool System.Text.Json.Serialization.Converters.JsonNodeConverterFactory:CanConvert (System.Type) + bool System.Text.Json.Serialization.Converters.MemoryByteConverter:get_HandleNull () bool System.Text.Json.Serialization.Converters.MemoryConverterFactory:CanConvert (System.Type) bool System.Text.Json.Serialization.Converters.NullableConverterFactory:CanConvert (System.Type) bool System.Text.Json.Serialization.Converters.ObjectConverterFactory:CanConvert (System.Type) @@ -714,6 +777,7 @@ Methods: bool System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1>>:get_SupportsCreateObjectDelegate () bool System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1:get_SupportsCreateObjectDelegate () bool System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1>>:get_ConstructorIsParameterized () + bool System.Text.Json.Serialization.Converters.ReadOnlyMemoryByteConverter:get_HandleNull () bool System.Text.Json.Serialization.Converters.UnsupportedTypeConverterFactory:CanConvert (System.Type) bool System.Text.Json.Serialization.IAsyncEnumerableConverterFactory:CanConvert (System.Type) bool System.Text.Json.Serialization.IEnumerableConverterFactoryHelpers:IsNonGenericStackOrQueue (System.Type) @@ -721,7 +785,7 @@ Methods: bool System.Text.Json.Serialization.JsonCollectionConverter`2, System.String>:get_SupportsCreateObjectDelegate () bool System.Text.Json.Serialization.JsonConverter:get_ConstructorIsParameterized () bool System.Text.Json.Serialization.JsonConverter:get_SupportsCreateObjectDelegate () - bool System.Text.Json.Serialization.JsonConverter:ShouldFlush (System.Text.Json.Utf8JsonWriter,System.Text.Json.WriteStack&) + bool System.Text.Json.Serialization.JsonConverter:ShouldFlush (System.Text.Json.WriteStack&,System.Text.Json.Utf8JsonWriter) bool System.Text.Json.Serialization.JsonConverter`1:CanConvert (System.Type) bool System.Text.Json.Serialization.JsonConverter`1:get_HandleNull () bool System.Text.Json.Serialization.JsonConverter`1>:TryWriteAsObject (System.Text.Json.Utf8JsonWriter,object,System.Text.Json.JsonSerializerOptions,System.Text.Json.WriteStack&) @@ -747,8 +811,6 @@ Methods: bool System.Text.Json.Serialization.JsonConverter`1:get_HandleNull () bool System.Text.Json.Serialization.JsonConverter`1:TryWrite (System.Text.Json.Utf8JsonWriter,long&,System.Text.Json.JsonSerializerOptions,System.Text.Json.WriteStack&) bool System.Text.Json.Serialization.JsonConverter`1:TryWriteAsObject (System.Text.Json.Utf8JsonWriter,object,System.Text.Json.JsonSerializerOptions,System.Text.Json.WriteStack&) - bool System.Text.Json.Serialization.JsonConverter`1>:get_HandleNull () - bool System.Text.Json.Serialization.JsonConverter`1>:get_HandleNull () bool System.Text.Json.Serialization.JsonConverter`1:get_HandleNull () bool System.Text.Json.Serialization.JsonConverter`1:get_HandleNull () bool System.Text.Json.Serialization.JsonConverter`1:get_HandleNull () @@ -767,8 +829,17 @@ Methods: bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo:get_IgnoreReadOnlyMember () bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo:get_IsIgnored () bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo:NumberHandingIsApplicable () + bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1:get_PropertyTypeCanBeNull () + bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1:get_PropertyTypeCanBeNull () + bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1:get_PropertyTypeCanBeNull () + bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1>>:get_PropertyTypeCanBeNull () + bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1:get_PropertyTypeCanBeNull () + bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1:get_PropertyTypeCanBeNull () + bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1:get_PropertyTypeCanBeNull () + bool System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1:get_PropertyTypeCanBeNull () bool System.Text.Json.Serialization.Metadata.JsonTypeInfo:g__IsCurrentNodeCompatible|178_0 () bool System.Text.Json.Serialization.Metadata.JsonTypeInfo:DetermineUsesParameterizedConstructor () + bool System.Text.Json.Serialization.Metadata.JsonTypeInfo:get_IsNullable () bool System.Text.Json.Serialization.Metadata.JsonTypeInfo:IsByRefLike (System.Type) bool System.Text.Json.Serialization.Metadata.JsonTypeInfo:IsInvalidForSerialization (System.Type) bool System.Text.Json.Serialization.Metadata.JsonTypeInfoResolver:IsCompatibleWithOptions (System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver,System.Text.Json.JsonSerializerOptions) @@ -801,10 +872,12 @@ Methods: bool System.Threading.CancellationTokenSource:TransitionToCancellationRequested () bool System.Threading.CancellationTokenSource/Registrations:Unregister (long,System.Threading.CancellationTokenSource/CallbackNode) bool System.Threading.EventWaitHandle:Set () + bool System.Threading.Lock:get_IsSingleProcessor () bool System.Threading.LowLevelLifoSemaphore:Wait (int,bool) bool System.Threading.LowLevelLifoSemaphore:WaitCore (int) bool System.Threading.LowLevelLifoSemaphore:WaitForSignal (int) bool System.Threading.LowLevelLock:TryAcquire () + bool System.Threading.LowLevelLock:TryAcquire_NoFastPath (int) bool System.Threading.LowLevelMonitor:Wait (int) bool System.Threading.LowLevelMonitor:WaitCore (int) bool System.Threading.PortableThreadPool:get_HasForcedMaxThreads () @@ -843,7 +916,7 @@ Methods: bool System.Threading.TimerQueueTimer:Change (uint,uint) bool System.Threading.WaitHandle:WaitOne () bool System.Threading.WaitHandle:WaitOne (int) - bool System.Threading.WaitHandle:WaitOneNoCheck (int) + bool System.Threading.WaitHandle:WaitOneNoCheck (int,bool,object,System.Diagnostics.Tracing.NativeRuntimeEventSource/WaitHandleWaitSourceMap) bool System.Threading.WaitSubsystem/ThreadWaitInfo:TrySignalToSatisfyWait (System.Threading.WaitSubsystem/ThreadWaitInfo/WaitedListNode,bool) bool System.Threading.WaitSubsystem/WaitableObject:get_IsAbandonedMutex () bool System.Type:get_HasElementType () @@ -856,6 +929,8 @@ Methods: bool System.Type:get_IsPrimitive () bool System.Type:get_IsSealed () bool System.Type:get_IsValueType () + bool System.Type:IsAssignableTo (System.Type) + bool System.Type:IsIntegerType (System.Type) bool System.Type:op_Equality (System.Type,System.Type) bool System.Type:op_Inequality (System.Type,System.Type) bool System.UInt128:op_Equality (System.UInt128,System.UInt128) @@ -893,21 +968,27 @@ Methods: bool System.Xml.XmlTextReaderImpl:Read () bool System.Xml.XmlTextReaderImpl:ReadDataInName (int&) bool Xamarin.Android.Net.AndroidMessageHandler:get_decompress_here () + bool Xamarin.Android.Net.AndroidMessageHandler:get_HasClientCertificates () + bool Xamarin.Android.Net.AndroidMessageHandler:get_HasTrustedCerts () bool Xamarin.Android.Net.AndroidMessageHandler:HandleRedirect (System.Net.HttpStatusCode,Java.Net.HttpURLConnection,Xamarin.Android.Net.AndroidMessageHandler/RequestRedirectionState,bool&) bool Xamarin.Android.Net.AndroidMessageHandler:IsErrorStatusCode (System.Net.HttpStatusCode) + bool[] System.Buffers.SharedArrayPool`1:Rent (int) + bool[] System.GC:AllocateArray (int,bool) + bool[] System.GC:AllocateUninitializedArray (int,bool) byte System.IO.BinaryReader:ReadByte () byte[] Microsoft.AspNetCore.Components.WebView.ArrayBuilder`1:get_Buffer () byte[] System.ArraySegment`1:get_Array () byte[] System.Buffers.SharedArrayPool`1:Rent (int) byte[] System.GC:AllocateArray (int,bool) byte[] System.GC:AllocateUninitializedArray (int,bool) + byte[] System.Guid:ToByteArray () byte[] System.Net.Http.HPack.HPackEncoder:EncodeLiteralHeaderFieldWithoutIndexingNewNameToAllocatedArray (string) byte[] System.Net.Http.HPack.HPackEncoder:EncodeLiteralHeaderFieldWithoutIndexingToAllocatedArray (int) byte[] System.Net.Http.QPack.QPackEncoder:EncodeLiteralHeaderFieldWithoutNameReferenceToArray (string) byte[] System.Net.Http.QPack.QPackEncoder:EncodeLiteralHeaderFieldWithStaticNameReferenceToArray (int) byte[] System.ReadOnlySpan`1:ToArray () + byte[] System.Reflection.AssemblyName:GetPublicKeyToken () byte[] System.Reflection.AssemblyNameHelpers:ComputePublicKeyToken (byte[]) - byte[] System.Reflection.AssemblyNameParser:ParsePKT (string,bool) byte[] System.Text.Encoding:GetBytes (string) byte[] System.Text.Json.JsonHelpers:GetPropertyNameSection (System.ReadOnlySpan`1) byte[] System.Text.UTF8Encoding/UTF8EncodingSealed:GetBytes (string) @@ -923,12 +1004,11 @@ Methods: char System.Numerics.INumber`1:Max (char,char) char System.Numerics.INumber`1:Min (char,char) char[] System.Buffers.SharedArrayPool`1:Rent (int) - char[] System.Collections.Generic.ArrayBuilder`1:ToArray () - char[] System.Collections.Generic.EnumerableHelpers:ToArray (System.Collections.Generic.IEnumerable`1) - char[] System.Collections.Generic.LargeArrayBuilder`1:ToArray () + char[] System.Collections.Generic.SegmentedArrayBuilder`1:ToArray () char[] System.GC:AllocateArray (int,bool) char[] System.GC:AllocateUninitializedArray (int,bool) char[] System.IO.Path:GetInvalidPathChars () + char[] System.Linq.Enumerable:g__EnumerableToArray|301_0 (System.Collections.Generic.IEnumerable`1) char[] System.Linq.Enumerable:ToArray (System.Collections.Generic.IEnumerable`1) char* Java.Interop.JniEnvironment/Strings:GetStringChars (Java.Interop.JniObjectReference,bool*) char* System.Text.Unicode.Utf16Utility:GetPointerToFirstInvalidChar (char*,int,long&,int&) @@ -973,6 +1053,7 @@ Methods: double Microsoft.Maui.Layouts.LayoutExtensions:AlignVertical (Microsoft.Maui.IView,Microsoft.Maui.Graphics.Rect,Microsoft.Maui.Thickness) double Microsoft.Maui.Platform.ContextExtensions:FromPixels (Android.Content.Context,double) double Microsoft.Maui.Platform.MeasureSpecExtensions:ToDouble (int,Android.Content.Context) + double System.Collections.Generic.List`1:get_Item (int) double System.Math:Ceiling (double) double System.Math:Pow (double,double) double System.Private.CoreLib.Interop/Sys:g____PInvoke|30_0 (Interop/Sys/ProcessCpuInformation*) @@ -991,6 +1072,7 @@ Methods: int Android.Runtime.IdentityHashTargets:get_Count () int Android.Runtime.InputStreamAdapter:Read (byte[],int,int) int Android.Runtime.InputStreamInvoker:Read (byte[],int,int) + int Android.Runtime.JavaList:get_Count () int Android.Runtime.JNIEnv:_GetArrayLength (intptr) int Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPLII_I (_JniMarshal_PPLII_I,intptr,intptr,intptr,int,int) int Android.Runtime.RuntimeNativeMethods:_monodroid_gref_get () @@ -1025,6 +1107,7 @@ Methods: int Microsoft.AspNetCore.Components.RenderTree.Renderer:AssignRootComponentId (Microsoft.AspNetCore.Components.IComponent) int Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder:NextSiblingIndex (Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame&,int) int Microsoft.AspNetCore.Components.RenderTree.WebRenderer:AddRootComponent (System.Type,string) + int Microsoft.AspNetCore.Components.RouteTableFactory/InboundRouteEntryAmbiguityEqualityComparer:GetHashCode (Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry) int Microsoft.AspNetCore.Components.Routing.RouteKey:GetHashCode () int Microsoft.AspNetCore.Components.WebView.ArrayBuilder`1:Append (byte[],int,int) int Microsoft.AspNetCore.Components.WebView.ArrayBuilder`1:Append (System.ReadOnlySpan`1) @@ -1046,14 +1129,12 @@ Methods: int Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey:GetHashCode () int Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier:GetHashCode () int Microsoft.Extensions.Logging.LogValuesFormatter:FindBraceIndex (string,char,int,int) - int Microsoft.Extensions.Logging.LogValuesFormatter:FindIndexOfAny (string,char[],int,int) int Microsoft.Extensions.Primitives.StringSegment:get_Length () int Microsoft.Extensions.Primitives.StringSegment:IndexOfAny (char[],int) int Microsoft.Maui.Controls.DefinitionCollection`1:get_Count () int Microsoft.Maui.Controls.Layout:get_Count () int Microsoft.Maui.Controls.MenuBar:get_Count () int Microsoft.Maui.Controls.ReadOnlyCastingList`2:get_Count () - int Microsoft.Maui.Controls.SetterSpecificity:CompareTo (Microsoft.Maui.Controls.SetterSpecificity) int Microsoft.Maui.Controls.VisualStateGroupList:get_Count () int Microsoft.Maui.Controls.WatchAddList`1:get_Count () int Microsoft.Maui.Graphics.Color:ParseInt (System.ReadOnlySpan`1) @@ -1067,26 +1148,28 @@ Methods: int System.Array:IndexOf (char[],char,int,int) int System.Array:IndexOf (char[],char) int System.Array:IndexOf (System.Type[],System.Type,int,int) + int System.Array:IndexOf (System.Type[],System.Type) int System.Array:LastIndexOf (System.Delegate[],System.Delegate,int,int) int System.Array:LastIndexOf (System.Delegate[],System.Delegate) int System.ArraySegment`1:get_Count () int System.ArraySegment`1:get_Offset () int System.Buffers.Any5SearchValues`2:IndexOfAny (System.ReadOnlySpan`1) int System.Buffers.AnyByteSearchValues:IndexOfAny (System.ReadOnlySpan`1) - int System.Buffers.AnyByteSearchValues:IndexOfAnyScalar (byte&,int) - int System.Buffers.Latin1CharSearchValues:IndexOfAny (char&,int) - int System.Buffers.Latin1CharSearchValues:IndexOfAny (char&,int) - int System.Buffers.Latin1CharSearchValues:IndexOfAny (System.ReadOnlySpan`1) - int System.Buffers.Latin1CharSearchValues:IndexOfAnyExcept (System.ReadOnlySpan`1) - int System.Buffers.Latin1CharSearchValues:LastIndexOfAny (char&,int) - int System.Buffers.Latin1CharSearchValues:LastIndexOfAny (System.ReadOnlySpan`1) + int System.Buffers.BitmapCharSearchValues:IndexOfAny (char&,int) + int System.Buffers.BitmapCharSearchValues:IndexOfAny (char&,int) + int System.Buffers.BitmapCharSearchValues:IndexOfAny (System.ReadOnlySpan`1) + int System.Buffers.BitmapCharSearchValues:IndexOfAnyExcept (System.ReadOnlySpan`1) + int System.Buffers.BitmapCharSearchValues:LastIndexOfAny (char&,int) + int System.Buffers.BitmapCharSearchValues:LastIndexOfAny (System.ReadOnlySpan`1) + int System.Buffers.IndexOfAnyAsciiSearcher:IndexOfAnyCore (byte&,int,System.Buffers.IndexOfAnyAsciiSearcher/AnyByteState&) + int System.Buffers.SharedArrayPoolStatics:GetMaxArraysPerPartition () + int System.Buffers.SharedArrayPoolStatics:GetPartitionCount () int System.Collections.Concurrent.ConcurrentDictionary`2:GetCountNoLocks () int System.Collections.Concurrent.ConcurrentDictionary`2:GetCountNoLocks () int System.Collections.Concurrent.ConcurrentDictionary`2:GetCountNoLocks () int System.Collections.Concurrent.ConcurrentDictionary`2:get_Count () int System.Collections.Concurrent.ConcurrentDictionary`2:GetCountNoLocks () int System.Collections.Concurrent.ConcurrentDictionary`2, System.Text.Json.Cache`1/CacheEntry>>:GetCountNoLocks () - int System.Collections.Generic.Dictionary`2/ValueCollection:get_Count () int System.Collections.Generic.Dictionary`2/ValueCollection:get_Count () int System.Collections.Generic.Dictionary`2:Initialize (int) int System.Collections.Generic.Dictionary`2:Initialize (int) @@ -1099,6 +1182,11 @@ Methods: int System.Collections.Generic.Dictionary`2:Initialize (int) int System.Collections.Generic.Dictionary`2:Initialize (int) int System.Collections.Generic.Dictionary`2:Initialize (int) + int System.Collections.Generic.Dictionary`2:Initialize (int) + int System.Collections.Generic.Dictionary`2:Initialize (int) + int System.Collections.Generic.Dictionary`2:Initialize (int) + int System.Collections.Generic.Dictionary`2:Initialize (int) + int System.Collections.Generic.Dictionary`2:Initialize (int) int System.Collections.Generic.Dictionary`2:get_Count () int System.Collections.Generic.Dictionary`2:get_Item (string) int System.Collections.Generic.Dictionary`2:Initialize (int) @@ -1111,19 +1199,20 @@ Methods: int System.Collections.Generic.EqualityComparer`1:LastIndexOf (System.Delegate[],System.Delegate,int,int) int System.Collections.Generic.EqualityComparer`1:System.Collections.IEqualityComparer.GetHashCode (object) int System.Collections.Generic.EqualityComparer`1:IndexOf (System.Type[],System.Type,int,int) + int System.Collections.Generic.GenericComparer`1:Compare (double,double) + int System.Collections.Generic.HashSet`1:EnsureCapacity (int) + int System.Collections.Generic.HashSet`1:FindItemIndex (string) int System.Collections.Generic.HashSet`1:Initialize (int) - int System.Collections.Generic.HashSet`1:FindItemIndex (System.Type) - int System.Collections.Generic.List`1:get_Count () + int System.Collections.Generic.List`1:GetNewCapacity (int) + int System.Collections.Generic.List`1:IndexOf (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) + int System.Collections.Generic.List`1:get_Count () int System.Collections.Generic.List`1>:get_Count () - int System.Collections.Generic.List`1>:get_Count () int System.Collections.Generic.List`1:EnsureCapacity (int) - int System.Collections.Generic.List`1:IndexOf (System.Type) int System.Collections.Generic.NonRandomizedStringEqualityComparer/OrdinalComparer:GetHashCode (string) int System.Collections.Generic.NonRandomizedStringEqualityComparer/OrdinalIgnoreCaseComparer:GetHashCode (string) int System.Collections.Generic.ObjectEqualityComparer`1:GetHashCode (System.Type) int System.Collections.Generic.Queue`1:Dequeue () int System.Collections.Generic.ReferenceEqualityComparer:GetHashCode (object) - int System.Collections.Generic.SortedList`2/ValueList:get_Count () int System.Collections.Generic.Stack`1:Peek () int System.Collections.Generic.Stack`1:Pop () int System.Collections.HashHelpers:ExpandPrime (int) @@ -1132,10 +1221,15 @@ Methods: int System.Collections.Hashtable:GetHash (object) int System.Collections.ObjectModel.Collection`1:get_Count () int System.Collections.ObjectModel.ReadOnlyCollection`1:get_Count () + int System.Collections.ObjectModel.ReadOnlyCollection`1:get_Count () int System.Convert:ToBase64_CalculateAndValidateOutputLength (int,bool) - int System.Decimal/DecCalc:VarDecCmp (System.Decimal&,System.Decimal&) - int System.Decimal/DecCalc:VarDecCmpSub (System.Decimal&,System.Decimal&) + int System.Decimal:GetHashCode () + int System.Decimal/DecCalc:GetHashCode (System.Decimal&) + int System.DefaultBinder:FindMostSpecific (System.ReadOnlySpan`1,int[],System.Type,System.ReadOnlySpan`1,int[],System.Type,System.Type[],object[]) + int System.DefaultBinder:FindMostSpecificMethod (System.Reflection.MethodBase,int[],System.Type,System.Reflection.MethodBase,int[],System.Type,System.Type[],object[]) + int System.DefaultBinder:GetHierarchyDepth (System.Type) int System.Environment:get_CurrentManagedThreadId () + int System.Environment:get_ProcessorCount () int System.Environment:get_TickCount () int System.Environment:GetProcessorCount () int System.Globalization.CultureData:get_LCID () @@ -1174,19 +1268,29 @@ Methods: int System.IO.UnmanagedMemoryStream:ReadByte () int System.IO.UnmanagedMemoryStream:ReadCore (System.Span`1) int System.Linq.Enumerable:Count (System.Collections.Generic.IEnumerable`1) + int System.Linq.Expressions.Block2:get_ExpressionCount () + int System.Linq.Expressions.BlockExpressionList:get_Count () + int System.Linq.Expressions.Compiler.BoundConstants/TypedConstant:GetHashCode () + int System.Linq.Expressions.Compiler.LambdaCompiler:GetLambdaArgument (int) + int System.Linq.Expressions.Compiler.ParameterList:get_Count () + int System.Linq.Expressions.Compiler.ParameterProviderExtensions:IndexOf (System.Linq.Expressions.IParameterProvider,System.Linq.Expressions.ParameterExpression) + int System.Linq.Expressions.LambdaExpression:System.Linq.Expressions.IParameterProvider.get_ParameterCount () + int System.Linq.Expressions.NewExpression:get_ArgumentCount () int System.Marvin:ComputeHash32 (byte&,uint,uint,uint) + int System.Marvin:ComputeHash32OrdinalIgnoreCase (char&,int,uint,uint) int System.MemoryExtensions:Split (System.ReadOnlySpan`1,System.Span`1,char,System.StringSplitOptions) int System.MemoryExtensions:SplitCore (System.ReadOnlySpan`1,System.Span`1,System.ReadOnlySpan`1,System.ReadOnlySpan`1,bool,System.StringSplitOptions) int System.MemoryExtensions:ToLowerInvariant (System.ReadOnlySpan`1,System.Span`1) + int System.Net.Http.<>z__ReadOnlyArray`1:System.Collections.Generic.ICollection.get_Count () int System.Net.Http.Headers.HeaderUtilities:GetNextNonEmptyOrWhitespaceIndex (string,int,bool,bool&) int System.Net.Http.Headers.Int64NumberHeaderParser:GetParsedValueLength (string,int,object,object&) int System.Net.Http.HttpRuleParser:GetNumberLength (string,int,bool) - int System.Net.Http.HttpRuleParser:GetTokenLength (string,int) int System.Net.Http.HttpRuleParser:GetWhitespaceLength (string,int) int System.Net.Primitives.Interop/Sys:GetDomainName (byte*,int) int System.Nullable`1:get_Value () int System.Number:ParseBinaryInteger (System.ReadOnlySpan`1,System.Globalization.NumberStyles,System.Globalization.NumberFormatInfo) int System.Object:GetHashCode () + int System.OrdinalIgnoreCaseComparer:GetHashCode (string) int System.Private.CoreLib.Interop/Globalization:g____PInvoke|31_0 (char*,int) int System.Private.CoreLib.Interop/Globalization:g____PInvoke|35_0 (uint16*,uint,int*,int*) int System.Private.CoreLib.Interop/Globalization:g____PInvoke|34_0 (uint16*,uint,int*) @@ -1196,6 +1300,7 @@ Methods: int System.Private.CoreLib.Interop/Sys:g____PInvoke|67_0 (intptr,int) int System.Private.CoreLib.Interop/Sys:g____PInvoke|119_0 (byte*,Interop/Sys/FileStatus*) int System.Private.CoreLib.Interop/Sys:CanGetHiddenFlag () + int System.Private.CoreLib.Interop/Sys:GetCryptographicallySecureRandomBytes (byte*,int) int System.Private.CoreLib.Interop/Sys:GetErrNo () int System.Private.CoreLib.Interop/Sys:LChflagsCanSetHiddenFlag () int System.Private.CoreLib.Interop/Sys:LStat (byte&,Interop/Sys/FileStatus&) @@ -1207,8 +1312,10 @@ Methods: int System.Reflection.Emit.DynamicMethod:AddRef (object) int System.Reflection.Emit.DynamicMethod/DynamicMethodTokenGenerator:GetToken (System.Reflection.MemberInfo,bool) int System.Reflection.Emit.RuntimeILGenerator:get_ILOffset () + int System.Reflection.Emit.RuntimeModuleBuilder:get_next_table_index (int,int) int System.Reflection.MemberInfo:GetHashCode () int System.Reflection.MethodBase:GetHashCode () + int System.Reflection.MethodInfo:GetHashCode () int System.Reflection.MonoMethodInfo:get_method_attributes (intptr) int System.Reflection.PropertyInfo:GetHashCode () int System.Reflection.RuntimeConstructorInfo:GetParametersCount () @@ -1221,13 +1328,14 @@ Methods: int System.Resources.ResourceReader:GetNamePosition (int) int System.Resources.ResourceReader:ReadUnalignedI4 (int*) int System.Runtime.CompilerServices.RuntimeHelpers:InternalGetHashCode (object) - int System.Runtime.CompilerServices.RuntimeHelpers:InternalTryGetHashCode (object) int System.Runtime.InteropServices.Marshal:GetLastPInvokeError () int System.Runtime.InteropServices.Marshal:GetLastSystemError () + int System.Runtime.Intrinsics.Vector128`1:System.Runtime.Intrinsics.ISimdVector,T>.IndexOfLastMatch (System.Runtime.Intrinsics.Vector128`1) int System.RuntimeType:GetArrayRank () int System.RuntimeType:GetHashCode () int System.RuntimeTypeHandle:GetArrayRank (System.Runtime.CompilerServices.QCallTypeHandle) int System.RuntimeTypeHandle:GetArrayRank (System.RuntimeType) + int System.SpanHelpers:g__SimdImpl|91_0 (int16&,int16,int) int System.SpanHelpers:IndexOf (char&,int,char&,int) int System.SpanHelpers:IndexOfAnyValueType (int16&,int16,int16,int16,int16,int) int System.SpanHelpers:IndexOfAnyValueType (int16&,int16,int16,int16,int16,int16,int) @@ -1236,8 +1344,8 @@ Methods: int System.SpanHelpers:LastIndexOfValueType (int16&,int16,int) int System.SpanHelpers:NonPackedIndexOfAnyInRangeUnsignedNumber (uint16&,uint16,uint16,int) int System.SpanHelpers:NonPackedIndexOfAnyValueType (int16&,int16,int16,int) - int System.SpanHelpers:NonPackedIndexOfAnyValueType (int16&,int16,int16,int16,int) int System.SpanHelpers:NonPackedIndexOfValueType (byte&,byte,int) + int System.SpanHelpers:NonPackedIndexOfValueType (int&,int,int) int System.SpanHelpers:NonPackedIndexOfValueType (int16&,int16,int) int System.SpanHelpers:SequenceCompareTo (byte&,int,byte&,int) int System.SpanHelpers:SequenceCompareTo (char&,int,char&,int) @@ -1257,12 +1365,12 @@ Methods: int System.String:LastIndexOf (char) int System.String:strlen (byte*) int System.String:wcslen (char*) + int System.Text.ASCIIEncoding:GetByteCount (string) + int System.Text.ASCIIEncoding:GetByteCountFast (char*,int,System.Text.EncoderFallback,int&) + int System.Text.ASCIIEncoding:GetBytes (string,int,int,byte[],int) int System.Text.ASCIIEncoding:GetBytes (System.ReadOnlySpan`1,System.Span`1) int System.Text.ASCIIEncoding:GetBytesFast (char*,int,byte*,int,int&) int System.Text.DecoderExceptionFallbackBuffer:get_Remaining () - int System.Text.DecoderNLS:GetChars (byte[],int,int,char[],int,bool) - int System.Text.DecoderNLS:GetChars (byte[],int,int,char[],int) - int System.Text.DecoderNLS:GetChars (byte*,int,char*,int,bool) int System.Text.EncoderReplacementFallback:get_MaxCharCount () int System.Text.Encoding:get_CodePage () int System.Text.Encoding:GetChars (byte*,int,char*,int,System.Text.DecoderNLS) @@ -1281,7 +1389,10 @@ Methods: int System.Text.Json.JsonSerializerOptions/EqualityComparer:GetHashCode (System.Text.Json.JsonSerializerOptions) int System.Text.Json.JsonWriterHelper:NeedsEscaping (System.ReadOnlySpan`1,System.Text.Encodings.Web.JavaScriptEncoder) int System.Text.Json.JsonWriterHelper:NeedsEscaping (System.ReadOnlySpan`1,System.Text.Encodings.Web.JavaScriptEncoder) + int System.Text.Json.JsonWriterOptions:EncodeIndentSize (int) + int System.Text.Json.JsonWriterOptions:get_IndentSize () int System.Text.Json.Serialization.ConfigurationList`1:get_Count () + int System.Text.Json.Utf8JsonReader:get_CurrentDepth () int System.Text.RegularExpressions.RegexNode:ChildCount () int System.Text.RegularExpressions.RegexNode:ComputeMinLength () int System.Text.RegularExpressions.RegexParser:MapCaptureNumber (int,System.Collections.Hashtable) @@ -1312,7 +1423,7 @@ Methods: int System.Threading.Thread:GetSmallId () int System.Threading.ThreadLocal`1/IdManager:GetId (bool) int System.Threading.ThreadLocal`1:GetNewTableSize (int) - int System.Threading.WaitHandle:WaitOneCore (intptr,int) + int System.Threading.WaitHandle:WaitOneCore (intptr,int,bool) int System.Threading.WaitSubsystem:Wait (intptr,int,bool) int System.Threading.WaitSubsystem:Wait (System.Threading.WaitSubsystem/WaitableObject,int,bool,bool) int System.Threading.WaitSubsystem/ThreadWaitInfo:ProcessSignaledWaitState () @@ -1343,17 +1454,22 @@ Methods: int[] System.Globalization.CultureData:get_NumberGroupSizes () int[] System.Globalization.CultureData:GetLocaleInfoCoreUserOverride (System.Globalization.CultureData/LocaleGroupingData) int[] System.Globalization.CultureData:IcuGetLocaleInfo (System.Globalization.CultureData/LocaleGroupingData) - int[] System.Linq.EnumerableSorter`1:ComputeMap (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[],int) - int[] System.Linq.EnumerableSorter`1:Sort (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[],int) - int[] System.Linq.OrderedEnumerable`1:SortedMap (System.Linq.Buffer`1) + int[] System.Linq.Enumerable/EnumerableSorter`1:ComputeMap (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[],int) + int[] System.Linq.Enumerable/EnumerableSorter`1:Sort (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[],int) + int[] System.Linq.Enumerable/OrderedIterator`1:SortedMap (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[]) int[] System.ReadOnlySpan`1:ToArray () int& System.Collections.Generic.Dictionary`2/CollectionsMarshalHelper:GetValueRefOrAddDefault (System.Collections.Generic.Dictionary`2,string,bool&) + int& System.Collections.Generic.Dictionary`2:FindValue (System.Linq.Expressions.Compiler.BoundConstants/TypedConstant) + int& System.Collections.Generic.Dictionary`2:FindValue (System.Linq.Expressions.ParameterExpression) + int& System.Collections.Generic.Dictionary`2:FindValue (object) int& System.Collections.Generic.Dictionary`2:FindValue (string) int& System.Collections.Generic.Dictionary`2:FindValue (System.Type) int& System.Runtime.InteropServices.CollectionsMarshal:GetValueRefOrAddDefault (System.Collections.Generic.Dictionary`2,string,bool&) int16 System.AppContextConfigHelper:GetInt16Config (string,int16,bool) int16 System.AppContextConfigHelper:GetInt16Config (string,string,int16,bool) int16 System.DateTimeOffset:ValidateOffset (System.TimeSpan) + int16 System.Threading.Lock:DetermineMaxSpinCount () + int16 System.Threading.Lock:DetermineMinSpinCountForAdaptiveSpin () int16 System.Threading.PortableThreadPool:get_MinThreadsGoal () int16 System.Threading.PortableThreadPool:get_TargetThreadsGoalForBlockingAdjustment () int16 System.Threading.PortableThreadPool/WorkerThread:DetermineThreadsToKeepAlive () @@ -1398,27 +1514,21 @@ Methods: intptr Android.Runtime.JNIEnv:StartCreateInstance (string,string,Android.Runtime.JValue[]) intptr Android.Runtime.JNIEnv:StartCreateInstance (string,string,Android.Runtime.JValue*) intptr Android.Runtime.JNIEnv:ToLocalJniHandle (Android.Runtime.IJavaObject) - intptr Android.Runtime.JNIEnv/<>c:b__119_9 (System.Array) + intptr Android.Runtime.JNIEnv/<>c:b__121_9 (System.Array) intptr Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPLL_L (_JniMarshal_PPLL_L,intptr,intptr,intptr,intptr) intptr Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPLLL_L (_JniMarshal_PPLLL_L,intptr,intptr,intptr,intptr,intptr) intptr Android.Runtime.RuntimeNativeMethods:_monodroid_get_identity_hash_code (intptr,intptr) intptr Android.Runtime.RuntimeNativeMethods:monodroid_TypeManager_get_java_class_name (intptr) - intptr Android.Views.IWindowManagerInvoker:get_java_class_ref () - intptr Android.Views.IWindowManagerInvoker:Validate (intptr) - intptr Android.Webkit.IWebResourceRequestInvoker:get_java_class_ref () - intptr Android.Webkit.IWebResourceRequestInvoker:Validate (intptr) intptr Android.Webkit.WebViewClient:n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_ (intptr,intptr,intptr,intptr) intptr AndroidX.Fragment.App.Fragment:n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_ (intptr,intptr,intptr,intptr,intptr) intptr Java.Interop.JavaConvert:ToLocalJniHandle (object) intptr Java.Interop.JavaConvert:WithLocalJniHandle (string,System.Func`2) - intptr Java.Interop.JavaConvert/<>c:<.cctor>b__20_29 (object) + intptr Java.Interop.JavaConvert/<>c:<.cctor>b__21_29 (object) intptr Java.Interop.JniRuntime:_AttachCurrentThread (string,Java.Interop.JniObjectReference) intptr Java.Interop.JniRuntime:get_InvocationPointer () intptr Java.Interop.JniType:RawGetStaticMethodID (intptr,string,string,intptr&) intptr Java.Lang.Object:get_Handle () intptr Java.Lang.Object:Java.Interop.IJavaObjectEx.ToLocalJniHandle () - intptr Java.Util.IIteratorInvoker:get_java_class_ref () - intptr Java.Util.IIteratorInvoker:Validate (intptr) intptr Mono.RuntimeGPtrArrayHandle:get_Item (int) intptr Mono.RuntimeGPtrArrayHandle:Lookup (int) intptr Mono.SafeGPtrArrayHandle:get_Item (int) @@ -1445,7 +1555,6 @@ Methods: intptr System.RuntimeType:GetMethodsByName_native (System.Runtime.CompilerServices.QCallTypeHandle,intptr,System.Reflection.BindingFlags,System.RuntimeType/MemberListType) intptr System.RuntimeType:GetPropertiesByName_native (System.Runtime.CompilerServices.QCallTypeHandle,intptr,System.Reflection.BindingFlags,System.RuntimeType/MemberListType) intptr System.Threading.LowLevelLifoSemaphore:InitInternal () - intptr System.Threading.WaitSubsystem/HandleManager:NewHandle (System.Threading.WaitSubsystem/WaitableObject) intptr& System.Collections.Generic.Dictionary`2:FindValue (string) Java.Interop.IJavaPeerable Android.Runtime.AndroidValueManager:PeekPeer (Java.Interop.JniObjectReference) Java.Interop.IJavaPeerable Java.Interop.TypeManager:CreateInstance (intptr,Android.Runtime.JniHandleOwnership,System.Type) @@ -1453,6 +1562,7 @@ Methods: Java.Interop.IJavaPeerable Java.Lang.Object:GetObject (intptr,Android.Runtime.JniHandleOwnership,System.Type) Java.Interop.IJavaPeerable Java.Lang.Object:PeekObject (intptr,System.Type) Java.Interop.JavaVMInterface Java.Interop.JniRuntime:CreateInvoker (intptr) + Java.Interop.JavaVMInterface System.Runtime.InteropServices.Marshal:PtrToStructure (intptr) Java.Interop.JniEnvironmentInfo Java.Interop.JniEnvironment/<>c:<.cctor>b__35_0 () Java.Interop.JniEnvironmentInfo System.Threading.ThreadLocal`1:get_Value () Java.Interop.JniEnvironmentInfo System.Threading.ThreadLocal`1:GetValueSlow () @@ -1546,12 +1656,12 @@ Methods: Java.Net.URL Java.Net.URLConnection:get_URL () Java.Net.URLConnection Java.Net.URL:OpenConnection () Java.Security.KeyStore Java.Security.KeyStore:GetInstance (string) - Java.Security.KeyStore Xamarin.Android.Net.AndroidMessageHandler:g__InitializeKeyStore|161_0 (bool&) Java.Security.KeyStore Xamarin.Android.Net.AndroidMessageHandler:ConfigureKeyStore (Java.Security.KeyStore) - Java.Util.IIterator Android.Runtime.JavaList:Iterator () + Java.Security.KeyStore Xamarin.Android.Net.AndroidMessageHandler:GetConfiguredKeyStoreInstance () Java.Util.IIterator Android.Runtime.JavaSet:Iterator () Javax.Net.Ssl.IHostnameVerifier Xamarin.Android.Net.AndroidMessageHandler:GetSSLHostnameVerifier (Javax.Net.Ssl.HttpsURLConnection) Javax.Net.Ssl.KeyManagerFactory Xamarin.Android.Net.AndroidMessageHandler:ConfigureKeyManagerFactory (Java.Security.KeyStore) + Javax.Net.Ssl.KeyManagerFactory Xamarin.Android.Net.AndroidMessageHandler:GetConfiguredKeyManagerFactory (Java.Security.KeyStore) Javax.Net.Ssl.SSLSocketFactory Xamarin.Android.Net.AndroidMessageHandler:ConfigureCustomSSLSocketFactory (Javax.Net.Ssl.HttpsURLConnection) Javax.Net.Ssl.TrustManagerFactory Xamarin.Android.Net.AndroidMessageHandler:ConfigureTrustManagerFactory (Java.Security.KeyStore) long Java.Interop.JniEnvironment/StaticMethods:CallStaticLongMethod (Java.Interop.JniObjectReference,Java.Interop.JniMethodInfo,Java.Interop.JniArgumentValue*) @@ -1564,16 +1674,19 @@ Methods: long System.Diagnostics.Stopwatch:QueryPerformanceCounter () long System.Environment:get_TickCount64 () long System.IO.MemoryStream:Seek (long,System.IO.SeekOrigin) + long System.IO.MemoryStream:SeekCore (long,int) long System.IO.UnmanagedMemoryStream:get_Length () long System.IO.UnmanagedMemoryStream:get_Position () long System.IO.UnmanagedMemoryStream:Seek (long,System.IO.SeekOrigin) long System.IPv4AddressHelper:ParseNonCanonical (char*,int,int&,bool) + long System.Math:BigMul (long,long,long&) long System.Net.Http.HttpContent/LimitArrayPoolWriteStream:get_Length () long System.Nullable`1:get_Value () long System.Private.CoreLib.Interop/Sys:GetSystemTimeAsTicks () long System.Runtime.InteropServices.Marshal:ReadInt64 (intptr,int) long System.Text.Json.JsonElement:GetInt64 () long System.Text.Json.JsonSerializer:UnboxOnWrite (object) + long System.Text.Json.Serialization.Converters.EnumConverter`1:ConvertToInt64 (Microsoft.JSInterop.JSCallResultType) long System.Text.Json.Utf8JsonReader:GetInt64 () long System.Threading.ThreadInt64PersistentCounter:get_Count () long System.Threading.TimerQueue:get_TickCount64 () @@ -1583,11 +1696,16 @@ Methods: Microsoft.AspNetCore.Components.CascadingParameterInfo[] Microsoft.AspNetCore.Components.CascadingParameterState:GetCascadingParameterInfos (System.Type) Microsoft.AspNetCore.Components.ComponentFactory/ComponentTypeInfoCacheEntry Microsoft.AspNetCore.Components.ComponentFactory:GetComponentTypeInfo (System.Type) Microsoft.AspNetCore.Components.Dispatcher Microsoft.AspNetCore.Components.WebView.Services.WebViewRenderer:get_Dispatcher () + Microsoft.AspNetCore.Components.ICascadingValueSupplier[] System.Linq.Enumerable:ICollectionToArray (System.Collections.Generic.ICollection`1) + Microsoft.AspNetCore.Components.ICascadingValueSupplier[] System.Linq.Enumerable:ToArray (System.Collections.Generic.IEnumerable`1) Microsoft.AspNetCore.Components.IComponent Microsoft.AspNetCore.Components.ComponentFactory:InstantiateComponent (System.IServiceProvider,System.Type,Microsoft.AspNetCore.Components.IComponentRenderMode,System.Nullable`1) Microsoft.AspNetCore.Components.IComponent Microsoft.AspNetCore.Components.DefaultComponentActivator:CreateInstance (System.Type) Microsoft.AspNetCore.Components.IComponent Microsoft.AspNetCore.Components.RenderTree.Renderer:InstantiateComponent (System.Type) - Microsoft.AspNetCore.Components.IComponentActivator Microsoft.AspNetCore.Components.DefaultComponentActivator:get_Instance () Microsoft.AspNetCore.Components.IComponentActivator Microsoft.AspNetCore.Components.RenderTree.Renderer:GetComponentActivatorOrDefault (System.IServiceProvider) + Microsoft.AspNetCore.Components.IComponentRenderMode Microsoft.AspNetCore.Components.ComponentBase:get_AssignedRenderMode () + Microsoft.AspNetCore.Components.IComponentRenderMode Microsoft.AspNetCore.Components.RenderHandle:get_RenderMode () + Microsoft.AspNetCore.Components.IComponentRenderMode Microsoft.AspNetCore.Components.RenderTree.Renderer:GetComponentRenderMode (int) + Microsoft.AspNetCore.Components.IComponentRenderMode Microsoft.AspNetCore.Components.RenderTree.Renderer:GetComponentRenderMode (Microsoft.AspNetCore.Components.IComponent) Microsoft.AspNetCore.Components.ParameterValue Microsoft.AspNetCore.Components.ParameterView/Enumerator:get_Current () Microsoft.AspNetCore.Components.ParameterView Microsoft.AspNetCore.Components.ParameterView:get_Empty () Microsoft.AspNetCore.Components.ParameterView/Enumerator Microsoft.AspNetCore.Components.ParameterView:GetEnumerator () @@ -1639,12 +1757,9 @@ Methods: Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder:MapInbound (System.Type,Microsoft.AspNetCore.Routing.Patterns.RoutePattern,System.Collections.Generic.List`1) Microsoft.AspNetCore.Routing.Tree.TreeRouter Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder:Build () Microsoft.AspNetCore.Routing.Tree.TreeRouter Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder:Build (int) - Microsoft.AspNetCore.Routing.Tree.UrlMatchingNode System.Collections.Generic.Stack`1:Pop () - Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree System.Linq.OrderedEnumerable`1/d__4:System.Collections.Generic.IEnumerator.get_Current () - Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[] System.Collections.Generic.ArrayBuilder`1:ToArray () - Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[] System.Collections.Generic.EnumerableHelpers:ToArray (System.Collections.Generic.IEnumerable`1,int&) - Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[] System.Collections.Generic.LargeArrayBuilder`1:ToArray () Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree& System.Collections.Generic.Dictionary`2:FindValue (int) + Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorInfoEx[] Microsoft.Extensions.DependencyInjection.ActivatorUtilities:CreateConstructorInfoExs (System.Type) + Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorInfoEx[] Microsoft.Extensions.DependencyInjection.ActivatorUtilities:GetOrAddConstructors (System.Type) Microsoft.Extensions.DependencyInjection.AsyncServiceScope Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions:CreateAsyncScope (System.IServiceProvider) Microsoft.Extensions.DependencyInjection.IServiceCollection Microsoft.AspNetCore.Components.SupplyParameterFromQueryProviderServiceCollectionExtensions:AddSupplyValueFromQueryProvider (Microsoft.Extensions.DependencyInjection.IServiceCollection) Microsoft.Extensions.DependencyInjection.IServiceCollection Microsoft.Extensions.DependencyInjection.ComponentsWebViewServiceCollectionExtensions:AddBlazorWebView (Microsoft.Extensions.DependencyInjection.IServiceCollection) @@ -1665,6 +1780,8 @@ Methods: Microsoft.Extensions.DependencyInjection.IServiceScope Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope:CreateScope () Microsoft.Extensions.DependencyInjection.IServiceScope Microsoft.Extensions.DependencyInjection.ServiceProvider:CreateScope () Microsoft.Extensions.DependencyInjection.IServiceScope Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions:CreateScope (System.IServiceProvider) + Microsoft.Extensions.DependencyInjection.ObjectFactory Microsoft.AspNetCore.Components.DefaultComponentActivator:GetObjectFactory (System.Type) + Microsoft.Extensions.DependencyInjection.ObjectFactory Microsoft.Extensions.DependencyInjection.ActivatorUtilities:CreateFactory (System.Type,System.Type[]) Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Extensions.DependencyInjection.ServiceCollection:get_Item (int) Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Extensions.DependencyInjection.ServiceDescriptor:Describe (System.Type,System.Func`2,Microsoft.Extensions.DependencyInjection.ServiceLifetime) Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Extensions.DependencyInjection.ServiceDescriptor:Describe (System.Type,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) @@ -1682,7 +1799,6 @@ Methods: Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Extensions.DependencyInjection.ServiceDescriptor:Transient (System.Type,System.Type) Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/ServiceDescriptorCacheItem:get_Item (int) Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/ServiceDescriptorCacheItem:get_Last () - Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Maui.Hosting.Internal.MauiFactory:GetServiceDescriptor (System.Type) Microsoft.Extensions.DependencyInjection.ServiceDescriptor System.Collections.Generic.List`1:get_Item (int) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain/ChainItemInfo& System.Collections.Generic.Dictionary`2:FindValue (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory Microsoft.Extensions.DependencyInjection.ServiceProvider:get_CallSiteFactory () @@ -1758,6 +1874,7 @@ Methods: Microsoft.Maui.ApplicationModel.AppTheme Microsoft.Maui.ApplicationModel.AppInfoImplementation:get_RequestedTheme () Microsoft.Maui.ApplicationModel.AppTheme Microsoft.Maui.ApplicationModel.AppInfoImplementation:GetRequestedTheme () Microsoft.Maui.ApplicationModel.AppTheme Microsoft.Maui.Controls.Application:get_RequestedTheme () + Microsoft.Maui.ApplicationModel.AppTheme Microsoft.Maui.Controls.Application:get_UserAppTheme () Microsoft.Maui.ApplicationModel.IActivityStateManager Microsoft.Maui.ApplicationModel.ActivityStateManager:get_Default () Microsoft.Maui.ApplicationModel.IAppActions Microsoft.Maui.ApplicationModel.AppActions:get_Current () Microsoft.Maui.ApplicationModel.IAppInfo Microsoft.Maui.ApplicationModel.AppInfo:get_Current () @@ -1768,20 +1885,16 @@ Methods: Microsoft.Maui.Controls.Application Microsoft.Maui.Controls.Page:FindApplication (Microsoft.Maui.Controls.Element) Microsoft.Maui.Controls.Application Microsoft.Maui.Controls.Window:get_Application () Microsoft.Maui.Controls.BindableObject Microsoft.Maui.Controls.MergedStyle:get_Target () - Microsoft.Maui.Controls.BindableObject/BindablePropertyContext[] System.Collections.Generic.EnumerableHelpers:ToArray (System.Collections.Generic.IEnumerable`1) - Microsoft.Maui.Controls.BindableObject/BindablePropertyContext[] System.Linq.Enumerable:ToArray (System.Collections.Generic.IEnumerable`1) Microsoft.Maui.Controls.BindableProperty Microsoft.Maui.Controls.BindableProperty:Create (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindablePropertyBindingChanging,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) Microsoft.Maui.Controls.BindableProperty Microsoft.Maui.Controls.BindableProperty:Create (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) Microsoft.Maui.Controls.BindableProperty Microsoft.Maui.Controls.BindableProperty:CreateAttached (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindablePropertyBindingChanging,bool,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) Microsoft.Maui.Controls.BindableProperty Microsoft.Maui.Controls.BindableProperty:CreateAttached (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) Microsoft.Maui.Controls.BindablePropertyKey Microsoft.Maui.Controls.BindableProperty:CreateReadOnly (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) - Microsoft.Maui.Controls.BindingBase System.Linq.Enumerable:LastOrDefault (System.Collections.Generic.IEnumerable`1) - Microsoft.Maui.Controls.BindingBase System.Linq.Enumerable:TryGetLast (System.Collections.Generic.IEnumerable`1,bool&) + Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.SetterSpecificityList`1:GetValue () Microsoft.Maui.Controls.Brush Microsoft.Maui.Controls.Brush:get_Default () Microsoft.Maui.Controls.Brush Microsoft.Maui.Controls.VisualElement:get_Background () Microsoft.Maui.Controls.ColumnDefinitionCollection Microsoft.Maui.Controls.Grid:get_ColumnDefinitions () Microsoft.Maui.Controls.ControlTemplate Microsoft.Maui.Controls.TemplatedPage:get_ControlTemplate () - Microsoft.Maui.Controls.DependencyService/DependencyType System.Collections.Generic.List`1/Enumerator:get_Current () Microsoft.Maui.Controls.DependencyService/DependencyType System.Linq.Enumerable:FirstOrDefault (System.Collections.Generic.IEnumerable`1,System.Func`2) Microsoft.Maui.Controls.DependencyService/DependencyType System.Linq.Enumerable:TryGetFirst (System.Collections.Generic.IEnumerable`1,System.Func`2,bool&) Microsoft.Maui.Controls.EffectiveFlowDirection Microsoft.Maui.Controls.EffectiveFlowDirectionExtensions:ToEffectiveFlowDirection (Microsoft.Maui.FlowDirection,bool) @@ -1790,7 +1903,7 @@ Methods: Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element:get_Parent () Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element:get_ParentOverride () Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element:get_RealParent () - Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element/d__101`1:System.Collections.Generic.IEnumerator.get_Current () + Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element/d__103`1:System.Collections.Generic.IEnumerator.get_Current () Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.TemplatedPage:Microsoft.Maui.Controls.IControlTemplated.get_TemplateRoot () Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.ViewExtensions/d__22:System.Collections.Generic.IEnumerator.get_Current () Microsoft.Maui.Controls.Element System.Collections.Generic.Queue`1:Dequeue () @@ -1801,13 +1914,10 @@ Methods: Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.Page:get_BackgroundImageSource () Microsoft.Maui.Controls.IMessagingCenter Microsoft.Maui.Controls.MessagingCenter:get_Instance () Microsoft.Maui.Controls.INavigation Microsoft.Maui.Controls.NavigableElement:get_Navigation () - Microsoft.Maui.Controls.Internals.DynamicResource Microsoft.Maui.Controls.Xaml.DynamicResourceExtension:Microsoft.Maui.Controls.Xaml.IMarkupExtension.ProvideValue (System.IServiceProvider) Microsoft.Maui.Controls.Internals.INameScope Microsoft.Maui.Controls.Internals.NameScope:GetNameScope (Microsoft.Maui.Controls.BindableObject) Microsoft.Maui.Controls.Internals.IResourceDictionary Microsoft.Maui.Controls.Application:<.ctor>b__8_0 () Microsoft.Maui.Controls.Internals.IResourceDictionary Microsoft.Maui.Controls.Application:get_SystemResources () Microsoft.Maui.Controls.Internals.IResourceDictionary Microsoft.Maui.Controls.Compatibility.Platform.Android.ResourcesProvider:GetSystemResources () - Microsoft.Maui.Controls.Internals.IResourceDictionary System.Lazy`1:CreateValue () - Microsoft.Maui.Controls.Internals.IResourceDictionary System.Lazy`1:get_Value () Microsoft.Maui.Controls.Internals.ISystemResourcesProvider Microsoft.Maui.Controls.DependencyService:Get (Microsoft.Maui.Controls.DependencyFetchTarget) Microsoft.Maui.Controls.Internals.NavigationProxy Microsoft.Maui.Controls.NavigableElement:get_NavigationProxy () Microsoft.Maui.Controls.IVisual Microsoft.Maui.Controls.VisualElement:get_Visual () @@ -1816,8 +1926,8 @@ Methods: Microsoft.Maui.Controls.IVisual Microsoft.Maui.Controls.VisualMarker:get_MatchParent () Microsoft.Maui.Controls.LayoutOptions Microsoft.Maui.Controls.View:get_HorizontalOptions () Microsoft.Maui.Controls.LayoutOptions Microsoft.Maui.Controls.View:get_VerticalOptions () - Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Application:get_MainPage () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.MenuItemTracker`1:get_Target () + Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_CurrentPage () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_CurrentPlatformPage () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Window:get_Page () Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific.WindowSoftInputModeAdjust Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific.Application:GetWindowSoftInputModeAdjust (Microsoft.Maui.Controls.BindableObject) @@ -1826,11 +1936,9 @@ Methods: Microsoft.Maui.Controls.Shadow Microsoft.Maui.Controls.VisualElement:get_Shadow () Microsoft.Maui.Controls.Shapes.Geometry Microsoft.Maui.Controls.VisualElement:get_Clip () Microsoft.Maui.Controls.Style Microsoft.Maui.Controls.Compatibility.Platform.Android.ResourcesProvider:GetStyle (int) - Microsoft.Maui.Controls.Style Microsoft.Maui.Controls.Style:GetBasedOnResource (Microsoft.Maui.Controls.BindableObject) Microsoft.Maui.Controls.View Microsoft.Maui.Controls.ContentPage:get_Content () Microsoft.Maui.Controls.View Microsoft.Maui.Controls.Platform.GesturePlatformManager:get_View () Microsoft.Maui.Controls.VisualElement Microsoft.Maui.Controls.Platform.GesturePlatformManager:get_Element () - Microsoft.Maui.Controls.Window Microsoft.Maui.Controls.Application:CreateWindow (Microsoft.Maui.IActivationState) Microsoft.Maui.Controls.Window Microsoft.Maui.Controls.VisualElement:get_Window () Microsoft.Maui.Controls.Window Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.Controls.IWindowController.get_Window () Microsoft.Maui.Controls.Window Microsoft.Maui.Controls.Window:Microsoft.Maui.Controls.IWindowController.get_Window () @@ -1856,7 +1964,6 @@ Methods: Microsoft.Maui.FlowDirection Microsoft.Maui.Controls.Window:get_FlowDirection () Microsoft.Maui.Graphics.Color Microsoft.Maui.Controls.ImmutableBrush:get_Color () Microsoft.Maui.Graphics.Color Microsoft.Maui.Controls.KnownColor:get_Default () - Microsoft.Maui.Graphics.Color Microsoft.Maui.Controls.SolidColorBrush:get_Color () Microsoft.Maui.Graphics.Color Microsoft.Maui.Controls.VisualElement:get_BackgroundColor () Microsoft.Maui.Graphics.Color Microsoft.Maui.Graphics.Color:FromArgb (System.ReadOnlySpan`1) Microsoft.Maui.Graphics.Color Microsoft.Maui.Graphics.Color:FromRgba (byte,byte,byte,byte) @@ -1865,19 +1972,16 @@ Methods: Microsoft.Maui.Graphics.Color Microsoft.Maui.Graphics.Color:GetNamedColor (System.ReadOnlySpan`1) Microsoft.Maui.Graphics.Color Microsoft.Maui.Graphics.Color:Parse (string) Microsoft.Maui.Graphics.IShape Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.IView.get_Clip () - Microsoft.Maui.Graphics.Paint Microsoft.Maui.Controls.Brush:op_Implicit (Microsoft.Maui.Controls.Brush) Microsoft.Maui.Graphics.Paint Microsoft.Maui.Controls.Page:Microsoft.Maui.IView.get_Background () Microsoft.Maui.Graphics.Paint Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.IView.get_Background () Microsoft.Maui.Graphics.Platform.PlatformCanvasState Microsoft.Maui.Graphics.Platform.PlatformCanvasStateService:CreateNew (object) Microsoft.Maui.Graphics.Point Microsoft.Maui.VisualDiagnosticsOverlay:GenerateAdornerOffset (Android.Views.View) - Microsoft.Maui.Graphics.Rect Microsoft.Maui.Controls.VisualElement:get_Bounds () Microsoft.Maui.Graphics.Rect Microsoft.Maui.Controls.VisualElement:get_Frame () Microsoft.Maui.Graphics.Rect Microsoft.Maui.Graphics.Rect:FromLTRB (double,double,double,double) Microsoft.Maui.Graphics.Rect Microsoft.Maui.Layouts.LayoutExtensions:ComputeFrame (Microsoft.Maui.IView,Microsoft.Maui.Graphics.Rect) Microsoft.Maui.Graphics.Rect Microsoft.Maui.Platform.ActivityExtensions:GetWindowFrame (Android.App.Activity) Microsoft.Maui.Graphics.Rect Microsoft.Maui.Platform.ContextExtensions:FromPixels (Android.Content.Context,Android.Graphics.Rect) Microsoft.Maui.Graphics.Rect Microsoft.Maui.Platform.ContextExtensions:ToCrossPlatformRectInReferenceFrame (Android.Content.Context,int,int,int,int) - Microsoft.Maui.Graphics.Rect System.Collections.Generic.List`1:get_Item (int) Microsoft.Maui.Graphics.Size Microsoft.Maui.Controls.ContentPage:Microsoft.Maui.ICrossPlatformLayout.CrossPlatformArrange (Microsoft.Maui.Graphics.Rect) Microsoft.Maui.Graphics.Size Microsoft.Maui.Controls.ContentPage:Microsoft.Maui.ICrossPlatformLayout.CrossPlatformMeasure (double,double) Microsoft.Maui.Graphics.Size Microsoft.Maui.Controls.VisualElement:ArrangeOverride (Microsoft.Maui.Graphics.Rect) @@ -1896,17 +2000,22 @@ Methods: Microsoft.Maui.Graphics.Size Microsoft.Maui.ViewHandlerExtensions:GetDesiredSizeFromHandler (Microsoft.Maui.IViewHandler,double,double) Microsoft.Maui.Hosting.FontDescriptor System.Collections.Generic.List`1/Enumerator:get_Current () Microsoft.Maui.Hosting.IFontCollection Microsoft.Maui.Hosting.FontCollectionExtensions:AddFont (Microsoft.Maui.Hosting.IFontCollection,string,string) - Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:AddMauiControlsHandlers (Microsoft.Maui.Hosting.IMauiHandlersCollection) + Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:AddControlsHandlers (Microsoft.Maui.Hosting.IMauiHandlersCollection) + Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/<>c:b__1_1 (System.IServiceProvider) Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions:AddHandler (Microsoft.Maui.Hosting.IMauiHandlersCollection,System.Func`2) Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions:AddHandler (Microsoft.Maui.Hosting.IMauiHandlersCollection,System.Type,System.Type) Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions:AddHandler (Microsoft.Maui.Hosting.IMauiHandlersCollection) Microsoft.Maui.Hosting.IMauiInitializeService System.SZGenericArrayEnumerator`1:get_Current () - Microsoft.Maui.Hosting.Internal.MauiHandlersCollection Microsoft.Maui.Hosting.Internal.MauiHandlersFactory:CreateHandlerCollection (System.Collections.Generic.IEnumerable`1) + Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:GetInstance (Microsoft.Maui.Hosting.IMauiHandlersCollection) + Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet/<>c:b__1_0 (Microsoft.Maui.Hosting.IMauiHandlersCollection) + Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet System.Collections.Concurrent.ConcurrentDictionary`2:GetOrAdd (Microsoft.Maui.Hosting.IMauiHandlersCollection,System.Func`2) Microsoft.Maui.Hosting.MauiApp Microsoft.Maui.Hosting.MauiAppBuilder:Build () Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:ConfigureImageSourceHandlers (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:RemapForControls (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:SetupDefaults (Microsoft.Maui.Hosting.MauiAppBuilder) + Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:SetupXamlDefaults (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:UseMauiApp (Microsoft.Maui.Hosting.MauiAppBuilder) + Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:UseMauiPrimaryApp (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Hosting.AppHostBuilderExtensions:ConfigureAnimations (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Hosting.AppHostBuilderExtensions:ConfigureDispatching (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Hosting.EssentialsExtensions:UseEssentials (Microsoft.Maui.Hosting.MauiAppBuilder) @@ -1932,7 +2041,6 @@ Methods: Microsoft.Maui.IElementHandler Microsoft.Maui.Platform.ElementExtensions:ToHandler (Microsoft.Maui.IElement,Microsoft.Maui.IMauiContext) Microsoft.Maui.IEmbeddedFontLoader Microsoft.Maui.Hosting.FontsMauiAppBuilderExtensions/<>c:b__1_0 (System.IServiceProvider) Microsoft.Maui.IFontRegistrar Microsoft.Maui.Hosting.FontsMauiAppBuilderExtensions/<>c:b__1_1 (System.IServiceProvider) - Microsoft.Maui.IMauiContext Microsoft.Maui.ActivationState:get_Context () Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.ViewExtensions:FindMauiContext (Microsoft.Maui.Controls.Element,bool) Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.Window:get_MauiContext () Microsoft.Maui.IMauiContext Microsoft.Maui.Handlers.ElementHandler:get_MauiContext () @@ -1942,6 +2050,8 @@ Methods: Microsoft.Maui.IMauiHandlersFactory Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/<>c:b__1_0 (System.IServiceProvider) Microsoft.Maui.IMauiHandlersFactory Microsoft.Maui.MauiContext:<.ctor>b__6_0 () Microsoft.Maui.IMauiHandlersFactory Microsoft.Maui.MauiContext:get_Handlers () + Microsoft.Maui.IMauiHandlersFactory System.Lazy`1:CreateValue () + Microsoft.Maui.IMauiHandlersFactory System.Lazy`1:get_Value () Microsoft.Maui.IPersistedState Microsoft.Maui.ActivationState:get_State () Microsoft.Maui.IShadow Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.IView.get_Shadow () Microsoft.Maui.IToolbar Microsoft.Maui.Controls.Page:Microsoft.Maui.IToolbarElement.get_Toolbar () @@ -1964,7 +2074,7 @@ Methods: Microsoft.Maui.Layouts.GridLayoutManager/Definition[] Microsoft.Maui.Layouts.GridLayoutManager/GridStructure:InitializeColumns (System.Collections.Generic.IReadOnlyList`1) Microsoft.Maui.Layouts.GridLayoutManager/Definition[] Microsoft.Maui.Layouts.GridLayoutManager/GridStructure:InitializeRows (System.Collections.Generic.IReadOnlyList`1) Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnCreate Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions/d__3`1:System.Collections.Generic.IEnumerator.get_Current () - Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnCreate System.Linq.Enumerable/d__41`1:System.Collections.Generic.IEnumerator.get_Current () + Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnCreate System.Linq.Enumerable/Iterator`1:get_Current () Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions:OnBackPressed (Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder,Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnBackPressed) Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions:OnConfigurationChanged (Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder,Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnConfigurationChanged) Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions:OnCreate (Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder,Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnCreate) @@ -2009,13 +2119,12 @@ Methods: Microsoft.Win32.SafeHandles.SafeWaitHandle System.Threading.WaitSubsystem:NewHandle (System.Threading.WaitSubsystem/WaitableObject) Mono.MonoAssemblyName* System.Reflection.AssemblyName:GetNativeName (intptr) object Android.Runtime.AndroidEnvironment:GetHttpMessageHandler () - object Android.Runtime.JNIEnv/<>c:b__70_8 (System.Type,intptr,int) - object Android.Runtime.JNIEnv/<>c:b__70_9 (System.Type,intptr,int) - object Java.Interop.JavaConvert/<>c:<.cctor>b__20_9 (intptr,Android.Runtime.JniHandleOwnership) + object Android.Runtime.JNIEnv/<>c:b__72_8 (System.Type,intptr,int) + object Android.Runtime.JNIEnv/<>c:b__72_9 (System.Type,intptr,int) + object Java.Interop.JavaConvert/<>c:<.cctor>b__21_9 (intptr,Android.Runtime.JniHandleOwnership) object Java.Interop.TypeManager:CreateProxy (System.Type,intptr,Android.Runtime.JniHandleOwnership) object Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder:KeyValue (Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame&) object Microsoft.Extensions.DependencyInjection.KeyedService:get_AnyKey () - object Microsoft.Extensions.DependencyInjection.ServiceDescriptor:get_ImplementationInstance () object Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/<>c:b__16_0 (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier) object Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver:Resolve (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope) object Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver:VisitCache (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite,Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope,Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverLock) @@ -2058,8 +2167,6 @@ Methods: object Microsoft.Maui.Handlers.ViewHandler:OnCreatePlatformElement () object Microsoft.Maui.Handlers.ViewHandler`2:Microsoft.Maui.IElementHandler.get_PlatformView () object Microsoft.Maui.Hosting.Internal.MauiFactory:CreateInstance (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) - object Microsoft.Maui.Hosting.Internal.MauiFactory:GetService (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) - object Microsoft.Maui.Hosting.Internal.MauiFactory:GetService (System.Type,Microsoft.Extensions.DependencyInjection.ServiceDescriptor,System.Collections.Generic.IEnumerable`1) object Microsoft.Maui.Hosting.Internal.MauiFactory:GetService (System.Type) object Microsoft.Maui.MauiContext/<>c__11`1:b__11_0 (object) object Microsoft.Maui.MauiContext/<>c__12`1:b__12_0 (object) @@ -2080,17 +2187,18 @@ Methods: object System.Collections.Specialized.SingleItemReadOnlyList/d__15:System.Collections.IEnumerator.get_Current () object System.Convert:ChangeType (object,System.Type,System.IFormatProvider) object System.Delegate:get_Target () - object System.Enum:InternalBoxEnum (System.RuntimeType,long) + object System.Enum:InternalBoxEnum (System.RuntimeTypeHandle,long) object System.Enum:Parse (System.Type,string,bool) object System.Enum:Parse (System.Type,string) object System.GC:get_ephemeron_tombstone () object System.Globalization.CultureInfo:GetFormat (System.Type) - object System.Linq.Enumerable/Iterator`1:get_Current () object System.MulticastDelegate:GetTarget () object System.Net.Http.Headers.HttpHeaders:GetSingleParsedValue (System.Net.Http.Headers.HeaderDescriptor) object System.Net.Http.Headers.HttpHeaders/HeaderStoreItemInfo:GetSingleParsedValue () object System.Object:MemberwiseClone () + object System.Reflection.AssemblyName:Clone () object System.Reflection.ConstructorInfo:Invoke (object[]) + object System.Reflection.CustomAttributeTypedArgument:CanonicalizeValue (object) object System.Reflection.MethodBase:Invoke (object,object[]) object System.Reflection.MethodBaseInvoker:InterpretedInvoke_Constructor (object,intptr*) object System.Reflection.MethodBaseInvoker:InterpretedInvoke_Method (object,intptr*) @@ -2109,12 +2217,13 @@ Methods: object System.Reflection.RuntimeParameterInfo:GetDefaultValueFromCustomAttributes () object System.Resources.RuntimeResourceSet:GetObject (string,bool,bool) object System.Resources.RuntimeResourceSet:ReadValue (System.Resources.ResourceReader,int,bool,System.Resources.ResourceLocator&) + object System.Runtime.CompilerServices.RuntimeHelpers:Box (byte&,System.RuntimeTypeHandle) object System.Runtime.CompilerServices.RuntimeHelpers:GetUninitializedObject (System.Type) object System.Runtime.CompilerServices.RuntimeHelpers:GetUninitializedObjectInternal (intptr) + object System.Runtime.CompilerServices.RuntimeHelpers:InternalBox (System.Runtime.CompilerServices.QCallTypeHandle,byte&) object System.Runtime.DependentHandle:UnsafeGetTargetAndDependent (object&) object System.Runtime.InteropServices.GCHandle:get_Target () object System.Runtime.InteropServices.GCHandle:InternalGet (intptr) - object System.Runtime.InteropServices.Marshal:PtrToStructure (intptr,System.Type) object System.RuntimeType:CreateInstanceDefaultCtor (bool,bool) object System.RuntimeType:CreateInstanceForAnotherGenericParameter (System.Type,System.RuntimeType,System.RuntimeType) object System.RuntimeType:CreateInstanceImpl (System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) @@ -2126,22 +2235,25 @@ Methods: object System.Text.Json.JsonSerializer:ReadAsObject (System.Text.Json.Utf8JsonReader&,System.Text.Json.Serialization.Metadata.JsonTypeInfo) object System.Text.Json.JsonSerializer:ReadFromSpanAsObject (System.ReadOnlySpan`1,System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Nullable`1) object System.Text.Json.JsonSerializer:ReadFromSpanAsObject (System.ReadOnlySpan`1,System.Text.Json.Serialization.Metadata.JsonTypeInfo) + object System.Text.Json.Reflection.ReflectionExtensions:CreateInstanceNoWrapExceptions (System.Type,System.Type[],object[]) object System.Threading.PortableThreadPool:CreateThreadLocalCompletionCountObject () object System.Threading.PortableThreadPool:GetOrCreateThreadLocalCompletionCountObject () object System.Threading.ThreadInt64PersistentCounter:CreateThreadLocalCountObject () object System.Threading.ThreadPool:GetOrCreateThreadLocalCompletionCountObject () object System.Threading.ThreadPoolWorkQueue:Dequeue (System.Threading.ThreadPoolWorkQueueThreadLocals,bool&) + object System.Threading.ThreadPoolWorkQueue:DequeueWithPriorityAlternation (System.Threading.ThreadPoolWorkQueue,System.Threading.ThreadPoolWorkQueueThreadLocals,bool&) object System.Threading.ThreadPoolWorkQueue/WorkStealingQueue:LocalPop () + object System.Threading.ThreadPoolWorkQueue/WorkStealingQueue:LocalPopCore () object System.Threading.ThreadPoolWorkQueue/WorkStealingQueue:TrySteal (bool&) object System.WeakReference:get_Target () object[] Android.Runtime.JNIEnv:GetObjectArray (intptr,System.Type[]) + object[] System.Linq.Expressions.Compiler.BoundConstants:ToArray () object[] System.Reflection.CustomAttribute:GetCustomAttributes (System.Reflection.ICustomAttributeProvider,bool) object[] System.Reflection.CustomAttribute:GetCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type,bool) object[] System.Reflection.CustomAttribute:GetCustomAttributesBase (System.Reflection.ICustomAttributeProvider,System.Type,bool) object[] System.Reflection.CustomAttribute:GetPseudoCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type) object[] System.Reflection.CustomAttribute:GetPseudoCustomAttributes (System.Type) object[] System.Reflection.FieldInfo:GetPseudoCustomAttributes () - object[] System.Reflection.RuntimeConstructorInfo:GetCustomAttributes (bool) object[] System.Reflection.RuntimeParameterInfo:GetCustomAttributes (bool) object[] System.Reflection.RuntimeParameterInfo:GetCustomAttributes (System.Type,bool) object[] System.Reflection.RuntimeParameterInfo:GetPseudoCustomAttributes () @@ -2150,7 +2262,7 @@ Methods: object[] System.RuntimeType:GetCustomAttributes (System.Type,bool) object& System.Collections.Generic.Dictionary`2:FindValue (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey) object& System.Collections.Generic.Dictionary`2:FindValue (string) - object& System.Net.Http.Headers.HttpHeaders:g__GrowEntriesAndAddDefault|73_0 (System.Net.Http.Headers.HeaderDescriptor) + object& System.Net.Http.Headers.HttpHeaders:g__GrowEntriesAndAddDefault|74_0 (System.Net.Http.Headers.HeaderDescriptor) object& System.Net.Http.Headers.HttpHeaders:GetValueRefOrAddDefault (System.Net.Http.Headers.HeaderDescriptor) object& System.Net.Http.Headers.HttpHeaders:GetValueRefOrNullRef (System.Net.Http.Headers.HeaderDescriptor) single Android.Util.DisplayMetrics:get_Density () @@ -2168,6 +2280,8 @@ Methods: string Android.Runtime.AndroidTypeManager:GetReplacementTypeCore (string) string Android.Runtime.AndroidTypeManager:GetSimpleReference (System.Type) string Android.Runtime.JavaArray`1/d__13:System.Collections.Generic.IEnumerator.get_Current () + string Android.Runtime.JavaList`1:get_Item (int) + string Android.Runtime.JavaList`1:InternalGet (int) string Android.Runtime.JNIEnv:GetCharSequence (intptr,Android.Runtime.JniHandleOwnership) string Android.Runtime.JNIEnv:GetClassNameFromInstance (intptr) string Android.Runtime.JNIEnv:GetJniName (System.Type) @@ -2197,9 +2311,11 @@ Methods: string Microsoft.AspNetCore.Components.NavigationManager:ToBaseRelativePath (string) string Microsoft.AspNetCore.Components.Routing.NavLink:CombineWithSpace (string,string) string Microsoft.AspNetCore.Components.WebView.FileExtensionContentTypeProvider:GetExtension (string) + string Microsoft.AspNetCore.Components.WebView.HostAddressHelper:GetAppHostAddress () string Microsoft.AspNetCore.Components.WebView.IpcCommon:Serialize (Microsoft.AspNetCore.Components.WebView.IpcCommon/OutgoingMessageType,object[]) string Microsoft.AspNetCore.Components.WebView.IpcCommon:Serialize (string,object[]) string Microsoft.AspNetCore.Components.WebView.Maui.AndroidMauiAssetFileProvider/AndroidMauiAssetFileInfo:get_Name () + string Microsoft.AspNetCore.Components.WebView.Maui.AndroidWebKitWebViewManager:get_AppOrigin () string Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebView:get_HostPage () string Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebView:get_StartPath () string Microsoft.AspNetCore.Components.WebView.QueryStringHelper:RemovePossibleQueryString (string) @@ -2216,6 +2332,7 @@ Methods: string Microsoft.Maui.ApplicationModel.AppInfoImplementation:get_Name () string Microsoft.Maui.ApplicationModel.AppInfoImplementation/<>c:<.cctor>b__23_0 () string Microsoft.Maui.Controls.Element:get_AutomationId () + string Microsoft.Maui.Controls.PropertyChangingEventArgs:get_PropertyName () string Microsoft.Maui.Controls.Window:get_Title () string Microsoft.Maui.Controls.Window:Microsoft.Maui.ITitledElement.get_Title () string Microsoft.Maui.Handlers.AndroidBatchPropertyMapper`2/d__2:System.Collections.Generic.IEnumerator.get_Current () @@ -2231,6 +2348,7 @@ Methods: string System.Enum:ToString () string System.Environment:GetEnvironmentVariable (string) string System.Environment:GetEnvironmentVariableCore (string) + string System.Environment:GetEnvironmentVariableCore_NoArrayPool (string) string System.Globalization.CultureData:AnsiToLower (string) string System.Globalization.CultureData:get_CultureName () string System.Globalization.CultureData:get_NaNSymbol () @@ -2271,7 +2389,9 @@ Methods: string System.IO.PathInternal:NormalizeDirectorySeparators (string) string System.IO.PathInternal:RemoveRelativeSegments (string,int) string System.IPv4AddressHelper:ParseCanonicalName (string,int,int,bool&) - string System.Linq.Extensions/d__5`1:System.Collections.Generic.IEnumerator.get_Current () + string System.Linq.Expressions.LambdaExpression:get_Name () + string System.Linq.Expressions.LambdaExpression:get_NameCore () + string System.Linq.Extensions/d__6`1:System.Collections.Generic.IEnumerator.get_Current () string System.Net.CookieContainer:CreateFqdnMyDomain () string System.Net.CookieContainer:GetCookieHeader (System.Uri,string&) string System.Net.CookieContainer:GetCookieHeader (System.Uri) @@ -2279,7 +2399,7 @@ Methods: string System.Net.NetworkInformation.HostInformation:get_DomainName () string System.Net.NetworkInformation.HostInformationPal:GetDomainName () string System.Net.Primitives.Interop/Sys:GetDomainName () - string System.Number:g__CreateAndCacheString|70_0 (uint) + string System.Number:g__CreateAndCacheString|47_0 (uint) string System.Number:FormatInt32 (int,int,string,System.IFormatProvider) string System.Number:Int32ToDecStr (int) string System.Number:UInt32ToDecStr (uint) @@ -2291,8 +2411,12 @@ Methods: string System.ReadOnlySpan`1:ToString () string System.Reflection.AssemblyName:get_CultureName () string System.Reflection.AssemblyName:get_FullName () - string System.Reflection.AssemblyNameFormatter:ComputeDisplayName (string,System.Version,string,byte[],System.Reflection.AssemblyNameFlags,System.Reflection.AssemblyContentType) - string System.Reflection.AssemblyNameParser:ParseCulture (string) + string System.Reflection.AssemblyNameFormatter:ComputeDisplayName (string,System.Version,string,byte[],System.Reflection.AssemblyNameFlags,System.Reflection.AssemblyContentType,byte[]) + string System.Reflection.Emit.RuntimeTypeBuilder:get_FullName () + string System.Reflection.Emit.RuntimeTypeBuilder:get_Name () + string System.Reflection.Emit.RuntimeTypeBuilder:get_Namespace () + string System.Reflection.Emit.TypeNameBuilder:ToString () + string System.Reflection.Emit.TypeNameBuilder:ToString (System.Type,System.Reflection.Emit.TypeNameBuilder/Format) string System.Reflection.ParameterInfo:get_Name () string System.Reflection.RuntimeAssembly:get_FullName () string System.Reflection.RuntimeAssembly:get_Location () @@ -2307,6 +2431,7 @@ Methods: string System.Runtime.InteropServices.Marshal:PtrToStringUTF8 (intptr) string System.RuntimeType:get_FullName () string System.RuntimeType:get_Name () + string System.RuntimeType:get_Namespace () string System.RuntimeType:getFullName (bool,bool) string System.RuntimeType:ToString () string System.Span`1:ToString () @@ -2319,7 +2444,6 @@ Methods: string System.String:Create (int,string,System.Buffers.SpanAction`2) string System.String:CreateStringForSByteConstructor (byte*,int) string System.String:CreateStringFromEncoding (byte*,int,System.Text.Encoding) - string System.String:CreateTrimmedString (int,int) string System.String:Ctor (char,int) string System.String:Ctor (char[],int,int) string System.String:Ctor (char*,int,int) @@ -2327,8 +2451,8 @@ Methods: string System.String:Ctor (sbyte*) string System.String:Ctor (System.ReadOnlySpan`1) string System.String:InternalSubString (int,int) - string System.String:Join (string,object[]) - string System.String:JoinCore (System.ReadOnlySpan`1,object[]) + string System.String:Join (string,System.ReadOnlySpan`1) + string System.String:JoinCore (System.ReadOnlySpan`1,System.ReadOnlySpan`1) string System.String:Replace (char,char) string System.String:Replace (string,string) string System.String:Substring (int,int) @@ -2337,8 +2461,6 @@ Methods: string System.String:ToString () string System.String:ToString (System.IFormatProvider) string System.String:Trim () - string System.String:Trim (char) - string System.String:TrimHelper (char*,int,System.Text.TrimType) string System.Text.Encoding:get_WebName () string System.Text.Encoding:GetString (System.ReadOnlySpan`1) string System.Text.EncodingTable:GetDisplayName (int) @@ -2349,7 +2471,9 @@ Methods: string System.Text.Json.JsonReaderHelper:TranscodeHelper (System.ReadOnlySpan`1) string System.Text.Json.JsonSerializer:Serialize (object[],System.Text.Json.JsonSerializerOptions) string System.Text.Json.JsonSerializer:WriteString (object[]&,System.Text.Json.Serialization.Metadata.JsonTypeInfo`1) - string System.Text.Json.Serialization.Converters.EnumConverter`1:FormatJsonName (string,System.Text.Json.JsonNamingPolicy) + string System.Text.Json.JsonSerializerOptions:get_NewLine () + string System.Text.Json.JsonWriterOptions:get_NewLine () + string System.Text.Json.Serialization.Converters.EnumConverter`1:ResolveAndValidateJsonName (string,System.Text.Json.JsonNamingPolicy,System.Text.Json.Serialization.Converters.EnumConverter`1/EnumFieldNameKind) string System.Text.RegularExpressions.RegexCharClass:ToStringClass () string System.Text.RegularExpressions.RegexParser:ScanCapname () string System.Text.StringBuilder:ToString () @@ -2378,7 +2502,6 @@ Methods: string System.Uri:PathDifference (string,string,bool) string System.Uri:RecreateParts (System.UriComponents,uint16,System.UriFormat) string System.Uri:ToString () - string System.Uri:UnescapeDataString (string) string System.UriBuilder:EncodeUserInfo (string) string System.UriBuilder:ToString () string System.UriParser:get_SchemeName () @@ -2402,8 +2525,6 @@ Methods: string[] Microsoft.AspNetCore.Components.RouteTableFactory:GetTemplates (System.Type) string[] System.Buffers.SharedArrayPool`1:Rent (int) string[] System.Enum:GetNames () - string[] System.GC:AllocateArray (int,bool) - string[] System.GC:AllocateUninitializedArray (int,bool) string[] System.Globalization.CultureData:GetNativeDigits () string[] System.ReadOnlySpan`1:ToArray () string[] System.String:Split (char,System.StringSplitOptions) @@ -2411,9 +2532,9 @@ Methods: string[] System.String:SplitWithoutPostProcessing (System.ReadOnlySpan`1,System.ReadOnlySpan`1,int,int) System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__16`1>:get_MoveNextAction () System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__0>:get_MoveNextAction () - System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__81>:get_MoveNextAction () - System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__76>:get_MoveNextAction () - System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__15>:get_MoveNextAction () + System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__89>:get_MoveNextAction () + System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__84>:get_MoveNextAction () + System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__17>:get_MoveNextAction () System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1c__DisplayClass14_0/<g__AwaitAndNotify|0>d>:get_MoveNextAction () System.Action System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__0>:get_MoveNextAction () System.Action`2 Microsoft.Extensions.Logging.LoggerMessage:Define (Microsoft.Extensions.Logging.LogLevel,Microsoft.Extensions.Logging.EventId,string,Microsoft.Extensions.Logging.LogDefineOptions) @@ -2430,9 +2551,10 @@ Methods: System.Action`5 Microsoft.Extensions.Logging.LoggerMessage:Define (Microsoft.Extensions.Logging.LogLevel,Microsoft.Extensions.Logging.EventId,string,Microsoft.Extensions.Logging.LogDefineOptions) System.Action`6 Microsoft.Extensions.Logging.LoggerMessage:Define (Microsoft.Extensions.Logging.LogLevel,Microsoft.Extensions.Logging.EventId,string,Microsoft.Extensions.Logging.LogDefineOptions) System.Array Android.Runtime.JNIEnv:_GetArray (intptr,System.Type) + System.Array Android.Runtime.JNIEnv:ArrayCreateInstance (System.Type,int) System.Array Android.Runtime.JNIEnv:GetArray (intptr,Android.Runtime.JniHandleOwnership,System.Type) - System.Array Android.Runtime.JNIEnv/<>c:b__96_1 (System.Type,intptr,int) - System.Array Android.Runtime.JNIEnv/<>c:b__96_12 (System.Type,intptr,int) + System.Array Android.Runtime.JNIEnv/<>c:b__98_1 (System.Type,intptr,int) + System.Array Android.Runtime.JNIEnv/<>c:b__98_12 (System.Type,intptr,int) System.Array Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver:g__CreateArray|12_0 (System.Type,int) System.Array System.Array:CreateInstance (System.Type,int) System.Array System.Array:InternalCreate (System.RuntimeType,int,int*,int*) @@ -2449,6 +2571,7 @@ Methods: System.Attribute[] System.Reflection.CustomAttribute:GetCustomAttributesInternal (System.Reflection.ICustomAttributeProvider,System.Type,bool) System.AttributeUsageAttribute System.Reflection.CustomAttribute:RetrieveAttributeUsage (System.Type) System.AttributeUsageAttribute System.Reflection.CustomAttribute:RetrieveAttributeUsageNoCache (System.Type) + System.Buffers.ArrayPool`1 System.Buffers.ArrayPool`1:get_Shared () System.Buffers.ArrayPool`1 System.Buffers.ArrayPool`1:get_Shared () System.Buffers.ArrayPool`1 System.Buffers.ArrayPool`1:get_Shared () System.Buffers.ArrayPool`1 System.Buffers.ArrayPool`1:get_Shared () @@ -2457,6 +2580,8 @@ Methods: System.Buffers.ArrayPool`1 System.Buffers.ArrayPool`1:get_Shared () System.Buffers.ArrayPool`1 System.Buffers.ArrayPool`1:get_Shared () System.Buffers.OperationStatus System.Buffers.Text.Base64:EncodeToUtf8 (System.ReadOnlySpan`1,System.Span`1,int&,int&,bool) + System.Buffers.OperationStatus System.Buffers.Text.Base64Helper:EncodeTo (System.Buffers.Text.Base64Helper/Base64EncoderByte,System.ReadOnlySpan`1,System.Span`1,int&,int&,bool) + System.Buffers.OperationStatus System.Text.Ascii:ChangeCase (System.ReadOnlySpan`1,System.Span`1,int&) System.Buffers.OperationStatus System.Text.Ascii:ChangeCase (System.ReadOnlySpan`1,System.Span`1,int&) System.Buffers.OperationStatus System.Text.Json.JsonWriterHelper:ToUtf8 (System.ReadOnlySpan`1,System.Span`1,int&) System.Buffers.OperationStatus System.Text.Rune:DecodeFromUtf8 (System.ReadOnlySpan`1,System.Text.Rune&,int&) @@ -2466,24 +2591,34 @@ Methods: System.Buffers.OperationStatus System.Text.UTF8Encoding:DecodeFirstRune (System.ReadOnlySpan`1,System.Text.Rune&,int&) System.Buffers.SearchValues`1 System.Buffers.SearchValues:Create (System.ReadOnlySpan`1) System.Buffers.SearchValues`1 System.Buffers.SearchValues:Create (System.ReadOnlySpan`1) - System.Buffers.SharedArrayPool`1/ThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () - System.Buffers.SharedArrayPool`1/ThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () - System.Buffers.SharedArrayPool`1/ThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () - System.Buffers.SharedArrayPool`1/ThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () - System.Buffers.SharedArrayPool`1/ThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () - System.Buffers.SharedArrayPool`1/ThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Buffers.SharedArrayPoolPartitions System.Buffers.SharedArrayPool`1:CreatePerCorePartitions (int) + System.Buffers.SharedArrayPoolThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Buffers.SharedArrayPoolThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Buffers.SharedArrayPoolThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Buffers.SharedArrayPoolThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Buffers.SharedArrayPoolThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Buffers.SharedArrayPoolThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Buffers.SharedArrayPoolThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Collections.Frozen.FrozenDictionary`2 System.Collections.Frozen.FrozenDictionary:GetExistingFrozenOrNewDictionary (System.Collections.Generic.IEnumerable`1>,System.Collections.Generic.IEqualityComparer`1,System.Collections.Generic.Dictionary`2&) + System.Collections.Frozen.FrozenDictionary`2 System.Collections.Frozen.FrozenDictionary:ToFrozenDictionary (System.Collections.Generic.IEnumerable`1>,System.Collections.Generic.IEqualityComparer`1) + System.Collections.Frozen.FrozenDictionary`2 System.Collections.Frozen.FrozenDictionary`2:get_Empty () + System.Collections.Frozen.FrozenSet`1 System.Collections.Frozen.FrozenSet:GetExistingFrozenOrNewSet (System.Collections.Generic.IEnumerable`1,System.Collections.Generic.IEqualityComparer`1,System.Collections.Generic.HashSet`1&) + System.Collections.Frozen.FrozenSet`1 System.Collections.Frozen.FrozenSet:ToFrozenSet (System.Collections.Generic.IEnumerable`1,System.Collections.Generic.IEqualityComparer`1) + System.Collections.Frozen.FrozenSet`1 System.Collections.Frozen.FrozenSet`1:get_Empty () + System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:CreateComparer () + System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:get_Default () System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:CreateComparer () System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:get_Default () - System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:CreateComparer () - System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:get_Default () System.Collections.Generic.Dictionary`2/Enumerator> System.Collections.Generic.Dictionary`2>:GetEnumerator () System.Collections.Generic.Dictionary`2/Enumerator System.Collections.Generic.Dictionary`2:GetEnumerator () System.Collections.Generic.Dictionary`2/Enumerator System.Collections.Generic.Dictionary`2:GetEnumerator () + System.Collections.Generic.Dictionary`2/Enumerator System.Collections.Generic.Dictionary`2:GetEnumerator () + System.Collections.Generic.Dictionary`2/Enumerator System.Collections.Generic.Dictionary`2:GetEnumerator () System.Collections.Generic.Dictionary`2/KeyCollection/Enumerator> System.Collections.Generic.Dictionary`2/KeyCollection>:GetEnumerator () System.Collections.Generic.Dictionary`2/KeyCollection> System.Collections.Generic.Dictionary`2>:get_Keys () System.Collections.Generic.Dictionary`2/ValueCollection/Enumerator System.Collections.Generic.Dictionary`2/ValueCollection:GetEnumerator () System.Collections.Generic.Dictionary`2/ValueCollection System.Collections.Generic.Dictionary`2:get_Values () - System.Collections.Generic.Dictionary`2/ValueCollection System.Collections.Generic.Dictionary`2:get_Values () + System.Collections.Generic.Dictionary`2/ValueCollection System.Collections.Generic.Dictionary`2:get_Values () System.Collections.Generic.Dictionary`2> System.Runtime.Loader.AssemblyLoadContext:get_AllContexts () System.Collections.Generic.Dictionary`2> Microsoft.Maui.Controls.Element:get_DynamicResources () System.Collections.Generic.Dictionary`2 System.Globalization.CultureInfo:get_CachedCulturesByName () @@ -2501,9 +2636,8 @@ Methods: System.Collections.Generic.EqualityComparer`1 System.Collections.Generic.EqualityComparer`1:CreateComparer () System.Collections.Generic.EqualityComparer`1 System.Collections.Generic.EqualityComparer`1:CreateComparer () System.Collections.Generic.EqualityComparer`1 System.Collections.Generic.EqualityComparer`1:CreateComparer () - System.Collections.Generic.EqualityComparer`1> System.Collections.Generic.EqualityComparer`1>:CreateComparer () System.Collections.Generic.EqualityComparer`1> System.Collections.Generic.EqualityComparer`1>:CreateComparer () - System.Collections.Generic.HashSet`1/Enumerator System.Collections.Generic.HashSet`1:GetEnumerator () + System.Collections.Generic.HashSet`1/Enumerator System.Collections.Generic.HashSet`1:GetEnumerator () System.Collections.Generic.HashSet`1 Microsoft.AspNetCore.Components.RouteTableFactory:GetParameterNames (Microsoft.AspNetCore.Routing.Patterns.RoutePattern) System.Collections.Generic.HashSet`1 Microsoft.Maui.PropertyMapper:PopulateKeys () System.Collections.Generic.IArraySortHelper`1 System.Collections.Generic.ArraySortHelper`1:CreateArraySortHelper () @@ -2528,7 +2662,6 @@ Methods: System.Collections.Generic.IEnumerable`1 Microsoft.Maui.LifecycleEvents.LifecycleEventService:GetEventDelegates (string) System.Collections.Generic.IEnumerable`1 Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions:GetLifecycleEventDelegates (System.IServiceProvider,string) System.Collections.Generic.IEnumerable`1 System.Linq.Enumerable:OfType (System.Collections.IEnumerable) - System.Collections.Generic.IEnumerable`1 System.Linq.Enumerable:OfTypeIterator (System.Collections.IEnumerable) System.Collections.Generic.IEnumerable`1 System.Linq.Enumerable:Prepend (System.Collections.Generic.IEnumerable`1,object) System.Collections.Generic.IEnumerable`1 Microsoft.Maui.Handlers.AndroidBatchPropertyMapper`2:GetKeys () System.Collections.Generic.IEnumerable`1 Microsoft.Maui.PropertyMapper:GetKeys () @@ -2536,30 +2669,29 @@ Methods: System.Collections.Generic.IEnumerable`1 System.Reflection.CustomAttributeExtensions:GetCustomAttributes (System.Reflection.MemberInfo) System.Collections.Generic.IEnumerable`1> Microsoft.Maui.Controls.ResourceDictionary:get_MergedResources () System.Collections.Generic.IEnumerable`1> Microsoft.Maui.Controls.ResourcesExtensions:GetMergedResources (Microsoft.Maui.Controls.IElementDefinition) + System.Collections.Generic.IEnumerable`1 System.Linq.Expressions.Compiler.CompilerScope:GetVariables () System.Collections.Generic.IEnumerable`1 Microsoft.AspNetCore.Components.Reflection.ComponentProperties:GetCandidateBindableProperties (System.Type) System.Collections.Generic.IEnumerable`1 Microsoft.AspNetCore.Components.Reflection.MemberAssignment:GetPropertiesIncludingInherited (System.Type,System.Reflection.BindingFlags) System.Collections.Generic.IEnumerable`1 System.Reflection.CustomAttributeExtensions:GetCustomAttributes (System.Reflection.MemberInfo,bool) + System.Collections.Generic.IEnumerable`1 System.Linq.Enumerable:Select (System.Collections.Generic.IEnumerable`1,System.Func`2) + System.Collections.Generic.IEnumerable`1 System.Linq.Enumerable/ArrayWhereIterator`1:Select (System.Func`2) System.Collections.Generic.IEnumerable`1 System.Reflection.Assembly:get_ExportedTypes () System.Collections.Generic.IEnumerable`1 System.Xml.Linq.XContainer:Elements () System.Collections.Generic.IEnumerable`1 System.Xml.Linq.XContainer:GetElements (System.Xml.Linq.XName) System.Collections.Generic.IEnumerable`1 System.Xml.Linq.XContainer:Nodes () - System.Collections.Generic.IEnumerator`1 System.Linq.Enumerable/Iterator`1:GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Linq.OrderedEnumerable`1:GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Collections.ObjectModel.Collection`1:GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Collections.Generic.List`1:System.Collections.Generic.IEnumerable.GetEnumerator () - System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.Element/d__101`1:System.Collections.Generic.IEnumerable.GetEnumerator () + System.Collections.Generic.IEnumerator`1 System.Linq.Enumerable/Iterator`1:System.Collections.Generic.IEnumerable.GetEnumerator () + System.Collections.Generic.IEnumerator`1 System.Collections.ObjectModel.Collection`1:GetEnumerator () + System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.Element/d__103`1:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.ViewExtensions/d__22:System.Collections.Generic.IEnumerable.GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Collections.Generic.List`1:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 System.Collections.ObjectModel.ReadOnlyCollection`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.MenuItemTracker`1/d__7:System.Collections.Generic.IEnumerable.GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Linq.Enumerable/Iterator`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.StyleSheets.StyleSheetExtensions/d__0:System.Collections.Generic.IEnumerable.GetEnumerator () + System.Collections.Generic.IEnumerator`1 System.Collections.Generic.List`1:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Hosting.Internal.FontCollection:GetEnumerator () System.Collections.Generic.IEnumerator`1 System.Array:InternalArray__IEnumerable_GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions/d__3`1:System.Collections.Generic.IEnumerable.GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Linq.Enumerable/d__41`1:System.Collections.Generic.IEnumerable.GetEnumerator () + System.Collections.Generic.IEnumerator`1 System.Linq.Enumerable/Iterator`1:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Android.Runtime.JavaArray`1:GetEnumerator () - System.Collections.Generic.IEnumerator`1 Android.Runtime.JavaList`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 Android.Runtime.JavaSet`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Handlers.AndroidBatchPropertyMapper`2/d__2:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.PropertyMapper/d__17:System.Collections.Generic.IEnumerable.GetEnumerator () @@ -2567,34 +2699,40 @@ Methods: System.Collections.Generic.IEnumerator`1 System.Collections.Generic.HashSet`1:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 System.Linq.Extensions:ToEnumerator_Dispose (Java.Util.IIterator) System.Collections.Generic.IEnumerator`1> System.Runtime.CompilerServices.ConditionalWeakTable`2:System.Collections.Generic.IEnumerable>.GetEnumerator () - System.Collections.Generic.IEnumerator`1> System.Array:InternalArray__IEnumerable_GetEnumerator () - System.Collections.Generic.IEnumerator`1> System.Collections.Generic.EnumerableHelpers:GetEmptyEnumerator () - System.Collections.Generic.IEnumerator`1> System.Collections.Generic.SortedList`2:System.Collections.Generic.IEnumerable>.GetEnumerator () System.Collections.Generic.IEnumerator`1> System.Collections.Concurrent.ConcurrentDictionary`2:GetEnumerator () System.Collections.Generic.IEnumerator`1> Microsoft.Maui.Controls.ResourceDictionary:GetEnumerator () - System.Collections.Generic.IEnumerator`1> Microsoft.Maui.Controls.ResourceDictionary/d__42:System.Collections.Generic.IEnumerable>.GetEnumerator () + System.Collections.Generic.IEnumerator`1> Microsoft.Maui.Controls.ResourceDictionary/d__46:System.Collections.Generic.IEnumerable>.GetEnumerator () System.Collections.Generic.IEnumerator`1> System.Collections.Generic.Dictionary`2:System.Collections.Generic.IEnumerable>.GetEnumerator () System.Collections.Generic.IEnumerator`1>> System.Array:InternalArray__IEnumerable_GetEnumerator () System.Collections.Generic.IEnumerator`1>> System.Net.Http.Headers.HttpHeaders:GetEnumerator () System.Collections.Generic.IEnumerator`1, System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>>> System.Collections.Concurrent.ConcurrentDictionary`2, System.Text.Json.Cache`1/CacheEntry>>:GetEnumerator () + System.Collections.Generic.IEnumerator`1 System.Linq.Expressions.Compiler.ParameterList:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.AspNetCore.Components.Reflection.MemberAssignment/d__0:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 System.Xml.Linq.XContainer/d__39:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 System.Xml.Linq.XContainer/d__18:System.Collections.Generic.IEnumerable.GetEnumerator () + System.Collections.Generic.IEqualityComparer`1 System.Collections.Frozen.FrozenDictionary`2:get_Comparer () + System.Collections.Generic.IEqualityComparer`1 System.Collections.Frozen.FrozenSet`1:get_Comparer () System.Collections.Generic.IEqualityComparer`1 System.Collections.Generic.NonRandomizedStringEqualityComparer:GetStringComparer (object) - System.Collections.Generic.IList`1 Microsoft.Maui.Controls.Style:get_Behaviors () - System.Collections.Generic.IList`1 System.Collections.Generic.SortedList`2:get_Values () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.Element:get_LogicalChildrenInternalBackingStore () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.TemplatedPage:Microsoft.Maui.Controls.IControlTemplated.get_InternalChildren () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.View:Microsoft.Maui.Controls.Internals.IGestureController.get_CompositeGestureRecognizers () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.ViewExtensions:GetCompositeGestureRecognizers (Microsoft.Maui.Controls.Element) System.Collections.Generic.IList`1 Microsoft.Maui.Controls.MenuBarTracker:GetMenuItems (Microsoft.Maui.Controls.Page) System.Collections.Generic.IList`1 Microsoft.Maui.Controls.MenuItemTracker`1:get_ToolbarItems () - System.Collections.Generic.IList`1 Microsoft.Maui.Controls.Style:get_Triggers () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.VisualStateManager:GetVisualStateGroups (Microsoft.Maui.Controls.VisualElement) System.Collections.Generic.IList`1 Android.Content.PM.PackageInfo:get_RequestedPermissions () System.Collections.Generic.IList`1 Android.Runtime.JavaDictionary`2>:Get (string) System.Collections.Generic.IList`1 Android.Runtime.JavaDictionary`2>:get_Item (string) System.Collections.Generic.IList`1 Android.Runtime.JavaList`1:FromJniHandle (intptr,Android.Runtime.JniHandleOwnership) + System.Collections.Generic.IList`1 System.Reflection.CustomAttribute:GetCustomAttributesData (System.Reflection.ICustomAttributeProvider,bool) + System.Collections.Generic.IList`1 System.Reflection.CustomAttribute:GetCustomAttributesDataBase (System.Reflection.ICustomAttributeProvider,System.Type,bool) + System.Collections.Generic.IList`1 System.Reflection.RuntimeCustomAttributeData:GetCustomAttributesInternal (System.Reflection.RuntimeParameterInfo) + System.Collections.Generic.IList`1 System.Reflection.RuntimeCustomAttributeData:GetCustomAttributesInternal (System.Reflection.RuntimePropertyInfo) + System.Collections.Generic.IList`1 System.Reflection.RuntimeCustomAttributeData:GetCustomAttributesInternal (System.RuntimeType) + System.Collections.Generic.IList`1 System.Reflection.RuntimeParameterInfo:GetCustomAttributesData () + System.Collections.Generic.IList`1 System.Reflection.RuntimePropertyInfo:GetCustomAttributesData () + System.Collections.Generic.IList`1 System.RuntimeType:GetCustomAttributesData () + System.Collections.Generic.IList`1 System.Reflection.RuntimeCustomAttributeData:get_ConstructorArguments () System.Collections.Generic.IList`1 System.Text.Json.JsonSerializerOptions:get_Converters () System.Collections.Generic.IReadOnlyCollection`1 Microsoft.Maui.PropertyMapper:get_UpdateKeys () System.Collections.Generic.IReadOnlyList`1 Microsoft.AspNetCore.Components.CascadingParameterState:FindCascadingParameters (Microsoft.AspNetCore.Components.Rendering.ComponentState,bool&) @@ -2606,35 +2744,42 @@ Methods: System.Collections.Generic.IReadOnlyList`1 Microsoft.Maui.Controls.Element:Microsoft.Maui.IVisualTreeElement.GetVisualChildren () System.Collections.Generic.IReadOnlyList`1 Microsoft.Maui.Controls.Application:Microsoft.Maui.IApplication.get_Windows () System.Collections.Generic.IReadOnlyList`1 Microsoft.Maui.Platform.WindowExtensions:GetWindows () + System.Collections.Generic.IReadOnlyList`1 System.Linq.Expressions.Compiler.CompilerScope:GetVariables (object) System.Collections.Generic.KeyValuePair`2 System.Collections.Generic.List`1>:get_Item (int) - System.Collections.Generic.KeyValuePair`2 System.Linq.Enumerable:LastOrDefault (System.Collections.Generic.IEnumerable`1>) - System.Collections.Generic.KeyValuePair`2 System.Linq.Enumerable:TryGetLast (System.Collections.Generic.IEnumerable`1>,bool&) - System.Collections.Generic.KeyValuePair`2 Microsoft.Maui.Controls.SetterSpecificityList:GetSpecificityAndValue () - System.Collections.Generic.KeyValuePair`2 System.Nullable`1>:get_Value () - System.Collections.Generic.KeyValuePair`2 Microsoft.Maui.Controls.ResourceDictionary/d__42:System.Collections.Generic.IEnumerator>.get_Current () + System.Collections.Generic.KeyValuePair`2 Microsoft.Maui.Controls.SetterSpecificityList`1:GetSpecificityAndValue () System.Collections.Generic.KeyValuePair`2 System.Collections.Generic.Dictionary`2/Enumerator:get_Current () System.Collections.Generic.KeyValuePair`2, System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>> System.Collections.Concurrent.ConcurrentDictionary`2/Enumerator, System.Text.Json.Cache`1/CacheEntry>>:get_Current () - System.Collections.Generic.List`1/Enumerator System.Collections.Generic.List`1:GetEnumerator () System.Collections.Generic.List`1/Enumerator System.Collections.Generic.List`1:GetEnumerator () - System.Collections.Generic.List`1/Enumerator> System.Collections.Generic.List`1>:GetEnumerator () System.Collections.Generic.List`1/Enumerator System.Text.Json.Serialization.ConfigurationList`1:GetEnumerator () - System.Collections.Generic.List`1/Enumerator> System.Collections.Generic.List`1>:GetEnumerator () System.Collections.Generic.List`1/Enumerator> System.Collections.Generic.List`1>:GetEnumerator () System.Collections.Generic.List`1 Microsoft.Maui.Controls.MenuItemTracker`1:GetCurrentToolbarItems (Microsoft.Maui.Controls.Page) System.Collections.Generic.List`1 Microsoft.AspNetCore.Components.RouteTableFactory:GetUnusedParameterNames (System.Collections.Generic.HashSet`1,System.Collections.Generic.HashSet`1) - System.Collections.Generic.List`1 Microsoft.Extensions.Logging.LogValuesFormatter:get_ValueNames () System.Collections.Generic.List`1> System.Linq.Enumerable:ToList (System.Collections.Generic.IEnumerable`1>) + System.Collections.Generic.List`1 System.Linq.Expressions.Compiler.LambdaCompiler:EmitArguments (System.Reflection.MethodBase,System.Linq.Expressions.IArgumentProvider,int) + System.Collections.Generic.List`1 System.Linq.Expressions.Compiler.LambdaCompiler:EmitArguments (System.Reflection.MethodBase,System.Linq.Expressions.IArgumentProvider) System.Collections.Generic.List`1 System.Threading.TimerQueue:InitializeScheduledTimerManager_Locked () System.Collections.Generic.List`1 Microsoft.AspNetCore.Components.RouteTableFactory:GetRouteableComponents (Microsoft.AspNetCore.Components.Routing.RouteKey) - System.Collections.Generic.List`1 Microsoft.Maui.Hosting.Internal.MauiFactory:GetServiceBaseTypes (System.Type) System.Collections.Generic.List`1> System.Text.RegularExpressions.RegexCharClass:EnsureRangeList () System.Collections.Generic.ReferenceEqualityComparer System.Collections.Generic.ReferenceEqualityComparer:get_Instance () - System.Collections.Generic.SortedList`2/ValueList System.Collections.Generic.SortedList`2:GetValueListHelper () + System.Collections.Generic.Stack`1/Enumerator System.Collections.Generic.Stack`1:GetEnumerator () System.Collections.IEnumerator System.Array:GetEnumerator () - System.Collections.IEnumerator System.Collections.Generic.List`1:System.Collections.IEnumerable.GetEnumerator () + System.Collections.IEnumerator System.Collections.Generic.List`1:System.Collections.IEnumerable.GetEnumerator () System.Collections.IEnumerator System.Collections.ObjectModel.ReadOnlyCollection`1:System.Collections.IEnumerable.GetEnumerator () System.Collections.IEnumerator System.Collections.Specialized.SingleItemReadOnlyList:GetEnumerator () System.Collections.ObjectModel.ObservableCollection`1 Microsoft.Maui.Controls.Page:get_InternalChildren () + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Dynamic.Utils.CollectionExtensions:ToReadOnly (System.Collections.Generic.IEnumerable`1) + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Linq.Expressions.Block2:GetOrMakeExpressions () + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Linq.Expressions.BlockExpression:get_Expressions () + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Linq.Expressions.BlockExpression:ReturnReadOnlyExpressions (System.Linq.Expressions.BlockExpression,object&) + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Linq.Expressions.Compiler.VariableBinder:MergeScopes (System.Linq.Expressions.Expression) + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Linq.Expressions.ExpressionVisitor:Visit (System.Collections.ObjectModel.ReadOnlyCollection`1) + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Linq.Expressions.BlockExpression:get_Variables () + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Linq.Expressions.BlockExpression:GetOrMakeVariables () + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Array:AsReadOnly (System.Reflection.CustomAttributeData[]) + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Collections.ObjectModel.ReadOnlyCollection`1:get_Empty () + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Array:AsReadOnly (System.Reflection.CustomAttributeNamedArgument[]) + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Collections.ObjectModel.ReadOnlyCollection`1:get_Empty () + System.Collections.ObjectModel.ReadOnlyCollection`1 System.Array:AsReadOnly (System.Reflection.CustomAttributeTypedArgument[]) System.DateTime System.DateTime:FromFileTimeUtc (long) System.DateTime System.DateTime:get_UtcNow () System.DateTime System.DateTime:SpecifyKind (System.DateTime,System.DateTimeKind) @@ -2731,18 +2876,21 @@ Methods: System.Delegate System.Delegate:CreateDelegate (System.Type,System.Type,string) System.Delegate System.Delegate:CreateDelegate_internal (System.Runtime.CompilerServices.QCallTypeHandle,object,System.Reflection.MethodInfo,bool) System.Delegate System.Delegate:Remove (System.Delegate,System.Delegate) + System.Delegate System.Linq.Expressions.Compiler.LambdaCompiler:Compile (System.Linq.Expressions.LambdaExpression) + System.Delegate System.Linq.Expressions.Compiler.LambdaCompiler:CreateDelegate () System.Delegate System.MulticastDelegate:CombineImpl (System.Delegate) System.Delegate System.MulticastDelegate:RemoveImpl (System.Delegate) + System.Delegate System.Reflection.Emit.DynamicMethod:CreateDelegate (System.Type,object) System.Delegate System.Reflection.Emit.DynamicMethod:CreateDelegate (System.Type) System.Delegate System.Reflection.RuntimeMethodInfo:CreateDelegate (System.Type,object) System.Delegate System.Reflection.RuntimeMethodInfo:CreateDelegate (System.Type) - System.Diagnostics.Metrics.Histogram`1 System.Diagnostics.Metrics.Meter:CreateHistogram (string,string,string,System.Collections.Generic.IEnumerable`1>) - System.Diagnostics.Metrics.Histogram`1 System.Diagnostics.Metrics.Meter:CreateHistogram (string,string,string) + System.Diagnostics.Metrics.Histogram`1 System.Diagnostics.Metrics.Meter:CreateHistogram (string,string,string,System.Collections.Generic.IEnumerable`1>,System.Diagnostics.Metrics.InstrumentAdvice`1) System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter:GetCachedInstrument (System.Collections.Generic.List`1,System.Type,string,string,System.Collections.Generic.IEnumerable`1>) System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter:GetOrCreateInstrument (System.Type,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Func`1) System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter:GetOrCreateInstrument (System.Type,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Func`1) - System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter/<>c__DisplayClass35_0`1:b__0 () - System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter/<>c__DisplayClass37_0`1:b__0 () + System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter/<>c__DisplayClass39_0`1:b__0 () + System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter/<>c__DisplayClass41_0`1:b__0 () + System.Diagnostics.Metrics.InstrumentAdvice`1 System.Net.Http.DiagnosticsHelper:get_ShortHistogramAdvice () System.Diagnostics.Metrics.Meter System.Net.Http.Metrics.MetricsHandler/SharedMeter:get_Instance () System.Diagnostics.Metrics.UpDownCounter`1 System.Diagnostics.Metrics.Meter:CreateUpDownCounter (string,string,string,System.Collections.Generic.IEnumerable`1>) System.Diagnostics.Metrics.UpDownCounter`1 System.Diagnostics.Metrics.Meter:CreateUpDownCounter (string,string,string) @@ -2753,20 +2901,18 @@ Methods: System.Exception Java.Lang.Throwable:_GetInnerException (intptr) System.Exception/DispatchState System.Exception:CaptureDispatchState () System.Func`1 System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:DetermineCreateObjectDelegate (System.Type,System.Text.Json.Serialization.JsonConverter) + System.Func`1 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor:b__6_0 (System.ValueTuple`3) System.Func`1 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor:CreateParameterlessConstructor (System.Type,System.Reflection.ConstructorInfo) - System.Func`1 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/<>c:b__5_0 (System.ValueTuple`3) System.Func`1 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1>:GetOrAdd (System.ValueTuple`3,System.Func`2, System.Func`1>) System.Func`1 System.Text.Json.Serialization.Metadata.ReflectionEmitMemberAccessor:CreateDelegate (System.Reflection.Emit.DynamicMethod) System.Func`1 System.Text.Json.Serialization.Metadata.ReflectionEmitMemberAccessor:CreateParameterlessConstructor (System.Type,System.Reflection.ConstructorInfo) System.Func`2 Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeServiceProviderEngine:RealizeService (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite) System.Func`2 Java.Interop.JavaConvert:GetLocalJniHandleConverter (object) - System.Func`2 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1>:GetOrAdd (System.ValueTuple`3,System.Func`2, System.Func`2>) + System.Func`2 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor:b__13_0 (System.ValueTuple`3) System.Func`2 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor:CreatePropertyGetter (System.Reflection.PropertyInfo) - System.Func`2 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/<>c__12`1:b__12_0 (System.ValueTuple`3) System.Func`2 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1>:GetOrAdd (System.ValueTuple`3,System.Func`2, System.Func`2>) System.Func`2 System.Text.Json.Serialization.Metadata.ReflectionEmitMemberAccessor:CreatePropertyGetter (System.Reflection.PropertyInfo) System.Func`2 System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1>:GetOrAdd (System.ValueTuple`3,System.Func`2, System.Func`2>) - System.Func`2> System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1>:GetOrAdd (System.ValueTuple`3,System.Func`2, System.Func`2>>) System.Func`2 Microsoft.Extensions.DependencyInjection.ServiceDescriptor:get_ImplementationFactory () System.Func`3 Java.Interop.JavaConvert:GetJniHandleConverter (System.Type) System.Func`3 Java.Interop.JavaConvert:GetJniHandleConverterForType (System.Type) @@ -2801,6 +2947,7 @@ Methods: System.Globalization.NumberFormatInfo System.Globalization.NumberFormatInfo:get_InvariantInfo () System.Globalization.NumberFormatInfo System.Globalization.NumberFormatInfo:GetInstance (System.IFormatProvider) System.Globalization.UnicodeCategory System.Char:GetLatin1UnicodeCategory (char) + System.Guid System.Guid:NewGuid () System.Guid System.Reflection.RuntimeModule:get_ModuleVersionId () System.Guid System.Reflection.RuntimeModule:GetModuleVersionId () System.IDisposable Microsoft.Extensions.Options.OptionsMonitor`1:OnChange (System.Action`2) @@ -2809,6 +2956,8 @@ Methods: System.IDisposable Microsoft.Maui.Platform.ViewExtensions:OnLoaded (Android.Views.View,System.Action) System.IDisposable Microsoft.Maui.Platform.ViewExtensions:OnLoaded (Microsoft.Maui.IElement,System.Action) System.IDisposable& System.Collections.Generic.Dictionary`2:FindValue (intptr) + System.Int128 System.Int128:op_Addition (System.Int128,System.Int128) + System.Int128 System.Math:BigMul (long,long) System.IO.Stream Android.Content.Res.AssetManager:Open (string) System.IO.Stream Android.Runtime.InputStreamInvoker:FromJniHandle (intptr,Android.Runtime.JniHandleOwnership) System.IO.Stream Java.Net.URLConnection:get_InputStream () @@ -2832,8 +2981,91 @@ Methods: System.Lazy`1 Microsoft.Extensions.Options.OptionsCache`1/<>c__3`1>:b__3_0 (string,System.ValueTuple`2, Microsoft.Extensions.Logging.LoggerFilterOptions>, Microsoft.Extensions.Options.IOptionsFactory`1>) System.Lazy`1 System.Collections.Concurrent.ConcurrentDictionary`2>:GetOrAdd (string,System.Func`3, Microsoft.Extensions.Logging.LoggerFilterOptions>, Microsoft.Extensions.Options.IOptionsFactory`1>, System.Lazy`1>,System.ValueTuple`2, Microsoft.Extensions.Logging.LoggerFilterOptions>, Microsoft.Extensions.Options.IOptionsFactory`1>) System.LazyHelper System.LazyHelper:Create (System.Threading.LazyThreadSafetyMode,bool) - System.Linq.EnumerableSorter`1 System.Linq.OrderedEnumerable`1:GetEnumerableSorter () - System.Linq.EnumerableSorter`1 System.Linq.OrderedEnumerable`2:GetEnumerableSorter (System.Linq.EnumerableSorter`1) + System.Linq.Enumerable/EnumerableSorter`1 System.Linq.Enumerable/OrderedIterator`2:GetEnumerableSorter (System.Linq.Enumerable/EnumerableSorter`1) + System.Linq.Enumerable/Iterator`1 System.Linq.Enumerable/Iterator`1:GetEnumerator () + System.Linq.Enumerable/Iterator`1 System.Linq.Enumerable/Iterator`1:GetEnumerator () + System.Linq.Expressions.BinaryExpression System.Linq.Expressions.BinaryExpression:Update (System.Linq.Expressions.Expression,System.Linq.Expressions.LambdaExpression,System.Linq.Expressions.Expression) + System.Linq.Expressions.BinaryExpression System.Linq.Expressions.Expression:Equal (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,bool,System.Reflection.MethodInfo) + System.Linq.Expressions.BinaryExpression System.Linq.Expressions.Expression:Equal (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression) + System.Linq.Expressions.BinaryExpression System.Linq.Expressions.Expression:GetEqualityComparisonOperator (System.Linq.Expressions.ExpressionType,string,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,bool) + System.Linq.Expressions.BinaryExpression System.Linq.Expressions.Expression:GetUserDefinedBinaryOperator (System.Linq.Expressions.ExpressionType,string,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,bool) + System.Linq.Expressions.BinaryExpression System.Linq.Expressions.ExpressionVisitor:ValidateBinary (System.Linq.Expressions.BinaryExpression,System.Linq.Expressions.BinaryExpression) + System.Linq.Expressions.BlockExpression Microsoft.Extensions.DependencyInjection.ActivatorUtilities:BuildFactoryExpression (System.Reflection.ConstructorInfo,System.Nullable`1[],System.Linq.Expressions.Expression,System.Linq.Expressions.Expression) + System.Linq.Expressions.BlockExpression System.Linq.Expressions.Expression:Block (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression) + System.Linq.Expressions.Compiler.AnalyzedTree System.Linq.Expressions.Compiler.LambdaCompiler:AnalyzeLambda (System.Linq.Expressions.LambdaExpression&) + System.Linq.Expressions.Compiler.AnalyzedTree System.Linq.Expressions.Compiler.VariableBinder:Bind (System.Linq.Expressions.LambdaExpression) + System.Linq.Expressions.Compiler.BoundConstants System.Collections.Generic.Stack`1:Pop () + System.Linq.Expressions.Compiler.CompilerScope System.Collections.Generic.Stack`1/Enumerator:get_Current () + System.Linq.Expressions.Compiler.CompilerScope System.Collections.Generic.Stack`1:Peek () + System.Linq.Expressions.Compiler.CompilerScope System.Linq.Expressions.Compiler.CompilerScope:Enter (System.Linq.Expressions.Compiler.LambdaCompiler,System.Linq.Expressions.Compiler.CompilerScope) + System.Linq.Expressions.Compiler.CompilerScope System.Linq.Expressions.Compiler.CompilerScope:Exit () + System.Linq.Expressions.Compiler.CompilerScope/Storage System.Linq.Expressions.Compiler.CompilerScope:ResolveVariable (System.Linq.Expressions.ParameterExpression,System.Linq.Expressions.Compiler.HoistedLocals) + System.Linq.Expressions.Compiler.CompilerScope/Storage System.Linq.Expressions.Compiler.CompilerScope:ResolveVariable (System.Linq.Expressions.ParameterExpression) + System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags System.Linq.Expressions.Compiler.LambdaCompiler:EmitExpressionStart (System.Linq.Expressions.Expression) + System.Linq.Expressions.Compiler.StackSpiller/Result System.Linq.Expressions.Compiler.StackSpiller:RewriteBinaryExpression (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.StackSpiller/Stack) + System.Linq.Expressions.Compiler.StackSpiller/Result System.Linq.Expressions.Compiler.StackSpiller:RewriteBlockExpression (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.StackSpiller/Stack) + System.Linq.Expressions.Compiler.StackSpiller/Result System.Linq.Expressions.Compiler.StackSpiller:RewriteConditionalExpression (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.StackSpiller/Stack) + System.Linq.Expressions.Compiler.StackSpiller/Result System.Linq.Expressions.Compiler.StackSpiller:RewriteExpression (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.StackSpiller/Stack) + System.Linq.Expressions.Compiler.StackSpiller/Result System.Linq.Expressions.Compiler.StackSpiller:RewriteExpressionFreeTemps (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.StackSpiller/Stack) + System.Linq.Expressions.Compiler.StackSpiller/Result System.Linq.Expressions.Compiler.StackSpiller:RewriteNewExpression (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.StackSpiller/Stack) + System.Linq.Expressions.Compiler.StackSpiller/Result System.Linq.Expressions.Compiler.StackSpiller:RewriteThrowUnaryExpression (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.StackSpiller/Stack) + System.Linq.Expressions.Compiler.StackSpiller/Result System.Linq.Expressions.Compiler.StackSpiller/ChildRewriter:Finish (System.Linq.Expressions.Expression) + System.Linq.Expressions.Compiler.VariableStorageKind System.Collections.Generic.Dictionary`2:get_Item (System.Linq.Expressions.ParameterExpression) + System.Linq.Expressions.Compiler.VariableStorageKind& System.Collections.Generic.Dictionary`2:FindValue (System.Linq.Expressions.ParameterExpression) + System.Linq.Expressions.ConditionalExpression System.Linq.Expressions.ConditionalExpression:Make (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Type) + System.Linq.Expressions.ConditionalExpression System.Linq.Expressions.ConditionalExpression:Update (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression) + System.Linq.Expressions.ConditionalExpression System.Linq.Expressions.Expression:Condition (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Type) + System.Linq.Expressions.ConditionalExpression System.Linq.Expressions.Expression:IfThen (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression) + System.Linq.Expressions.Expression System.Dynamic.Utils.ExpressionUtils:ReturnObject (object) + System.Linq.Expressions.Expression System.Linq.Expressions.BinaryExpression:Accept (System.Linq.Expressions.ExpressionVisitor) + System.Linq.Expressions.Expression System.Linq.Expressions.Block2:GetExpression (int) + System.Linq.Expressions.Expression System.Linq.Expressions.BlockExpressionList:get_Item (int) + System.Linq.Expressions.Expression System.Linq.Expressions.Compiler.LambdaCompiler:GetEqualityOperand (System.Linq.Expressions.Expression) + System.Linq.Expressions.Expression System.Linq.Expressions.Compiler.VariableBinder:Visit (System.Linq.Expressions.Expression) + System.Linq.Expressions.Expression System.Linq.Expressions.Compiler.VariableBinder:VisitConstant (System.Linq.Expressions.ConstantExpression) + System.Linq.Expressions.Expression System.Linq.Expressions.Compiler.VariableBinder:VisitLambda (System.Linq.Expressions.Expression`1>) + System.Linq.Expressions.Expression System.Linq.Expressions.Compiler.VariableBinder:VisitParameter (System.Linq.Expressions.ParameterExpression) + System.Linq.Expressions.Expression System.Linq.Expressions.Compiler.VariableBinder:VisitUnary (System.Linq.Expressions.UnaryExpression) + System.Linq.Expressions.Expression System.Linq.Expressions.ConditionalExpression:Accept (System.Linq.Expressions.ExpressionVisitor) + System.Linq.Expressions.Expression System.Linq.Expressions.ConditionalExpression:get_IfFalse () + System.Linq.Expressions.Expression System.Linq.Expressions.ConditionalExpression:GetFalse () + System.Linq.Expressions.Expression System.Linq.Expressions.ConstantExpression:Accept (System.Linq.Expressions.ExpressionVisitor) + System.Linq.Expressions.Expression System.Linq.Expressions.DefaultExpression:Accept (System.Linq.Expressions.ExpressionVisitor) + System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor:Visit (System.Linq.Expressions.Expression) + System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor:VisitBinary (System.Linq.Expressions.BinaryExpression) + System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor:VisitConditional (System.Linq.Expressions.ConditionalExpression) + System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor:VisitDefault (System.Linq.Expressions.DefaultExpression) + System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor:VisitNew (System.Linq.Expressions.NewExpression) + System.Linq.Expressions.Expression System.Linq.Expressions.NewExpression:Accept (System.Linq.Expressions.ExpressionVisitor) + System.Linq.Expressions.Expression System.Linq.Expressions.ParameterExpression:Accept (System.Linq.Expressions.ExpressionVisitor) + System.Linq.Expressions.Expression System.Linq.Expressions.UnaryExpression:Accept (System.Linq.Expressions.ExpressionVisitor) + System.Linq.Expressions.Expression[] System.Dynamic.Utils.ExpressionVisitorUtils:VisitArguments (System.Linq.Expressions.ExpressionVisitor,System.Linq.Expressions.IArgumentProvider) + System.Linq.Expressions.Expression[] System.Linq.Expressions.ExpressionVisitor:VisitArguments (System.Linq.Expressions.IArgumentProvider) + System.Linq.Expressions.Expression`1> System.Linq.Expressions.Compiler.StackSpiller:Rewrite (System.Linq.Expressions.Expression`1>) + System.Linq.Expressions.Expression`1> System.Linq.Expressions.Expression:Lambda (System.Linq.Expressions.Expression,bool,System.Collections.Generic.IEnumerable`1) + System.Linq.Expressions.Expression`1> System.Linq.Expressions.Expression:Lambda (System.Linq.Expressions.Expression,string,bool,System.Collections.Generic.IEnumerable`1) + System.Linq.Expressions.Expression`1> System.Linq.Expressions.Expression:Lambda (System.Linq.Expressions.Expression,System.Linq.Expressions.ParameterExpression[]) + System.Linq.Expressions.ExpressionType System.Linq.Expressions.BlockExpression:get_NodeType () + System.Linq.Expressions.ExpressionType System.Linq.Expressions.ConditionalExpression:get_NodeType () + System.Linq.Expressions.ExpressionType System.Linq.Expressions.ConstantExpression:get_NodeType () + System.Linq.Expressions.ExpressionType System.Linq.Expressions.DefaultExpression:get_NodeType () + System.Linq.Expressions.ExpressionType System.Linq.Expressions.LogicalBinaryExpression:get_NodeType () + System.Linq.Expressions.ExpressionType System.Linq.Expressions.NewExpression:get_NodeType () + System.Linq.Expressions.ExpressionType System.Linq.Expressions.ParameterExpression:get_NodeType () + System.Linq.Expressions.ExpressionType System.Linq.Expressions.UnaryExpression:get_NodeType () + System.Linq.Expressions.LambdaExpression System.Linq.Expressions.BinaryExpression:get_Conversion () + System.Linq.Expressions.LambdaExpression System.Linq.Expressions.BinaryExpression:GetConversion () + System.Linq.Expressions.LambdaExpression System.Linq.Expressions.Compiler.StackSpiller:AnalyzeLambda (System.Linq.Expressions.LambdaExpression) + System.Linq.Expressions.LambdaExpression System.Linq.Expressions.ExpressionVisitor:VisitAndConvert (System.Linq.Expressions.LambdaExpression,string) + System.Linq.Expressions.NewExpression System.Linq.Expressions.Expression:New (System.Reflection.ConstructorInfo,System.Collections.Generic.IEnumerable`1) + System.Linq.Expressions.NewExpression System.Linq.Expressions.Expression:New (System.Reflection.ConstructorInfo,System.Linq.Expressions.Expression[]) + System.Linq.Expressions.ParameterExpression System.Array:InternalArray__get_Item (int) + System.Linq.Expressions.ParameterExpression System.Linq.Expressions.Compiler.ParameterList/d__6:System.Collections.Generic.IEnumerator.get_Current () + System.Linq.Expressions.ParameterExpression System.Linq.Expressions.Expression:Parameter (System.Type,string) + System.Linq.Expressions.ParameterExpression System.Linq.Expressions.LambdaExpression:System.Linq.Expressions.IParameterProvider.GetParameter (int) + System.Linq.Expressions.ParameterExpression System.Linq.Expressions.ParameterExpression:Make (System.Type,string,bool) + System.Linq.Expressions.UnaryExpression System.Linq.Expressions.Expression:Throw (System.Linq.Expressions.Expression,System.Type) + System.Linq.Expressions.UnaryExpression System.Linq.Expressions.Expression:Throw (System.Linq.Expressions.Expression) System.Linq.IOrderedEnumerable`1 System.Linq.Enumerable:OrderBy (System.Collections.Generic.IEnumerable`1,System.Func`2) System.Memory`1 System.MemoryExtensions:AsMemory (byte[],int,int) System.Memory`1 System.MemoryExtensions:AsMemory (byte[],int) @@ -2864,6 +3096,7 @@ Methods: System.Nullable`1 Android.Runtime.AndroidTypeManager:GetReplacementMethodInfoCore (string,string,string) System.Nullable`1 Java.Interop.JniRuntime/JniTypeManager:GetReplacementMethodInfo (string,string,string) System.Nullable`1 System.Net.Http.Headers.HttpContentHeaders:get_ContentLength () + System.Nullable`1 System.Reflection.NullabilityInfoContext:GetNullableContext (System.Reflection.MemberInfo) System.Nullable`1 System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:GetNumberHandlingForType (System.Type) System.Nullable`1 System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:GetObjectCreationHandlingForType (System.Type) System.Nullable`1 System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:GetUnmappedMemberHandling (System.Type) @@ -2874,18 +3107,19 @@ Methods: System.Number/ParsingStatus System.Number:TryParseBinaryIntegerStyle (System.ReadOnlySpan`1,System.Globalization.NumberStyles,System.Globalization.NumberFormatInfo,uint16&) System.Numerics.Matrix3x2 System.Numerics.Matrix3x2:CreateScale (single,single) System.Numerics.Matrix3x2 System.Numerics.Matrix3x2:op_Multiply (System.Numerics.Matrix3x2,System.Numerics.Matrix3x2) + System.Numerics.Vector2 System.Numerics.Vector2:Create (single,single) System.ParsingError System.Uri:ParseScheme (string,System.Uri/Flags&,System.UriParser&) System.ParsingError System.Uri:PrivateParseMinimal () System.ReadOnlyMemory`1 System.Text.Json.PooledByteBufferWriter:get_WrittenMemory () System.ReadOnlySpan`1 System.Globalization.CompareInfo:get_HighCharTable () - System.ReadOnlySpan`1 System.Buffers.Text.Base64:get_EncodingMap () + System.ReadOnlySpan`1 System.Buffers.Text.Base64Helper/Base64EncoderByte:get_EncodingMap () System.ReadOnlySpan`1 System.Char:get_Latin1CharInfo () System.ReadOnlySpan`1 System.Globalization.IcuLocaleData:get_CultureNames () System.ReadOnlySpan`1 System.Globalization.IcuLocaleData:get_LocalesNamesIndexes () System.ReadOnlySpan`1 System.Globalization.IcuLocaleData:get_NameIndexToNumericData () System.ReadOnlySpan`1 System.Globalization.IcuLocaleData:GetCultureName (int) System.ReadOnlySpan`1 System.HexConverter:get_CharToHexLookup () - System.ReadOnlySpan`1 System.IO.BinaryReader:InternalRead (int) + System.ReadOnlySpan`1 System.IO.BinaryReader:InternalRead (System.Span`1) System.ReadOnlySpan`1 System.Text.Json.JsonConstants:get_Delimiters () System.ReadOnlySpan`1 System.Text.Json.JsonConstants:get_NullValue () System.ReadOnlySpan`1 System.Text.Json.JsonConstants:get_TrueValue () @@ -2905,13 +3139,15 @@ Methods: System.ReadOnlySpan`1 System.IO.Path:GetPathRoot (System.ReadOnlySpan`1) System.ReadOnlySpan`1 System.IO.Path:TrimEndingDirectorySeparator (System.ReadOnlySpan`1) System.ReadOnlySpan`1 System.IO.PathInternal:TrimEndingDirectorySeparator (System.ReadOnlySpan`1) - System.ReadOnlySpan`1 System.MemoryExtensions:g__TrimFallback|219_0 (System.ReadOnlySpan`1) + System.ReadOnlySpan`1 System.MemoryExtensions:g__TrimFallback|231_0 (System.ReadOnlySpan`1) System.ReadOnlySpan`1 System.Runtime.CompilerServices.DefaultInterpolatedStringHandler:get_Text () System.ReadOnlySpan`1 System.Text.ValueStringBuilder:AsSpan () System.ReadOnlySpan`1 System.Uri:RecreateParts (System.Text.ValueStringBuilder&,string,System.UriComponents,uint16,System.UriFormat) System.ReadOnlySpan`1 System.Decimal/DecCalc:get_DoublePowers10 () System.ReadOnlySpan`1 System.Collections.Generic.ValueListBuilder`1:AsSpan () System.ReadOnlySpan`1 System.Collections.Generic.ValueListBuilder`1:AsSpan () + System.ReadOnlySpan`1 System.Reflection.Emit.DynamicMethod:GetParametersAsSpan () + System.ReadOnlySpan`1 System.Reflection.MethodBase:GetParametersAsSpan () System.Reflection.Assembly System.Reflection.Assembly:GetEntryAssembly () System.Reflection.Assembly System.Reflection.Assembly:GetEntryAssemblyInternal () System.Reflection.Assembly System.Reflection.Assembly:GetEntryAssemblyNative () @@ -2921,24 +3157,21 @@ Methods: System.Reflection.Assembly System.Resources.ManifestBasedResourceGroveler:GetSatelliteAssembly (System.Globalization.CultureInfo) System.Reflection.Assembly System.Resources.ManifestBasedResourceGroveler:InternalGetSatelliteAssembly (System.Reflection.Assembly,System.Globalization.CultureInfo,System.Version) System.Reflection.Assembly System.Runtime.Loader.AssemblyLoadContext:LoadFromAssemblyName (System.Reflection.AssemblyName) - System.Reflection.Assembly System.Runtime.Loader.AssemblyLoadContext:MonoResolveUsingResolveSatelliteAssembly (intptr,string) - System.Reflection.Assembly System.Runtime.Loader.AssemblyLoadContext:ResolveSatelliteAssembly (System.Reflection.AssemblyName) System.Reflection.Assembly System.RuntimeType:get_Assembly () System.Reflection.Assembly System.Text.Json.Serialization.Metadata.FSharpCoreReflectionProxy:GetFSharpCoreAssembly (System.Type) System.Reflection.AssemblyContentType System.Reflection.AssemblyName:get_ContentType () System.Reflection.AssemblyName System.Reflection.Assembly:GetName () System.Reflection.AssemblyName System.Reflection.AssemblyName:Create (intptr,string) System.Reflection.AssemblyName System.Reflection.RuntimeAssembly:GetName (bool) - System.Reflection.AssemblyNameParser/AssemblyNameParts System.Reflection.AssemblyNameParser:Parse () System.Reflection.AssemblyNameParser/AssemblyNameParts System.Reflection.AssemblyNameParser:Parse (string) - System.Reflection.AssemblyNameParser/Token System.Reflection.AssemblyNameParser:GetNextToken () - System.Reflection.AssemblyNameParser/Token System.Reflection.AssemblyNameParser:GetNextToken (string&) + System.Reflection.AssemblyNameParser/AssemblyNameParts System.Reflection.AssemblyNameParser:Parse (System.ReadOnlySpan`1) System.Reflection.Binder System.Type:get_DefaultBinder () System.Reflection.BindingFlags System.Reflection.RuntimePropertyInfo:FilterPreCalculate (bool,bool,bool) System.Reflection.BindingFlags System.Reflection.RuntimePropertyInfo:get_BindingFlags () System.Reflection.CallingConventions System.Reflection.MonoMethodInfo:GetCallingConvention (intptr) System.Reflection.CallingConventions System.Reflection.RuntimeConstructorInfo:get_CallingConvention () System.Reflection.CallingConventions System.Reflection.RuntimeMethodInfo:get_CallingConvention () + System.Reflection.ConstructorInfo System.Reflection.RuntimeCustomAttributeData:get_Constructor () System.Reflection.ConstructorInfo System.RuntimeType:GetConstructorImpl (System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[]) System.Reflection.ConstructorInfo System.RuntimeType/ListBuilder`1:get_Item (int) System.Reflection.ConstructorInfo System.Type:GetConstructor (System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[]) @@ -2953,20 +3186,37 @@ Methods: System.Reflection.CorElementType System.RuntimeType:GetCorElementType () System.Reflection.CorElementType System.RuntimeTypeHandle:GetCorElementType (System.Runtime.CompilerServices.QCallTypeHandle) System.Reflection.CorElementType System.RuntimeTypeHandle:GetCorElementType (System.RuntimeType) + System.Reflection.CustomAttributeData[] System.Reflection.CustomAttribute:GetCustomAttributesDataInternal (System.Reflection.ICustomAttributeProvider) + System.Reflection.CustomAttributeData[] System.Reflection.CustomAttribute:GetPseudoCustomAttributesData (System.Reflection.ICustomAttributeProvider,System.Type) + System.Reflection.CustomAttributeData[] System.Reflection.CustomAttribute:GetPseudoCustomAttributesData (System.Type) + System.Reflection.CustomAttributeData[] System.Reflection.RuntimeParameterInfo:GetPseudoCustomAttributesData () + System.Reflection.CustomAttributeNamedArgument[] System.Reflection.RuntimeCustomAttributeData:UnboxValues (object[]) + System.Reflection.CustomAttributeTypedArgument System.Array:InternalArray__get_Item (int) + System.Reflection.CustomAttributeTypedArgument System.Collections.ObjectModel.ReadOnlyCollection`1:System.Collections.Generic.IList.get_Item (int) + System.Reflection.CustomAttributeTypedArgument[] System.Reflection.RuntimeCustomAttributeData:UnboxValues (object[]) + System.Reflection.Emit.AssemblyBuilder System.Reflection.Emit.AssemblyBuilder:DefineDynamicAssembly (System.Reflection.AssemblyName,System.Reflection.Emit.AssemblyBuilderAccess,System.Collections.Generic.IEnumerable`1) + System.Reflection.Emit.AssemblyBuilder System.Reflection.Emit.AssemblyBuilder:DefineDynamicAssembly (System.Reflection.AssemblyName,System.Reflection.Emit.AssemblyBuilderAccess) + System.Reflection.Emit.AssemblyBuilder System.Reflection.Emit.RuntimeAssemblyBuilder:InternalDefineDynamicAssembly (System.Reflection.AssemblyName,System.Reflection.Emit.AssemblyBuilderAccess,System.Runtime.Loader.AssemblyLoadContext,System.Collections.Generic.IEnumerable`1) System.Reflection.Emit.DynamicMethod System.Text.Json.Serialization.Metadata.ReflectionEmitMemberAccessor:CreateGetterMethod (string,System.Type) System.Reflection.Emit.DynamicMethod System.Text.Json.Serialization.Metadata.ReflectionEmitMemberAccessor:CreatePropertyGetter (System.Reflection.PropertyInfo,System.Type) System.Reflection.Emit.ILGenerator System.Reflection.Emit.DynamicMethod:GetILGenerator () System.Reflection.Emit.ILGenerator System.Reflection.Emit.DynamicMethod:GetILGenerator (int) + System.Reflection.Emit.Label System.Reflection.Emit.RuntimeILGenerator:DefineLabel () System.Reflection.Emit.LocalBuilder System.Reflection.Emit.ILGenerator:DeclareLocal (System.Type) System.Reflection.Emit.LocalBuilder System.Reflection.Emit.RuntimeILGenerator:DeclareLocal (System.Type,bool) + System.Reflection.Emit.LocalBuilder& System.Collections.Generic.Dictionary`2:FindValue (System.Linq.Expressions.Compiler.BoundConstants/TypedConstant) System.Reflection.Emit.RuntimeILGenerator System.Reflection.Emit.DynamicMethod:GetILGeneratorInternal (int) System.Reflection.FieldAttributes System.Reflection.RuntimeFieldInfo:get_Attributes () + System.Reflection.FieldInfo System.Linq.Expressions.CachedReflectionInfo:get_Closure_Constants () System.Reflection.FieldInfo System.Reflection.FieldInfo:GetFieldFromHandle (System.RuntimeFieldHandle,System.RuntimeTypeHandle) System.Reflection.FieldInfo System.Reflection.FieldInfo:internal_from_handle_type (intptr,intptr) + System.Reflection.FieldInfo System.RuntimeType:GetField (string,System.Reflection.BindingFlags) + System.Reflection.FieldInfo System.Type:GetField (string) System.Reflection.FieldInfo[] System.RuntimeType:GetFields (System.Reflection.BindingFlags) System.Reflection.ICustomAttributeProvider System.Reflection.CustomAttribute:GetBase (System.Reflection.ICustomAttributeProvider) System.Reflection.InvocationFlags System.Reflection.RuntimeConstructorInfo:ComputeAndUpdateInvocationFlags () System.Reflection.InvocationFlags System.Reflection.RuntimeMethodInfo:ComputeAndUpdateInvocationFlags () + System.Reflection.MemberInfo System.Reflection.NullabilityInfoContext:GetMemberMetadataDefinition (System.Reflection.MemberInfo) System.Reflection.MethodAttributes System.Reflection.Emit.DynamicMethod:get_Attributes () System.Reflection.MethodAttributes System.Reflection.MonoMethodInfo:GetAttributes (intptr) System.Reflection.MethodAttributes System.Reflection.RuntimeConstructorInfo:get_Attributes () @@ -2980,6 +3230,11 @@ Methods: System.Reflection.MethodInfo System.Delegate:GetCandidateMethod (System.RuntimeType,System.Type,string,System.Reflection.BindingFlags,bool) System.Reflection.MethodInfo System.Delegate:GetDelegateInvokeMethod (System.RuntimeType) System.Reflection.MethodInfo System.Delegate:GetMethodImpl () + System.Reflection.MethodInfo System.Dynamic.Utils.TypeExtensions:GetAnyStaticMethodValidated (System.Type,string,System.Type[]) + System.Reflection.MethodInfo System.Dynamic.Utils.TypeUtils:GetInvokeMethod (System.Type) + System.Reflection.MethodInfo System.Linq.Expressions.BinaryExpression:get_Method () + System.Reflection.MethodInfo System.Linq.Expressions.BinaryExpression:GetMethod () + System.Reflection.MethodInfo System.Linq.Expressions.Expression:GetUserDefinedBinaryOperator (System.Linq.Expressions.ExpressionType,System.Type,System.Type,string) System.Reflection.MethodInfo System.MulticastDelegate:GetMethodImpl () System.Reflection.MethodInfo System.Reflection.PropertyInfo:get_GetMethod () System.Reflection.MethodInfo System.Reflection.PropertyInfo:get_SetMethod () @@ -2993,31 +3248,44 @@ Methods: System.Reflection.MethodInfo System.Type:GetMethod (string,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[]) System.Reflection.MethodInfo System.Type:GetMethod (string,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type[],System.Reflection.ParameterModifier[]) System.Reflection.MethodInfo System.Type:GetMethod (string,System.Reflection.BindingFlags) + System.Reflection.MethodInfo System.Type:GetMethod (string,System.Type[],System.Reflection.ParameterModifier[]) + System.Reflection.MethodInfo System.Type:GetMethod (string,System.Type[]) System.Reflection.MethodInfo System.Type:GetMethod (string) + System.Reflection.Module System.Reflection.Emit.DynamicMethod:GetDynamicMethodsModule () + System.Reflection.Module System.Reflection.Emit.RuntimeAssemblyBuilder:get_ManifestModule () System.Reflection.Module System.Reflection.Emit.RuntimeModuleBuilder:GetRuntimeModuleFromModule (System.Reflection.Module) System.Reflection.Module System.RuntimeType:get_Module () System.Reflection.MonoMethodInfo System.Reflection.MonoMethodInfo:GetMethodInfo (intptr) + System.Reflection.NullabilityInfo System.Reflection.NullabilityInfoContext:Create (System.Reflection.PropertyInfo) + System.Reflection.NullabilityInfo System.Reflection.NullabilityInfoContext:GetNullabilityInfo (System.Reflection.MemberInfo,System.Type,System.Reflection.NullabilityInfoContext/NullableAttributeStateParser,int&) + System.Reflection.NullabilityInfo System.Reflection.NullabilityInfoContext:GetNullabilityInfo (System.Reflection.MemberInfo,System.Type,System.Reflection.NullabilityInfoContext/NullableAttributeStateParser) + System.Reflection.NullabilityInfoContext/NullableAttributeStateParser System.Reflection.NullabilityInfoContext:CreateParser (System.Collections.Generic.IList`1) + System.Reflection.NullabilityState System.Reflection.NullabilityInfoContext:TranslateByte (byte) + System.Reflection.NullabilityState System.Reflection.NullabilityInfoContext:TranslateByte (object) + System.Reflection.NullabilityState& System.Collections.Generic.Dictionary`2:FindValue (System.Reflection.MemberInfo) System.Reflection.ParameterAttributes System.Reflection.ParameterInfo:get_Attributes () - System.Reflection.ParameterInfo[] System.Reflection.Emit.DynamicMethod:GetParametersNoCopy () - System.Reflection.ParameterInfo[] System.Reflection.MethodBase:GetParametersNoCopy () + System.Reflection.ParameterInfo System.Reflection.MonoMethodInfo:GetReturnParameterInfo (System.Reflection.RuntimeMethodInfo) + System.Reflection.ParameterInfo System.Reflection.RuntimeMethodInfo:get_ReturnParameter () + System.Reflection.ParameterInfo System.Reflection.RuntimeParameterInfo:New (System.Type,System.Reflection.MemberInfo,System.Runtime.InteropServices.MarshalAsAttribute) + System.Reflection.ParameterInfo[] System.Dynamic.Utils.ExpressionUtils:GetParametersForValidation (System.Reflection.MethodBase,System.Linq.Expressions.ExpressionType) + System.Reflection.ParameterInfo[] System.Dynamic.Utils.TypeExtensions:GetParametersCached (System.Reflection.MethodBase) System.Reflection.ParameterInfo[] System.Reflection.MonoMethodInfo:get_parameter_info (intptr,System.Reflection.MemberInfo) System.Reflection.ParameterInfo[] System.Reflection.MonoMethodInfo:GetParametersInfo (intptr,System.Reflection.MemberInfo) System.Reflection.ParameterInfo[] System.Reflection.RuntimeConstructorInfo:GetParameters () System.Reflection.ParameterInfo[] System.Reflection.RuntimeConstructorInfo:GetParametersInternal () + System.Reflection.ParameterInfo[] System.Reflection.RuntimeMethodInfo:GetParameters () System.Reflection.ParameterInfo[] System.Reflection.RuntimeMethodInfo:GetParametersInternal () System.Reflection.ParameterInfo[] System.Reflection.RuntimePropertyInfo:GetIndexParameters () System.Reflection.PropertyInfo Microsoft.AspNetCore.Components.Reflection.MemberAssignment/d__0:System.Collections.Generic.IEnumerator.get_Current () System.Reflection.PropertyInfo System.Reflection.CustomAttribute:GetBasePropertyDefinition (System.Reflection.RuntimePropertyInfo) System.Reflection.PropertyInfo System.Reflection.RuntimePropertyInfo:GetPropertyFromHandle (Mono.RuntimePropertyHandle,System.RuntimeTypeHandle) System.Reflection.PropertyInfo System.Reflection.RuntimePropertyInfo:internal_from_handle_type (intptr,intptr) - System.Reflection.PropertyInfo System.Reflection.RuntimeReflectionExtensions:GetRuntimeProperty (System.Type,string) - System.Reflection.PropertyInfo System.RuntimeType:GetPropertyImpl (string,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[]) - System.Reflection.PropertyInfo System.Type:GetProperty (string,System.Reflection.BindingFlags) - System.Reflection.PropertyInfo System.Type:GetProperty (string) System.Reflection.PropertyInfo[] System.RuntimeType:GetProperties (System.Reflection.BindingFlags) System.Reflection.RuntimeAssembly System.Reflection.RuntimeAssembly:InternalLoad (System.Reflection.AssemblyName,System.Threading.StackCrawlMark&,System.Runtime.Loader.AssemblyLoadContext) System.Reflection.RuntimeAssembly System.Runtime.Loader.AssemblyLoadContext:InvokeResolveEvent (System.ResolveEventHandler,System.Reflection.RuntimeAssembly,string) + System.Reflection.RuntimeAssembly System.Runtime.Loader.AssemblyLoadContext:MonoResolveUsingResolveSatelliteAssembly (intptr,string) System.Reflection.RuntimeAssembly System.Runtime.Loader.AssemblyLoadContext:OnAssemblyResolve (System.Reflection.RuntimeAssembly,string) + System.Reflection.RuntimeAssembly System.Runtime.Loader.AssemblyLoadContext:ResolveSatelliteAssembly (System.Reflection.AssemblyName) System.Reflection.RuntimeAssembly System.RuntimeTypeHandle:GetAssembly (System.RuntimeType) System.Reflection.RuntimeConstructorInfo System.RuntimeType:GetDefaultConstructor () System.Reflection.RuntimeConstructorInfo[] System.RuntimeType:GetConstructors_internal (System.Reflection.BindingFlags,System.RuntimeType) @@ -3027,11 +3295,15 @@ Methods: System.Reflection.RuntimeModule System.RuntimeTypeHandle:GetModule (System.RuntimeType) System.Reflection.RuntimeParameterInfo[] System.Reflection.Emit.DynamicMethod:LoadParameters () System.Reflection.RuntimePropertyInfo[] System.RuntimeType:GetPropertiesByName (string,System.Reflection.BindingFlags,System.RuntimeType/MemberListType,System.RuntimeType) + System.Reflection.TypeAttributes System.Reflection.Emit.RuntimeTypeBuilder:GetAttributeFlagsImpl () System.Reflection.TypeAttributes System.RuntimeType:GetAttributeFlagsImpl () System.Reflection.TypeAttributes System.RuntimeType:GetAttributes () System.Reflection.TypeAttributes System.RuntimeTypeHandle:GetAttributes (System.Runtime.CompilerServices.QCallTypeHandle) System.Reflection.TypeAttributes System.RuntimeTypeHandle:GetAttributes (System.RuntimeType) System.Reflection.TypeAttributes System.Type:get_Attributes () + System.Reflection.TypeInfo System.Reflection.Emit.RuntimeTypeBuilder:create_runtime_class () + System.Reflection.TypeInfo System.Reflection.Emit.RuntimeTypeBuilder:CreateTypeInfoCore () + System.Reflection.TypeInfo System.Reflection.Emit.TypeBuilder:CreateTypeInfo () System.Resources.NeutralResourcesLanguageAttribute System.Reflection.CustomAttributeExtensions:GetCustomAttribute (System.Reflection.Assembly) System.Resources.ResourceLocator& System.Collections.Generic.Dictionary`2:FindValue (string) System.Resources.ResourceSet System.Resources.ManifestBasedResourceGroveler:CreateResourceSet (System.IO.Stream,System.Reflection.Assembly) @@ -3052,18 +3324,19 @@ Methods: System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (Xamarin.Android.Net.AndroidMessageHandler/d__131&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (CommonMethods/d__0&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (System.Net.Http.HttpClient/d__41&,System.Threading.Tasks.Task`1&) - System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__81&,System.Threading.Tasks.Task`1&) - System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__76&,System.Threading.Tasks.Task`1&) - System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (Microsoft.AspNetCore.Components.Routing.FocusOnNavigate/d__15&,System.Threading.Tasks.Task`1&) + System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__89&,System.Threading.Tasks.Task`1&) + System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__84&,System.Threading.Tasks.Task`1&) + System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (Microsoft.AspNetCore.Components.Routing.FocusOnNavigate/d__17&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (Microsoft.AspNetCore.Components.WebView.IpcSender/<>c__DisplayClass14_0/<g__AwaitAndNotify|0>d&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (Microsoft.JSInterop.JSRuntimeExtensions/d__0&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (System.IO.BufferedStream/d__68&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (System.IO.Stream/<g__Core|27_0>d&,System.Threading.Tasks.Task`1&) + System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (System.Net.Http.HttpContent/d__63&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (System.Net.Http.StreamToStreamCopy/<g__DisposeSourceAsync|1_0>d&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.TaskAwaiter`1 System.Threading.Tasks.Task`1:GetAwaiter () System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo:Capture (System.Exception) - System.Runtime.InteropServices.GCHandle System.Runtime.InteropServices.GCHandle:Alloc (object,System.Runtime.InteropServices.GCHandleType) System.Runtime.InteropServices.MarshalAsAttribute System.Reflection.FieldInfo:get_marshal_info () + System.Runtime.InteropServices.MarshalAsAttribute System.Reflection.MonoMethodInfo:get_retval_marshal (intptr) System.Runtime.Loader.AssemblyLoadContext System.Runtime.Loader.AssemblyLoadContext:GetAssemblyLoadContext (intptr) System.Runtime.Loader.AssemblyLoadContext System.Runtime.Loader.AssemblyLoadContext:GetLoadContext (System.Reflection.Assembly) System.RuntimeType System.Enum:InternalGetUnderlyingType (System.RuntimeType) @@ -3083,7 +3356,6 @@ Methods: System.RuntimeType/TypeCache System.RuntimeType:get_Cache () System.RuntimeTypeHandle System.RuntimeType:get_TypeHandle () System.Span`1 System.Text.ValueUtf8Converter:ConvertAndTerminateString (System.ReadOnlySpan`1) - System.Span`1 System.Runtime.InteropServices.CollectionsMarshal:AsSpan (System.Collections.Generic.List`1) System.Text.CodePageDataItem System.Text.EncodingTable:GetCodePageDataItem (int) System.Text.CodePageDataItem System.Text.EncodingTable:InternalGetCodePageDataItem (int,int) System.Text.CompositeFormat System.Text.CompositeFormat:Parse (string) @@ -3136,7 +3408,7 @@ Methods: System.Text.Json.ConverterStrategy System.Text.Json.Serialization.JsonObjectConverter`1:GetDefaultConverterStrategy () System.Text.Json.ConverterStrategy System.Text.Json.Serialization.JsonObjectConverter`1>>:GetDefaultConverterStrategy () System.Text.Json.ConverterStrategy System.Text.Json.Serialization.JsonObjectConverter`1:GetDefaultConverterStrategy () - System.Text.Json.JsonDocument System.Text.Json.JsonDocument:g__Create|73_0 (byte[],System.Text.Json.JsonDocument/<>c__DisplayClass73_0&) + System.Text.Json.JsonDocument System.Text.Json.JsonDocument:g__Create|77_0 (byte[],System.Text.Json.JsonDocument/<>c__DisplayClass77_0&) System.Text.Json.JsonDocument System.Text.Json.JsonDocument:CreateForLiteral (System.Text.Json.JsonTokenType) System.Text.Json.JsonDocument System.Text.Json.JsonDocument:ParseUnrented (System.ReadOnlyMemory`1,System.Text.Json.JsonReaderOptions,System.Text.Json.JsonTokenType) System.Text.Json.JsonDocument/DbRow System.Text.Json.JsonDocument/MetadataDb:Get (int) @@ -3150,15 +3422,16 @@ Methods: System.Text.Json.JsonEncodedText System.Text.Json.JsonEncodedText:EncodeHelper (System.ReadOnlySpan`1,System.Text.Encodings.Web.JavaScriptEncoder) System.Text.Json.JsonEncodedText System.Text.Json.JsonEncodedText:TranscodeAndEncode (System.ReadOnlySpan`1,System.Text.Encodings.Web.JavaScriptEncoder) System.Text.Json.JsonNamingPolicy System.Text.Json.JsonNamingPolicy:get_CamelCase () - System.Text.Json.JsonPropertyDictionary`1 System.Text.Json.Serialization.Metadata.JsonTypeInfo:CreatePropertyCache (int) System.Text.Json.JsonReaderOptions System.Text.Json.JsonSerializerOptions:GetReaderOptions () System.Text.Json.JsonReaderState System.Text.Json.Utf8JsonReader:get_CurrentState () + System.Text.Json.JsonSerializerOptions/CachingContext System.Text.Json.JsonSerializerOptions:g__GetOrCreate|1_0 () System.Text.Json.JsonSerializerOptions/CachingContext System.Text.Json.JsonSerializerOptions:get_CacheContext () System.Text.Json.JsonSerializerOptions/CachingContext System.Text.Json.JsonSerializerOptions/TrackedCachingContexts:GetOrCreate (System.Text.Json.JsonSerializerOptions) System.Text.Json.JsonSerializerOptions/CachingContext/CacheEntry System.Collections.Concurrent.ConcurrentDictionary`2:GetOrAdd (System.Type,System.Func`3,System.Text.Json.JsonSerializerOptions/CachingContext) System.Text.Json.JsonSerializerOptions/CachingContext/CacheEntry System.Text.Json.JsonSerializerOptions/CachingContext:CreateCacheEntry (System.Type,System.Text.Json.JsonSerializerOptions/CachingContext) System.Text.Json.JsonSerializerOptions/CachingContext/CacheEntry System.Text.Json.JsonSerializerOptions/CachingContext:GetOrAddCacheEntry (System.Type) System.Text.Json.JsonWriterOptions System.Text.Json.JsonSerializerOptions:GetWriterOptions () + System.Text.Json.Serialization.Converters.EnumConverter`1/EnumFieldInfo[] System.Text.Json.Serialization.Converters.EnumConverter`1:ResolveEnumFields (System.Text.Json.JsonNamingPolicy) System.Text.Json.Serialization.JsonConstructorAttribute System.Reflection.CustomAttributeExtensions:GetCustomAttribute (System.Reflection.MemberInfo) System.Text.Json.Serialization.JsonConverter Microsoft.JSInterop.Infrastructure.DotNetObjectReferenceJsonConverterFactory:CreateConverter (System.Type,System.Text.Json.JsonSerializerOptions) System.Text.Json.Serialization.JsonConverter System.Text.Json.JsonSerializerOptions:ExpandConverterFactory (System.Text.Json.Serialization.JsonConverter,System.Type) @@ -3168,6 +3441,7 @@ Methods: System.Text.Json.Serialization.JsonConverter System.Text.Json.Serialization.Converters.EnumConverterFactory:CreateConverter (System.Type,System.Text.Json.JsonSerializerOptions) System.Text.Json.Serialization.JsonConverter System.Text.Json.Serialization.Converters.IEnumerableConverterFactory:CreateConverter (System.Type,System.Text.Json.JsonSerializerOptions) System.Text.Json.Serialization.JsonConverter System.Text.Json.Serialization.Converters.ObjectConverterFactory:CreateConverter (System.Type,System.Text.Json.JsonSerializerOptions) + System.Text.Json.Serialization.JsonConverter System.Text.Json.Serialization.JsonConverter:get_NullableElementConverter () System.Text.Json.Serialization.JsonConverter System.Text.Json.Serialization.JsonConverter:ResolvePolymorphicConverter (object,System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Text.Json.JsonSerializerOptions,System.Text.Json.WriteStack&) System.Text.Json.Serialization.JsonConverter System.Text.Json.Serialization.JsonConverterFactory:GetConverterInternal (System.Type,System.Text.Json.JsonSerializerOptions) System.Text.Json.Serialization.JsonConverter System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:GetBuiltInConverter (System.Type) @@ -3216,9 +3490,9 @@ Methods: System.Text.Json.Serialization.JsonConverterAttribute System.Text.Json.Reflection.ReflectionExtensions:GetUniqueCustomAttribute (System.Reflection.MemberInfo,bool) System.Text.Json.Serialization.JsonConverterFactory[] System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:GetDefaultFactoryConverters () System.Text.Json.Serialization.JsonPolymorphicAttribute System.Reflection.CustomAttributeExtensions:GetCustomAttribute (System.Reflection.MemberInfo,bool) - System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:RootDefaultInstance () + System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:get_DefaultInstance () System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions:CreateFromAttributeDeclarations (System.Type) - System.Text.Json.Serialization.Metadata.JsonPropertyInfo System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:CreatePropertyInfo (System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Type,System.Reflection.MemberInfo,System.Text.Json.JsonSerializerOptions,bool,bool) + System.Text.Json.Serialization.Metadata.JsonPropertyInfo System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:CreatePropertyInfo (System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Type,System.Reflection.MemberInfo,System.Reflection.NullabilityInfoContext,System.Text.Json.JsonSerializerOptions,bool,bool) System.Text.Json.Serialization.Metadata.JsonPropertyInfo System.Text.Json.Serialization.Metadata.JsonPropertyInfo:GetPropertyPlaceholder () System.Text.Json.Serialization.Metadata.JsonPropertyInfo System.Text.Json.Serialization.Metadata.JsonTypeInfo:CreatePropertyUsingReflection (System.Type,System.Type) System.Text.Json.Serialization.Metadata.JsonPropertyInfo System.Text.Json.Serialization.Metadata.JsonTypeInfo`1:CreatePropertyInfoForTypeInfo () @@ -3245,33 +3519,32 @@ Methods: System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:CreateJsonTypeInfo (System.Type,System.Text.Json.JsonSerializerOptions) System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:CreateTypeInfoCore (System.Type,System.Text.Json.Serialization.JsonConverter,System.Text.Json.JsonSerializerOptions) System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:GetTypeInfo (System.Type,System.Text.Json.JsonSerializerOptions) + System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.JsonPropertyInfo:get_DeclaringTypeInfo () System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.JsonPropertyInfo:get_JsonTypeInfo () - System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.JsonPropertyInfo:get_ParentTypeInfo () System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.JsonTypeInfo:CreateJsonTypeInfo (System.Type,System.Text.Json.Serialization.JsonConverter,System.Text.Json.JsonSerializerOptions) System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.JsonTypeInfo:get_AncestorPolymorphicType () System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.JsonTypeInfo:get_ElementTypeInfo () - System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.PolymorphicTypeResolver:g__ResolveAncestorTypeInfo|30_0 (System.Type,System.Text.Json.JsonSerializerOptions) + System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.PolymorphicTypeResolver:g__ResolveAncestorTypeInfo|27_0 (System.Type,System.Text.Json.JsonSerializerOptions) System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.PolymorphicTypeResolver:FindNearestPolymorphicBaseType (System.Text.Json.Serialization.Metadata.JsonTypeInfo) System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.WriteStack:PeekNestedJsonTypeInfo () System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.WriteStackFrame:GetNestedJsonTypeInfo () System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.WriteStackFrame:InitializePolymorphicReEntry (System.Type,System.Text.Json.JsonSerializerOptions) - System.Text.Json.Serialization.Metadata.JsonTypeInfo/JsonPropertyInfoList System.Text.Json.Serialization.Metadata.JsonTypeInfo:g__CreatePropertyList|65_0 () + System.Text.Json.Serialization.Metadata.JsonTypeInfo/JsonPropertyInfoList System.Text.Json.Serialization.Metadata.JsonTypeInfo:g__CreatePropertyList|61_0 () System.Text.Json.Serialization.Metadata.JsonTypeInfo/JsonPropertyInfoList System.Text.Json.Serialization.Metadata.JsonTypeInfo:get_PropertyList () System.Text.Json.Serialization.Metadata.JsonTypeInfo`1 System.Text.Json.JsonSerializer:GetTypeInfo (System.Text.Json.JsonSerializerOptions) System.Text.Json.Serialization.Metadata.JsonTypeInfoKind System.Text.Json.Serialization.Metadata.JsonTypeInfo:GetTypeInfoKind (System.Type,System.Text.Json.Serialization.JsonConverter) + System.Text.Json.Serialization.Metadata.MemberAccessor System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:g__Initialize|10_0 () System.Text.Json.Serialization.Metadata.MemberAccessor System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:get_MemberAccessor () System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry> System.Collections.Concurrent.ConcurrentDictionary`2, System.Text.Json.Cache`1/CacheEntry>>:GetOrAdd (System.ValueTuple`3,System.Func`3, System.Func`2, System.Func`1>, System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>>,System.Func`2, System.Func`1>) - System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry> System.Collections.Concurrent.ConcurrentDictionary`2, System.Text.Json.Cache`1/CacheEntry>>:GetOrAdd (System.ValueTuple`3,System.Func`3, System.Func`2, System.Func`2>, System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>>,System.Func`2, System.Func`2>) System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry> System.Collections.Concurrent.ConcurrentDictionary`2, System.Text.Json.Cache`1/CacheEntry>>:GetOrAdd (System.ValueTuple`3,System.Func`3, System.Func`2, System.Func`2>, System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>>,System.Func`2, System.Func`2>) System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry> System.Collections.Concurrent.ConcurrentDictionary`2, System.Text.Json.Cache`1/CacheEntry>>:GetOrAdd (System.ValueTuple`3,System.Func`3, System.Func`2, System.Func`2>, System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>>,System.Func`2, System.Func`2>) - System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry> System.Collections.Concurrent.ConcurrentDictionary`2, System.Text.Json.Cache`1/CacheEntry>>:GetOrAdd (System.ValueTuple`3,System.Func`3, System.Func`2, System.Func`2>>, System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>>,System.Func`2, System.Func`2>>) System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry> System.Text.Json.Cache`1/<>c__6`1, System.Func`1>:b__6_0 (System.ValueTuple`3,System.Func`2, System.Func`1>) - System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry> System.Text.Json.Cache`1/<>c__6`1, System.Func`2>>:b__6_0 (System.ValueTuple`3,System.Func`2, System.Func`2>>) System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry> System.Text.Json.Cache`1/<>c__6`1, System.Func`2>:b__6_0 (System.ValueTuple`3,System.Func`2, System.Func`2>) System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry> System.Text.Json.Cache`1/<>c__6`1, System.Func`2>:b__6_0 (System.ValueTuple`3,System.Func`2, System.Func`2>) System.Text.Json.Utf8JsonReader System.Text.Json.JsonSerializer:GetReaderScopedToNextValue (System.Text.Json.Utf8JsonReader&,System.Text.Json.ReadStack&) - System.Text.Json.Utf8JsonWriter System.Text.Json.Utf8JsonWriter:CreateEmptyInstanceForCaching () System.Text.Json.Utf8JsonWriter System.Text.Json.Utf8JsonWriterCache:RentWriterAndBuffer (System.Text.Json.JsonSerializerOptions,System.Text.Json.PooledByteBufferWriter&) + System.Text.Json.Utf8JsonWriter System.Text.Json.Utf8JsonWriterCache:RentWriterAndBuffer (System.Text.Json.JsonWriterOptions,int,System.Text.Json.PooledByteBufferWriter&) + System.Text.RegularExpressions.Regex System.Text.Json.JsonHelpers:CreateIntegerRegex () System.Text.RegularExpressions.RegexCharClass System.Text.RegularExpressions.RegexParser:ScanCharClass (bool,bool) System.Text.RegularExpressions.RegexInterpreterCode System.Text.RegularExpressions.RegexWriter:EmitCode () System.Text.RegularExpressions.RegexInterpreterCode System.Text.RegularExpressions.RegexWriter:Write (System.Text.RegularExpressions.RegexTree) @@ -3319,15 +3592,19 @@ Methods: System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__131>:get_Context () System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__0>:get_Context () System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__41>:get_Context () - System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__81>:get_Context () - System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__76>:get_Context () - System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__15>:get_Context () + System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__89>:get_Context () + System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__84>:get_Context () + System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__17>:get_Context () System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1c__DisplayClass14_0/<g__AwaitAndNotify|0>d>:get_Context () System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__0>:get_Context () System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__68>:get_Context () System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__Core|27_0>d>:get_Context () + System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__63>:get_Context () System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__DisposeSourceAsync|1_0>d>:get_Context () - System.Threading.LowLevelLifoSemaphoreBase/Counts System.Threading.LowLevelLifoSemaphoreBase/Counts:InterlockedCompareExchange (System.Threading.LowLevelLifoSemaphoreBase/Counts,System.Threading.LowLevelLifoSemaphoreBase/Counts) + System.Threading.Lock/State System.Threading.Lock/State:CompareExchange (System.Threading.Lock,System.Threading.Lock/State,System.Threading.Lock/State) + System.Threading.Lock/ThreadId System.Threading.Lock:EnterAndGetCurrentThreadId () + System.Threading.Lock/ThreadId System.Threading.Lock:TryEnterSlow (int,System.Threading.Lock/ThreadId) + System.Threading.LowLevelLifoSemaphore/Counts System.Threading.LowLevelLifoSemaphore/Counts:InterlockedCompareExchange (System.Threading.LowLevelLifoSemaphore/Counts,System.Threading.LowLevelLifoSemaphore/Counts) System.Threading.PortableThreadPool/ThreadCounts System.Threading.PortableThreadPool/ThreadCounts:InterlockedCompareExchange (System.Threading.PortableThreadPool/ThreadCounts,System.Threading.PortableThreadPool/ThreadCounts) System.Threading.SemaphoreSlim System.IO.Stream:EnsureAsyncActiveSemaphoreInitialized () System.Threading.SynchronizationContext Android.App.Application:get_SynchronizationContext () @@ -3344,7 +3621,7 @@ Methods: System.Threading.Tasks.Task Microsoft.AspNetCore.Components.LayoutComponentBase:SetParametersAsync (Microsoft.AspNetCore.Components.ParameterView) System.Threading.Tasks.Task Microsoft.AspNetCore.Components.LayoutView:SetParametersAsync (Microsoft.AspNetCore.Components.ParameterView) System.Threading.Tasks.Task Microsoft.AspNetCore.Components.Rendering.ComponentState:NotifyRenderCompletedAsync () - System.Threading.Tasks.Task Microsoft.AspNetCore.Components.RenderTree.Renderer:g__ProcessAsynchronousWork|54_0 () + System.Threading.Tasks.Task Microsoft.AspNetCore.Components.RenderTree.Renderer:g__ProcessAsynchronousWork|62_0 () System.Threading.Tasks.Task Microsoft.AspNetCore.Components.RenderTree.Renderer:GetErrorHandledTask (System.Threading.Tasks.Task,Microsoft.AspNetCore.Components.Rendering.ComponentState) System.Threading.Tasks.Task Microsoft.AspNetCore.Components.RenderTree.Renderer:InvokeRenderCompletedCalls (Microsoft.AspNetCore.Components.RenderTree.ArrayRange`1,System.Threading.Tasks.Task) System.Threading.Tasks.Task Microsoft.AspNetCore.Components.RenderTree.Renderer:InvokeRenderCompletedCallsAfterUpdateDisplayTask (System.Threading.Tasks.Task,int[]) @@ -3392,7 +3669,6 @@ Methods: System.Threading.Tasks.Task System.Threading.Tasks.Task:Run (System.Action,System.Threading.CancellationToken) System.Threading.Tasks.Task System.Threading.Tasks.Task:WhenAll (System.Collections.Generic.IEnumerable`1) System.Threading.Tasks.Task System.Threading.Tasks.Task:WhenAll (System.ReadOnlySpan`1) - System.Threading.Tasks.Task System.Threading.Tasks.Task:WhenAll (System.Threading.Tasks.Task[]) System.Threading.Tasks.Task System.Threading.Tasks.ValueTask:AsTask () System.Threading.Tasks.Task Xamarin.Android.Net.AndroidMessageHandler:ConnectAsync (Java.Net.HttpURLConnection,System.Threading.CancellationToken) System.Threading.Tasks.Task Xamarin.Android.Net.AndroidMessageHandler:SetupRequest (System.Net.Http.HttpRequestMessage,Java.Net.HttpURLConnection) @@ -3465,11 +3741,9 @@ Methods: System.Threading.WaitSubsystem/WaitableObject[] System.Threading.WaitSubsystem/ThreadWaitInfo:GetWaitedObjectArray (int) System.TimeProvider System.TimeProvider:get_System () System.TimeSpan System.Text.RegularExpressions.Regex:InitDefaultMatchTimeout () - System.TimeSpan System.TimeSpan:FromHours (double) - System.TimeSpan System.TimeSpan:FromMilliseconds (double) - System.TimeSpan System.TimeSpan:FromSeconds (double) - System.TimeSpan System.TimeSpan:Interval (double,double) - System.TimeSpan System.TimeSpan:IntervalFromDoubleTicks (double) + System.TimeSpan System.TimeSpan:FromHours (int) + System.TimeSpan System.TimeSpan:FromMilliseconds (long,long) + System.TimeSpan System.TimeSpan:FromSeconds (long) System.Type Android.App.Application:get_ThresholdType () System.Type Android.App.UiModeManager:get_ThresholdType () System.Type Android.Content.Intent:get_ThresholdType () @@ -3479,6 +3753,9 @@ Methods: System.Type Android.Graphics.Paint:get_ThresholdType () System.Type Android.Net.ConnectivityManager:get_ThresholdType () System.Type Android.Net.NetworkInfo:get_ThresholdType () + System.Type Android.Runtime.AndroidEnvironment:g__TypeGetType|26_0 (string) + System.Type Android.Runtime.JNIEnv:MakeArrayType (System.Type) + System.Type Android.Runtime.JNIEnvInit:g__TypeGetType|13_0 (string) System.Type Android.Runtime.XAPeerMembers:GetThresholdType (Java.Interop.IJavaPeerable) System.Type Android.Text.TextPaint:get_ThresholdType () System.Type Android.Views.LayoutInflaterInvoker:get_ThresholdType () @@ -3495,6 +3772,8 @@ Methods: System.Type AndroidX.Fragment.App.FragmentManagerInvoker:get_ThresholdType () System.Type AndroidX.Fragment.App.FragmentTransactionInvoker:get_ThresholdType () System.Type Google.Android.Material.AppBar.AppBarLayout:get_ThresholdType () + System.Type Java.Interop.JavaConvert:g__MakeGenericType|2_0 (System.Type,System.Type[]) + System.Type Java.Interop.JavaObjectExtensions:g__AssemblyGetType|10_0 (System.Reflection.Assembly,string) System.Type Java.Interop.JavaObjectExtensions:GetInvokerType (System.Type) System.Type Java.Interop.JniRuntime/JniTypeManager:GetUnderlyingType (System.Type,int&) System.Type Java.Interop.TypeManager:GetJavaToManagedType (string) @@ -3506,21 +3785,38 @@ Methods: System.Type Javax.Net.Ssl.HttpsURLConnectionInvoker:get_ThresholdType () System.Type Microsoft.AspNetCore.Components.LayoutView:GetParentLayoutType (System.Type) System.Type Microsoft.AspNetCore.Components.RouteView/<>c:b__17_0 (System.Type) - System.Type Microsoft.Extensions.DependencyInjection.ServiceDescriptor:get_ImplementationType () System.Type Microsoft.Extensions.DependencyInjection.ServiceDescriptor:GetImplementationType () System.Type Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceDescriptorExtensions:GetImplementationType (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) System.Type Microsoft.JSInterop.Infrastructure.TaskGenericsUtil:GetTaskCompletionSourceResultType (object) System.Type Microsoft.JSInterop.Infrastructure.TaskGenericsUtil/TcsResultSetter`1:get_ResultType () System.Type Microsoft.Maui.Controls.DependencyService:FindImplementor (System.Type) + System.Type Microsoft.Maui.Hosting.Internal.MauiHandlersFactory:GetVirtualViewHandlerServiceType (System.Type) + System.Type Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:ResolveVirtualViewFromTypeSet (System.Type,System.Collections.Generic.HashSet`1) + System.Type Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:ResolveVirtualViewToRegisteredHandlerServiceType (System.Type) System.Type Microsoft.Maui.PlatformContentViewGroup:get_ThresholdType () - System.Type System.Collections.Concurrent.ConcurrentDictionary`2:GetOrAdd (System.Type,System.Func`2) + System.Type System.Dynamic.Utils.TypeUtils:GetNonNullableType (System.Type) + System.Type System.Dynamic.Utils.TypeUtils/<>c:<.cctor>b__54_1 (System.Type) System.Type System.Enum:GetUnderlyingType (System.Type) + System.Type System.Linq.Expressions.BlockExpression:get_Type () + System.Type System.Linq.Expressions.ConditionalExpression:get_Type () + System.Type System.Linq.Expressions.ConstantExpression:get_Type () + System.Type System.Linq.Expressions.DefaultExpression:get_Type () + System.Type System.Linq.Expressions.LambdaExpression:get_ReturnType () + System.Type System.Linq.Expressions.LambdaExpression:get_Type () + System.Type System.Linq.Expressions.LogicalBinaryExpression:get_Type () + System.Type System.Linq.Expressions.NewExpression:get_Type () + System.Type System.Linq.Expressions.TypedParameterExpression:get_Type () + System.Type System.Linq.Expressions.UnaryExpression:get_Type () System.Type System.Nullable:GetUnderlyingType (System.Type) System.Type System.Reflection.Assembly:GetType (string) System.Type System.Reflection.Assembly:InternalGetType (System.Reflection.Module,string,bool,bool) + System.Type System.Reflection.CustomAttributeData:get_AttributeType () System.Type System.Reflection.Emit.DynamicMethod:get_ReturnType () + System.Type System.Reflection.Emit.RuntimeTypeBuilder:get_DeclaringType () + System.Type System.Reflection.Emit.RuntimeTypeBuilder:ResolveUserType (System.Type) System.Type System.Reflection.MonoMethodInfo:GetDeclaringType (intptr) System.Type System.Reflection.MonoMethodInfo:GetReturnType (intptr) + System.Type System.Reflection.NullabilityInfoContext:GetPropertyMetaType (System.Reflection.PropertyInfo) System.Type System.Reflection.ParameterInfo:get_ParameterType () System.Type System.Reflection.RuntimeAssembly:GetType (string,bool,bool) System.Type System.Reflection.RuntimeConstructorInfo:get_DeclaringType () @@ -3532,6 +3828,7 @@ Methods: System.Type System.Reflection.RuntimePropertyInfo:get_PropertyType () System.Type System.Reflection.RuntimePropertyInfo:get_ReflectedType () System.Type System.RuntimeType:get_BaseType () + System.Type System.RuntimeType:get_DeclaringType () System.Type System.RuntimeType:get_UnderlyingSystemType () System.Type System.RuntimeType:GetElementType () System.Type System.RuntimeType:GetEnumUnderlyingType () @@ -3542,24 +3839,19 @@ Methods: System.Type System.RuntimeTypeHandle:GetGenericTypeDefinition (System.RuntimeType) System.Type System.Text.Json.Reflection.ReflectionExtensions:GetCompatibleGenericBaseClass (System.Type,System.Type) System.Type System.Text.Json.Reflection.ReflectionExtensions:GetCompatibleGenericInterface (System.Type,System.Type) - System.Type System.Text.Json.Serialization.Converters.EnumConverterFactory:GetEnumConverterType (System.Type) System.Type System.Text.Json.Serialization.IAsyncEnumerableConverterFactory:GetAsyncEnumerableInterface (System.Type) System.Type System.Text.Json.Serialization.IEnumerableConverterFactoryHelpers:GetTypeIfExists (string) System.Type System.Text.Json.Serialization.JsonCollectionConverter`2>>, System.Collections.Generic.KeyValuePair`2>>:get_ElementType () System.Type System.Text.Json.Serialization.JsonCollectionConverter`2, System.Char>:get_ElementType () System.Type System.Text.Json.Serialization.JsonCollectionConverter`2>>, System.Collections.Generic.KeyValuePair`2>>:get_ElementType () System.Type System.Text.Json.Serialization.JsonCollectionConverter`2>>, System.Collections.Generic.KeyValuePair`2>>:get_ElementType () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_KeyType () + System.Type System.Text.Json.Serialization.JsonConverter:get_ElementType () + System.Type System.Text.Json.Serialization.JsonConverter:get_KeyType () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_ElementType () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_KeyType () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_ElementType () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_KeyType () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () - System.Type System.Text.Json.Serialization.JsonConverter`1>>:get_KeyType () System.Type System.Text.Json.Serialization.JsonConverter`1>>:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () @@ -3570,19 +3862,12 @@ Methods: System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_ElementType () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_KeyType () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_ElementType () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_KeyType () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1>:get_Type () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_ElementType () System.Type System.Text.Json.Serialization.JsonConverter`1>:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_ElementType () - System.Type System.Text.Json.Serialization.JsonConverter`1:get_KeyType () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () @@ -3590,13 +3875,17 @@ Methods: System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () System.Type System.Text.Json.Serialization.JsonConverter`1:get_Type () - System.Type System.Text.Json.Serialization.JsonObjectConverter`1:get_ElementType () - System.Type System.Text.Json.Serialization.JsonObjectConverter`1>>:get_ElementType () - System.Type System.Text.Json.Serialization.JsonObjectConverter`1:get_ElementType () System.Type System.Type:GetRootElementType () System.Type System.Type:GetType (string,bool) System.Type System.Type:GetType (string) + System.Type System.Type:GetTypeFromHandle (System.RuntimeTypeHandle) + System.Type System.Type:internal_from_handle (intptr) System.Type[] Java.Interop.TypeManager:GetParameterTypes (string) + System.Type[] System.Collections.Generic.SegmentedArrayBuilder`1:ToArray () + System.Type[] System.GC:AllocateArray (int,bool) + System.Type[] System.GC:AllocateUninitializedArray (int,bool) + System.Type[] System.Linq.Enumerable:g__EnumerableToArray|301_0 (System.Collections.Generic.IEnumerable`1) + System.Type[] System.Linq.Expressions.Compiler.LambdaCompiler:GetParameterTypes (System.Linq.Expressions.LambdaExpression,System.Type) System.Type[] System.Reflection.RuntimeAssembly:GetExportedTypes () System.Type[] System.Reflection.RuntimeMethodInfo:GetGenericArguments () System.Type[] System.RuntimeType:GetGenericArguments () @@ -3604,8 +3893,10 @@ Methods: System.Type[] System.Text.Json.JsonHelpers:TraverseGraphWithTopologicalSort (System.Type,System.Func`2>,System.Collections.Generic.IEqualityComparer`1) System.Type[] System.Text.Json.Reflection.ReflectionExtensions:GetSortedTypeHierarchy (System.Type) System.Type[] System.Type:get_GenericTypeArguments () + System.TypeCode System.Dynamic.Utils.TypeExtensions:GetTypeCode (System.Type) System.TypeCode System.RuntimeType:GetTypeCodeImpl () System.Uri Microsoft.AspNetCore.Components.NavigationManager:ToAbsoluteUri (string) + System.Uri Microsoft.AspNetCore.Components.WebView.Maui.AndroidWebKitWebViewManager:get_AppOriginUri () System.Uri Microsoft.AspNetCore.Components.WebView.WebViewManager:EnsureTrailingSlash (System.Uri) System.Uri System.Net.Http.HttpClient:CreateUri (string) System.Uri System.Uri:MakeRelativeUri (System.Uri) @@ -3619,9 +3910,9 @@ Methods: System.ValueTuple`2 Microsoft.Extensions.Logging.LoggerFactory:ApplyFilters (Microsoft.Extensions.Logging.LoggerInformation[]) System.ValueTuple`2[] Microsoft.Maui.ApplicationModel.Permissions/NetworkState:get_RequiredPermissions () System.ValueTuple`2[] System.Collections.Generic.List`1>:ToArray () + System.ValueTuple`2& System.Collections.Generic.Dictionary`2>:FindValue (Microsoft.Maui.Controls.BindableProperty) System.ValueTuple`3 System.Net.Http.HttpClient:PrepareCancellationTokenSource (System.Threading.CancellationToken) System.ValueTuple`4[] System.Collections.Generic.List`1>:ToArray () - System.Version System.Reflection.AssemblyNameParser:ParseVersion (string) System.Version System.Resources.ResourceManager:GetSatelliteContractVersion (System.Reflection.Assembly) System.Version System.Resources.ResourceManager/ResourceManagerMediator:ObtainSatelliteContractVersion (System.Reflection.Assembly) System.WeakReference`1 Android.Runtime.IdentityHashTargets:CreateWeakReference (Java.Interop.IJavaPeerable) @@ -3664,13 +3955,16 @@ Methods: System.Xml.XmlTextReaderImpl/NodeData System.Xml.XmlTextReaderImpl:AllocNode (int,int) System.Xml.XmlTextReaderImpl/NodeData System.Xml.XmlTextReaderImpl/NodeData:get_None () uint Android.Runtime.Logger:monodroid_get_log_categories () + uint System.Buffers.ProbabilisticMapState:FindModulus (System.ReadOnlySpan`1,int) uint System.Collections.Hashtable:InitHash (object,int,uint&,uint&) uint System.Decimal/DecCalc:Div96By32 (System.Decimal/DecCalc/Buf12&,uint) uint System.Decimal/DecCalc:GetExponent (double) uint System.HashCode:GenerateGlobalSeed () uint System.HashCode:MixEmptyState () uint System.Private.CoreLib.GateThread/DelayHelper:GetNextDelay (int) + uint System.Private.CoreLib.Interop/Sys:TryGetUInt32OSThreadId () uint System.Threading.TimerQueueTimer:GetMilliseconds (System.TimeSpan,string) + uintptr System.Text.Ascii:ChangeCase (uint16*,byte*,uintptr) uintptr System.Text.Ascii:ChangeCase (uint16*,uint16*,uintptr) uintptr System.Text.Ascii:GetIndexOfFirstNonAsciiByte_Vector (byte*,uintptr) uintptr System.Text.Ascii:GetIndexOfFirstNonAsciiChar_Vector (char*,uintptr) @@ -3679,7 +3973,7 @@ Methods: ulong System.Marvin:GenerateSeed () ulong System.Marvin:get_DefaultSeed () ulong System.Private.CoreLib.Interop/Sys:GetTimestamp () - ulong System.Text.Json.Serialization.Converters.EnumConverter`1:ConvertToUInt64 (object) + ulong System.Text.Json.Serialization.Converters.EnumConverter`1:ConvertToUInt64 (Microsoft.JSInterop.JSCallResultType) void Android.App.Activity:.cctor () void Android.App.Activity:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.App.Activity:n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) @@ -3716,6 +4010,8 @@ Methods: void Android.App.SyncContext/<>c__DisplayClass2_0:b__0 () void Android.App.UiModeManager:.cctor () void Android.App.UiModeManager:.ctor (intptr,Android.Runtime.JniHandleOwnership) + void Android.Content.ContentProvider:.cctor () + void Android.Content.ContentProvider:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.Content.Context:.cctor () void Android.Content.Context:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.Content.ContextWrapper:.cctor () @@ -3750,10 +4046,6 @@ Methods: void Android.Graphics.Color:.ctor (int,int,int,int) void Android.Graphics.Color:CheckARGBValues (int,int,int,int) void Android.Graphics.Color:CheckRGBValues (int,int,int) - void Android.Graphics.Drawables.ColorDrawable:.cctor () - void Android.Graphics.Drawables.ColorDrawable:.ctor (intptr,Android.Runtime.JniHandleOwnership) - void Android.Graphics.Drawables.Drawable:.cctor () - void Android.Graphics.Drawables.Drawable:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.Graphics.Matrix:.cctor () void Android.Graphics.Matrix:.ctor () void Android.Graphics.Paint:.cctor () @@ -3794,10 +4086,10 @@ Methods: void Android.Runtime.AndroidObjectReferenceManager:CreatedLocalReference (Java.Interop.JniObjectReference,int&) void Android.Runtime.AndroidObjectReferenceManager:DeleteGlobalReference (Java.Interop.JniObjectReference&) void Android.Runtime.AndroidObjectReferenceManager:DeleteLocalReference (Java.Interop.JniObjectReference&,int&) - void Android.Runtime.AndroidRuntime:.ctor (intptr,intptr,bool,intptr,intptr,bool) + void Android.Runtime.AndroidRuntime:.ctor (intptr,intptr,intptr,intptr,bool) void Android.Runtime.AndroidRuntimeInternal:.cctor () void Android.Runtime.AndroidRuntimeInternal:WaitForBridgeProcessing () - void Android.Runtime.AndroidRuntimeOptions:.ctor (intptr,intptr,bool,intptr,intptr,bool) + void Android.Runtime.AndroidRuntimeOptions:.ctor (intptr,intptr,intptr,intptr,bool) void Android.Runtime.AndroidTypeManager:.cctor () void Android.Runtime.AndroidTypeManager:.ctor (bool) void Android.Runtime.AndroidTypeManager:RegisterNativeMembers (Java.Interop.JniType,System.Type,System.ReadOnlySpan`1) @@ -3815,6 +4107,7 @@ Methods: void Android.Runtime.InputStreamAdapter:Close () void Android.Runtime.InputStreamInvoker:.ctor (Java.IO.InputStream) void Android.Runtime.InputStreamInvoker:Close () + void Android.Runtime.InputStreamInvoker:Dispose (bool) void Android.Runtime.JavaArray`1/d__13:System.IDisposable.Dispose () void Android.Runtime.JavaArray`1:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.Runtime.JavaDictionary:.cctor () @@ -3907,16 +4200,15 @@ Methods: void Android.Views.View:set_LayoutDirection (Android.Views.LayoutDirection) void Android.Views.View:set_LayoutParameters (Android.Views.ViewGroup/LayoutParams) void Android.Views.View:set_OnFocusChangeListener (Android.Views.View/IOnFocusChangeListener) - void Android.Views.View:SetBackgroundColor (Android.Graphics.Color) void Android.Views.View:SetMeasuredDimension (int,int) void Android.Views.View:SetOnTouchListener (Android.Views.View/IOnTouchListener) - void Android.Views.View/<>c__DisplayClass2962_0:b__0 (Android.Views.View/IOnAttachStateChangeListenerImplementor) - void Android.Views.View/<>c__DisplayClass2963_0:b__0 (Android.Views.View/IOnAttachStateChangeListener) - void Android.Views.View/<>c__DisplayClass2963_0:b__1 (Android.Views.View/IOnAttachStateChangeListenerImplementor) - void Android.Views.View/<>c__DisplayClass2970_0:b__0 (Android.Views.View/IOnLayoutChangeListenerImplementor) - void Android.Views.View/<>c__DisplayClass3047_0:b__0 (Android.Views.View/IOnTouchListenerImplementor) - void Android.Views.View/<>c__DisplayClass3052_0:b__0 (Android.Views.View/IOnFocusChangeListener) - void Android.Views.View/<>c__DisplayClass3052_0:b__1 (Android.Views.View/IOnFocusChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3029_0:b__0 (Android.Views.View/IOnAttachStateChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3030_0:b__0 (Android.Views.View/IOnAttachStateChangeListener) + void Android.Views.View/<>c__DisplayClass3030_0:b__1 (Android.Views.View/IOnAttachStateChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3037_0:b__0 (Android.Views.View/IOnLayoutChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3114_0:b__0 (Android.Views.View/IOnTouchListenerImplementor) + void Android.Views.View/<>c__DisplayClass3119_0:b__0 (Android.Views.View/IOnFocusChangeListener) + void Android.Views.View/<>c__DisplayClass3119_0:b__1 (Android.Views.View/IOnFocusChangeListenerImplementor) void Android.Views.View/IOnAttachStateChangeListenerImplementor:.ctor (object) void Android.Views.View/IOnAttachStateChangeListenerImplementor:OnViewAttachedToWindow (Android.Views.View) void Android.Views.View/IOnAttachStateChangeListenerInvoker:.cctor () @@ -3999,6 +4291,8 @@ Methods: void AndroidX.Activity.ComponentActivity:.ctor (intptr,Android.Runtime.JniHandleOwnership) void AndroidX.AppCompat.App.AppCompatActivity:.cctor () void AndroidX.AppCompat.App.AppCompatActivity:.ctor () + void AndroidX.AppCompat.App.AppCompatDelegate:.cctor () + void AndroidX.AppCompat.App.AppCompatDelegate:set_DefaultNightMode (int) void AndroidX.AppCompat.Widget.TooltipCompat:.cctor () void AndroidX.AppCompat.Widget.TooltipCompat:SetTooltipText (Android.Views.View,Java.Lang.ICharSequence) void AndroidX.AppCompat.Widget.TooltipCompat:SetTooltipText (Android.Views.View,string) @@ -4008,6 +4302,8 @@ Methods: void AndroidX.CoordinatorLayout.Widget.CoordinatorLayout/LayoutParams:.ctor (int,int) void AndroidX.Core.App.ComponentActivity:.cctor () void AndroidX.Core.App.ComponentActivity:.ctor (intptr,Android.Runtime.JniHandleOwnership) + void AndroidX.Core.Content.FileProvider:.cctor () + void AndroidX.Core.Content.FileProvider:.ctor () void AndroidX.Core.View.ViewCompat:.cctor () void AndroidX.Fragment.App.Fragment:.cctor () void AndroidX.Fragment.App.Fragment:.ctor () @@ -4094,7 +4390,6 @@ Methods: void Java.Interop.JniRuntime:AssertValid () void Java.Interop.JniRuntime:set_InvocationPointer (intptr) void Java.Interop.JniRuntime:set_JniVersion (Java.Interop.JniVersion) - void Java.Interop.JniRuntime:set_NewObjectRequired (bool) void Java.Interop.JniRuntime:set_ObjectReferenceManager (Java.Interop.JniRuntime/JniObjectReferenceManager) void Java.Interop.JniRuntime:set_TrackIDs (bool) void Java.Interop.JniRuntime:set_TypeManager (Java.Interop.JniRuntime/JniTypeManager) @@ -4124,6 +4419,7 @@ Methods: void Java.Interop.JniType:Initialize (Java.Interop.JniObjectReference&,Java.Interop.JniObjectReferenceOptions) void Java.Interop.JniType:RegisterNativeMethods (Java.Interop.JniNativeMethodRegistration[]) void Java.Interop.JniType:RegisterWithRuntime () + void Java.Interop.JniTypeManager/JniPrimitiveArrayInfo:.ctor (string,System.Type,System.Type[]) void Java.Interop.JniTypeSignature:.ctor (string,int,bool) void Java.Interop.ManagedPeer:.cctor () void Java.Interop.ManagedPeer:Init () @@ -4136,6 +4432,8 @@ Methods: void Java.Interop.TypeManager:n_Activate (intptr,intptr,intptr,intptr,intptr,intptr) void Java.Interop.TypeManager:RegisterType (string,System.Type) void Java.Interop.TypeManagerMapDictionaries:.cctor () + void Java.IO.FileNotFoundException:.cctor () + void Java.IO.FileNotFoundException:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Java.IO.InputStream:.cctor () void Java.IO.InputStream:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Java.IO.InputStream:Close () @@ -4189,7 +4487,6 @@ Methods: void Java.Security.KeyStore:Load (System.IO.Stream,char[]) void Java.Util.IIteratorInvoker:.cctor () void Java.Util.IIteratorInvoker:.ctor (intptr,Android.Runtime.JniHandleOwnership) - void Java.Util.IIteratorInvoker:Dispose (bool) void Javax.Net.Ssl.HttpsURLConnection:.cctor () void Javax.Net.Ssl.HttpsURLConnection:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Javax.Net.Ssl.HttpsURLConnectionInvoker:.cctor () @@ -4197,14 +4494,13 @@ Methods: void Javax.Net.Ssl.HttpsURLConnectionInvoker:Connect () void Microsoft.AspNetCore.Components.CascadingParameterState:.cctor () void Microsoft.AspNetCore.Components.ComponentBase:.ctor () - void Microsoft.AspNetCore.Components.ComponentBase:<.ctor>b__6_0 (Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder) - void Microsoft.AspNetCore.Components.ComponentBase:BuildRenderTree (Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder) + void Microsoft.AspNetCore.Components.ComponentBase:<.ctor>b__7_0 (Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder) void Microsoft.AspNetCore.Components.ComponentBase:Microsoft.AspNetCore.Components.IComponent.Attach (Microsoft.AspNetCore.Components.RenderHandle) void Microsoft.AspNetCore.Components.ComponentBase:OnAfterRender (bool) void Microsoft.AspNetCore.Components.ComponentBase:OnInitialized () void Microsoft.AspNetCore.Components.ComponentBase:OnParametersSet () void Microsoft.AspNetCore.Components.ComponentBase:StateHasChanged () - void Microsoft.AspNetCore.Components.ComponentBase/d__21:MoveNext () + void Microsoft.AspNetCore.Components.ComponentBase/d__28:MoveNext () void Microsoft.AspNetCore.Components.ComponentFactory:.cctor () void Microsoft.AspNetCore.Components.ComponentFactory:.ctor (Microsoft.AspNetCore.Components.IComponentActivator,Microsoft.AspNetCore.Components.RenderTree.Renderer) void Microsoft.AspNetCore.Components.ComponentFactory/<>c__DisplayClass9_0:g__Initialize|1 (System.IServiceProvider,Microsoft.AspNetCore.Components.IComponent) @@ -4213,20 +4509,16 @@ Methods: void Microsoft.AspNetCore.Components.ComponentFactory/<>c:b__9_0 (System.IServiceProvider,Microsoft.AspNetCore.Components.IComponent) void Microsoft.AspNetCore.Components.ComponentFactory/ComponentTypeInfoCacheEntry:.ctor (Microsoft.AspNetCore.Components.IComponentRenderMode,System.Action`2) void Microsoft.AspNetCore.Components.DefaultComponentActivator:.cctor () - void Microsoft.AspNetCore.Components.DefaultComponentActivator:.ctor () + void Microsoft.AspNetCore.Components.DefaultComponentActivator:.ctor (System.IServiceProvider) void Microsoft.AspNetCore.Components.Dispatcher:AssertAccess () void Microsoft.AspNetCore.Components.EditorRequiredAttribute:.ctor () void Microsoft.AspNetCore.Components.ElementReferenceJsonConverter:.cctor () void Microsoft.AspNetCore.Components.ElementReferenceJsonConverter:.ctor (Microsoft.AspNetCore.Components.ElementReferenceContext) - void Microsoft.AspNetCore.Components.EventCallback`1/<>c:.cctor () - void Microsoft.AspNetCore.Components.EventCallback`1/<>c:.ctor () - void Microsoft.AspNetCore.Components.EventCallback`1:.cctor () - void Microsoft.AspNetCore.Components.EventCallback`1:.ctor (Microsoft.AspNetCore.Components.IHandleEvent,System.MulticastDelegate) - void Microsoft.AspNetCore.Components.EventCallbackWorkItem:.cctor () - void Microsoft.AspNetCore.Components.EventCallbackWorkItem:.ctor (System.MulticastDelegate) void Microsoft.AspNetCore.Components.HotReload.HotReloadManager:.cctor () void Microsoft.AspNetCore.Components.HotReload.HotReloadManager:.ctor () void Microsoft.AspNetCore.Components.InjectAttribute:.ctor () + void Microsoft.AspNetCore.Components.JsonConverterFactoryTypeInfoResolver`1>:.cctor () + void Microsoft.AspNetCore.Components.JsonConverterFactoryTypeInfoResolver`1>:.ctor () void Microsoft.AspNetCore.Components.JsonSerializerOptionsProvider:.cctor () void Microsoft.AspNetCore.Components.LayoutComponentBase:.ctor () void Microsoft.AspNetCore.Components.LayoutComponentBase:set_Body (Microsoft.AspNetCore.Components.RenderFragment) @@ -4268,6 +4560,7 @@ Methods: void Microsoft.AspNetCore.Components.Reflection.PropertySetter:CallPropertySetter (System.Action`2,object,object) void Microsoft.AspNetCore.Components.Reflection.PropertySetter:CallPropertySetter (System.Action`2,object,object) void Microsoft.AspNetCore.Components.Reflection.PropertySetter:SetValue (object,object) + void Microsoft.AspNetCore.Components.RendererInfo:.ctor (string,bool) void Microsoft.AspNetCore.Components.RenderHandle:.ctor (Microsoft.AspNetCore.Components.RenderTree.Renderer,int) void Microsoft.AspNetCore.Components.RenderHandle:Render (Microsoft.AspNetCore.Components.RenderFragment) void Microsoft.AspNetCore.Components.Rendering.ComponentState:.ctor (Microsoft.AspNetCore.Components.RenderTree.Renderer,int,Microsoft.AspNetCore.Components.IComponent,Microsoft.AspNetCore.Components.Rendering.ComponentState) @@ -4343,11 +4636,11 @@ Methods: void Microsoft.AspNetCore.Components.RenderTree.Renderer:ProcessRenderQueue () void Microsoft.AspNetCore.Components.RenderTree.Renderer:RemoveEventHandlerIds (Microsoft.AspNetCore.Components.RenderTree.ArrayRange`1,System.Threading.Tasks.Task) void Microsoft.AspNetCore.Components.RenderTree.Renderer:RenderInExistingBatch (Microsoft.AspNetCore.Components.Rendering.RenderQueueEntry) - void Microsoft.AspNetCore.Components.RenderTree.Renderer/<g__ProcessAsynchronousWork|54_0>d:MoveNext () - void Microsoft.AspNetCore.Components.RenderTree.Renderer/d__81:MoveNext () - void Microsoft.AspNetCore.Components.RenderTree.Renderer/d__76:MoveNext () - void Microsoft.AspNetCore.Components.RenderTree.Renderer/d__50:MoveNext () - void Microsoft.AspNetCore.Components.RenderTree.Renderer/d__54:MoveNext () + void Microsoft.AspNetCore.Components.RenderTree.Renderer/<g__ProcessAsynchronousWork|62_0>d:MoveNext () + void Microsoft.AspNetCore.Components.RenderTree.Renderer/d__89:MoveNext () + void Microsoft.AspNetCore.Components.RenderTree.Renderer/d__84:MoveNext () + void Microsoft.AspNetCore.Components.RenderTree.Renderer/d__58:MoveNext () + void Microsoft.AspNetCore.Components.RenderTree.Renderer/d__62:MoveNext () void Microsoft.AspNetCore.Components.RenderTree.Renderer/Log:.cctor () void Microsoft.AspNetCore.Components.RenderTree.Renderer/Log:InitializingComponent (Microsoft.Extensions.Logging.ILogger,Microsoft.AspNetCore.Components.Rendering.ComponentState,Microsoft.AspNetCore.Components.Rendering.ComponentState) void Microsoft.AspNetCore.Components.RenderTree.Renderer/Log:RenderingComponent (Microsoft.Extensions.Logging.ILogger,Microsoft.AspNetCore.Components.Rendering.ComponentState) @@ -4368,11 +4661,15 @@ Methods: void Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrameArrayBuilder:AppendRegion (int) void Microsoft.AspNetCore.Components.RenderTree.StackObjectPool`1>:.ctor (int,System.Func`1>) void Microsoft.AspNetCore.Components.RenderTree.WebRenderer:.ctor (System.IServiceProvider,Microsoft.Extensions.Logging.ILoggerFactory,System.Text.Json.JsonSerializerOptions,Microsoft.AspNetCore.Components.Web.Infrastructure.JSComponentInterop) + void Microsoft.AspNetCore.Components.RenderTree.WebRenderer:AttachWebRendererInterop (Microsoft.JSInterop.IJSRuntime,System.Text.Json.JsonSerializerOptions,Microsoft.AspNetCore.Components.Web.Infrastructure.JSComponentInterop) void Microsoft.AspNetCore.Components.RenderTree.WebRenderer/WebRendererInteropMethods:.ctor (Microsoft.AspNetCore.Components.RenderTree.WebRenderer,System.Text.Json.JsonSerializerOptions,Microsoft.AspNetCore.Components.Web.Infrastructure.JSComponentInterop) + void Microsoft.AspNetCore.Components.ResourceAssetCollection:.cctor () + void Microsoft.AspNetCore.Components.ResourceAssetCollection:.ctor (System.Collections.Generic.IReadOnlyList`1) void Microsoft.AspNetCore.Components.RouteAttribute:.ctor (string) void Microsoft.AspNetCore.Components.RouteData:.ctor (System.Type,System.Collections.Generic.IReadOnlyDictionary`2) void Microsoft.AspNetCore.Components.RouteTableFactory:.cctor () - void Microsoft.AspNetCore.Components.RouteTableFactory:g__GetRouteableComponents|4_0 (System.Collections.Generic.List`1,System.Reflection.Assembly) + void Microsoft.AspNetCore.Components.RouteTableFactory:.ctor () + void Microsoft.AspNetCore.Components.RouteTableFactory:g__GetRouteableComponents|5_0 (System.Collections.Generic.List`1,System.Reflection.Assembly) void Microsoft.AspNetCore.Components.RouteTableFactory:DetectAmbiguousRoutes (Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder) void Microsoft.AspNetCore.Components.RouteTableFactory/<>c:.cctor () void Microsoft.AspNetCore.Components.RouteTableFactory/<>c:.ctor () @@ -4388,11 +4685,12 @@ Methods: void Microsoft.AspNetCore.Components.RouteView/<>c:.cctor () void Microsoft.AspNetCore.Components.RouteView/<>c:.ctor () void Microsoft.AspNetCore.Components.Routing.FocusOnNavigate:.ctor () + void Microsoft.AspNetCore.Components.Routing.FocusOnNavigate:BuildRenderTree (Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder) void Microsoft.AspNetCore.Components.Routing.FocusOnNavigate:OnParametersSet () void Microsoft.AspNetCore.Components.Routing.FocusOnNavigate:set_JSRuntime (Microsoft.JSInterop.IJSRuntime) void Microsoft.AspNetCore.Components.Routing.FocusOnNavigate:set_RouteData (Microsoft.AspNetCore.Components.RouteData) void Microsoft.AspNetCore.Components.Routing.FocusOnNavigate:set_Selector (string) - void Microsoft.AspNetCore.Components.Routing.FocusOnNavigate/d__15:MoveNext () + void Microsoft.AspNetCore.Components.Routing.FocusOnNavigate/d__17:MoveNext () void Microsoft.AspNetCore.Components.Routing.NavigationContext:.ctor (string,System.Threading.CancellationToken) void Microsoft.AspNetCore.Components.Routing.NavLink:.ctor () void Microsoft.AspNetCore.Components.Routing.NavLink:BuildRenderTree (Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder) @@ -4406,9 +4704,6 @@ Methods: void Microsoft.AspNetCore.Components.Routing.Patterns.RoutePatternFactory:.cctor () void Microsoft.AspNetCore.Components.Routing.Patterns.RoutePatternFactory/<>c:.cctor () void Microsoft.AspNetCore.Components.Routing.Patterns.RoutePatternFactory/<>c:.ctor () - void Microsoft.AspNetCore.Components.Routing.QueryParameterNameComparer:.cctor () - void Microsoft.AspNetCore.Components.Routing.QueryParameterNameComparer:.ctor () - void Microsoft.AspNetCore.Components.Routing.QueryParameterValueSupplier:.ctor () void Microsoft.AspNetCore.Components.Routing.RouteContext:.ctor (string) void Microsoft.AspNetCore.Components.Routing.RouteKey:.ctor (System.Reflection.Assembly,System.Collections.Generic.IEnumerable`1) void Microsoft.AspNetCore.Components.Routing.Router:.cctor () @@ -4435,7 +4730,7 @@ Methods: void Microsoft.AspNetCore.Components.Routing.RouteTable:ProcessParameters (Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry,Microsoft.AspNetCore.Components.Routing.RouteValueDictionary) void Microsoft.AspNetCore.Components.Routing.RouteTable:Route (Microsoft.AspNetCore.Components.Routing.RouteContext) void Microsoft.AspNetCore.Components.Routing.RouteValueDictionary/Enumerator:.ctor (Microsoft.AspNetCore.Components.Routing.RouteValueDictionary) - void Microsoft.AspNetCore.Components.SupplyParameterFromQueryProviderServiceCollectionExtensions/SupplyValueFromQueryValueProvider:.ctor (Microsoft.AspNetCore.Components.NavigationManager) + void Microsoft.AspNetCore.Components.Routing.SupplyParameterFromQueryValueProvider:.ctor (Microsoft.AspNetCore.Components.NavigationManager) void Microsoft.AspNetCore.Components.Web.Infrastructure.JSComponentInterop:.cctor () void Microsoft.AspNetCore.Components.Web.Infrastructure.JSComponentInterop:.ctor (Microsoft.AspNetCore.Components.Web.JSComponentConfigurationStore) void Microsoft.AspNetCore.Components.Web.JSComponentConfigurationStore:.ctor () @@ -4481,7 +4776,7 @@ Methods: void Microsoft.AspNetCore.Components.WebView.Maui.AndroidMauiAssetFileProvider/AndroidMauiAssetFileInfo:.ctor (Android.Content.Res.AssetManager,string) void Microsoft.AspNetCore.Components.WebView.Maui.AndroidWebKitWebViewManager:.cctor () void Microsoft.AspNetCore.Components.WebView.Maui.AndroidWebKitWebViewManager:.ctor (Android.Webkit.WebView,System.IServiceProvider,Microsoft.AspNetCore.Components.Dispatcher,Microsoft.Extensions.FileProviders.IFileProvider,Microsoft.AspNetCore.Components.Web.JSComponentConfigurationStore,string,string,Microsoft.Extensions.Logging.ILogger) - void Microsoft.AspNetCore.Components.WebView.Maui.AndroidWebKitWebViewManager:b__10_0 (string) + void Microsoft.AspNetCore.Components.WebView.Maui.AndroidWebKitWebViewManager:b__16_0 (string) void Microsoft.AspNetCore.Components.WebView.Maui.AndroidWebKitWebViewManager:NavigateCore (System.Uri) void Microsoft.AspNetCore.Components.WebView.Maui.AndroidWebKitWebViewManager:SendMessage (string) void Microsoft.AspNetCore.Components.WebView.Maui.AndroidWebKitWebViewManager:SetUpMessageChannel () @@ -4525,6 +4820,7 @@ Methods: void Microsoft.AspNetCore.Components.WebView.Services.WebViewNavigationInterception:.ctor () void Microsoft.AspNetCore.Components.WebView.Services.WebViewNavigationManager:.ctor (Microsoft.Extensions.Logging.ILogger`1) void Microsoft.AspNetCore.Components.WebView.Services.WebViewNavigationManager:AttachToWebView (Microsoft.AspNetCore.Components.WebView.IpcSender,string,string) + void Microsoft.AspNetCore.Components.WebView.Services.WebViewRenderer:.cctor () void Microsoft.AspNetCore.Components.WebView.Services.WebViewRenderer:.ctor (System.IServiceProvider,Microsoft.AspNetCore.Components.Dispatcher,Microsoft.AspNetCore.Components.WebView.IpcSender,Microsoft.Extensions.Logging.ILoggerFactory,Microsoft.AspNetCore.Components.WebView.Services.WebViewJSRuntime,Microsoft.AspNetCore.Components.Web.Infrastructure.JSComponentInterop) void Microsoft.AspNetCore.Components.WebView.Services.WebViewRenderer:AttachRootComponentToBrowser (int,string) void Microsoft.AspNetCore.Components.WebView.Services.WebViewRenderer:NotifyRenderCompleted (long) @@ -4544,13 +4840,13 @@ Methods: void Microsoft.AspNetCore.Routing.DefaultInlineConstraintResolver:.ctor (Microsoft.Extensions.Options.IOptions`1,System.IServiceProvider) void Microsoft.AspNetCore.Routing.PathTokenizer:.ctor (Microsoft.AspNetCore.Components.Routing.PathString) void Microsoft.AspNetCore.Routing.PathTokenizer/Enumerator:.ctor (Microsoft.AspNetCore.Routing.PathTokenizer) - void Microsoft.AspNetCore.Routing.Patterns.RoutePattern:.cctor () void Microsoft.AspNetCore.Routing.Patterns.RoutePattern:.ctor (string,System.Collections.Generic.IReadOnlyDictionary`2,System.Collections.Generic.IReadOnlyDictionary`2>,System.Collections.Generic.IReadOnlyDictionary`2,System.Collections.Generic.IReadOnlyList`1,System.Collections.Generic.IReadOnlyList`1) void Microsoft.AspNetCore.Routing.Patterns.RoutePatternParser:.cctor () void Microsoft.AspNetCore.Routing.Patterns.RoutePatternParser/Context:.ctor (string) void Microsoft.AspNetCore.Routing.RouteConstraintBuilder:.ctor (Microsoft.AspNetCore.Routing.IInlineConstraintResolver,string) void Microsoft.AspNetCore.Routing.RouteOptions:.ctor () void Microsoft.AspNetCore.Routing.RouteOptions:AddConstraint (System.Collections.Generic.Dictionary`2,string) + void Microsoft.AspNetCore.Routing.RouteOptions:SetParameterPolicy (string,System.Type) void Microsoft.AspNetCore.Routing.RoutePatternMatcher:.ctor (Microsoft.AspNetCore.Routing.Patterns.RoutePattern,Microsoft.AspNetCore.Components.Routing.RouteValueDictionary) void Microsoft.AspNetCore.Routing.RouteValueEqualityComparer:.cctor () void Microsoft.AspNetCore.Routing.RouteValueEqualityComparer:.ctor () @@ -4567,6 +4863,11 @@ Methods: void Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree:AddEntry (Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry) void Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree/<>c:.cctor () void Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree/<>c:.ctor () + void Microsoft.AspNetCore.Shared.ArgumentThrowHelper:ThrowIfNullOrWhiteSpace (string,string) + void Microsoft.Extensions.DependencyInjection.ActivatorUtilities:.cctor () + void Microsoft.Extensions.DependencyInjection.ActivatorUtilities:CreateFactoryInternal (System.Type,System.Type[],System.Linq.Expressions.ParameterExpression&,System.Linq.Expressions.ParameterExpression&,System.Linq.Expressions.Expression&) + void Microsoft.Extensions.DependencyInjection.ActivatorUtilities:FindApplicableConstructor (System.Type,System.Type[],Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorInfoEx[],System.Reflection.ConstructorInfo&,System.Nullable`1[]&) + void Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorInfoEx:.ctor (System.Reflection.ConstructorInfo) void Microsoft.Extensions.DependencyInjection.BlazorWebViewServiceCollectionExtensions/<>c:.cctor () void Microsoft.Extensions.DependencyInjection.BlazorWebViewServiceCollectionExtensions/<>c:.ctor () void Microsoft.Extensions.DependencyInjection.BlazorWebViewServiceCollectionExtensions/<>c:b__0_1 (Microsoft.Maui.Hosting.IMauiHandlersCollection) @@ -4655,9 +4956,7 @@ Methods: void Microsoft.Extensions.Logging.LoggerFactory:RefreshFilters (Microsoft.Extensions.Logging.LoggerFilterOptions) void Microsoft.Extensions.Logging.LoggerFactoryOptions:.ctor () void Microsoft.Extensions.Logging.LoggerFilterOptions:.ctor () - void Microsoft.Extensions.Logging.LogValuesFormatter:.cctor () void Microsoft.Extensions.Logging.LogValuesFormatter:.ctor (string) - void Microsoft.Extensions.Logging.LogValuesFormatter:set_OriginalFormat (string) void Microsoft.Extensions.Options.ConfigureOptions`1:Configure (Microsoft.Extensions.Logging.LoggerFilterOptions) void Microsoft.Extensions.Options.Options:.cctor () void Microsoft.Extensions.Options.OptionsCache`1/<>c__3`1>:.cctor () @@ -4749,11 +5048,7 @@ Methods: void Microsoft.Maui.Controls.Application:OnStart () void Microsoft.Maui.Controls.Application:RemapForControls () void Microsoft.Maui.Controls.Application:SendStart () - void Microsoft.Maui.Controls.Application:set_MainPage (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.Application:set_Resources (Microsoft.Maui.Controls.ResourceDictionary) - void Microsoft.Maui.Controls.AttachedCollection`1:.ctor () - void Microsoft.Maui.Controls.AttachedCollection`1:AttachTo (Microsoft.Maui.Controls.BindableObject) - void Microsoft.Maui.Controls.AttachedCollection`1:OnAttachedTo (Microsoft.Maui.Controls.BindableObject) void Microsoft.Maui.Controls.AutomationProperties:.cctor () void Microsoft.Maui.Controls.BarElement:.cctor () void Microsoft.Maui.Controls.BaseShellItem:.cctor () @@ -4762,8 +5057,8 @@ Methods: void Microsoft.Maui.Controls.BindableObject:.cctor () void Microsoft.Maui.Controls.BindableObject:.ctor () void Microsoft.Maui.Controls.BindableObject:add_PropertyChanged (System.ComponentModel.PropertyChangedEventHandler) - void Microsoft.Maui.Controls.BindableObject:ApplyBindings (bool,bool) - void Microsoft.Maui.Controls.BindableObject:Microsoft.Maui.Controls.Internals.IDynamicResourceHandler.SetDynamicResource (Microsoft.Maui.Controls.BindableProperty,string) + void Microsoft.Maui.Controls.BindableObject:add_PropertyChanging (Microsoft.Maui.Controls.PropertyChangingEventHandler) + void Microsoft.Maui.Controls.BindableObject:OnBindablePropertySet (Microsoft.Maui.Controls.BindableProperty,object,object,bool,bool) void Microsoft.Maui.Controls.BindableObject:OnPropertyChanged (string) void Microsoft.Maui.Controls.BindableObject:OnPropertyChanging (string) void Microsoft.Maui.Controls.BindableObject:SetDynamicResource (Microsoft.Maui.Controls.BindableProperty,string,Microsoft.Maui.Controls.SetterSpecificity) @@ -4793,8 +5088,6 @@ Methods: void Microsoft.Maui.Controls.CheckBox/<>c:.ctor () void Microsoft.Maui.Controls.ColorElement:.cctor () void Microsoft.Maui.Controls.ColumnDefinitionCollection:.ctor () - void Microsoft.Maui.Controls.Compatibility.Layout:.cctor () - void Microsoft.Maui.Controls.Compatibility.Layout:LayoutChildIntoBoundingRegion (Microsoft.Maui.Controls.VisualElement,Microsoft.Maui.Graphics.Rect) void Microsoft.Maui.Controls.Compatibility.Platform.Android.ResourcesProvider:.ctor () void Microsoft.Maui.Controls.Compatibility.Platform.Android.ResourcesProvider:UpdateStyles () void Microsoft.Maui.Controls.ContentPage:.cctor () @@ -4835,6 +5128,7 @@ Methods: void Microsoft.Maui.Controls.Element:MapAutomationPropertiesIsInAccessibleTree (Microsoft.Maui.IElementHandler,Microsoft.Maui.Controls.Element) void Microsoft.Maui.Controls.Element:MapAutomationPropertiesIsInAccessibleTree (Microsoft.Maui.IElementHandler,Microsoft.Maui.IElement) void Microsoft.Maui.Controls.Element:Microsoft.Maui.Controls.IElementDefinition.AddResourcesChangedListener (System.Action`2) + void Microsoft.Maui.Controls.Element:OnBindablePropertySet (Microsoft.Maui.Controls.BindableProperty,object,object,bool,bool) void Microsoft.Maui.Controls.Element:OnChildAdded (Microsoft.Maui.Controls.Element) void Microsoft.Maui.Controls.Element:OnDescendantAdded (Microsoft.Maui.Controls.Element) void Microsoft.Maui.Controls.Element:OnHandlerChanged () @@ -4849,8 +5143,6 @@ Methods: void Microsoft.Maui.Controls.Element:OnParentResourcesChanged (System.Collections.Generic.IEnumerable`1>) void Microsoft.Maui.Controls.Element:OnParentSet () void Microsoft.Maui.Controls.Element:OnPropertyChanged (string) - void Microsoft.Maui.Controls.Element:OnResourceChanged (Microsoft.Maui.Controls.BindableProperty,object,Microsoft.Maui.Controls.SetterSpecificity) - void Microsoft.Maui.Controls.Element:OnResourcesChanged (object,Microsoft.Maui.Controls.Internals.ResourcesChangedEventArgs) void Microsoft.Maui.Controls.Element:OnResourcesChanged (System.Collections.Generic.IEnumerable`1>) void Microsoft.Maui.Controls.Element:OnSetDynamicResource (Microsoft.Maui.Controls.BindableProperty,string,Microsoft.Maui.Controls.SetterSpecificity) void Microsoft.Maui.Controls.Element:RemapForControls () @@ -4863,16 +5155,15 @@ Methods: void Microsoft.Maui.Controls.Element:SetHandler (Microsoft.Maui.IElementHandler) void Microsoft.Maui.Controls.Element:SetParent (Microsoft.Maui.Controls.Element) void Microsoft.Maui.Controls.Element:SetupChildren () - void Microsoft.Maui.Controls.Element:UpdateHandlerValue (string) - void Microsoft.Maui.Controls.Element/d__101`1:.ctor (int) - void Microsoft.Maui.Controls.Element/d__101`1:System.IDisposable.Dispose () + void Microsoft.Maui.Controls.Element:UpdateHandlerValue (string,bool) + void Microsoft.Maui.Controls.Element/d__103`1:.ctor (int) + void Microsoft.Maui.Controls.Element/d__103`1:System.IDisposable.Dispose () void Microsoft.Maui.Controls.Entry:.cctor () void Microsoft.Maui.Controls.Entry:RemapForControls () void Microsoft.Maui.Controls.FlyoutPage:.cctor () void Microsoft.Maui.Controls.FlyoutPage:RemapForControls () void Microsoft.Maui.Controls.FontElement:.cctor () void Microsoft.Maui.Controls.FontElement:OnFontAttributesChanged (Microsoft.Maui.Controls.BindableObject,object,object) - void Microsoft.Maui.Controls.FontElement:OnFontFamilyChanged (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.Grid:.cctor () void Microsoft.Maui.Controls.Grid:.ctor () void Microsoft.Maui.Controls.Grid/<>c:.cctor () @@ -4915,8 +5206,6 @@ Methods: void Microsoft.Maui.Controls.Label:HandleFontChanged () void Microsoft.Maui.Controls.Label:InvalidateMeasureIfLabelSizeable () void Microsoft.Maui.Controls.Label:Microsoft.Maui.Controls.Internals.IFontElement.OnFontAttributesChanged (Microsoft.Maui.Controls.FontAttributes,Microsoft.Maui.Controls.FontAttributes) - void Microsoft.Maui.Controls.Label:Microsoft.Maui.Controls.Internals.IFontElement.OnFontFamilyChanged (string,string) - void Microsoft.Maui.Controls.Label:Microsoft.Maui.Controls.ITextElement.OnTextColorPropertyChanged (Microsoft.Maui.Graphics.Color,Microsoft.Maui.Graphics.Color) void Microsoft.Maui.Controls.Label:OnTextPropertyChanged (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.Label:RemapForControls () void Microsoft.Maui.Controls.Label:set_FontAttributes (Microsoft.Maui.Controls.FontAttributes) @@ -4948,12 +5237,8 @@ Methods: void Microsoft.Maui.Controls.MenuItemTracker`1:UntrackTarget (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.MergedStyle:.cctor () void Microsoft.Maui.Controls.MergedStyle:.ctor (System.Type,Microsoft.Maui.Controls.BindableObject) - void Microsoft.Maui.Controls.MergedStyle:b__31_0 (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.MergedStyle:Apply (Microsoft.Maui.Controls.BindableObject) - void Microsoft.Maui.Controls.MergedStyle:OnImplicitStyleChanged () void Microsoft.Maui.Controls.MergedStyle:RegisterImplicitStyles () - void Microsoft.Maui.Controls.MergedStyle:set_ImplicitStyle (Microsoft.Maui.Controls.IStyle) - void Microsoft.Maui.Controls.MergedStyle:SetStyle (Microsoft.Maui.Controls.IStyle,System.Collections.Generic.IList`1,Microsoft.Maui.Controls.IStyle) void Microsoft.Maui.Controls.MessagingCenter:.cctor () void Microsoft.Maui.Controls.MessagingCenter:.ctor () void Microsoft.Maui.Controls.MessagingCenter:InnerSubscribe (object,string,System.Type,System.Type,object,System.Reflection.MethodInfo,Microsoft.Maui.Controls.MessagingCenter/Filter) @@ -4968,8 +5253,6 @@ Methods: void Microsoft.Maui.Controls.NavigableElement:.ctor () void Microsoft.Maui.Controls.NavigableElement:OnParentSet () void Microsoft.Maui.Controls.NavigableElement:set_Navigation (Microsoft.Maui.Controls.INavigation) - void Microsoft.Maui.Controls.NavigableElement/<>c:.cctor () - void Microsoft.Maui.Controls.NavigableElement/<>c:.ctor () void Microsoft.Maui.Controls.NavigatingStepRequestList:.ctor () void Microsoft.Maui.Controls.NavigationPage:.cctor () void Microsoft.Maui.Controls.NavigationPage/<>c:.cctor () @@ -4980,17 +5263,16 @@ Methods: void Microsoft.Maui.Controls.Page:add_Appearing (System.EventHandler) void Microsoft.Maui.Controls.Page:add_NavigatedTo (System.EventHandler`1) void Microsoft.Maui.Controls.Page:InternalChildrenOnCollectionChanged (object,System.Collections.Specialized.NotifyCollectionChangedEventArgs) - void Microsoft.Maui.Controls.Page:LayoutChildren (double,double,double,double) void Microsoft.Maui.Controls.Page:OnAppearing () void Microsoft.Maui.Controls.Page:OnChildMeasureInvalidated (Microsoft.Maui.Controls.VisualElement,Microsoft.Maui.Controls.Internals.InvalidationTrigger) void Microsoft.Maui.Controls.Page:OnChildMeasureInvalidated (object,System.EventArgs) + void Microsoft.Maui.Controls.Page:OnChildMeasureInvalidatedInternal (Microsoft.Maui.Controls.VisualElement,Microsoft.Maui.Controls.Internals.InvalidationTrigger) void Microsoft.Maui.Controls.Page:OnParentSet () void Microsoft.Maui.Controls.Page:OnSizeAllocated (double,double) void Microsoft.Maui.Controls.Page:remove_NavigatedFrom (System.EventHandler`1) void Microsoft.Maui.Controls.Page:SendAppearing () void Microsoft.Maui.Controls.Page:set_MenuBarItems (System.Collections.Generic.IList`1) void Microsoft.Maui.Controls.Page:set_ToolbarItems (System.Collections.Generic.IList`1) - void Microsoft.Maui.Controls.Page:UpdateChildrenLayout () void Microsoft.Maui.Controls.Page/<>c:.cctor () void Microsoft.Maui.Controls.Page/<>c:.ctor () void Microsoft.Maui.Controls.ParentChangingEventArgs:.ctor (Microsoft.Maui.Controls.Element,Microsoft.Maui.Controls.Element) @@ -5022,19 +5304,22 @@ Methods: void Microsoft.Maui.Controls.Platform.GesturePlatformManager:UpdateIsEnabled () void Microsoft.Maui.Controls.Platform.GesturePlatformManager:UpdatePointer () void Microsoft.Maui.Controls.Platform.ModalNavigationManager:.ctor (Microsoft.Maui.Controls.Window) - void Microsoft.Maui.Controls.Platform.ModalNavigationManager:<.ctor>b__32_0 (object,System.ComponentModel.PropertyChangedEventArgs) - void Microsoft.Maui.Controls.Platform.ModalNavigationManager:b__31_0 (object,System.EventArgs) + void Microsoft.Maui.Controls.Platform.ModalNavigationManager:<.ctor>b__36_0 (object,System.ComponentModel.PropertyChangedEventArgs) + void Microsoft.Maui.Controls.Platform.ModalNavigationManager:b__35_0 (object,System.EventArgs) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:DisconnectPlatformPageWatchingForLoaded () void Microsoft.Maui.Controls.Platform.ModalNavigationManager:InitializePlatform () void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnCurrentPageHandlerChanged (object,System.EventArgs) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnCurrentPlatformPageLoaded (object,System.EventArgs) + void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnPlatformWindowHandlerChanging (object,Microsoft.Maui.Controls.HandlerChangingEventArgs) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnWindowHandlerChanging (object,Microsoft.Maui.Controls.HandlerChangingEventArgs) + void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnWindowPropertyChanging (object,Microsoft.Maui.Controls.PropertyChangingEventArgs) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:SettingNewPage () void Microsoft.Maui.Controls.Platform.ModalNavigationManager:SyncModalStackWhenPlatformIsReady (string) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:SyncPlatformModalStack (string) - void Microsoft.Maui.Controls.Platform.ModalNavigationManager/<>c__DisplayClass50_0:b__1 () - void Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__50:MoveNext () - void Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__41:MoveNext () + void Microsoft.Maui.Controls.Platform.ModalNavigationManager/<>c__DisplayClass55_0:b__1 () + void Microsoft.Maui.Controls.Platform.ModalNavigationManager/<>c__DisplayClass55_1:b__2 () + void Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__55:MoveNext () + void Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__45:MoveNext () void Microsoft.Maui.Controls.Platform.SemanticExtensions:AddOrRemoveControlsAccessibilityDelegate (Microsoft.Maui.Controls.View) void Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific.Application:.cctor () void Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific.Entry:.cctor () @@ -5044,38 +5329,35 @@ Methods: void Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific.WebView:.cctor () void Microsoft.Maui.Controls.PointerGestureRecognizer:.cctor () void Microsoft.Maui.Controls.PointerGestureRecognizer:SetupForPointerOverVSM (Microsoft.Maui.Controls.VisualElement,System.Action`1,Microsoft.Maui.Controls.PointerGestureRecognizer&) + void Microsoft.Maui.Controls.PropertyChangingEventArgs:.ctor (string) void Microsoft.Maui.Controls.RadioButton:.cctor () void Microsoft.Maui.Controls.RadioButton:RemapForControls () void Microsoft.Maui.Controls.RadioButton/<>c:.cctor () void Microsoft.Maui.Controls.RadioButton/<>c:.ctor () void Microsoft.Maui.Controls.RefreshView:.cctor () void Microsoft.Maui.Controls.RefreshView:RemapForControls () - void Microsoft.Maui.Controls.RefreshView/<>c:.cctor () - void Microsoft.Maui.Controls.RefreshView/<>c:.ctor () void Microsoft.Maui.Controls.ResourceDictionary:.cctor () void Microsoft.Maui.Controls.ResourceDictionary:.ctor () - void Microsoft.Maui.Controls.ResourceDictionary:Add (Microsoft.Maui.Controls.Style) - void Microsoft.Maui.Controls.ResourceDictionary:Add (string,object) void Microsoft.Maui.Controls.ResourceDictionary:add_ValuesChanged (System.EventHandler`1) void Microsoft.Maui.Controls.ResourceDictionary:Microsoft.Maui.Controls.Internals.IResourceDictionary.add_ValuesChanged (System.EventHandler`1) void Microsoft.Maui.Controls.ResourceDictionary:OnValueChanged (string,object) void Microsoft.Maui.Controls.ResourceDictionary:OnValuesChanged (System.Collections.Generic.KeyValuePair`2[]) void Microsoft.Maui.Controls.ResourceDictionary:set_Item (string,object) - void Microsoft.Maui.Controls.ResourceDictionary/d__42:.ctor (int) - void Microsoft.Maui.Controls.ResourceDictionary/d__42:<>m__Finally3 () - void Microsoft.Maui.Controls.ResourceDictionary/d__42:System.IDisposable.Dispose () + void Microsoft.Maui.Controls.ResourceDictionary/d__46:.ctor (int) + void Microsoft.Maui.Controls.ResourceDictionary/d__46:<>m__Finally3 () + void Microsoft.Maui.Controls.ResourceDictionary/d__46:System.IDisposable.Dispose () void Microsoft.Maui.Controls.RowDefinitionCollection:.ctor () void Microsoft.Maui.Controls.ScrollView:.cctor () void Microsoft.Maui.Controls.ScrollView:RemapForControls () void Microsoft.Maui.Controls.SearchBar:.cctor () void Microsoft.Maui.Controls.SearchBar:RemapForControls () void Microsoft.Maui.Controls.SemanticProperties:.cctor () - void Microsoft.Maui.Controls.Setter:Apply (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.SetterSpecificity) void Microsoft.Maui.Controls.SetterSpecificity:.cctor () - void Microsoft.Maui.Controls.SetterSpecificity:.ctor (int,int,int,int,int,int,int,int) - void Microsoft.Maui.Controls.SetterSpecificity:.ctor (int,int,int,int) - void Microsoft.Maui.Controls.SetterSpecificityList:set_Item (Microsoft.Maui.Controls.SetterSpecificity,object) - void Microsoft.Maui.Controls.SetterSpecificityList:SetValue (Microsoft.Maui.Controls.SetterSpecificity,object) + void Microsoft.Maui.Controls.SetterSpecificity:.ctor (byte,uint16,byte,byte,uint16,byte,byte,byte) + void Microsoft.Maui.Controls.SetterSpecificity:.ctor (ulong) + void Microsoft.Maui.Controls.SetterSpecificityList`1:.ctor () + void Microsoft.Maui.Controls.SetterSpecificityList`1:.ctor (int) + void Microsoft.Maui.Controls.SetterSpecificityList`1:set_Item (Microsoft.Maui.Controls.SetterSpecificity,object) void Microsoft.Maui.Controls.Shapes.Shape:.cctor () void Microsoft.Maui.Controls.Shapes.Shape:RemapForControls () void Microsoft.Maui.Controls.Shapes.Shape/<>c:.cctor () @@ -5085,13 +5367,13 @@ Methods: void Microsoft.Maui.Controls.Shell/<>c:.ctor () void Microsoft.Maui.Controls.SolidColorBrush:.cctor () void Microsoft.Maui.Controls.SolidColorBrush:.ctor () - void Microsoft.Maui.Controls.SolidColorBrush:.ctor (Microsoft.Maui.Graphics.Color) - void Microsoft.Maui.Controls.SolidColorBrush:set_Color (Microsoft.Maui.Graphics.Color) void Microsoft.Maui.Controls.Style:.ctor (System.Type) - void Microsoft.Maui.Controls.Style:ApplyCore (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.Style,Microsoft.Maui.Controls.SetterSpecificity) - void Microsoft.Maui.Controls.Style:Microsoft.Maui.Controls.IStyle.Apply (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.SetterSpecificity) void Microsoft.Maui.Controls.Style:set_BasedOn (Microsoft.Maui.Controls.Style) void Microsoft.Maui.Controls.Style:set_BaseResourceKey (string) + void Microsoft.Maui.Controls.StyleableElement:.cctor () + void Microsoft.Maui.Controls.StyleableElement:.ctor () + void Microsoft.Maui.Controls.StyleableElement/<>c:.cctor () + void Microsoft.Maui.Controls.StyleableElement/<>c:.ctor () void Microsoft.Maui.Controls.StyleSheets.StyleSheetExtensions/d__0:.ctor (int) void Microsoft.Maui.Controls.StyleSheets.StyleSheetExtensions/d__0:System.IDisposable.Dispose () void Microsoft.Maui.Controls.SwipeView:.cctor () @@ -5105,12 +5387,10 @@ Methods: void Microsoft.Maui.Controls.TemplateUtilities:OnContentChanged (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.TextAlignmentElement:.cctor () void Microsoft.Maui.Controls.TextElement:.cctor () - void Microsoft.Maui.Controls.TextElement:OnTextColorPropertyChanged (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.TimePicker:.cctor () void Microsoft.Maui.Controls.TimePicker:RemapForControls () void Microsoft.Maui.Controls.TimePicker/<>c:.cctor () void Microsoft.Maui.Controls.TimePicker/<>c:.ctor () - void Microsoft.Maui.Controls.Toolbar:.cctor () void Microsoft.Maui.Controls.Toolbar:RemapForControls () void Microsoft.Maui.Controls.ToolTipProperties:.cctor () void Microsoft.Maui.Controls.View:.cctor () @@ -5126,7 +5406,6 @@ Methods: void Microsoft.Maui.Controls.VisualElement:.ctor () void Microsoft.Maui.Controls.VisualElement:add__platformContainerViewChanged (System.EventHandler) void Microsoft.Maui.Controls.VisualElement:add__windowChanged (System.EventHandler) - void Microsoft.Maui.Controls.VisualElement:add_MeasureInvalidated (System.EventHandler) void Microsoft.Maui.Controls.VisualElement:BatchCommit () void Microsoft.Maui.Controls.VisualElement:ComputeConstrainsForChildren () void Microsoft.Maui.Controls.VisualElement:InvalidateMeasureInternal (Microsoft.Maui.Controls.Internals.InvalidationTrigger) @@ -5165,7 +5444,7 @@ Methods: void Microsoft.Maui.Controls.VisualElement:SetEffectiveFlowDirection (Microsoft.Maui.Controls.EffectiveFlowDirection,bool) void Microsoft.Maui.Controls.VisualElement:SizeAllocated (double,double) void Microsoft.Maui.Controls.VisualElement:UpdateBoundsComponents (Microsoft.Maui.Graphics.Rect) - void Microsoft.Maui.Controls.VisualElement:UpdateHandlerValue (string) + void Microsoft.Maui.Controls.VisualElement:UpdateHandlerValue (string,bool) void Microsoft.Maui.Controls.VisualElement:UpdatePlatformUnloadedLoadedWiring (Microsoft.Maui.Controls.Window,Microsoft.Maui.Controls.Window) void Microsoft.Maui.Controls.VisualElement:UpdateSemanticsFromMapper () void Microsoft.Maui.Controls.VisualElement/<>c:.cctor () @@ -5186,7 +5465,6 @@ Methods: void Microsoft.Maui.Controls.Window:.ctor (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.Window:add_Activated (System.EventHandler) void Microsoft.Maui.Controls.Window:add_Destroying (System.EventHandler) - void Microsoft.Maui.Controls.Window:add_Resumed (System.EventHandler) void Microsoft.Maui.Controls.Window:FinishedAddingWindowToApplication (Microsoft.Maui.Controls.Application) void Microsoft.Maui.Controls.Window:MapWindowSoftInputModeAdjust (Microsoft.Maui.Handlers.IWindowHandler,Microsoft.Maui.IWindow) void Microsoft.Maui.Controls.Window:Microsoft.Maui.Controls.IFlowDirectionController.set_EffectiveFlowDirection (Microsoft.Maui.Controls.EffectiveFlowDirection) @@ -5207,20 +5485,13 @@ Methods: void Microsoft.Maui.Controls.Window:set_IsActivated (bool) void Microsoft.Maui.Controls.Window:set_Page (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.Window:SetEffectiveFlowDirection (Microsoft.Maui.Controls.EffectiveFlowDirection,bool) - void Microsoft.Maui.Controls.Window:UpdateHandlerValue (string) + void Microsoft.Maui.Controls.Window:UpdateHandlerValue (string,bool) void Microsoft.Maui.Controls.Window/<>c:.cctor () void Microsoft.Maui.Controls.Window/<>c:.ctor () - void Microsoft.Maui.Controls.Window/<>c:<.cctor>b__220_0 (Microsoft.Maui.Controls.BindableObject,object,object) + void Microsoft.Maui.Controls.Window/<>c:<.cctor>b__224_0 (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.Window/NavigationImpl:.ctor (Microsoft.Maui.Controls.Window) - void Microsoft.Maui.Controls.Xaml.Internals.SimpleValueTargetProvider:.ctor (object[],object,Microsoft.Maui.Controls.Internals.INameScope[],bool) - void Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider:.ctor () - void Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider:Add (System.Type,object) - void Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider:set_IValueConverterProvider (Microsoft.Maui.Controls.Xaml.IValueConverterProvider) - void Microsoft.Maui.Controls.Xaml.Internals.XamlTypeResolver:.ctor (System.Xml.IXmlNamespaceResolver,Microsoft.Maui.Controls.Xaml.Internals.XamlTypeResolver/GetTypeFromXmlName,System.Reflection.Assembly) - void Microsoft.Maui.Controls.Xaml.Internals.XamlTypeResolver:.ctor (System.Xml.IXmlNamespaceResolver,System.Reflection.Assembly) - void Microsoft.Maui.Controls.Xaml.Internals.XmlNamespaceResolver:.ctor () - void Microsoft.Maui.Controls.Xaml.Internals.XmlNamespaceResolver:Add (string,string) - void Microsoft.Maui.Controls.Xaml.XmlLineInfo:.ctor (int,int) + void Microsoft.Maui.Controls.Xaml.:.cctor () + void Microsoft.Maui.Controls.Xaml.ResourceDictionaryHotReloadHelper:Init () void Microsoft.Maui.Devices.DeviceIdiom:.cctor () void Microsoft.Maui.Devices.DeviceIdiom:.ctor (string) void Microsoft.Maui.Dispatching.Dispatcher:.ctor (Android.OS.Looper) @@ -5287,6 +5558,7 @@ Methods: void Microsoft.Maui.Handlers.AndroidBatchPropertyMapper`2:.ctor (Microsoft.Maui.IPropertyMapper[]) void Microsoft.Maui.Handlers.ApplicationHandler:.cctor () void Microsoft.Maui.Handlers.ApplicationHandler:.ctor () + void Microsoft.Maui.Handlers.ApplicationHandler:MapAppTheme (Microsoft.Maui.Handlers.ApplicationHandler,Microsoft.Maui.IApplication) void Microsoft.Maui.Handlers.ButtonHandler:.cctor () void Microsoft.Maui.Handlers.CheckBoxHandler:.cctor () void Microsoft.Maui.Handlers.ContentViewHandler:.cctor () @@ -5294,7 +5566,6 @@ Methods: void Microsoft.Maui.Handlers.ContentViewHandler:MapContent (Microsoft.Maui.Handlers.IContentViewHandler,Microsoft.Maui.IContentView) void Microsoft.Maui.Handlers.ContentViewHandler:SetVirtualView (Microsoft.Maui.IView) void Microsoft.Maui.Handlers.ContentViewHandler:UpdateContent (Microsoft.Maui.Handlers.IContentViewHandler) - void Microsoft.Maui.Handlers.DatePickerHandler:.cctor () void Microsoft.Maui.Handlers.EditorHandler:.cctor () void Microsoft.Maui.Handlers.ElementHandler:.cctor () void Microsoft.Maui.Handlers.ElementHandler:.ctor (Microsoft.Maui.IPropertyMapper,Microsoft.Maui.CommandMapper) @@ -5309,19 +5580,15 @@ Methods: void Microsoft.Maui.Handlers.EntryHandler:.cctor () void Microsoft.Maui.Handlers.FlyoutViewHandler:.cctor () void Microsoft.Maui.Handlers.LabelHandler:.cctor () - void Microsoft.Maui.Handlers.NavigationViewHandler:.cctor () void Microsoft.Maui.Handlers.PageHandler:.cctor () void Microsoft.Maui.Handlers.PageHandler:.ctor () void Microsoft.Maui.Handlers.PageHandler:MapTitle (Microsoft.Maui.Handlers.IPageHandler,Microsoft.Maui.IContentView) void Microsoft.Maui.Handlers.PickerHandler:.cctor () void Microsoft.Maui.Handlers.RadioButtonHandler:.cctor () - void Microsoft.Maui.Handlers.RefreshViewHandler:.cctor () - void Microsoft.Maui.Handlers.ScrollViewHandler:.cctor () void Microsoft.Maui.Handlers.SearchBarHandler:.cctor () void Microsoft.Maui.Handlers.ShapeViewHandler:.cctor () void Microsoft.Maui.Handlers.SwipeViewHandler:.cctor () void Microsoft.Maui.Handlers.TabbedViewHandler:.cctor () - void Microsoft.Maui.Handlers.TimePickerHandler:.cctor () void Microsoft.Maui.Handlers.ToolbarHandler:.cctor () void Microsoft.Maui.Handlers.ViewHandler:.cctor () void Microsoft.Maui.Handlers.ViewHandler:.ctor (Microsoft.Maui.IPropertyMapper,Microsoft.Maui.CommandMapper) @@ -5390,22 +5657,26 @@ Methods: void Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/<>c:.cctor () void Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/<>c:.ctor () void Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/HandlerRegistration:AddRegistration (Microsoft.Maui.Hosting.IMauiHandlersCollection) + void Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/HandlerServiceBuilder:.ctor (System.Collections.Generic.IEnumerable`1) void Microsoft.Maui.Hosting.ImageSourcesMauiAppBuilderExtensions/<>c:.cctor () void Microsoft.Maui.Hosting.ImageSourcesMauiAppBuilderExtensions/<>c:.ctor () void Microsoft.Maui.Hosting.Internal.FontCollection:.ctor () void Microsoft.Maui.Hosting.Internal.FontCollection:Add (Microsoft.Maui.Hosting.FontDescriptor) - void Microsoft.Maui.Hosting.Internal.MauiFactory:.cctor () void Microsoft.Maui.Hosting.Internal.MauiFactory:.ctor (Microsoft.Maui.Hosting.IMauiServiceCollection) - void Microsoft.Maui.Hosting.Internal.MauiHandlersCollection:.ctor () - void Microsoft.Maui.Hosting.Internal.MauiHandlersFactory:.ctor (System.Collections.Generic.IEnumerable`1) + void Microsoft.Maui.Hosting.Internal.MauiHandlersFactory:.ctor (Microsoft.Maui.Hosting.IMauiHandlersCollection) void Microsoft.Maui.Hosting.Internal.MauiServiceCollection:.ctor () void Microsoft.Maui.Hosting.Internal.MauiServiceCollection:Add (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:.cctor () + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:.ctor () + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:Add (System.Type) + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet/<>c:.cctor () + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet/<>c:.ctor () void Microsoft.Maui.Hosting.MauiAppBuilder:.ctor (bool) void Microsoft.Maui.Hosting.MauiAppBuilder:ConfigureDefaultLogging () void Microsoft.Maui.Hosting.MauiAppBuilder/<>c:.cctor () void Microsoft.Maui.Hosting.MauiAppBuilder/<>c:.ctor () + void Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions:RegisterHandlerServiceType (Microsoft.Maui.Hosting.IMauiHandlersCollection,System.Type) void Microsoft.Maui.HotReload.MauiHotReloadHelper:.cctor () - void Microsoft.Maui.HotReload.MauiHotReloadHelper:RegisterHandlers (Microsoft.Maui.Hosting.IMauiHandlersCollection) void Microsoft.Maui.Layouts.GridLayoutManager/Definition:.ctor (Microsoft.Maui.GridLength) void Microsoft.Maui.Layouts.GridLayoutManager/Definition:set_Size (double) void Microsoft.Maui.Layouts.GridLayoutManager/GridStructure:.ctor (Microsoft.Maui.IGridLayout,double,double) @@ -5472,6 +5743,7 @@ Methods: void Microsoft.Maui.Platform.ActivityExtensions:UpdateX (Android.App.Activity,Microsoft.Maui.IWindow) void Microsoft.Maui.Platform.ActivityExtensions:UpdateY (Android.App.Activity,Microsoft.Maui.IWindow) void Microsoft.Maui.Platform.ApplicationExtensions:CreatePlatformWindow (Android.App.Activity,Microsoft.Maui.IApplication,Android.OS.Bundle) + void Microsoft.Maui.Platform.ApplicationExtensions:UpdateNightMode (Microsoft.Maui.IApplication) void Microsoft.Maui.Platform.ContentViewGroup:.ctor (Android.Content.Context) void Microsoft.Maui.Platform.ContentViewGroup:OnLayout (bool,int,int,int,int) void Microsoft.Maui.Platform.ContentViewGroup:OnMeasure (int,int) @@ -5543,6 +5815,7 @@ Methods: void Microsoft.Maui.PropertyMapperExtensions/<>c__DisplayClass1_0`2:g__newMethod|0 (Microsoft.Maui.IElementHandler,Microsoft.Maui.IElement) void Microsoft.Maui.PropertyMapperExtensions/<>c__DisplayClass2_0`2:b__0 (Microsoft.Maui.Handlers.ApplicationHandler,Microsoft.Maui.Controls.Application,System.Action`2) void Microsoft.Maui.PropertyMapperExtensions/<>c__DisplayClass4_0`2:b__0 (Microsoft.Maui.IElementHandler,Microsoft.Maui.IElement,System.Action`2) + void Microsoft.Maui.Storage.FileProvider:.ctor () void Microsoft.Maui.TaskExtensions:FireAndForget (System.Threading.Tasks.Task,Microsoft.Extensions.Logging.ILogger,string) void Microsoft.Maui.TaskExtensions:FireAndForget (System.Threading.Tasks.Task,System.Action`1) void Microsoft.Maui.TaskExtensions/d__1:MoveNext () @@ -5557,15 +5830,15 @@ Methods: void Microsoft.Maui.ViewHandlerExtensions:PlatformArrangeHandler (Microsoft.Maui.IViewHandler,Microsoft.Maui.Graphics.Rect) void Microsoft.Maui.VisualDiagnostics:.cctor () void Microsoft.Maui.VisualDiagnostics:OnChildAdded (Microsoft.Maui.IVisualTreeElement,Microsoft.Maui.IVisualTreeElement) + void Microsoft.Maui.VisualDiagnostics/<>c:.cctor () + void Microsoft.Maui.VisualDiagnostics/<>c:.ctor () void Microsoft.Maui.VisualDiagnosticsOverlay:.ctor (Microsoft.Maui.IWindow) void Microsoft.Maui.VisualDiagnosticsOverlay:HandleUIChange () void Microsoft.Maui.WeakEventManager:.ctor () void Microsoft.Maui.WeakEventManager:AddEventHandler (string,object,System.Reflection.MethodInfo) void Microsoft.Maui.WeakEventManager:AddEventHandler (System.Delegate,string) void Microsoft.Maui.WeakEventManager/Subscription:.ctor (System.WeakReference,System.Reflection.MethodInfo) - void Microsoft.Maui.WeakList`1:.ctor () - void Microsoft.Maui.WeakList`1:Add (Microsoft.Maui.Controls.BindableObject) - void Microsoft.Maui.WeakList`1:CleanupIfNeeded () + void Microsoft.Maui.WeakList`1:.ctor () void Microsoft.Maui.WindowExtensions:UpdateTitle (Android.App.Activity,Microsoft.Maui.IWindow) void Microsoft.Maui.WindowExtensions:UpdateWindowSoftInputModeAdjust (Microsoft.Maui.IWindow,Android.Views.SoftInput) void Microsoft.Maui.WindowOverlay:.ctor (Microsoft.Maui.IWindow) @@ -5577,17 +5850,22 @@ Methods: void Microsoft.Win32.SafeHandles.SafeWaitHandle:.ctor () void modreq Microsoft.AspNetCore.Components.Reflection.PropertySetter:set_AcceptsCascadingParameters (System.Runtime.CompilerServices.IsExternalInit) Microsoft.AspNetCore.Components.Reflection.PropertySetter:set_AcceptsCascadingParameters (bool) void modreq Microsoft.AspNetCore.Components.Reflection.PropertySetter:set_AcceptsDirectParameters (System.Runtime.CompilerServices.IsExternalInit) Microsoft.AspNetCore.Components.Reflection.PropertySetter:set_AcceptsDirectParameters (bool) + void modreq System.Diagnostics.Metrics.InstrumentAdvice`1:set_HistogramBucketBoundaries (System.Runtime.CompilerServices.IsExternalInit) System.Diagnostics.Metrics.InstrumentAdvice`1:set_HistogramBucketBoundaries (System.Collections.Generic.IReadOnlyList`1) void modreq System.Text.Json.Serialization.JsonConverter:set_ConverterStrategy (System.Runtime.CompilerServices.IsExternalInit) System.Text.Json.Serialization.JsonConverter:set_ConverterStrategy (System.Text.Json.ConverterStrategy) + void modreq System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_IsForTypeInfo (System.Runtime.CompilerServices.IsExternalInit) System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_IsForTypeInfo (bool) void Mono.RuntimeGPtrArrayHandle:DestroyAndFree (Mono.RuntimeGPtrArrayHandle&) void Mono.RuntimeGPtrArrayHandle:GPtrArrayFree (Mono.RuntimeStructs/GPtrArray*) void Mono.SafeGPtrArrayHandle:Dispose () void Mono.SafeStringMarshal:Dispose () void Mono.SafeStringMarshal:GFree (intptr) - void System.AppContext:Setup (char**,char**,int) + void System.AppContext:Setup (char**,uint*,char**,uint*,int) + void System.ArgumentException:.ctor (string,string) void System.ArgumentException:ThrowIfNullOrEmpty (string,string) void System.ArgumentException:ThrowIfNullOrWhiteSpace (string,string) + void System.ArgumentNullException:.ctor (string) void System.ArgumentOutOfRangeException:ThrowIfGreaterThan (int,int,string) void System.ArgumentOutOfRangeException:ThrowIfGreaterThan (long,long,string) + void System.ArgumentOutOfRangeException:ThrowIfGreaterThan (uint,uint,string) void System.ArgumentOutOfRangeException:ThrowIfLessThan (int,int,string) void System.ArgumentOutOfRangeException:ThrowIfLessThan (long,long,string) void System.ArgumentOutOfRangeException:ThrowIfNegative (int,string) @@ -5601,6 +5879,7 @@ Methods: void System.Array:CopySlow (System.Array,int,System.Array,int,int,bool) void System.Array:CopyTo (System.Array,int) void System.Array:GetValueImpl (System.Runtime.CompilerServices.ObjectHandleOnStack,System.Runtime.CompilerServices.ObjectHandleOnStack,int) + void System.Array:InternalArray__ICollection_CopyTo (double[],int) void System.Array:InternalArray__ICollection_CopyTo (Microsoft.AspNetCore.Components.ICascadingValueSupplier[],int) void System.Array:InternalCreate (System.Array&,intptr,int,int*,int*) void System.Array:InternalSetValue (object,intptr) @@ -5621,12 +5900,15 @@ Methods: void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () - void System.Array/EmptyArray`1>:.cctor () void System.Array/EmptyArray`1>>:.cctor () void System.Array/EmptyArray`1>:.cctor () + void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () + void System.Array/EmptyArray`1:.cctor () + void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () + void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () void System.ArrayEnumerator:.ctor (System.Array) @@ -5636,7 +5918,6 @@ Methods: void System.ArraySegment`1:.cctor () void System.ArraySegment`1:.ctor (System.Text.Json.JsonElement[],int,int) void System.ArraySegment`1:.ctor (System.Text.Json.JsonElement[]) - void System.AttributeUsageAttribute:.cctor () void System.AttributeUsageAttribute:.ctor (System.AttributeTargets) void System.AttributeUsageAttribute:set_AllowMultiple (bool) void System.AttributeUsageAttribute:set_Inherited (bool) @@ -5645,7 +5926,6 @@ Methods: void System.Buffer:__ZeroMemory (void*,uintptr) void System.Buffer:_ZeroMemory (byte&,uintptr) void System.Buffer:BulkMoveWithWriteBarrier (byte&,byte&,uintptr,intptr) - void System.Buffer:Memmove (byte&,byte&,uintptr) void System.Buffers.Any4SearchValues`2:.ctor (System.ReadOnlySpan`1) void System.Buffers.Any5SearchValues`2:.ctor (System.ReadOnlySpan`1) void System.Buffers.AnyByteSearchValues:.ctor (System.ReadOnlySpan`1) @@ -5655,6 +5935,8 @@ Methods: void System.Buffers.ArrayPool`1:.ctor () void System.Buffers.ArrayPool`1:.cctor () void System.Buffers.ArrayPool`1:.ctor () + void System.Buffers.ArrayPool`1:.cctor () + void System.Buffers.ArrayPool`1:.ctor () void System.Buffers.ArrayPool`1:.cctor () void System.Buffers.ArrayPool`1:.ctor () void System.Buffers.ArrayPool`1:.cctor () @@ -5665,11 +5947,13 @@ Methods: void System.Buffers.ArrayPool`1:.ctor () void System.Buffers.ArrayPoolEventSource:.cctor () void System.Buffers.ArrayPoolEventSource:.ctor () + void System.Buffers.BitmapCharSearchValues:.ctor (System.ReadOnlySpan`1,int) void System.Buffers.BitVector256:Set (int) - void System.Buffers.IndexOfAnyAsciiSearcher:ComputeBitmap256 (System.ReadOnlySpan`1,System.Runtime.Intrinsics.Vector256`1&,System.Runtime.Intrinsics.Vector256`1&,System.Buffers.BitVector256&) - void System.Buffers.Latin1CharSearchValues:.ctor (System.ReadOnlySpan`1) - void System.Buffers.ProbabilisticCharSearchValues:.ctor (System.ReadOnlySpan`1) + void System.Buffers.IndexOfAnyAsciiSearcher:ComputeAnyByteState (System.ReadOnlySpan`1,System.Buffers.IndexOfAnyAsciiSearcher/AnyByteState&) + void System.Buffers.IndexOfAnyAsciiSearcher/AnyByteState:.ctor (System.Runtime.Intrinsics.Vector128`1,System.Runtime.Intrinsics.Vector128`1,System.Buffers.BitVector256) + void System.Buffers.ProbabilisticCharSearchValues:.ctor (System.ReadOnlySpan`1,int) void System.Buffers.ProbabilisticMap:.ctor (System.ReadOnlySpan`1) + void System.Buffers.ProbabilisticMapState:.ctor (System.ReadOnlySpan`1,int) void System.Buffers.ReadOnlySequence`1:.cctor () void System.Buffers.ReadOnlySequence`1:.ctor (byte[]) void System.Buffers.SharedArrayPool`1/<>c:.cctor () @@ -5678,6 +5962,8 @@ Methods: void System.Buffers.SharedArrayPool`1/<>c:.ctor () void System.Buffers.SharedArrayPool`1/<>c:.cctor () void System.Buffers.SharedArrayPool`1/<>c:.ctor () + void System.Buffers.SharedArrayPool`1/<>c:.cctor () + void System.Buffers.SharedArrayPool`1/<>c:.ctor () void System.Buffers.SharedArrayPool`1/<>c:.cctor () void System.Buffers.SharedArrayPool`1/<>c:.ctor () void System.Buffers.SharedArrayPool`1/<>c:.cctor () @@ -5690,6 +5976,8 @@ Methods: void System.Buffers.SharedArrayPool`1:Return (Microsoft.AspNetCore.Components.RenderTree.RenderTreeEdit[],bool) void System.Buffers.SharedArrayPool`1:.ctor () void System.Buffers.SharedArrayPool`1:Return (Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame[],bool) + void System.Buffers.SharedArrayPool`1:.ctor () + void System.Buffers.SharedArrayPool`1:Return (bool[],bool) void System.Buffers.SharedArrayPool`1:.ctor () void System.Buffers.SharedArrayPool`1:Return (byte[],bool) void System.Buffers.SharedArrayPool`1:.ctor () @@ -5697,7 +5985,11 @@ Methods: void System.Buffers.SharedArrayPool`1:.ctor () void System.Buffers.SharedArrayPool`1:Return (string[],bool) void System.Buffers.SharedArrayPool`1:.ctor () + void System.Buffers.SharedArrayPoolPartitions:.ctor () + void System.Buffers.SharedArrayPoolPartitions/Partition:.ctor () + void System.Buffers.SharedArrayPoolStatics:.cctor () void System.Buffers.StandardFormat:.ctor (char,byte) + void System.CLSCompliantAttribute:.ctor (bool) void System.Collections.Concurrent.CDSCollectionETWBCLProvider:.cctor () void System.Collections.Concurrent.CDSCollectionETWBCLProvider:.ctor () void System.Collections.Concurrent.ConcurrentDictionary`2/Enumerator:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2) @@ -5708,9 +6000,10 @@ Methods: void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,Microsoft.Extensions.DependencyInjection.ServiceProvider/ServiceAccessor,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,object,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) + void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (Microsoft.Maui.Hosting.IMauiHandlersCollection,Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (long,Microsoft.JSInterop.Infrastructure.IDotNetObjectReference,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (long,object,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) - void System.Collections.Concurrent.ConcurrentDictionary`2/Node>:.ctor (string,System.Lazy`1,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node>) + void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (string,ulong,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) void System.Collections.Concurrent.ConcurrentDictionary`2/Node>>:.ctor (System.Type,System.ValueTuple`2>,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node>>) void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (ulong,System.Text.Json.JsonEncodedText,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) void System.Collections.Concurrent.ConcurrentDictionary`2/Node, System.Text.Json.Cache`1/CacheEntry>>:.ctor (System.ValueTuple`3,System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node, System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1/CacheEntry>>) @@ -5718,10 +6011,11 @@ Methods: void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) - void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2/Tables>>:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode>>[],object[],int[],System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2/Tables:.ctor (System.Collections.Concurrent.ConcurrentDictionary`2/VolatileNode[],object[],int[],System.Collections.Generic.IEqualityComparer`1) @@ -5748,6 +6042,8 @@ Methods: void System.Collections.Concurrent.ConcurrentDictionary`2:AcquirePostFirstLock (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,int&) void System.Collections.Concurrent.ConcurrentDictionary`2:GrowTable (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,bool,bool) void System.Collections.Concurrent.ConcurrentDictionary`2:ReleaseLocks (int) + void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor () + void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor (int,int,bool,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor () void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor (int,int,bool,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2:set_Item (long,Microsoft.JSInterop.Infrastructure.IDotNetObjectReference) @@ -5760,8 +6056,8 @@ Methods: void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor (System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2:set_Item (string,Microsoft.Extensions.Logging.Logger) void System.Collections.Concurrent.ConcurrentDictionary`2>:.ctor (int,int,System.Collections.Generic.IEqualityComparer`1) - void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor () - void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor (int,int,bool,System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor (int,int,bool,System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor (System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor () void System.Collections.Concurrent.ConcurrentDictionary`2:.ctor (int,int,bool,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Concurrent.ConcurrentDictionary`2:AcquireFirstLock (int&) @@ -5783,16 +6079,17 @@ Methods: void System.Collections.Concurrent.ConcurrentDictionary`2, System.Text.Json.Cache`1/CacheEntry>>:ReleaseLocks (int) void System.Collections.Concurrent.ConcurrentDictionaryTypeProps`1:.cctor () void System.Collections.Concurrent.ConcurrentDictionaryTypeProps`1:.cctor () + void System.Collections.Concurrent.ConcurrentDictionaryTypeProps`1:.cctor () void System.Collections.Concurrent.ConcurrentDictionaryTypeProps`1>>:.cctor () void System.Collections.Concurrent.ConcurrentQueue`1:.ctor () void System.Collections.Concurrent.ConcurrentQueue`1:Enqueue (object) void System.Collections.Concurrent.ConcurrentQueueSegment`1:.ctor (int) - void System.Collections.Generic.ArrayBuilder`1:Add (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree) - void System.Collections.Generic.ArrayBuilder`1:EnsureCapacity (int) - void System.Collections.Generic.ArrayBuilder`1:UncheckedAdd (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree) - void System.Collections.Generic.ArrayBuilder`1:Add (char) - void System.Collections.Generic.ArrayBuilder`1:EnsureCapacity (int) - void System.Collections.Generic.ArrayBuilder`1:UncheckedAdd (char) + void System.Collections.Frozen.EmptyFrozenDictionary`2:.ctor (System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Frozen.EmptyFrozenSet`1:.ctor (System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Frozen.FrozenDictionary`2:.cctor () + void System.Collections.Frozen.FrozenDictionary`2:.ctor (System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Frozen.FrozenSet`1:.cctor () + void System.Collections.Frozen.FrozenSet`1:.ctor (System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.ArraySortHelper`1:.cctor () void System.Collections.Generic.ArraySortHelper`1:.ctor () void System.Collections.Generic.ArraySortHelper`1:InsertionSort (System.Span`1,System.Comparison`1) @@ -5801,12 +6098,13 @@ Methods: void System.Collections.Generic.ArraySortHelper`1:Sort (System.Span`1,System.Comparison`1) void System.Collections.Generic.ArraySortHelper`1:SwapIfGreater (System.Span`1,System.Comparison`1,int,int) void System.Collections.Generic.Dictionary`2/Enumerator>:.ctor (System.Collections.Generic.Dictionary`2>,int) + void System.Collections.Generic.Dictionary`2/Enumerator:.ctor (System.Collections.Generic.Dictionary`2,int) + void System.Collections.Generic.Dictionary`2/Enumerator:.ctor (System.Collections.Generic.Dictionary`2,int) void System.Collections.Generic.Dictionary`2/Enumerator:.ctor (System.Collections.Generic.Dictionary`2,int) void System.Collections.Generic.Dictionary`2/Enumerator:.ctor (System.Collections.Generic.Dictionary`2,int) void System.Collections.Generic.Dictionary`2/Enumerator:Dispose () void System.Collections.Generic.Dictionary`2/KeyCollection>:.ctor (System.Collections.Generic.Dictionary`2>) - void System.Collections.Generic.Dictionary`2/ValueCollection:.ctor (System.Collections.Generic.Dictionary`2) - void System.Collections.Generic.Dictionary`2/ValueCollection:CopyTo (Microsoft.Maui.Controls.BindableObject/BindablePropertyContext[],int) + void System.Collections.Generic.Dictionary`2/ValueCollection:.ctor (System.Collections.Generic.Dictionary`2) void System.Collections.Generic.Dictionary`2/ValueCollection:.ctor (System.Collections.Generic.Dictionary`2) void System.Collections.Generic.Dictionary`2/ValueCollection:CopyTo (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[],int) void System.Collections.Generic.Dictionary`2:.ctor () @@ -5829,6 +6127,8 @@ Methods: void System.Collections.Generic.Dictionary`2>:Resize () void System.Collections.Generic.Dictionary`2>:Resize (int,bool) void System.Collections.Generic.Dictionary`2>:set_Item (Microsoft.Maui.Controls.BindableProperty,System.ValueTuple`2) + void System.Collections.Generic.Dictionary`2:.ctor () + void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2:.ctor () void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2:Clear () @@ -5863,12 +6163,31 @@ Methods: void System.Collections.Generic.Dictionary`2:Resize () void System.Collections.Generic.Dictionary`2:Resize (int,bool) void System.Collections.Generic.Dictionary`2:set_Item (intptr,System.IDisposable) - void System.Collections.Generic.Dictionary`2, Microsoft.AspNetCore.Components.Routing.StringSegmentAccumulator>:.ctor (int,System.Collections.Generic.IEqualityComparer`1>) - void System.Collections.Generic.Dictionary`2, Microsoft.AspNetCore.Components.Routing.StringSegmentAccumulator>:.ctor (System.Collections.Generic.IEqualityComparer`1>) + void System.Collections.Generic.Dictionary`2:.ctor () + void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Generic.Dictionary`2:set_Item (System.Linq.Expressions.Compiler.BoundConstants/TypedConstant,int) + void System.Collections.Generic.Dictionary`2:.ctor () + void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Generic.Dictionary`2:.ctor () + void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Generic.Dictionary`2:set_Item (System.Linq.Expressions.ParameterExpression,int) + void System.Collections.Generic.Dictionary`2:Clear () + void System.Collections.Generic.Dictionary`2:.ctor () + void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Generic.Dictionary`2:.ctor (int) + void System.Collections.Generic.Dictionary`2:Add (System.Linq.Expressions.ParameterExpression,System.Linq.Expressions.Compiler.VariableStorageKind) + void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Generic.Dictionary`2:.ctor (System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Generic.Dictionary`2:.ctor () + void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Generic.Dictionary`2:Add (System.Reflection.MemberInfo,System.Reflection.NullabilityState) + void System.Collections.Generic.Dictionary`2:.ctor () + void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2:.ctor (System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2>:set_Item (string,System.Action`2) void System.Collections.Generic.Dictionary`2:.ctor () void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) + void System.Collections.Generic.Dictionary`2:.ctor (int) void System.Collections.Generic.Dictionary`2:.ctor (System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2:Add (string,int) void System.Collections.Generic.Dictionary`2:Clear () @@ -5903,7 +6222,7 @@ Methods: void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2>:.ctor () void System.Collections.Generic.Dictionary`2>:.ctor (int,System.Collections.Generic.IEqualityComparer`1) - void System.Collections.Generic.GenericComparer`1:.ctor () + void System.Collections.Generic.GenericComparer`1:.ctor () void System.Collections.Generic.GenericComparer`1:.ctor () void System.Collections.Generic.GenericEqualityComparer`1:.ctor () void System.Collections.Generic.GenericEqualityComparer`1:.ctor () @@ -5911,28 +6230,22 @@ Methods: void System.Collections.Generic.GenericEqualityComparer`1:.ctor () void System.Collections.Generic.GenericEqualityComparer`1:.ctor () void System.Collections.Generic.GenericEqualityComparer`1:.ctor () - void System.Collections.Generic.GenericEqualityComparer`1>:.ctor () void System.Collections.Generic.GenericEqualityComparer`1>:.ctor () - void System.Collections.Generic.HashSet`1/Enumerator:.ctor (System.Collections.Generic.HashSet`1) void System.Collections.Generic.HashSet`1/Enumerator:Dispose () + void System.Collections.Generic.HashSet`1/Enumerator:.ctor (System.Collections.Generic.HashSet`1) + void System.Collections.Generic.HashSet`1:.ctor () void System.Collections.Generic.HashSet`1:.ctor (System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.HashSet`1:Resize () void System.Collections.Generic.HashSet`1:Resize (int,bool) - void System.Collections.Generic.HashSet`1:.ctor () void System.Collections.Generic.KeyValuePair`2:Deconstruct (string&,Microsoft.AspNetCore.Components.WebView.WebViewManager/RootComponent&) - void System.Collections.Generic.LargeArrayBuilder`1:AddRange (System.Collections.Generic.IEnumerable`1) - void System.Collections.Generic.LargeArrayBuilder`1:AddRange (System.Collections.Generic.IEnumerable`1) - void System.Collections.Generic.List`1/Enumerator:.ctor (System.Collections.Generic.List`1) - void System.Collections.Generic.List`1/Enumerator:Dispose () void System.Collections.Generic.List`1/Enumerator:.ctor (System.Collections.Generic.List`1) void System.Collections.Generic.List`1/Enumerator:Dispose () - void System.Collections.Generic.List`1/Enumerator>:.ctor (System.Collections.Generic.List`1>) - void System.Collections.Generic.List`1/Enumerator>:.ctor (System.Collections.Generic.List`1>) void System.Collections.Generic.List`1/Enumerator>:.ctor (System.Collections.Generic.List`1>) void System.Collections.Generic.List`1:.cctor () void System.Collections.Generic.List`1:.ctor () void System.Collections.Generic.List`1:.cctor () void System.Collections.Generic.List`1:.cctor () + void System.Collections.Generic.List`1:GrowForInsertion (int,int) void System.Collections.Generic.List`1:Insert (int,Microsoft.AspNetCore.Components.WebView.Maui.RootComponent) void System.Collections.Generic.List`1:Sort (System.Comparison`1) void System.Collections.Generic.List`1:.cctor () @@ -5952,12 +6265,10 @@ Methods: void System.Collections.Generic.List`1:AddWithResize (Microsoft.Maui.Controls.DependencyService/DependencyType) void System.Collections.Generic.List`1:Grow (int) void System.Collections.Generic.List`1:set_Capacity (int) + void System.Collections.Generic.List`1:Add (Microsoft.Maui.Controls.Element) void System.Collections.Generic.List`1:Sort (int,int,System.Collections.Generic.IComparer`1) void System.Collections.Generic.List`1:Sort (System.Collections.Generic.IComparer`1) - void System.Collections.Generic.List`1:Add (Microsoft.Maui.Controls.Setter) void System.Collections.Generic.List`1:AddRange (System.Collections.Generic.IEnumerable`1) - void System.Collections.Generic.List`1:.cctor () - void System.Collections.Generic.List`1:.ctor (int) void System.Collections.Generic.List`1:.cctor () void System.Collections.Generic.List`1:.ctor () void System.Collections.Generic.List`1:AddWithResize (Microsoft.Maui.WeakEventManager/Subscription) @@ -5972,9 +6283,8 @@ Methods: void System.Collections.Generic.List`1>:set_Capacity (int) void System.Collections.Generic.List`1>:Sort (System.Comparison`1>) void System.Collections.Generic.List`1>:.cctor () - void System.Collections.Generic.List`1>:.cctor () - void System.Collections.Generic.List`1>:.ctor (int) - void System.Collections.Generic.List`1>:Add (System.Collections.Generic.KeyValuePair`2) + void System.Collections.Generic.List`1:.cctor () + void System.Collections.Generic.List`1:.ctor (System.Collections.Generic.IEnumerable`1) void System.Collections.Generic.List`1:.cctor () void System.Collections.Generic.List`1:.ctor () void System.Collections.Generic.List`1:Grow (int) @@ -5989,10 +6299,6 @@ Methods: void System.Collections.Generic.List`1:set_Item (int,System.Text.RegularExpressions.RegexNode) void System.Collections.Generic.List`1:RemoveAt (int) void System.Collections.Generic.List`1>:.cctor () - void System.Collections.Generic.List`1>:.ctor () - void System.Collections.Generic.List`1>:AddWithResize (System.ValueTuple`2) - void System.Collections.Generic.List`1>:Grow (int) - void System.Collections.Generic.List`1>:set_Capacity (int) void System.Collections.Generic.List`1>:.cctor () void System.Collections.Generic.List`1>:.ctor (int) void System.Collections.Generic.List`1>:.cctor () @@ -6029,14 +6335,20 @@ Methods: void System.Collections.Generic.Queue`1:SetCapacity (int) void System.Collections.Generic.ReferenceEqualityComparer:.cctor () void System.Collections.Generic.ReferenceEqualityComparer:.ctor () - void System.Collections.Generic.SortedList`2:.ctor () - void System.Collections.Generic.Stack`1:Grow (int) - void System.Collections.Generic.Stack`1:Push (Microsoft.AspNetCore.Routing.Tree.UrlMatchingNode) - void System.Collections.Generic.Stack`1:PushWithResize (Microsoft.AspNetCore.Routing.Tree.UrlMatchingNode) + void System.Collections.Generic.SegmentedArrayBuilder`1:.ctor (System.Span`1) + void System.Collections.Generic.SegmentedArrayBuilder`1:AddNonICollectionRangeInlined (System.Collections.Generic.IEnumerable`1) + void System.Collections.Generic.SegmentedArrayBuilder`1:Dispose () + void System.Collections.Generic.SegmentedArrayBuilder`1:.ctor (System.Span`1) + void System.Collections.Generic.SegmentedArrayBuilder`1:AddNonICollectionRangeInlined (System.Collections.Generic.IEnumerable`1) + void System.Collections.Generic.SegmentedArrayBuilder`1:Dispose () + void System.Collections.Generic.Stack`1/Enumerator:.ctor (System.Collections.Generic.Stack`1) void System.Collections.Generic.Stack`1:Clear () void System.Collections.Generic.Stack`1:Grow (int) void System.Collections.Generic.Stack`1:Push (int) void System.Collections.Generic.Stack`1:PushWithResize (int) + void System.Collections.Generic.Stack`1:Grow (int) + void System.Collections.Generic.Stack`1:Push (System.Linq.Expressions.Compiler.CompilerScope) + void System.Collections.Generic.Stack`1:PushWithResize (System.Linq.Expressions.Compiler.CompilerScope) void System.Collections.Generic.Stack`1:Clear () void System.Collections.Generic.ValueListBuilder`1:.ctor (System.Span`1) void System.Collections.Generic.ValueListBuilder`1:.ctor (System.Span`1) @@ -6066,11 +6378,18 @@ Methods: void System.Collections.ObjectModel.ObservableCollection`1:add_CollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventHandler) void System.Collections.ObjectModel.ReadOnlyCollection`1:.cctor () void System.Collections.ObjectModel.ReadOnlyCollection`1:.ctor (System.Collections.Generic.IList`1) + void System.Collections.ObjectModel.ReadOnlyCollection`1:.cctor () + void System.Collections.ObjectModel.ReadOnlyCollection`1:.ctor (System.Collections.Generic.IList`1) + void System.Collections.ObjectModel.ReadOnlyCollection`1:.cctor () + void System.Collections.ObjectModel.ReadOnlyCollection`1:.ctor (System.Collections.Generic.IList`1) + void System.Collections.ObjectModel.ReadOnlyCollection`1:.cctor () + void System.Collections.ObjectModel.ReadOnlyCollection`1:.ctor (System.Collections.Generic.IList`1) void System.Collections.ObjectModel.ReadOnlyDictionary`2:.cctor () void System.Collections.ObjectModel.ReadOnlyDictionary`2:.ctor (System.Collections.Generic.IDictionary`2) void System.Collections.Specialized.NotifyCollectionChangedEventArgs:.ctor (System.Collections.Specialized.NotifyCollectionChangedAction,object,int) void System.Collections.Specialized.NotifyCollectionChangedEventArgs:.ctor (System.Collections.Specialized.NotifyCollectionChangedAction) void System.Collections.Specialized.SingleItemReadOnlyList/d__15:System.IDisposable.Dispose () + void System.ComponentModel.EditorBrowsableAttribute:.ctor (System.ComponentModel.EditorBrowsableState) void System.ComponentModel.PropertyChangedEventArgs:.ctor (string) void System.Convert:ToBase64CharsLargeNoLineBreaks (System.ReadOnlySpan`1,System.Span`1,int) void System.DateTime:.cctor () @@ -6092,9 +6411,8 @@ Methods: void System.Decimal/DecCalc:set_Low64 (ulong) void System.Decimal/DecCalc:VarDecDiv (System.Decimal/DecCalc&,System.Decimal/DecCalc&) void System.Decimal/DecCalc:VarDecFromR8 (double,System.Decimal/DecCalc&) - void System.DefaultBinder:.cctor () - void System.DefaultBinder:.ctor () - void System.Diagnostics.Metrics.Histogram`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) + void System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute:.ctor (System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes) + void System.Diagnostics.Metrics.Histogram`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Diagnostics.Metrics.InstrumentAdvice`1) void System.Diagnostics.Metrics.Instrument:.cctor () void System.Diagnostics.Metrics.Instrument:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) void System.Diagnostics.Metrics.Instrument:Publish () @@ -6102,8 +6420,10 @@ Methods: void System.Diagnostics.Metrics.Instrument:ValidateTypeParameter () void System.Diagnostics.Metrics.Instrument/<>c:.cctor () void System.Diagnostics.Metrics.Instrument/<>c:.ctor () - void System.Diagnostics.Metrics.Instrument`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) + void System.Diagnostics.Metrics.Instrument`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Diagnostics.Metrics.InstrumentAdvice`1) + void System.Diagnostics.Metrics.Instrument`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Diagnostics.Metrics.InstrumentAdvice`1) void System.Diagnostics.Metrics.Instrument`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) + void System.Diagnostics.Metrics.InstrumentAdvice`1:.ctor () void System.Diagnostics.Metrics.Meter:.cctor () void System.Diagnostics.Metrics.Meter:.ctor (string,string,System.Collections.Generic.IEnumerable`1>,object) void System.Diagnostics.Metrics.Meter:.ctor (string) @@ -6113,7 +6433,6 @@ Methods: void System.Diagnostics.Metrics.UpDownCounter`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) void System.Diagnostics.StackTrace:GetTrace (System.Runtime.CompilerServices.ObjectHandleOnStack,System.Runtime.CompilerServices.ObjectHandleOnStack,int,bool) void System.Diagnostics.Stopwatch:.cctor () - void System.Diagnostics.Tracing.EventSource:.cctor () void System.Diagnostics.Tracing.EventSource:.ctor () void System.Diagnostics.Tracing.EventSource:.ctor (System.Diagnostics.Tracing.EventSourceSettings,string[]) void System.Diagnostics.Tracing.EventSource:.ctor (System.Diagnostics.Tracing.EventSourceSettings) @@ -6124,8 +6443,22 @@ Methods: void System.Diagnostics.Tracing.NativeRuntimeEventSource:.cctor () void System.Diagnostics.Tracing.NativeRuntimeEventSource:.ctor () void System.DomainNameHelper:.cctor () + void System.Dynamic.Utils.CacheDict`2:.ctor (int) + void System.Dynamic.Utils.ContractUtils:RequiresNotNull (object,string,int) + void System.Dynamic.Utils.ExpressionUtils:RequiresCanRead (System.Linq.Expressions.Expression,string,int) + void System.Dynamic.Utils.ExpressionUtils:RequiresCanRead (System.Linq.Expressions.Expression,string) + void System.Dynamic.Utils.ExpressionUtils:ValidateArgumentCount (System.Linq.Expressions.LambdaExpression) + void System.Dynamic.Utils.ExpressionUtils:ValidateArgumentCount (System.Reflection.MethodBase,System.Linq.Expressions.ExpressionType,int,System.Reflection.ParameterInfo[]) + void System.Dynamic.Utils.ExpressionUtils:ValidateArgumentTypes (System.Reflection.MethodBase,System.Linq.Expressions.ExpressionType,System.Collections.ObjectModel.ReadOnlyCollection`1&,string) + void System.Dynamic.Utils.Helpers:IncrementCount (System.Linq.Expressions.Compiler.BoundConstants/TypedConstant,System.Collections.Generic.Dictionary`2) + void System.Dynamic.Utils.Helpers:IncrementCount (System.Linq.Expressions.ParameterExpression,System.Collections.Generic.Dictionary`2) + void System.Dynamic.Utils.TypeExtensions:.cctor () + void System.Dynamic.Utils.TypeUtils:.cctor () + void System.Dynamic.Utils.TypeUtils:ValidateType (System.Type,string,bool,bool) + void System.Dynamic.Utils.TypeUtils:ValidateType (System.Type,string) + void System.Dynamic.Utils.TypeUtils/<>c:.cctor () + void System.Dynamic.Utils.TypeUtils/<>c:.ctor () void System.Enum:GetEnumValuesAndNames (System.Runtime.CompilerServices.QCallTypeHandle,ulong[]&,string[]&) - void System.Enum:InternalBoxEnum (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack,long) void System.Enum:InternalGetUnderlyingType (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.Enum/EnumInfo`1:.ctor (bool,uint16[],string[]) void System.Enum/EnumInfo`1:.ctor (bool,uint[],string[]) @@ -6175,8 +6508,12 @@ Methods: void System.Guid:.ctor (uint,uint16,uint16,byte,byte,byte,byte,byte,byte,byte,byte) void System.HashCode:.cctor () void System.HashCode:Add (bool) + void System.HashCode:Add (char) void System.HashCode:Add (int) void System.HashCode:Add (int) + void System.HashCode:Add (string,System.Collections.Generic.IEqualityComparer`1) + void System.HashCode:Add (string) + void System.HashCode:Add (System.Decimal) void System.HashCode:Add (System.Text.Json.JsonCommentHandling) void System.HashCode:Add (System.Text.Json.Serialization.JsonIgnoreCondition) void System.HashCode:Add (System.Text.Json.Serialization.JsonNumberHandling) @@ -6186,8 +6523,6 @@ Methods: void System.IO.BinaryReader:.ctor (System.IO.Stream,System.Text.Encoding,bool) void System.IO.BinaryReader:.ctor (System.IO.Stream,System.Text.Encoding) void System.IO.BinaryReader:.ctor (System.IO.Stream) - void System.IO.BinaryWriter:.cctor () - void System.IO.BinaryWriter:.ctor () void System.IO.BinaryWriter:.ctor (System.IO.Stream,System.Text.Encoding,bool) void System.IO.BinaryWriter:Dispose () void System.IO.BinaryWriter:Dispose (bool) @@ -6231,8 +6566,8 @@ Methods: void System.IO.UnmanagedMemoryStream:EnsureReadable () void System.IO.UnmanagedMemoryStream:Initialize (byte*,long,long,System.IO.FileAccess) void System.IO.UnmanagedMemoryStream:set_Position (long) - void System.Lazy`1:ExecutionAndPublication (System.LazyHelper,bool) - void System.Lazy`1:ViaFactory (System.Threading.LazyThreadSafetyMode) + void System.Lazy`1:ExecutionAndPublication (System.LazyHelper,bool) + void System.Lazy`1:ViaFactory (System.Threading.LazyThreadSafetyMode) void System.Lazy`1:.ctor (System.Func`1,System.Threading.LazyThreadSafetyMode,bool) void System.Lazy`1:.ctor (System.Func`1) void System.Lazy`1:ExecutionAndPublication (System.LazyHelper,bool) @@ -6241,36 +6576,124 @@ Methods: void System.Lazy`1:.ctor (System.Func`1) void System.LazyHelper:.cctor () void System.LazyHelper:.ctor (System.LazyState) - void System.Linq.Buffer`1:.ctor (System.Collections.Generic.IEnumerable`1) - void System.Linq.Enumerable/d__41`1:.ctor (int) - void System.Linq.Enumerable/d__41`1:<>m__Finally1 () - void System.Linq.Enumerable/d__41`1:System.IDisposable.Dispose () + void System.Linq.Enumerable:FillIncrementing (System.Span`1,int) void System.Linq.Enumerable/AppendPrepend1Iterator`1:.ctor (System.Collections.Generic.IEnumerable`1,object,bool) void System.Linq.Enumerable/AppendPrependIterator`1:.ctor (System.Collections.Generic.IEnumerable`1) void System.Linq.Enumerable/AppendPrependIterator`1:Dispose () void System.Linq.Enumerable/AppendPrependIterator`1:GetSourceEnumerator () - void System.Linq.Enumerable/Iterator`1:.ctor () - void System.Linq.Enumerable/Iterator`1:Dispose () + void System.Linq.Enumerable/ArrayWhereIterator`1:.ctor (char[],System.Func`2) + void System.Linq.Enumerable/ArrayWhereIterator`1:.ctor (System.Type[],System.Func`2) + void System.Linq.Enumerable/ArrayWhereSelectIterator`2:.ctor (System.Type[],System.Func`2,System.Func`2) + void System.Linq.Enumerable/EnumerableSorter`1:.cctor () + void System.Linq.Enumerable/EnumerableSorter`1:.ctor () + void System.Linq.Enumerable/EnumerableSorter`2:.ctor (System.Func`2,System.Collections.Generic.IComparer`1,bool,System.Linq.Enumerable/EnumerableSorter`1) + void System.Linq.Enumerable/EnumerableSorter`2:ComputeKeys (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[],int) + void System.Linq.Enumerable/EnumerableSorter`2:QuickSort (int[],int,int) + void System.Linq.Enumerable/IEnumerableWhereIterator`1:.ctor (System.Collections.Generic.IEnumerable`1,System.Func`2) + void System.Linq.Enumerable/IEnumerableWhereIterator`1:Dispose () + void System.Linq.Enumerable/Iterator`1:.ctor () + void System.Linq.Enumerable/Iterator`1:Dispose () void System.Linq.Enumerable/Iterator`1:.ctor () void System.Linq.Enumerable/Iterator`1:Dispose () - void System.Linq.Enumerable/WhereArrayIterator`1:.ctor (char[],System.Func`2) - void System.Linq.Enumerable/WhereListIterator`1:.ctor (System.Collections.Generic.List`1,System.Func`2) + void System.Linq.Enumerable/ListWhereIterator`1:.ctor (System.Collections.Generic.List`1,System.Func`2) + void System.Linq.Enumerable/OfTypeIterator`1:.ctor (System.Collections.IEnumerable) + void System.Linq.Enumerable/OfTypeIterator`1:Dispose () + void System.Linq.Enumerable/OrderedIterator`1:.ctor (System.Collections.Generic.IEnumerable`1) + void System.Linq.Enumerable/OrderedIterator`2:.ctor (System.Collections.Generic.IEnumerable`1,System.Func`2,System.Collections.Generic.IComparer`1,bool,System.Linq.Enumerable/OrderedIterator`1) + void System.Linq.Enumerable/OrderedIterator`2:Dispose () void System.Linq.EnumerableSorter`1/<>c:.cctor () void System.Linq.EnumerableSorter`1/<>c:.ctor () - void System.Linq.EnumerableSorter`1:.cctor () - void System.Linq.EnumerableSorter`1:.ctor () - void System.Linq.EnumerableSorter`2:.ctor (System.Func`2,System.Collections.Generic.IComparer`1,bool,System.Linq.EnumerableSorter`1) - void System.Linq.EnumerableSorter`2:ComputeKeys (Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[],int) - void System.Linq.EnumerableSorter`2:QuickSort (int[],int,int) + void System.Linq.Expressions.BinaryExpression:.ctor (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression) + void System.Linq.Expressions.Block2:.ctor (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression) + void System.Linq.Expressions.BlockExpressionList:.ctor (System.Linq.Expressions.BlockExpression,System.Linq.Expressions.Expression) + void System.Linq.Expressions.Compiler.AnalyzedTree:.ctor () + void System.Linq.Expressions.Compiler.BoundConstants:.ctor () + void System.Linq.Expressions.Compiler.BoundConstants:AddReference (object,System.Type) + void System.Linq.Expressions.Compiler.BoundConstants:EmitCacheConstants (System.Linq.Expressions.Compiler.LambdaCompiler) + void System.Linq.Expressions.Compiler.BoundConstants:EmitConstant (System.Linq.Expressions.Compiler.LambdaCompiler,object,System.Type) + void System.Linq.Expressions.Compiler.BoundConstants:EmitConstantFromArray (System.Linq.Expressions.Compiler.LambdaCompiler,object,System.Type) + void System.Linq.Expressions.Compiler.BoundConstants:EmitConstantsArray (System.Linq.Expressions.Compiler.LambdaCompiler) + void System.Linq.Expressions.Compiler.CompilerScope:.ctor (object,bool) + void System.Linq.Expressions.Compiler.CompilerScope:AllocateLocals (System.Linq.Expressions.Compiler.LambdaCompiler) + void System.Linq.Expressions.Compiler.CompilerScope:EmitCachedVariables () + void System.Linq.Expressions.Compiler.CompilerScope:EmitGet (System.Linq.Expressions.ParameterExpression) + void System.Linq.Expressions.Compiler.CompilerScope:EmitNewHoistedLocals (System.Linq.Expressions.Compiler.LambdaCompiler) + void System.Linq.Expressions.Compiler.CompilerScope:SetParent (System.Linq.Expressions.Compiler.LambdaCompiler,System.Linq.Expressions.Compiler.CompilerScope) + void System.Linq.Expressions.Compiler.CompilerScope/ArgumentStorage:.ctor (System.Linq.Expressions.Compiler.LambdaCompiler,System.Linq.Expressions.ParameterExpression) + void System.Linq.Expressions.Compiler.CompilerScope/ArgumentStorage:EmitLoad () + void System.Linq.Expressions.Compiler.CompilerScope/Storage:.ctor (System.Linq.Expressions.Compiler.LambdaCompiler,System.Linq.Expressions.ParameterExpression) + void System.Linq.Expressions.Compiler.ILGen:.cctor () + void System.Linq.Expressions.Compiler.ILGen:EmitLoadArg (System.Reflection.Emit.ILGenerator,int) + void System.Linq.Expressions.Compiler.ILGen:EmitPrimitive (System.Reflection.Emit.ILGenerator,int) + void System.Linq.Expressions.Compiler.KeyedStack`2:.ctor () + void System.Linq.Expressions.Compiler.LabelScopeInfo:.ctor (System.Linq.Expressions.Compiler.LabelScopeInfo,System.Linq.Expressions.Compiler.LabelScopeKind) + void System.Linq.Expressions.Compiler.LambdaCompiler:.cctor () + void System.Linq.Expressions.Compiler.LambdaCompiler:.ctor (System.Linq.Expressions.Compiler.AnalyzedTree,System.Linq.Expressions.LambdaExpression) + void System.Linq.Expressions.Compiler.LambdaCompiler:AddReturnLabel (System.Linq.Expressions.LambdaExpression) + void System.Linq.Expressions.Compiler.LambdaCompiler:DefineBlockLabels (System.Linq.Expressions.Expression) + void System.Linq.Expressions.Compiler.LambdaCompiler:Emit (System.Linq.Expressions.BlockExpression,System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitBlockExpression (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitBranchComparison (bool,System.Linq.Expressions.BinaryExpression,System.Reflection.Emit.Label) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitBranchOp (bool,System.Reflection.Emit.Label) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitClosureArgument () + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitConditionalExpression (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitConstant (object,System.Type) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitConstantExpression (System.Linq.Expressions.Expression) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitExpression (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitExpression (System.Linq.Expressions.Expression) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitExpressionAndBranch (bool,System.Linq.Expressions.Expression,System.Reflection.Emit.Label) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitExpressionAsType (System.Linq.Expressions.Expression,System.Type,System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitExpressionAsVoid (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitExpressionEnd (System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitLambdaBody () + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitLambdaBody (System.Linq.Expressions.Compiler.CompilerScope,bool,System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitNewExpression (System.Linq.Expressions.Expression) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitParameterExpression (System.Linq.Expressions.Expression) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitThrow (System.Linq.Expressions.UnaryExpression,System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitUnreachable (System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.LambdaCompiler/CompilationFlags) + void System.Linq.Expressions.Compiler.LambdaCompiler:EmitWriteBack (System.Collections.Generic.List`1) + void System.Linq.Expressions.Compiler.LambdaCompiler:EnterScope (object) + void System.Linq.Expressions.Compiler.LambdaCompiler:ExitScope (object) + void System.Linq.Expressions.Compiler.LambdaCompiler:InitializeMethod () + void System.Linq.Expressions.Compiler.LambdaCompiler:PushLabelBlock (System.Linq.Expressions.Compiler.LabelScopeKind) + void System.Linq.Expressions.Compiler.LambdaCompiler/<>c:.cctor () + void System.Linq.Expressions.Compiler.LambdaCompiler/<>c:.ctor () + void System.Linq.Expressions.Compiler.ParameterList/d__6:System.IDisposable.Dispose () + void System.Linq.Expressions.Compiler.StackSpiller:.ctor (System.Linq.Expressions.Compiler.StackSpiller/Stack) + void System.Linq.Expressions.Compiler.StackSpiller:Free (int) + void System.Linq.Expressions.Compiler.StackSpiller/<>c:.cctor () + void System.Linq.Expressions.Compiler.StackSpiller/<>c:.ctor () + void System.Linq.Expressions.Compiler.StackSpiller/ChildRewriter:.ctor (System.Linq.Expressions.Compiler.StackSpiller,System.Linq.Expressions.Compiler.StackSpiller/Stack,int) + void System.Linq.Expressions.Compiler.StackSpiller/ChildRewriter:Add (System.Linq.Expressions.Expression) + void System.Linq.Expressions.Compiler.StackSpiller/ChildRewriter:AddArguments (System.Linq.Expressions.IArgumentProvider) + void System.Linq.Expressions.Compiler.StackSpiller/ChildRewriter:EnsureDone () + void System.Linq.Expressions.Compiler.StackSpiller/TempMaker:.ctor () + void System.Linq.Expressions.Compiler.StackSpiller/TempMaker:Free (int) + void System.Linq.Expressions.Compiler.VariableBinder:.ctor () + void System.Linq.Expressions.Compiler.VariableBinder:Reference (System.Linq.Expressions.ParameterExpression,System.Linq.Expressions.Compiler.VariableStorageKind) + void System.Linq.Expressions.Compiler.VariableBinder/<>c:.cctor () + void System.Linq.Expressions.Compiler.VariableBinder/<>c:.ctor () + void System.Linq.Expressions.ConditionalExpression:.ctor (System.Linq.Expressions.Expression,System.Linq.Expressions.Expression) + void System.Linq.Expressions.Expression:.cctor () + void System.Linq.Expressions.Expression:Validate (System.Type,bool) + void System.Linq.Expressions.Expression:ValidateArgumentTypes (System.Reflection.MethodBase,System.Linq.Expressions.ExpressionType,System.Collections.ObjectModel.ReadOnlyCollection`1&,string) + void System.Linq.Expressions.Expression:ValidateConstructor (System.Reflection.ConstructorInfo,string) + void System.Linq.Expressions.Expression:ValidateLambdaArgs (System.Type,System.Linq.Expressions.Expression&,System.Collections.ObjectModel.ReadOnlyCollection`1,string) + void System.Linq.Expressions.LambdaExpression:.cctor () + void System.Linq.Expressions.LambdaExpression:.ctor (System.Linq.Expressions.Expression) + void System.Linq.Expressions.LogicalBinaryExpression:.ctor (System.Linq.Expressions.ExpressionType,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression) + void System.Linq.Expressions.NewExpression:.ctor (System.Reflection.ConstructorInfo,System.Collections.Generic.IReadOnlyList`1,System.Collections.ObjectModel.ReadOnlyCollection`1) + void System.Linq.Expressions.UnaryExpression:.ctor (System.Linq.Expressions.ExpressionType,System.Linq.Expressions.Expression,System.Type,System.Reflection.MethodInfo) + void System.Linq.Expressions.Utils:.cctor () void System.Linq.Extensions:.cctor () - void System.Linq.Extensions/d__5`1:<>m__Finally1 () - void System.Linq.Extensions/d__5`1:System.IDisposable.Dispose () - void System.Linq.OrderedEnumerable`1/d__4:System.IDisposable.Dispose () - void System.Linq.OrderedEnumerable`2:.ctor (System.Collections.Generic.IEnumerable`1,System.Func`2,System.Collections.Generic.IComparer`1,bool,System.Linq.OrderedEnumerable`1) + void System.Linq.Extensions/d__6`1:<>m__Finally1 () + void System.Linq.Extensions/d__6`1:System.IDisposable.Dispose () void System.Marvin:.cctor () void System.MemoryExtensions:Sort (System.Span`1,System.Comparison`1) void System.Net.CookieContainer:.cctor () void System.Net.CookieContainer:.ctor () + void System.Net.Http.<>z__ReadOnlyArray`1:System.Collections.Generic.ICollection.CopyTo (double[],int) + void System.Net.Http.DiagnosticsHelper:.cctor () void System.Net.Http.Headers.AltSvcHeaderParser:.cctor () void System.Net.Http.Headers.AltSvcHeaderParser:.ctor () void System.Net.Http.Headers.BaseHeaderParser:.ctor (bool) @@ -6288,6 +6711,7 @@ Methods: void System.Net.Http.Headers.HeaderUtilities:.cctor () void System.Net.Http.Headers.HeaderUtilities:CheckValidToken (string,string) void System.Net.Http.Headers.HttpContentHeaders:.ctor (System.Net.Http.HttpContent) + void System.Net.Http.Headers.HttpHeaderParser:.cctor () void System.Net.Http.Headers.HttpHeaderParser:.ctor (bool,string) void System.Net.Http.Headers.HttpHeaderParser:.ctor (bool) void System.Net.Http.Headers.HttpHeaders:.ctor (System.Net.Http.Headers.HttpHeaderType,System.Net.Http.Headers.HttpHeaderType) @@ -6351,6 +6775,10 @@ Methods: void System.Net.Http.HttpMessageInvoker:Dispose (bool) void System.Net.Http.HttpMethod:.cctor () void System.Net.Http.HttpMethod:.ctor (string,int) + void System.Net.Http.HttpMethod:Initialize (int) + void System.Net.Http.HttpMethod:set_IsConnect (bool) + void System.Net.Http.HttpMethod:set_IsHead (bool) + void System.Net.Http.HttpMethod:set_MustHaveRequestBody (bool) void System.Net.Http.HttpRequestMessage:.ctor (System.Net.Http.HttpMethod,string) void System.Net.Http.HttpRequestMessage:.ctor (System.Net.Http.HttpMethod,System.Uri) void System.Net.Http.HttpRequestMessage:set_Version (System.Version) @@ -6378,12 +6806,15 @@ Methods: void System.NotSupportedException:.ctor (string) void System.NullReferenceException:.ctor (string) void System.Number:.cctor () + void System.Numerics.Vector`1:.ctor (uint16) + void System.ObsoleteAttribute:.ctor (string) void System.OrdinalCaseSensitiveComparer:.cctor () void System.OrdinalCaseSensitiveComparer:.ctor () void System.OrdinalIgnoreCaseComparer:.cctor () void System.OrdinalIgnoreCaseComparer:.ctor () void System.OutOfMemoryException:.ctor (string) void System.Private.CoreLib.DecCalc/PowerOvfl:.ctor (uint,uint,uint) + void System.Private.CoreLib.Interop:GetCryptographicallySecureRandomBytes (byte*,int) void System.Private.CoreLib.Interop:GetRandomBytes (byte*,int) void System.Private.CoreLib.Interop/ErrorInfo:.ctor (int) void System.Private.CoreLib.Interop/Sys:.cctor () @@ -6411,23 +6842,27 @@ Methods: void System.Reflection.AssemblyName:FillName (Mono.MonoAssemblyName*,string,bool,bool,bool) void System.Reflection.AssemblyNameFormatter:AppendQuoted (System.Text.ValueStringBuilder&,string) void System.Reflection.AssemblyNameParser:.ctor (System.ReadOnlySpan`1) - void System.Reflection.AssemblyNameParser:RecordNewSeenOrThrow (System.Reflection.AssemblyNameParser/AttributeKind&,System.Reflection.AssemblyNameParser/AttributeKind) void System.Reflection.AssemblyNameParser/AssemblyNameParts:.ctor (string,System.Version,string,System.Reflection.AssemblyNameFlags,byte[]) void System.Reflection.ConstructorInfo:.cctor () void System.Reflection.CustomAttribute:.cctor () void System.Reflection.CustomAttribute/AttributeInfo:.ctor (System.AttributeUsageAttribute,int) + void System.Reflection.CustomAttributeTypedArgument:.ctor (System.Type,object) void System.Reflection.DefaultMemberAttribute:.ctor (string) - void System.Reflection.Emit.AssemblyBuilder:EnsureDynamicCodeSupported () void System.Reflection.Emit.DynamicMethod:.cctor () + void System.Reflection.Emit.DynamicMethod:.ctor (string,System.Type,System.Type[],bool) void System.Reflection.Emit.DynamicMethod:.ctor (string,System.Type,System.Type[],System.Reflection.Module,bool) void System.Reflection.Emit.DynamicMethod:create_dynamic_method (System.Reflection.Emit.DynamicMethod,string,System.Reflection.MethodAttributes,System.Reflection.CallingConventions) void System.Reflection.Emit.DynamicMethod:CreateDynMethod () void System.Reflection.Emit.DynamicMethod:Init (string,System.Reflection.MethodAttributes,System.Reflection.CallingConventions,System.Type,System.Type[],System.Type,System.Reflection.Module,bool,bool) - void System.Reflection.Emit.LocalBuilder:.ctor (System.Type,System.Reflection.Emit.ILGenerator) void System.Reflection.Emit.OpCodes:.cctor () + void System.Reflection.Emit.RuntimeAssemblyBuilder:.ctor (System.Reflection.AssemblyName,System.Reflection.Emit.AssemblyBuilderAccess) + void System.Reflection.Emit.RuntimeAssemblyBuilder:basic_init (System.Reflection.Emit.RuntimeAssemblyBuilder) void System.Reflection.Emit.RuntimeILGenerator:.ctor (System.Reflection.Module,System.Reflection.Emit.ITokenGenerator,int) + void System.Reflection.Emit.RuntimeILGenerator:Emit (System.Reflection.Emit.OpCode,int) void System.Reflection.Emit.RuntimeILGenerator:Emit (System.Reflection.Emit.OpCode,System.Reflection.ConstructorInfo) + void System.Reflection.Emit.RuntimeILGenerator:Emit (System.Reflection.Emit.OpCode,System.Reflection.Emit.Label) void System.Reflection.Emit.RuntimeILGenerator:Emit (System.Reflection.Emit.OpCode,System.Reflection.Emit.LocalBuilder) + void System.Reflection.Emit.RuntimeILGenerator:Emit (System.Reflection.Emit.OpCode,System.Reflection.FieldInfo) void System.Reflection.Emit.RuntimeILGenerator:Emit (System.Reflection.Emit.OpCode,System.Reflection.MethodInfo) void System.Reflection.Emit.RuntimeILGenerator:Emit (System.Reflection.Emit.OpCode,System.Type) void System.Reflection.Emit.RuntimeILGenerator:Emit (System.Reflection.Emit.OpCode) @@ -6435,7 +6870,25 @@ Methods: void System.Reflection.Emit.RuntimeILGenerator:label_fixup (System.Reflection.MethodBase) void System.Reflection.Emit.RuntimeILGenerator:ll_emit (System.Reflection.Emit.OpCode) void System.Reflection.Emit.RuntimeILGenerator:make_room (int) + void System.Reflection.Emit.RuntimeILGenerator:MarkLabel (System.Reflection.Emit.Label) + void System.Reflection.Emit.RuntimeLocalBuilder:.ctor (System.Type,System.Reflection.Emit.ILGenerator) void System.Reflection.Emit.RuntimeModuleBuilder:.cctor () + void System.Reflection.Emit.RuntimeModuleBuilder:.ctor (System.Reflection.Emit.RuntimeAssemblyBuilder,string) + void System.Reflection.Emit.RuntimeModuleBuilder:basic_init (System.Reflection.Emit.RuntimeModuleBuilder) + void System.Reflection.Emit.RuntimeModuleBuilder:CreateGlobalType () + void System.Reflection.Emit.RuntimeModuleBuilder:set_wrappers_type (System.Reflection.Emit.RuntimeModuleBuilder,System.Type) + void System.Reflection.Emit.RuntimeTypeBuilder:.ctor (System.Reflection.Emit.RuntimeModuleBuilder,System.Reflection.TypeAttributes,int,bool) + void System.Reflection.Emit.RuntimeTypeBuilder:check_not_created () + void System.Reflection.Emit.RuntimeTypeBuilder:ResolveUserTypes () + void System.Reflection.Emit.RuntimeTypeBuilder:ResolveUserTypes (System.Type[]) + void System.Reflection.Emit.RuntimeTypeBuilder:SetParentCore (System.Type) + void System.Reflection.Emit.TypeBuilder:SetParent (System.Type) + void System.Reflection.Emit.TypeNameBuilder:.ctor () + void System.Reflection.Emit.TypeNameBuilder:AddAssemblyQualifiedName (System.Type,System.Reflection.Emit.TypeNameBuilder/Format) + void System.Reflection.Emit.TypeNameBuilder:AddElementType (System.Type) + void System.Reflection.Emit.TypeNameBuilder:AddName (string) + void System.Reflection.Emit.TypeNameBuilder:Append (string) + void System.Reflection.Emit.TypeNameBuilder:EscapeName (string) void System.Reflection.MethodBaseInvoker:.ctor (System.Reflection.MethodBase,System.RuntimeType[]) void System.Reflection.MethodBaseInvoker:.ctor (System.Reflection.RuntimeConstructorInfo) void System.Reflection.MethodBaseInvoker:.ctor (System.Reflection.RuntimeMethodInfo) @@ -6444,12 +6897,23 @@ Methods: void System.Reflection.Missing:.cctor () void System.Reflection.Missing:.ctor () void System.Reflection.MonoMethodInfo:get_method_info (intptr,System.Reflection.MonoMethodInfo&) + void System.Reflection.NullabilityInfo:.ctor (System.Type,System.Reflection.NullabilityState,System.Reflection.NullabilityState,System.Reflection.NullabilityInfo,System.Reflection.NullabilityInfo[]) + void System.Reflection.NullabilityInfoContext:.ctor () + void System.Reflection.NullabilityInfoContext:CheckGenericParameters (System.Reflection.NullabilityInfo,System.Reflection.MemberInfo,System.Type,System.Type) + void System.Reflection.NullabilityInfoContext:CheckNullabilityAttributes (System.Reflection.NullabilityInfo,System.Collections.Generic.IList`1) + void System.Reflection.NullabilityInfoContext:TryLoadGenericMetaTypeNullability (System.Reflection.MemberInfo,System.Reflection.NullabilityInfo) + void System.Reflection.NullabilityInfoContext/NullableAttributeStateParser:.cctor () + void System.Reflection.NullabilityInfoContext/NullableAttributeStateParser:.ctor (object) void System.Reflection.RuntimeAssembly:GetExportedTypes (System.Runtime.CompilerServices.QCallAssembly,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.Reflection.RuntimeAssembly:GetInfo (System.Runtime.CompilerServices.QCallAssembly,System.Runtime.CompilerServices.ObjectHandleOnStack,System.Reflection.RuntimeAssembly/AssemblyInfoKind) void System.Reflection.RuntimeAssembly/UnmanagedMemoryStreamForModule:.ctor (byte*,long,System.Reflection.Module) + void System.Reflection.RuntimeCustomAttributeData:.ctor (System.Reflection.ConstructorInfo,System.Reflection.Assembly,intptr,uint) + void System.Reflection.RuntimeCustomAttributeData:ResolveArguments () + void System.Reflection.RuntimeCustomAttributeData:ResolveArgumentsInternal (System.Reflection.ConstructorInfo,System.Reflection.Assembly,intptr,uint,object[]&,object[]&) void System.Reflection.RuntimeModule:GetGuidInternal (intptr,byte[]) void System.Reflection.RuntimeParameterInfo:.ctor (string,System.Type,int,int,object,System.Reflection.MemberInfo,System.Runtime.InteropServices.MarshalAsAttribute) void System.Reflection.RuntimeParameterInfo:.ctor (System.Reflection.MethodInfo,string,System.Type,int) + void System.Reflection.RuntimeParameterInfo:.ctor (System.Type,System.Reflection.MemberInfo,System.Runtime.InteropServices.MarshalAsAttribute) void System.Reflection.RuntimePropertyInfo:CachePropertyInfo (System.Reflection.PInfo) void System.Reflection.RuntimePropertyInfo:get_property_info (System.Reflection.RuntimePropertyInfo,System.Reflection.MonoPropertyInfo&,System.Reflection.PInfo) void System.Resources.FastResourceComparer:.cctor () @@ -6463,19 +6927,18 @@ Methods: void System.Resources.ResourceManager:CommonAssemblyInit () void System.Resources.ResourceManager/ResourceManagerMediator:.ctor (System.Resources.ResourceManager) void System.Resources.ResourceReader:_ReadResources () - void System.Resources.ResourceReader:.cctor () void System.Resources.ResourceReader:.ctor (System.IO.Stream,System.Collections.Generic.Dictionary`2,bool) void System.Resources.ResourceReader:ReadResources () void System.Resources.ResourceReader:SkipString () void System.Resources.RuntimeResourceSet:.ctor (System.IO.Stream,bool) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (CommonMethods/d__0&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.ComponentBase/d__21&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/<g__ProcessAsynchronousWork|54_0>d&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__81&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__76&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__50&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__54&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.Routing.FocusOnNavigate/d__15&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.ComponentBase/d__28&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/<g__ProcessAsynchronousWork|62_0>d&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__89&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__84&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__58&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.RenderTree.Renderer/d__62&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.Routing.FocusOnNavigate/d__17&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.Routing.Router/d__78&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.Routing.Router/d__76&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.Routing.Router/d__69&) @@ -6486,8 +6949,8 @@ Methods: void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.AspNetCore.Components.WebView.WebViewManager/d__21&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.JSInterop.JSRuntime/d__16`1&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.JSInterop.JSRuntimeExtensions/d__0&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__50&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__41&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__55&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__45&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Dispatching.DispatcherExtensions/<>c__DisplayClass2_0`1/<b__0>d&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Dispatching.DispatcherExtensions/<>c__DisplayClass3_0/<b__0>d&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.TaskExtensions/d__1&) @@ -6532,21 +6995,21 @@ Methods: void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__41>:ExecutionContextCallback (object) void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__41>:MoveNext () void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__41>:MoveNext (System.Threading.Thread) - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__81>:.cctor () - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__81>:.ctor () - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__81>:ExecutionContextCallback (object) - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__81>:MoveNext () - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__81>:MoveNext (System.Threading.Thread) - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__76>:.cctor () - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__76>:.ctor () - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__76>:ExecutionContextCallback (object) - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__76>:MoveNext () - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__76>:MoveNext (System.Threading.Thread) - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__15>:.cctor () - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__15>:.ctor () - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__15>:ExecutionContextCallback (object) - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__15>:MoveNext () - void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__15>:MoveNext (System.Threading.Thread) + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__89>:.cctor () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__89>:.ctor () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__89>:ExecutionContextCallback (object) + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__89>:MoveNext () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__89>:MoveNext (System.Threading.Thread) + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__84>:.cctor () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__84>:.ctor () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__84>:ExecutionContextCallback (object) + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__84>:MoveNext () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__84>:MoveNext (System.Threading.Thread) + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__17>:.cctor () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__17>:.ctor () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__17>:ExecutionContextCallback (object) + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__17>:MoveNext () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__17>:MoveNext (System.Threading.Thread) void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1c__DisplayClass14_0/<g__AwaitAndNotify|0>d>:.cctor () void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1c__DisplayClass14_0/<g__AwaitAndNotify|0>d>:.ctor () void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1c__DisplayClass14_0/<g__AwaitAndNotify|0>d>:ExecutionContextCallback (object) @@ -6567,6 +7030,11 @@ Methods: void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__Core|27_0>d>:ExecutionContextCallback (object) void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__Core|27_0>d>:MoveNext () void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__Core|27_0>d>:MoveNext (System.Threading.Thread) + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__63>:.cctor () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__63>:.ctor () + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__63>:ExecuteFromThreadPool (System.Threading.Thread) + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__63>:ExecutionContextCallback (object) + void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__63>:MoveNext (System.Threading.Thread) void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__DisposeSourceAsync|1_0>d>:.cctor () void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__DisposeSourceAsync|1_0>d>:.ctor () void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__DisposeSourceAsync|1_0>d>:ExecutionContextCallback (object) @@ -6595,24 +7063,28 @@ Methods: void System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1:SetResult (Microsoft.JSInterop.Infrastructure.IJSVoidResult) void System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1:Start (Microsoft.JSInterop.JSRuntime/d__16`1&) void System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1:.cctor () - void System.Runtime.CompilerServices.AsyncVoidMethodBuilder:NotifySynchronizationContextOfCompletion () + void System.Runtime.CompilerServices.AsyncVoidMethodBuilder:NotifySynchronizationContextOfCompletion (System.Threading.SynchronizationContext) void System.Runtime.CompilerServices.AsyncVoidMethodBuilder:SetResult () - void System.Runtime.CompilerServices.ConditionalWeakTable`2/Container:.ctor (System.Runtime.CompilerServices.ConditionalWeakTable`2) - void System.Runtime.CompilerServices.ConditionalWeakTable`2/Container:UpdateValue (int,object) + void System.Runtime.CompilerServices.Closure:.ctor (object[],object[]) void System.Runtime.CompilerServices.ConditionalWeakTable`2/Container:.ctor (System.Runtime.CompilerServices.ConditionalWeakTable`2,int[],System.Runtime.CompilerServices.ConditionalWeakTable`2/Entry[],int) void System.Runtime.CompilerServices.ConditionalWeakTable`2/Container:RemoveIndex (int) - void System.Runtime.CompilerServices.ConditionalWeakTable`2:.ctor () - void System.Runtime.CompilerServices.ConditionalWeakTable`2:AddOrUpdate (Microsoft.Maui.Controls.BindableObject,object) + void System.Runtime.CompilerServices.ConditionalWeakTable`2/Container:.ctor (System.Runtime.CompilerServices.ConditionalWeakTable`2) + void System.Runtime.CompilerServices.ConditionalWeakTable`2:AddOrUpdate (System.Action,Java.Lang.Thread/RunnableImplementor) + void System.Runtime.CompilerServices.ConditionalWeakTable`2:.ctor () void System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1/ConfiguredValueTaskAwaiter:System.Runtime.CompilerServices.IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted (System.Runtime.CompilerServices.IAsyncStateMachineBox) void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler:.ctor (int,int) void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler:AppendFormatted (int) void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler:AppendFormatted (Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrameType) void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler:AppendFormatted (System.ReadOnlySpan`1) + void System.Runtime.CompilerServices.IsReadOnlyAttribute:.ctor () + void System.Runtime.CompilerServices.NullableAttribute:.ctor (byte) + void System.Runtime.CompilerServices.NullableAttribute:.ctor (byte[]) + void System.Runtime.CompilerServices.NullableContextAttribute:.ctor (byte) void System.Runtime.CompilerServices.QCallAssembly:.ctor (System.Reflection.RuntimeAssembly&) void System.Runtime.CompilerServices.QCallTypeHandle:.ctor (System.RuntimeType&) - void System.Runtime.CompilerServices.RuntimeFeature:.cctor () void System.Runtime.CompilerServices.RuntimeHelpers:EnsureSufficientExecutionStack () void System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal (System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool) + void System.Runtime.CompilerServices.TrueReadOnlyCollection`1:.ctor (System.Linq.Expressions.ParameterExpression[]) void System.Runtime.CompilerServices.TypeForwardedFromAttribute:.ctor (string) void System.Runtime.CompilerServices.ValueTaskAwaiter:.cctor () void System.Runtime.CompilerServices.ValueTaskAwaiter:System.Runtime.CompilerServices.IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted (System.Runtime.CompilerServices.IAsyncStateMachineBox) @@ -6620,7 +7092,6 @@ Methods: void System.Runtime.CompilerServices.ValueTaskAwaiter/<>c:.ctor () void System.Runtime.CompilerServices.ValueTaskAwaiter`1:System.Runtime.CompilerServices.IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted (System.Runtime.CompilerServices.IAsyncStateMachineBox) void System.Runtime.DependentHandle:.ctor (object,object) - void System.Runtime.DependentHandle:UnsafeSetDependent (object) void System.Runtime.DependentHandle:UnsafeSetTargetToNull () void System.Runtime.ExceptionServices.ExceptionDispatchInfo:.ctor (System.Exception) void System.Runtime.ExceptionServices.ExceptionDispatchInfo:Throw () @@ -6631,7 +7102,6 @@ Methods: void System.Runtime.InteropServices.Marshal:FreeCoTaskMem (intptr) void System.Runtime.InteropServices.Marshal:FreeHGlobal (intptr) void System.Runtime.InteropServices.Marshal:PtrToStructureHelper (intptr,object,bool) - void System.Runtime.InteropServices.Marshal:PtrToStructureInternal (intptr,object,bool) void System.Runtime.InteropServices.Marshal:SetLastPInvokeError (int) void System.Runtime.InteropServices.Marshal:SetLastSystemError (int) void System.Runtime.InteropServices.Marshal:ZeroFreeCoTaskMemUTF8 (intptr) @@ -6645,16 +7115,20 @@ Methods: void System.Runtime.InteropServices.SafeHandle:DangerousRelease () void System.Runtime.InteropServices.SafeHandle:InternalRelease (bool) void System.Runtime.Loader.AssemblyLoadContext:.ctor (bool,bool,string) + void System.Runtime.Loader.AssemblyLoadContext:InvokeAssemblyLoadEvent (System.Reflection.Assembly) void System.Runtime.Loader.DefaultAssemblyLoadContext:.cctor () void System.Runtime.Loader.DefaultAssemblyLoadContext:.ctor () void System.RuntimeType:.cctor () void System.RuntimeType:CacheFlag (System.RuntimeType/TypeCacheEntries,bool) void System.RuntimeType:CreateInstanceCheckThis () void System.RuntimeType:FilterHelper (System.Reflection.BindingFlags,string&,bool,bool&,bool&,System.RuntimeType/MemberListType&) + void System.RuntimeType:FilterHelper (System.Reflection.BindingFlags,string&,bool&,System.RuntimeType/MemberListType&) + void System.RuntimeType:GetDeclaringType (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.RuntimeType:getFullName (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack,bool,bool) void System.RuntimeType:GetGenericArgumentsInternal (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack,bool) void System.RuntimeType:GetInterfaces (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.RuntimeType:GetName (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack) + void System.RuntimeType:GetNamespace (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.RuntimeType:make_array_type (System.Runtime.CompilerServices.QCallTypeHandle,int,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.RuntimeType:make_byref_type (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.RuntimeType:MakeGenericType (System.Type,System.Type[],System.Runtime.CompilerServices.ObjectHandleOnStack) @@ -6672,6 +7146,8 @@ Methods: void System.SpanHelpers:ClearWithoutReferences (byte&,uintptr) void System.SpanHelpers:ClearWithReferences (intptr&,uintptr) void System.SpanHelpers:Fill (char&,uintptr,char) + void System.SpanHelpers:Memmove (byte&,byte&,uintptr) + void System.SpanHelpers:ReplaceValueType (uint16&,uint16&,uint16,uint16,uintptr) void System.StackOverflowException:.ctor (string) void System.String:.ctor (char,int) void System.String:.ctor (char[],int,int) @@ -6684,12 +7160,8 @@ Methods: void System.String:MakeSeparatorListAny (System.ReadOnlySpan`1,System.ReadOnlySpan`1,System.Collections.Generic.ValueListBuilder`1&) void System.String:memcpy (byte*,byte*,int) void System.String:memset (byte*,int,int) - void System.SZGenericArrayEnumerator`1:.cctor () - void System.SZGenericArrayEnumerator`1:.ctor (Microsoft.Maui.Controls.DependencyService/DependencyType[],int) void System.SZGenericArrayEnumerator`1:.cctor () void System.SZGenericArrayEnumerator`1:.ctor (Microsoft.Maui.Hosting.IMauiInitializeService[],int) - void System.SZGenericArrayEnumerator`1>:.cctor () - void System.SZGenericArrayEnumerator`1>:.ctor (System.Collections.Generic.KeyValuePair`2[],int) void System.SZGenericArrayEnumerator`1>>:.cctor () void System.SZGenericArrayEnumerator`1>>:.ctor (System.Collections.Generic.KeyValuePair`2>[],int) void System.SZGenericArrayEnumeratorBase:.ctor (int) @@ -6737,11 +7209,10 @@ Methods: void System.Text.Encodings.Web.TextEncoderSettings:AllowRange (System.Text.Unicode.UnicodeRange) void System.Text.Encodings.Web.TextEncoderSettings:AllowRanges (System.Text.Unicode.UnicodeRange[]) void System.Text.EncodingTable:.cctor () + void System.Text.Json.AppContextSwitchHelper:.cctor () void System.Text.Json.BitStack:ResetFirstBit () void System.Text.Json.Cache`1/<>c__6`1, System.Func`1>:.cctor () void System.Text.Json.Cache`1/<>c__6`1, System.Func`1>:.ctor () - void System.Text.Json.Cache`1/<>c__6`1, System.Func`2>>:.cctor () - void System.Text.Json.Cache`1/<>c__6`1, System.Func`2>>:.ctor () void System.Text.Json.Cache`1/<>c__6`1, System.Func`2>:.cctor () void System.Text.Json.Cache`1/<>c__6`1, System.Func`2>:.ctor () void System.Text.Json.Cache`1/<>c__6`1, System.Func`2>:.cctor () @@ -6762,15 +7233,15 @@ Methods: void System.Text.Json.JsonDocument/MetadataDb:Append (System.Text.Json.JsonTokenType,int,int) void System.Text.Json.JsonDocument/MetadataDb:CompleteAllocations () void System.Text.Json.JsonEncodedText:.ctor (byte[]) + void System.Text.Json.JsonHelpers:.cctor () void System.Text.Json.JsonKebabCaseLowerNamingPolicy:.ctor () void System.Text.Json.JsonKebabCaseUpperNamingPolicy:.ctor () void System.Text.Json.JsonNamingPolicy:.cctor () void System.Text.Json.JsonNamingPolicy:.ctor () - void System.Text.Json.JsonPropertyDictionary`1:.ctor (bool,int) - void System.Text.Json.JsonPropertyDictionary`1:CreateDictionaryIfThresholdMet () void System.Text.Json.JsonReaderHelper:.cctor () void System.Text.Json.JsonReaderOptions:set_CommentHandling (System.Text.Json.JsonCommentHandling) void System.Text.Json.JsonReaderOptions:set_MaxDepth (int) + void System.Text.Json.JsonReaderState:.ctor (long,long,bool,bool,bool,bool,System.Text.Json.JsonTokenType,System.Text.Json.JsonTokenType,System.Text.Json.JsonReaderOptions,System.Text.Json.BitStack) void System.Text.Json.JsonReaderState:.ctor (System.Text.Json.JsonReaderOptions) void System.Text.Json.JsonSeparatorNamingPolicy:.ctor (bool,char) void System.Text.Json.JsonSerializer:.cctor () @@ -6788,6 +7259,7 @@ Methods: void System.Text.Json.JsonSerializerOptions/ConverterList:.ctor (System.Text.Json.JsonSerializerOptions,System.Collections.Generic.IList`1) void System.Text.Json.JsonSerializerOptions/ConverterList:OnCollectionModifying () void System.Text.Json.JsonSerializerOptions/EqualityComparer:g__AddHashCode|1_1 (System.HashCode&,bool) + void System.Text.Json.JsonSerializerOptions/EqualityComparer:g__AddHashCode|1_1 (System.HashCode&,char) void System.Text.Json.JsonSerializerOptions/EqualityComparer:g__AddHashCode|1_1 (System.HashCode&,int) void System.Text.Json.JsonSerializerOptions/EqualityComparer:g__AddHashCode|1_1 (System.HashCode&,System.Text.Json.JsonCommentHandling) void System.Text.Json.JsonSerializerOptions/EqualityComparer:g__AddHashCode|1_1 (System.HashCode&,System.Text.Json.JsonNamingPolicy) @@ -6804,8 +7276,13 @@ Methods: void System.Text.Json.JsonWriterHelper:.cctor () void System.Text.Json.JsonWriterHelper:EscapeNextChars (char,System.Span`1,int&) void System.Text.Json.JsonWriterHelper:EscapeString (System.ReadOnlySpan`1,System.Span`1,int,System.Text.Encodings.Web.JavaScriptEncoder,int&) + void System.Text.Json.JsonWriterOptions:.cctor () + void System.Text.Json.JsonWriterOptions:set_Encoder (System.Text.Encodings.Web.JavaScriptEncoder) + void System.Text.Json.JsonWriterOptions:set_IndentCharacter (char) void System.Text.Json.JsonWriterOptions:set_Indented (bool) + void System.Text.Json.JsonWriterOptions:set_IndentSize (int) void System.Text.Json.JsonWriterOptions:set_MaxDepth (int) + void System.Text.Json.JsonWriterOptions:set_NewLine (string) void System.Text.Json.JsonWriterOptions:set_SkipValidation (bool) void System.Text.Json.PooledByteBufferWriter:Advance (int) void System.Text.Json.PooledByteBufferWriter:CheckAndResizeBuffer (int) @@ -6820,6 +7297,7 @@ Methods: void System.Text.Json.Reflection.ReflectionExtensions/<>c:.ctor () void System.Text.Json.Serialization.ConfigurationList`1:.ctor (System.Collections.Generic.IEnumerable`1) void System.Text.Json.Serialization.ConfigurationList`1:Add (System.Text.Json.Serialization.JsonConverter) + void System.Text.Json.Serialization.ConfigurationList`1:OnCollectionModified () void System.Text.Json.Serialization.ConfigurationList`1:ValidateAddedValue (System.Text.Json.Serialization.JsonConverter) void System.Text.Json.Serialization.Converters.BooleanConverter:.ctor () void System.Text.Json.Serialization.Converters.ByteArrayConverter:.ctor () @@ -6831,8 +7309,10 @@ Methods: void System.Text.Json.Serialization.Converters.DecimalConverter:.ctor () void System.Text.Json.Serialization.Converters.DefaultObjectConverter:.ctor () void System.Text.Json.Serialization.Converters.DoubleConverter:.ctor () + void System.Text.Json.Serialization.Converters.EnumConverter`1/EnumFieldInfo:.ctor (ulong,System.Text.Json.Serialization.Converters.EnumConverter`1/EnumFieldNameKind,string,string) void System.Text.Json.Serialization.Converters.EnumConverter`1:.cctor () void System.Text.Json.Serialization.Converters.EnumConverter`1:.ctor (System.Text.Json.Serialization.Converters.EnumConverterOptions,System.Text.Json.JsonNamingPolicy,System.Text.Json.JsonSerializerOptions) + void System.Text.Json.Serialization.Converters.EnumConverter`1:<.ctor>g__AddToEnumFieldIndex|10_0 (System.Text.Json.Serialization.Converters.EnumConverter`1/EnumFieldInfo) void System.Text.Json.Serialization.Converters.EnumConverter`1:Write (System.Text.Json.Utf8JsonWriter,Microsoft.JSInterop.JSCallResultType,System.Text.Json.JsonSerializerOptions) void System.Text.Json.Serialization.Converters.EnumConverterFactory:.ctor () void System.Text.Json.Serialization.Converters.FSharpTypeConverterFactory:.ctor () @@ -6934,7 +7414,6 @@ Methods: void System.Text.Json.Serialization.JsonConverter`1:.ctor () void System.Text.Json.Serialization.JsonConverter`1:.ctor () void System.Text.Json.Serialization.JsonConverter`1>>:.ctor () - void System.Text.Json.Serialization.JsonConverter`1:.ctor () void System.Text.Json.Serialization.JsonConverter`1:.ctor () void System.Text.Json.Serialization.JsonConverter`1:.ctor () void System.Text.Json.Serialization.JsonConverter`1:.ctor () @@ -6968,17 +7447,17 @@ Methods: void System.Text.Json.Serialization.JsonResumableConverter`1:.ctor () void System.Text.Json.Serialization.JsonResumableConverter`1>>:.ctor () void System.Text.Json.Serialization.JsonResumableConverter`1:.ctor () - void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:.ctor (bool) void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:g__Add|3_0 (System.Text.Json.Serialization.JsonConverter,System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver/<>c__DisplayClass3_0&) - void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:AddMember (System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Type,System.Reflection.MemberInfo,bool,bool,System.Text.Json.Serialization.Metadata.JsonTypeInfo/PropertyHierarchyResolutionState&) - void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:AddMembersDeclaredBySuperType (System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Type,bool,System.Text.Json.Serialization.Metadata.JsonTypeInfo/PropertyHierarchyResolutionState&) + void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:AddMember (System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Type,System.Reflection.MemberInfo,System.Reflection.NullabilityInfoContext,bool,bool,System.Text.Json.Serialization.Metadata.JsonTypeInfo/PropertyHierarchyResolutionState&) + void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:AddMembersDeclaredBySuperType (System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Type,System.Reflection.NullabilityInfoContext,bool,System.Text.Json.Serialization.Metadata.JsonTypeInfo/PropertyHierarchyResolutionState&) void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:DeterminePropertyAccessors (System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1,System.Reflection.MemberInfo,bool) void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:DeterminePropertyIsRequired (System.Text.Json.Serialization.Metadata.JsonPropertyInfo,System.Reflection.MemberInfo,bool) void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:DeterminePropertyName (System.Text.Json.Serialization.Metadata.JsonPropertyInfo,System.Reflection.MemberInfo) + void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:DeterminePropertyNullability (System.Text.Json.Serialization.Metadata.JsonPropertyInfo,System.Reflection.MemberInfo,System.Reflection.NullabilityInfoContext) void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:DeterminePropertyPolicies (System.Text.Json.Serialization.Metadata.JsonPropertyInfo,System.Reflection.MemberInfo) - void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:PopulateParameterInfoValues (System.Text.Json.Serialization.Metadata.JsonTypeInfo) - void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:PopulateProperties (System.Text.Json.Serialization.Metadata.JsonTypeInfo) - void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:PopulatePropertyInfo (System.Text.Json.Serialization.Metadata.JsonPropertyInfo,System.Reflection.MemberInfo,System.Text.Json.Serialization.JsonConverter,System.Nullable`1,bool,bool) + void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:PopulateParameterInfoValues (System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Reflection.NullabilityInfoContext) + void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:PopulateProperties (System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Reflection.NullabilityInfoContext) + void System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver:PopulatePropertyInfo (System.Text.Json.Serialization.Metadata.JsonPropertyInfo,System.Reflection.MemberInfo,System.Text.Json.Serialization.JsonConverter,System.Nullable`1,System.Reflection.NullabilityInfoContext,bool,bool) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:.cctor () void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:.ctor (System.Type,System.Type,System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Text.Json.JsonSerializerOptions) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:CacheNameAsUtf8BytesAndEscapedNameSection () @@ -6991,16 +7470,17 @@ Methods: void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:EnsureChildOf (System.Text.Json.Serialization.Metadata.JsonTypeInfo) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_AttributeProvider (System.Reflection.ICustomAttributeProvider) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_CustomConverter (System.Text.Json.Serialization.JsonConverter) + void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_DeclaringTypeInfo (System.Text.Json.Serialization.Metadata.JsonTypeInfo) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_IgnoreCondition (System.Nullable`1) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_IsExtensionData (bool) - void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_IsForTypeInfo (bool) + void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_IsGetNullable (bool) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_IsRequired (bool) + void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_IsSetNullable (bool) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_JsonTypeInfo (System.Text.Json.Serialization.Metadata.JsonTypeInfo) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_Name (string) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_NumberHandling (System.Nullable`1) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_ObjectCreationHandling (System.Nullable`1) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_Order (int) - void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:set_ParentTypeInfo (System.Text.Json.Serialization.Metadata.JsonTypeInfo) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo:VerifyMutable () void System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1:.ctor (System.Type,System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Text.Json.JsonSerializerOptions) void System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1:DetermineEffectiveConverter (System.Text.Json.Serialization.Metadata.JsonTypeInfo) @@ -7028,6 +7508,8 @@ Methods: void System.Text.Json.Serialization.Metadata.JsonTypeInfo:EnsureConfigured () void System.Text.Json.Serialization.Metadata.JsonTypeInfo:MapInterfaceTypesToCallbacks () void System.Text.Json.Serialization.Metadata.JsonTypeInfo:PopulatePolymorphismMetadata () + void System.Text.Json.Serialization.Metadata.JsonTypeInfo:ResolveMatchingParameterInfo (System.Text.Json.Serialization.Metadata.JsonPropertyInfo) + void System.Text.Json.Serialization.Metadata.JsonTypeInfo:set_ConstructorAttributeProvider (System.Reflection.ICustomAttributeProvider) void System.Text.Json.Serialization.Metadata.JsonTypeInfo:set_CreateObject (System.Func`1) void System.Text.Json.Serialization.Metadata.JsonTypeInfo:set_OriginatingResolver (System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver) void System.Text.Json.Serialization.Metadata.JsonTypeInfo:SetCreateObjectIfCompatible (System.Delegate) @@ -7050,20 +7532,13 @@ Methods: void System.Text.Json.Serialization.Metadata.JsonTypeInfo`1:.ctor (System.Text.Json.Serialization.JsonConverter,System.Text.Json.JsonSerializerOptions) void System.Text.Json.Serialization.Metadata.JsonTypeInfo`1:SetCreateObject (System.Delegate) void System.Text.Json.Serialization.Metadata.JsonTypeInfoResolver:.cctor () - void System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor:.cctor () void System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor:.ctor () - void System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/<>c__12`1:.cctor () - void System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/<>c__12`1:.ctor () - void System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/<>c:.cctor () - void System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/<>c:.ctor () void System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1>:.ctor (System.TimeSpan,System.TimeSpan) void System.Text.Json.Serialization.Metadata.ReflectionEmitCachingMemberAccessor/Cache`1>:EvictStaleCacheEntries (long) void System.Text.Json.ThrowHelper:ThrowNotSupportedException_ConstructorContainsNullParameterNames (System.Type) void System.Text.Json.Utf8JsonReader:.ctor (System.ReadOnlySpan`1,bool,System.Text.Json.JsonReaderState) void System.Text.Json.Utf8JsonReader:.ctor (System.ReadOnlySpan`1,System.Text.Json.JsonReaderOptions) void System.Text.Json.Utf8JsonReader:EndArray () - void System.Text.Json.Utf8JsonWriter:.cctor () - void System.Text.Json.Utf8JsonWriter:.ctor () void System.Text.Json.Utf8JsonWriter:CheckNotDisposed () void System.Text.Json.Utf8JsonWriter:FirstCallToGetMemory (int) void System.Text.Json.Utf8JsonWriter:Flush () @@ -7071,6 +7546,7 @@ Methods: void System.Text.Json.Utf8JsonWriter:Reset (System.Buffers.IBufferWriter`1,System.Text.Json.JsonWriterOptions) void System.Text.Json.Utf8JsonWriter:ResetAllStateForCacheReuse () void System.Text.Json.Utf8JsonWriter:ResetHelper () + void System.Text.Json.Utf8JsonWriter:SetOptions (System.Text.Json.JsonWriterOptions) void System.Text.Json.Utf8JsonWriter:WriteEnd (byte) void System.Text.Json.Utf8JsonWriter:WriteEndArray () void System.Text.Json.Utf8JsonWriter:WriteEndMinimized (byte) @@ -7078,7 +7554,6 @@ Methods: void System.Text.Json.Utf8JsonWriter:WriteNumber (System.Text.Json.JsonEncodedText,long) void System.Text.Json.Utf8JsonWriter:WriteNumberByOptions (System.ReadOnlySpan`1,long) void System.Text.Json.Utf8JsonWriter:WriteNumberMinimized (System.ReadOnlySpan`1,long) - void System.Text.Json.Utf8JsonWriter:WriteNumberValue (int) void System.Text.Json.Utf8JsonWriter:WriteNumberValue (long) void System.Text.Json.Utf8JsonWriter:WriteNumberValueMinimized (long) void System.Text.Json.Utf8JsonWriter:WriteStart (byte) @@ -7096,6 +7571,8 @@ Methods: void System.Text.Json.WriteStack:Initialize (System.Text.Json.Serialization.Metadata.JsonTypeInfo,object,bool,bool) void System.Text.Json.WriteStack:Pop (bool) void System.Text.Json.WriteStack:Push () + void System.Text.RegularExpressions.Generated.F263ABC6EE6712A162FC515A4292A6E13BB40673A6EB0FA3803720FEF34BB7A5D__CreateIntegerRegex_0:.cctor () + void System.Text.RegularExpressions.Generated.F263ABC6EE6712A162FC515A4292A6E13BB40673A6EB0FA3803720FEF34BB7A5D__CreateIntegerRegex_0:.ctor () void System.Text.RegularExpressions.Regex:.cctor () void System.Text.RegularExpressions.Regex:.ctor (string,System.Globalization.CultureInfo) void System.Text.RegularExpressions.Regex:.ctor (string) @@ -7200,20 +7677,23 @@ Methods: void System.Threading.ExecutionContext:.ctor () void System.Threading.ExecutionContext:RunFromThreadPoolDispatchLoop (System.Threading.Thread,System.Threading.ExecutionContext,System.Threading.ContextCallback,object) void System.Threading.ExecutionContext:RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object) + void System.Threading.Lock:.cctor () + void System.Threading.Lock:.ctor () + void System.Threading.Lock:Exit (System.Threading.Lock/ThreadId) + void System.Threading.Lock/ThreadId:InitializeForCurrentThread () void System.Threading.LowLevelLifoSemaphore:.ctor (int,int,int,System.Action) void System.Threading.LowLevelLifoSemaphore:Create (int) + void System.Threading.LowLevelLifoSemaphore:Release (int) void System.Threading.LowLevelLifoSemaphore:ReleaseCore (int) void System.Threading.LowLevelLifoSemaphore:ReleaseInternal (intptr,int) - void System.Threading.LowLevelLifoSemaphoreBase:.ctor (int,int,int,System.Action) - void System.Threading.LowLevelLifoSemaphoreBase:Release (int) - void System.Threading.LowLevelLifoSemaphoreBase/Counts:AddUpToMaxCountOfWaitersSignaledToWake (uint) - void System.Threading.LowLevelLifoSemaphoreBase/Counts:DecrementCountOfWaitersSignaledToWake () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:DecrementSpinnerCount () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:DecrementWaiterCount () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:IncrementSpinnerCount () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:IncrementWaiterCount () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:set_SignalCount (uint) - void System.Threading.LowLevelLifoSemaphoreBase/Counts:SetUInt32Value (uint,byte) + void System.Threading.LowLevelLifoSemaphore/Counts:AddUpToMaxCountOfWaitersSignaledToWake (uint) + void System.Threading.LowLevelLifoSemaphore/Counts:DecrementCountOfWaitersSignaledToWake () + void System.Threading.LowLevelLifoSemaphore/Counts:DecrementSpinnerCount () + void System.Threading.LowLevelLifoSemaphore/Counts:DecrementWaiterCount () + void System.Threading.LowLevelLifoSemaphore/Counts:IncrementSpinnerCount () + void System.Threading.LowLevelLifoSemaphore/Counts:IncrementWaiterCount () + void System.Threading.LowLevelLifoSemaphore/Counts:set_SignalCount (uint) + void System.Threading.LowLevelLifoSemaphore/Counts:SetUInt32Value (uint,byte) void System.Threading.LowLevelLock:.cctor () void System.Threading.LowLevelLock:.ctor () void System.Threading.LowLevelLock:Acquire () @@ -7227,7 +7707,7 @@ Methods: void System.Threading.LowLevelMonitor:Signal_ReleaseCore () void System.Threading.LowLevelMonitor:Wait () void System.Threading.LowLevelMonitor:WaitCore () - void System.Threading.LowLevelSpinWaiter:Wait (int,int,int) + void System.Threading.LowLevelSpinWaiter:Wait (int,int,bool) void System.Threading.Monitor:Exit (object) void System.Threading.Monitor:InternalExit (object) void System.Threading.PortableThreadPool:.cctor () @@ -7303,7 +7783,7 @@ Methods: void System.Threading.Tasks.Task:UnsafeSetContinuationForAwait (System.Runtime.CompilerServices.IAsyncStateMachineBox,bool) void System.Threading.Tasks.Task/<>c:.cctor () void System.Threading.Tasks.Task/<>c:.ctor () - void System.Threading.Tasks.Task/<>c:<.cctor>b__281_0 (object) + void System.Threading.Tasks.Task/<>c:<.cctor>b__292_0 (object) void System.Threading.Tasks.Task/ContingentProperties:SetCompleted () void System.Threading.Tasks.Task/ContingentProperties:UnregisterCancellationCallback () void System.Threading.Tasks.Task/DelayPromise:.cctor () @@ -7449,7 +7929,7 @@ Methods: void System.Uri:.ctor (string,System.UriKind) void System.Uri:.ctor (string) void System.Uri:.ctor (System.Uri,string) - void System.Uri:CheckAuthorityHelperHandleDnsIri (char*,int,int,bool,System.Uri/Flags&,bool&,string&,System.ParsingError&) + void System.Uri:CheckAuthorityHelperHandleDnsIri (char*,int,int,bool,System.Uri/Flags&,string&,System.ParsingError&) void System.Uri:Compress (char[],int,int&,System.UriParser) void System.Uri:CreateHostString () void System.Uri:CreateThis (string,bool,System.UriKind,System.UriCreationOptions&) diff --git a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui.aotprofile b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui.aotprofile index e8295af5c4e0..d3d22f4af567 100644 Binary files a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui.aotprofile and b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui.aotprofile differ diff --git a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui.aotprofile.txt b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui.aotprofile.txt index 788e45ca973b..86d1beb208c9 100644 --- a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui.aotprofile.txt +++ b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui.aotprofile.txt @@ -1,4 +1,5 @@ Methods: + __XamlGeneratedCode__.__TypeA6EB4B27A3A00AE8 System.Activator:CreateInstance () Android.Animation.Animator Android.Animation.ValueAnimator:SetDuration (long) Android.Animation.ValueAnimator Android.Animation.ValueAnimator:OfFloat (single[]) Android.Animation.ValueAnimator/IAnimatorUpdateListenerImplementor Android.Animation.ValueAnimator:__CreateIAnimatorUpdateListenerImplementor () @@ -233,6 +234,7 @@ Methods: AndroidX.Navigation.NavigatorProvider AndroidX.Navigation.NavController:get_NavigatorProvider () AndroidX.Navigation.UI.AppBarConfiguration AndroidX.Navigation.UI.AppBarConfiguration/Builder:Build () AndroidX.Navigation.UI.AppBarConfiguration/Builder AndroidX.Navigation.UI.AppBarConfiguration/Builder:SetOpenableLayout (AndroidX.CustomView.Widget.IOpenable) + AndroidX.RecyclerView.Widget.RecyclerView/Adapter AndroidX.RecyclerView.Widget.RecyclerView:GetAdapter () AndroidX.RecyclerView.Widget.RecyclerView/Adapter AndroidX.ViewPager2.Widget.ViewPager2:get_Adapter () AndroidX.RecyclerView.Widget.RecyclerView/ViewHolder Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRecyclerAdapter:OnCreateViewHolder (Android.Views.ViewGroup,int) AndroidX.ViewPager2.Widget.ViewPager2 Microsoft.Maui.Controls.TabbedPage:CreatePlatformView () @@ -256,13 +258,13 @@ Methods: bool Android.Runtime.InputStreamInvoker:get_CanSeek () bool Android.Runtime.InputStreamInvoker:get_CanWrite () bool Android.Runtime.JavaArray`1/d__13:MoveNext () - bool Android.Runtime.JavaDictionary:b__36_0 (intptr) + bool Android.Runtime.JavaDictionary:b__37_0 (intptr) bool Android.Runtime.JavaDictionary:Contains (object) bool Android.Runtime.JNIEnv:CallBooleanMethod (intptr,intptr,Android.Runtime.JValue[]) bool Android.Runtime.JNIEnv:CallBooleanMethod (intptr,intptr,Android.Runtime.JValue*) - bool Android.Runtime.JNIEnv:CallBooleanMethod (intptr,intptr) bool Android.Runtime.JNIEnv:IsGCUserPeer (intptr) bool Android.Runtime.JNIEnv:IsInstanceOf (intptr,intptr) + bool Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPJ_Z (_JniMarshal_PPJ_Z,intptr,intptr,long) bool Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPL_Z (_JniMarshal_PPL_Z,intptr,intptr,intptr) bool Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPLLJ_Z (_JniMarshal_PPLLJ_Z,intptr,intptr,intptr,intptr,long) bool Android.Runtime.Logger:get_LogGlobalRef () @@ -272,21 +274,26 @@ Methods: bool Android.Views.View:get_ScrollbarFadingEnabled () bool Android.Views.View:get_VerticalScrollBarEnabled () bool Android.Views.View/IOnAttachStateChangeListenerImplementor:__IsEmpty (Android.Views.View/IOnAttachStateChangeListenerImplementor) + bool Android.Views.View/IOnFocusChangeListenerImplementor:__IsEmpty (Android.Views.View/IOnFocusChangeListenerImplementor) bool Android.Views.View/IOnLayoutChangeListenerImplementor:__IsEmpty (Android.Views.View/IOnLayoutChangeListenerImplementor) bool Android.Views.ViewGroup:DrawChild (Android.Graphics.Canvas,Android.Views.View,long) bool Android.Views.ViewGroup:n_DrawChild_Landroid_graphics_Canvas_Landroid_view_View_J (intptr,intptr,intptr,intptr,long) + bool Android.Views.ViewGroup/IOnHierarchyChangeListenerImplementor:__IsEmpty (Android.Views.ViewGroup/IOnHierarchyChangeListenerImplementor) bool AndroidX.AppCompat.View.Menu.MenuItemImpl:get_IsChecked () bool AndroidX.AppCompat.View.Menu.MenuItemImpl:get_IsEnabled () bool AndroidX.Core.Widget.NestedScrollView:get_FillViewport () + bool AndroidX.Core.Widget.NestedScrollView/IOnScrollChangeListenerImplementor:__IsEmpty (AndroidX.Core.Widget.NestedScrollView/IOnScrollChangeListenerImplementor) bool AndroidX.DrawerLayout.Widget.DrawerLayout:IsDrawerOpen (Android.Views.View) + bool AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor:__IsEmpty (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor) bool AndroidX.Fragment.App.Fragment:get_IsAdded () bool AndroidX.Fragment.App.FragmentManager:get_IsDestroyed () bool AndroidX.Fragment.App.FragmentManager:get_IsStateSaved () + bool AndroidX.ViewPager2.Adapter.FragmentStateAdapter:n_ContainsItem_J (intptr,intptr,long) bool Google.Android.Material.Navigation.NavigationBarView/IOnItemSelectedListenerInvoker:n_OnNavigationItemSelected_Landroid_view_MenuItem_ (intptr,intptr,intptr) bool Java.Interop.JavaConvert:WithLocalJniHandle (object,System.Func`2) bool Java.Interop.JniEnvironment/InstanceMethods:CallBooleanMethod (Java.Interop.JniObjectReference,Java.Interop.JniMethodInfo,Java.Interop.JniArgumentValue*) - bool Java.Interop.JniEnvironment/InstanceMethods:CallBooleanMethod (Java.Interop.JniObjectReference,Java.Interop.JniMethodInfo) bool Java.Interop.JniEnvironment/InstanceMethods:CallNonvirtualBooleanMethod (Java.Interop.JniObjectReference,Java.Interop.JniObjectReference,Java.Interop.JniMethodInfo,Java.Interop.JniArgumentValue*) + bool Java.Interop.JniEnvironment/Types:IsAssignableFrom (Java.Interop.JniObjectReference,Java.Interop.JniObjectReference) bool Java.Interop.JniEnvironment/Types:IsInstanceOf (Java.Interop.JniObjectReference,Java.Interop.JniObjectReference) bool Java.Interop.JniEnvironment/Types:IsSameObject (Java.Interop.JniObjectReference,Java.Interop.JniObjectReference) bool Java.Interop.JniEnvironment/Types:TryRawFindClass (intptr,string,intptr&,intptr&) @@ -299,9 +306,9 @@ Methods: bool Java.Interop.JniPeerMembers/JniInstanceMethods:TryInvokeObjectStaticRedirect (Java.Interop.JniMethodInfo,Java.Interop.IJavaPeerable,Java.Interop.JniArgumentValue*,Java.Interop.JniObjectReference&) bool Java.Interop.JniPeerMembers/JniInstanceMethods:TryInvokeSingleStaticRedirect (Java.Interop.JniMethodInfo,Java.Interop.IJavaPeerable,Java.Interop.JniArgumentValue*,single&) bool Java.Interop.JniPeerMembers/JniInstanceMethods:TryInvokeVoidStaticRedirect (Java.Interop.JniMethodInfo,Java.Interop.IJavaPeerable,Java.Interop.JniArgumentValue*) - bool Java.Interop.JniRuntime:GetBuiltInTypeArraySignature (System.Type,Java.Interop.JniTypeSignature&) bool Java.Interop.JniRuntime:GetBuiltInTypeSignature (System.Type,Java.Interop.JniTypeSignature&) bool Java.Interop.JniRuntime/JniObjectReferenceManager:get_LogGlobalReferenceMessages () + bool Java.Interop.JniRuntime/JniTypeManager:GetBuiltInTypeArraySignature (System.Type,Java.Interop.JniTypeSignature&) bool Java.Interop.JniType:TryGetStaticMethod (string,string,Java.Interop.JniMethodInfo&) bool Java.Interop.Runtime:IsGCUserPeer (intptr) bool Java.Interop.TypeManager:get_ActivationEnabled () @@ -325,8 +332,8 @@ Methods: bool Microsoft.Maui.Controls.BaseShellItem:get_IsVisible () bool Microsoft.Maui.Controls.BindableObject:IsSet (Microsoft.Maui.Controls.BindableProperty) bool Microsoft.Maui.Controls.BindableProperty:TryConvert (object&) - bool Microsoft.Maui.Controls.BindingExpression:TryConvert (object&,Microsoft.Maui.Controls.BindableProperty,System.Type,bool) bool Microsoft.Maui.Controls.BindingExpression/BindingExpressionPart:TryGetValue (object,object&) + bool Microsoft.Maui.Controls.BindingExpressionHelper:TryConvert (object&,Microsoft.Maui.Controls.BindableProperty,System.Type,bool) bool Microsoft.Maui.Controls.Brush:IsNullOrEmpty (Microsoft.Maui.Controls.Brush) bool Microsoft.Maui.Controls.Button:get_FontAutoScalingEnabled () bool Microsoft.Maui.Controls.Button:get_IsEnabledCore () @@ -344,12 +351,13 @@ Methods: bool Microsoft.Maui.Controls.DependencyService/<>c__DisplayClass11_0:b__0 (Microsoft.Maui.Controls.DependencyService/DependencyType) bool Microsoft.Maui.Controls.Element:RemoveLogicalChild (Microsoft.Maui.Controls.Element,int) bool Microsoft.Maui.Controls.Element:RemoveLogicalChild (Microsoft.Maui.Controls.Element) - bool Microsoft.Maui.Controls.Element/d__101`1:MoveNext () - bool Microsoft.Maui.Controls.Element/d__112:MoveNext () + bool Microsoft.Maui.Controls.Element/d__103`1:MoveNext () + bool Microsoft.Maui.Controls.Element/d__114:MoveNext () bool Microsoft.Maui.Controls.FileImageSource:get_IsEmpty () bool Microsoft.Maui.Controls.FlyoutPage:get_IsPresented () bool Microsoft.Maui.Controls.FlyoutPage:Microsoft.Maui.Controls.IFlyoutPageController.get_ShouldShowSplitMode () bool Microsoft.Maui.Controls.FlyoutPage:ShouldShowToolbarButton () + bool Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors:ShouldUseSetter (Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty) bool Microsoft.Maui.Controls.Grid/<>c:<.cctor>b__59_0 (Microsoft.Maui.Controls.BindableObject,object) bool Microsoft.Maui.Controls.Grid/<>c:<.cctor>b__59_4 (Microsoft.Maui.Controls.BindableObject,object) bool Microsoft.Maui.Controls.Grid/<>c:<.cctor>b__59_5 (Microsoft.Maui.Controls.BindableObject,object) @@ -360,6 +368,7 @@ Methods: bool Microsoft.Maui.Controls.Handlers.TabbedPageManager/Listeners:Google.Android.Material.Navigation.NavigationBarView.IOnItemSelectedListener.OnNavigationItemSelected (Android.Views.IMenuItem) bool Microsoft.Maui.Controls.IElementExtensions:IsShimmed (Microsoft.Maui.IElement) bool Microsoft.Maui.Controls.ImageSource:IsNullOrEmpty (Microsoft.Maui.Controls.ImageSource) + bool Microsoft.Maui.Controls.ImageSourceConverter:CanConvertFrom (System.ComponentModel.ITypeDescriptorContext,System.Type) bool Microsoft.Maui.Controls.Label:get_FontAutoScalingEnabled () bool Microsoft.Maui.Controls.Label:get_HasFormattedTextSpans () bool Microsoft.Maui.Controls.Label:IsLabelSizeable (Microsoft.Maui.Controls.Label) @@ -392,6 +401,8 @@ Methods: bool Microsoft.Maui.Controls.Platform.DragAndDropGestureHandler:HasAnyDropGestures () bool Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_IsModalPlatformReady () bool Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_IsModalReady () + bool Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_IsWindowReadyForModals () + bool Microsoft.Maui.Controls.Platform.MultiPageFragmentStateAdapter`1:ContainsItem (long) bool Microsoft.Maui.Controls.Platform.PointerGestureHandler:HasAnyPointerGestures () bool Microsoft.Maui.Controls.Platform.SemanticExtensions:ControlsAccessibilityDelegateNeeded (Microsoft.Maui.Controls.View) bool Microsoft.Maui.Controls.Platform.SemanticExtensions:TapGestureRecognizerNeedsDelegate (Microsoft.Maui.Controls.View) @@ -405,7 +416,7 @@ Methods: bool Microsoft.Maui.Controls.ResourceDictionary:TryGetMergedDictionaryValue (string,object&,Microsoft.Maui.Controls.ResourceDictionary&) bool Microsoft.Maui.Controls.ResourceDictionary:TryGetValue (string,object&) bool Microsoft.Maui.Controls.ResourceDictionary:TryGetValueAndSource (string,object&,Microsoft.Maui.Controls.ResourceDictionary&) - bool Microsoft.Maui.Controls.ResourceDictionary/d__42:MoveNext () + bool Microsoft.Maui.Controls.ResourceDictionary/d__46:MoveNext () bool Microsoft.Maui.Controls.ResourcesExtensions:TryGetResource (Microsoft.Maui.Controls.IElementDefinition,string,object&) bool Microsoft.Maui.Controls.RouteRequestBuilder:g__AddNode|27_0 (Microsoft.Maui.Controls.BaseShellItem,string) bool Microsoft.Maui.Controls.RouteRequestBuilder:AddMatch (Microsoft.Maui.Controls.ShellUriHandler/NodeLocation) @@ -414,13 +425,12 @@ Methods: bool Microsoft.Maui.Controls.Routing:IsImplicit (string) bool Microsoft.Maui.Controls.Routing:IsUserDefined (Microsoft.Maui.Controls.BindableObject) bool Microsoft.Maui.Controls.Routing:IsUserDefined (string) - bool Microsoft.Maui.Controls.SetterSpecificity:Equals (Microsoft.Maui.Controls.SetterSpecificity) - bool Microsoft.Maui.Controls.SetterSpecificity:op_Equality (Microsoft.Maui.Controls.SetterSpecificity,Microsoft.Maui.Controls.SetterSpecificity) - bool Microsoft.Maui.Controls.SetterSpecificity:op_Inequality (Microsoft.Maui.Controls.SetterSpecificity,Microsoft.Maui.Controls.SetterSpecificity) bool Microsoft.Maui.Controls.Shell:get_FlyoutIsPresented () bool Microsoft.Maui.Controls.Shell:GetEffectiveValue (Microsoft.Maui.Controls.BindableProperty,System.Func`1,System.Action`1,Microsoft.Maui.Controls.Element,bool) bool Microsoft.Maui.Controls.Shell:GetFlyoutItemIsVisible (Microsoft.Maui.Controls.BindableObject) bool Microsoft.Maui.Controls.Shell:GetNavBarHasShadow (Microsoft.Maui.Controls.BindableObject) + bool Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.RemoveAppearanceObserver (Microsoft.Maui.Controls.IAppearanceObserver) + bool Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.RemoveFlyoutBehaviorObserver (Microsoft.Maui.Controls.IFlyoutBehaviorObserver) bool Microsoft.Maui.Controls.ShellAppearance:Ingest (Microsoft.Maui.Controls.Element) bool Microsoft.Maui.Controls.ShellAppearance:op_Equality (Microsoft.Maui.Controls.ShellAppearance,Microsoft.Maui.Controls.ShellAppearance) bool Microsoft.Maui.Controls.ShellContent:get_IsVisibleContent () @@ -435,6 +445,7 @@ Methods: bool Microsoft.Maui.Controls.ShellNavigatingEventArgs:get_NavigationDelayedOrCancelled () bool Microsoft.Maui.Controls.ShellNavigationManager:ProposeNavigationOutsideGotoAsync (Microsoft.Maui.Controls.ShellNavigationSource,Microsoft.Maui.Controls.ShellItem,Microsoft.Maui.Controls.ShellSection,Microsoft.Maui.Controls.ShellContent,System.Collections.Generic.IReadOnlyList`1,bool,bool) bool Microsoft.Maui.Controls.ShellSection:get_IsVisibleSection () + bool Microsoft.Maui.Controls.ShellSection:Microsoft.Maui.Controls.IShellSectionController.RemoveDisplayedPageObserver (object) bool Microsoft.Maui.Controls.ShellToolbar:b__11_0 () bool Microsoft.Maui.Controls.ShellToolbar:get_DrawerToggleVisible () bool Microsoft.Maui.Controls.ShellUriHandler:IsTargetRelativePop (Microsoft.Maui.Controls.ShellNavigationParameters) @@ -444,15 +455,21 @@ Methods: bool Microsoft.Maui.Controls.StyleSheets.StyleSheetExtensions/d__0:MoveNext () bool Microsoft.Maui.Controls.Toolbar:get_BackButtonVisible () bool Microsoft.Maui.Controls.Toolbar:get_DrawerToggleVisible () + bool Microsoft.Maui.Controls.TypeConversionHelper:g__HasSuitableParameterType|3_2 (System.Reflection.MethodInfo,System.Type) + bool Microsoft.Maui.Controls.TypeConversionHelper:g__HasSuitableReturnType|3_3 (System.Reflection.MethodInfo,System.Type) + bool Microsoft.Maui.Controls.TypeConversionHelper:g__IsImplicitOperator|3_1 (System.Reflection.MethodInfo) + bool Microsoft.Maui.Controls.TypeConversionHelper:ShouldCheckForImplicitConversionOperator (System.Type) + bool Microsoft.Maui.Controls.TypeConversionHelper:TryConvert (object,System.Type,object&) + bool Microsoft.Maui.Controls.TypeConversionHelper:TryConvertUsingImplicitCastOperator (object,System.Type,object&) bool Microsoft.Maui.Controls.ViewExtensions/d__22:MoveNext () bool Microsoft.Maui.Controls.VisualElement:get_InputTransparent () bool Microsoft.Maui.Controls.VisualElement:get_InputTransparentCore () bool Microsoft.Maui.Controls.VisualElement:get_IsEnabled () bool Microsoft.Maui.Controls.VisualElement:get_IsEnabledCore () bool Microsoft.Maui.Controls.VisualElement:get_IsFocused () + bool Microsoft.Maui.Controls.VisualElement:get_IsLoaded () bool Microsoft.Maui.Controls.VisualElement:get_IsVisible () bool Microsoft.Maui.Controls.VisualElement:IsMocked () - bool Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.Controls.IFlowDirectionController.get_ApplyEffectiveFlowDirectionToChildContainer () bool Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.Controls.IResourcesProvider.get_IsResourcesCreated () bool Microsoft.Maui.Controls.VisualState:Equals (Microsoft.Maui.Controls.VisualState) bool Microsoft.Maui.Controls.VisualState:Equals (object) @@ -469,6 +486,7 @@ Methods: bool Microsoft.Maui.Controls.WeakEventProxy`2:TryGetSource (System.ComponentModel.INotifyPropertyChanged&) bool Microsoft.Maui.Controls.Xaml.StaticResourceExtension:TryGetApplicationLevelResource (string,object&,Microsoft.Maui.Controls.ResourceDictionary&) bool Microsoft.Maui.Controls.Xaml.StaticResourceExtension:TryGetResource (string,System.Collections.Generic.IEnumerable`1,object&,Microsoft.Maui.Controls.ResourceDictionary&) + bool Microsoft.Maui.Controls.Xaml.TypeConversionExtensions:TryGetTypeConverter (System.Reflection.MemberInfo,System.ComponentModel.TypeConverter&) bool Microsoft.Maui.DebuggerHelper:get_DebuggerIsAttached () bool Microsoft.Maui.Devices.DeviceIdiom:Equals (Microsoft.Maui.Devices.DeviceIdiom) bool Microsoft.Maui.Devices.DeviceIdiom:Equals (string) @@ -502,8 +520,8 @@ Methods: bool Microsoft.Maui.Handlers.ImageHandler:get_NeedsContainer () bool Microsoft.Maui.Handlers.ViewHandler:get_HasContainer () bool Microsoft.Maui.Handlers.ViewHandler:get_NeedsContainer () - bool Microsoft.Maui.Hosting.Internal.MauiFactory:TryGetServiceDescriptors (System.Type&,Microsoft.Extensions.DependencyInjection.ServiceDescriptor&,System.Collections.Generic.IEnumerable`1&) bool Microsoft.Maui.Hosting.Internal.MauiServiceCollection:TryGetService (System.Type,Microsoft.Extensions.DependencyInjection.ServiceDescriptor&) + bool Microsoft.Maui.HotReload.MauiHotReloadHelper:get_IsSupported () bool Microsoft.Maui.JavaObjectExtensions:IsAlive (Android.Runtime.IJavaObject) bool Microsoft.Maui.JavaObjectExtensions:IsAlive (Java.Lang.Object) bool Microsoft.Maui.JavaObjectExtensions:IsDisposed (Android.Runtime.IJavaObject) @@ -525,13 +543,18 @@ Methods: bool Microsoft.Maui.Platform.ThemeExtensions:TryResolveAttribute (Android.Content.Res.Resources/Theme,int) bool Microsoft.Maui.Platform.ViewExtensions:IsLoaded (Android.Views.View) bool Microsoft.Maui.Platform.ViewExtensions:IsLoadedOnPlatform (Microsoft.Maui.IElement) + bool Microsoft.Maui.PrimitiveTypeConversions:IsImplicitlyConvertibleToDouble (System.Type) + bool Microsoft.Maui.PrimitiveTypeConversions:TryGetDouble (object,double&) bool Microsoft.Maui.PropertyMapper/d__17:MoveNext () + bool Microsoft.Maui.RuntimeFeature:get_IsImplicitCastOperatorsUsageViaReflectionSupported () bool Microsoft.Maui.StringExtensions:ContainsChar (string,char) bool Microsoft.Maui.Thickness:Equals (Microsoft.Maui.Thickness) bool Microsoft.Maui.Thickness:Equals (object) bool Microsoft.Maui.Thickness:get_IsNaN () bool Microsoft.Maui.ViewExtensions:NeedsContainer (Microsoft.Maui.IView) bool Microsoft.Maui.ViewHandlerExtensions:NeedsExactMeasure (Microsoft.Maui.IView) + bool Microsoft.Maui.VisualDiagnostics:get_IsEnabled () + bool Microsoft.Maui.VisualDiagnostics/<>c:<.cctor>b__18_0 () bool Microsoft.Maui.VisualDiagnosticsOverlay:Deinitialize () bool Microsoft.Maui.WeakList`1/<>c:b__12_0 (System.WeakReference`1) bool Microsoft.Maui.WindowOverlay:Deinitialize () @@ -548,8 +571,11 @@ Methods: bool System.Boolean:IsTrueStringIgnoreCase (System.ReadOnlySpan`1) bool System.Boolean:TryParse (string,bool&) bool System.Boolean:TryParse (System.ReadOnlySpan`1,bool&) + bool System.Buffers.SearchValues:g__ShouldUseProbabilisticMap|1_0 (int,int) bool System.Buffers.SearchValues:TryGetSingleRange (System.ReadOnlySpan`1,byte&,byte&) bool System.Buffers.SearchValues:TryGetSingleRange (System.ReadOnlySpan`1,char&,char&) + bool System.Buffers.SearchValues`1:ContainsAny (System.ReadOnlySpan`1) + bool System.Buffers.SearchValues`1:ContainsAnyExcept (System.ReadOnlySpan`1) bool System.Buffers.SharedArrayPool`1/<>c:b__11_0 (object) bool System.Buffers.SharedArrayPool`1/<>c:b__11_0 (object) bool System.Buffers.SharedArrayPool`1:Trim () @@ -565,9 +591,9 @@ Methods: bool System.Collections.Concurrent.ConcurrentDictionary`2:TryGetValueInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,int,Microsoft.Extensions.DependencyInjection.ServiceProvider/ServiceAccessor&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,System.Nullable`1,object,bool,bool,object&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryGetValueInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,int,object&) + bool System.Collections.Concurrent.ConcurrentDictionary`2:TryGetValueInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,Microsoft.Maui.Hosting.IMauiHandlersCollection,int,Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,System.Reflection.MemberInfo,System.Nullable`1,System.ComponentModel.TypeConverter,bool,bool,System.ComponentModel.TypeConverter&) bool System.Collections.Concurrent.ConcurrentDictionary`2:TryGetValue (System.Reflection.MemberInfo,System.ComponentModel.TypeConverter&) - bool System.Collections.Concurrent.ConcurrentDictionary`2:TryGetValueInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables,System.Type,int,System.Type&) bool System.Collections.Concurrent.ConcurrentDictionary`2>>:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables>>,System.Type,System.Nullable`1,System.ValueTuple`2>,bool,bool,System.ValueTuple`2>&) bool System.Collections.Concurrent.ConcurrentDictionary`2>>:TryGetValue (System.Type,System.ValueTuple`2>&) bool System.Collections.Concurrent.ConcurrentDictionary`2, Android.Graphics.Typeface>:TryAddInternal (System.Collections.Concurrent.ConcurrentDictionary`2/Tables, Android.Graphics.Typeface>,System.ValueTuple`3,System.Nullable`1,Android.Graphics.Typeface,bool,bool,Android.Graphics.Typeface&) @@ -589,6 +615,7 @@ Methods: bool System.Collections.Generic.Dictionary`2:TryGetValue (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/ServiceDescriptorCacheItem&) bool System.Collections.Generic.Dictionary`2:TryInsert (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/ServiceDescriptorCacheItem,System.Collections.Generic.InsertionBehavior) bool System.Collections.Generic.Dictionary`2>:Remove (Microsoft.Maui.Controls.BindableProperty) + bool System.Collections.Generic.Dictionary`2>:TryGetValue (Microsoft.Maui.Controls.BindableProperty,System.ValueTuple`2&) bool System.Collections.Generic.Dictionary`2>:TryInsert (Microsoft.Maui.Controls.BindableProperty,System.ValueTuple`2,System.Collections.Generic.InsertionBehavior) bool System.Collections.Generic.Dictionary`2:TryInsert (int,bool,System.Collections.Generic.InsertionBehavior) bool System.Collections.Generic.Dictionary`2:TryInsert (long,Microsoft.Maui.Controls.ShellContent,System.Collections.Generic.InsertionBehavior) @@ -612,13 +639,12 @@ Methods: bool System.Collections.Generic.Dictionary`2>:TryInsert (string,System.ValueTuple`2,System.Collections.Generic.InsertionBehavior) bool System.Collections.Generic.Dictionary`2>:TryGetValue (string,System.ValueTuple`3&) bool System.Collections.Generic.EnumEqualityComparer`1:Equals (Microsoft.Maui.FontWeight,Microsoft.Maui.FontWeight) - bool System.Collections.Generic.GenericEqualityComparer`1:Equals (string,string) - bool System.Collections.Generic.HashSet`1/Enumerator:MoveNext () + bool System.Collections.Generic.GenericEqualityComparer`1>>:Equals (System.ValueTuple`2>,System.ValueTuple`2>) + bool System.Collections.Generic.HashSet`1/Enumerator:MoveNext () bool System.Collections.Generic.HashSet`1:Add (string) bool System.Collections.Generic.HashSet`1:AddIfNotPresent (string,int&) - bool System.Collections.Generic.HashSet`1:Contains (System.Type) - bool System.Collections.Generic.List`1/Enumerator:MoveNext () - bool System.Collections.Generic.List`1/Enumerator:MoveNextRare () + bool System.Collections.Generic.HashSet`1:Contains (string) + bool System.Collections.Generic.HashSet`1:Remove (string) bool System.Collections.Generic.List`1/Enumerator:MoveNext () bool System.Collections.Generic.List`1/Enumerator:MoveNextRare () bool System.Collections.Generic.List`1/Enumerator>:MoveNext () @@ -632,19 +658,19 @@ Methods: bool System.Collections.Generic.List`1:System.Collections.Generic.ICollection.get_IsReadOnly () bool System.Collections.Generic.List`1:Contains (Microsoft.Maui.Hosting.FontDescriptor) bool System.Collections.Generic.List`1>:Remove (System.Action`2) + bool System.Collections.Generic.List`1>>:Remove (System.ValueTuple`2>) bool System.Collections.Generic.NonRandomizedStringEqualityComparer/OrdinalComparer:Equals (string,string) bool System.Collections.Generic.NonRandomizedStringEqualityComparer/OrdinalIgnoreCaseComparer:Equals (string,string) bool System.Collections.Generic.NullableEqualityComparer`1:Equals (System.Nullable`1,System.Nullable`1) bool System.Collections.Generic.ObjectEqualityComparer`1:Equals (System.Type,System.Type) - bool System.Collections.Generic.SortedList`2/Enumerator:MoveNext () - bool System.Collections.Generic.SortedList`2/Enumerator:MoveNext () - bool System.Collections.Generic.SortedList`2:Remove (Microsoft.Maui.Controls.SetterSpecificity) - bool System.Collections.Generic.SortedList`2:Remove (Microsoft.Maui.Controls.SetterSpecificity) + bool System.Collections.Generic.Stack`1/Enumerator:MoveNext () + bool System.Collections.Generic.StringEqualityComparer:Equals (string,string) bool System.Collections.Hashtable:KeyEquals (object,object) bool System.Collections.ObjectModel.Collection`1:Contains (Microsoft.Maui.Controls.Element) bool System.Collections.ObjectModel.Collection`1:IsCompatibleObject (object) bool System.Collections.ObjectModel.Collection`1:System.Collections.IList.Contains (object) bool System.Collections.Specialized.SingleItemReadOnlyList/d__15:MoveNext () + bool System.ComponentModel.TypeConverter:CanConvertFrom (System.Type) bool System.DefaultBinder:CanChangePrimitive (System.Type,System.Type) bool System.Delegate:Equals (object) bool System.Delegate:IsArgumentTypeMatch (System.Type,System.Type) @@ -652,14 +678,15 @@ Methods: bool System.Delegate:IsReturnTypeMatch (System.Type,System.Type) bool System.Diagnostics.Debugger:get_IsAttached () bool System.Diagnostics.Debugger:IsAttached_internal () - bool System.Diagnostics.DiagnosticsHelper:CompareTags (System.Collections.Generic.List`1>,System.Collections.Generic.IEnumerable`1>) + bool System.Diagnostics.DiagnosticsHelper:CompareTags (System.Collections.Generic.IList`1>,System.Collections.Generic.IEnumerable`1>) + bool System.Diagnostics.Metrics.InstrumentAdvice`1:IsSortedAndDistinct (System.Collections.Generic.List`1) bool System.Diagnostics.Metrics.Meter:InitializeIsSupported () - bool System.Diagnostics.Tracing.EventSource:InitializeIsSupported () bool System.DomainNameHelper:IsValid (System.ReadOnlySpan`1,bool,bool,int&) bool System.Double:Equals (double) bool System.Double:Equals (object) bool System.Double:TryParse (string,System.Globalization.NumberStyles,System.IFormatProvider,double&) bool System.Enum:Equals (object) + bool System.Environment:get_IsSingleProcessor () bool System.GenericEmptyEnumeratorBase:MoveNext () bool System.Globalization.CompareInfo:GetIsAsciiEqualityOrdinal (string) bool System.Globalization.CompareInfo:IcuStartsWith (System.ReadOnlySpan`1,System.ReadOnlySpan`1,System.Globalization.CompareOptions,int*) @@ -675,12 +702,15 @@ Methods: bool System.Globalization.CultureInfo:get_HasInvariantCultureName () bool System.Globalization.CultureInfo:VerifyCultureName (string,bool) bool System.Globalization.GlobalizationMode:get_Invariant () + bool System.Globalization.GlobalizationMode:get_InvariantNoLoad () bool System.Globalization.GlobalizationMode:TryGetAppLocalIcuSwitchValue (string&) bool System.Globalization.GlobalizationMode:TryGetStringValue (string,string,string&) bool System.Globalization.GlobalizationMode/Settings:get_Invariant () bool System.Globalization.Ordinal:EqualsIgnoreCase_Scalar (char&,char&,int) - bool System.Globalization.Ordinal:EqualsIgnoreCase_Vector128 (char&,char&,int) + bool System.Globalization.Ordinal:EqualsIgnoreCase_Vector (char&,char&,int) bool System.Guid:TryWriteBytes (System.Span`1) + bool System.Int128:op_GreaterThan (System.Int128,System.Int128) + bool System.Int128:op_LessThan (System.Int128,System.Int128) bool System.Int32:Equals (object) bool System.Int32:TryFormat (System.Span`1,int&,System.ReadOnlySpan`1,System.IFormatProvider) bool System.Int64:TryParse (System.ReadOnlySpan`1,System.Globalization.NumberStyles,System.IFormatProvider,long&) @@ -689,24 +719,22 @@ Methods: bool System.IO.FileSystem:FileExists (System.ReadOnlySpan`1,Interop/ErrorInfo&) bool System.IO.FileSystem:FileExists (System.ReadOnlySpan`1) bool System.IO.MemoryStream:get_CanWrite () - bool System.IO.Path:IsPathRooted (string) - bool System.IO.Path:IsPathRooted (System.ReadOnlySpan`1) bool System.IO.PathInternal:EndsInDirectorySeparator (System.ReadOnlySpan`1) bool System.IO.Stream:HasOverriddenBeginEndRead () bool System.IO.UnmanagedMemoryStream:get_CanRead () bool System.IO.UnmanagedMemoryStream:get_CanSeek () - bool System.Linq.Enumerable:g__WithEnumerator|8_0 (System.Collections.Generic.IEnumerable`1) + bool System.Lazy`1:CreateValue () + bool System.Lazy`1:get_Value () bool System.Linq.Enumerable:Any (System.Collections.Generic.IEnumerable`1,System.Func`2) bool System.Linq.Enumerable:Any (System.Collections.Generic.IEnumerable`1) bool System.Linq.Enumerable:Any (System.Collections.Generic.IEnumerable`1,System.Func`2) bool System.Linq.Enumerable:Contains (System.Collections.Generic.IEnumerable`1,Microsoft.Maui.Controls.Element,System.Collections.Generic.IEqualityComparer`1) bool System.Linq.Enumerable:Contains (System.Collections.Generic.IEnumerable`1,Microsoft.Maui.Controls.Element) - bool System.Linq.Enumerable:TryGetNonEnumeratedCount (System.Collections.Generic.IEnumerable`1,int&) - bool System.Linq.Enumerable/d__41`1:MoveNext () - bool System.Linq.Enumerable/SelectListIterator`2:MoveNext () - bool System.Linq.Enumerable/WhereListIterator`1:MoveNext () - bool System.Linq.Extensions/d__5`1:MoveNext () - bool System.Linq.OrderedEnumerable`1/d__4:MoveNext () + bool System.Linq.Enumerable/ListSelectIterator`2:MoveNext () + bool System.Linq.Enumerable/ListWhereIterator`1:MoveNext () + bool System.Linq.Enumerable/OfTypeIterator`1:MoveNext () + bool System.Linq.Enumerable/OrderedIterator`2:MoveNext () + bool System.Linq.Extensions/d__6`1:MoveNext () bool System.LocalAppContextSwitches:GetCachedSwitchValueInternal (string,int&) bool System.LocalAppContextSwitches:GetSwitchDefaultValue (string) bool System.MemoryExtensions:Equals (System.ReadOnlySpan`1,System.ReadOnlySpan`1,System.StringComparison) @@ -719,7 +747,6 @@ Methods: bool System.Net.Http.Headers.HeaderDescriptor:TryGet (string,System.Net.Http.Headers.HeaderDescriptor&) bool System.Net.Http.Headers.HeaderUtilities:TryParseInt64 (string,int,int,long&) bool System.Net.Http.Headers.HttpHeaders:TryAddWithoutValidation (string,System.Collections.Generic.IEnumerable`1) - bool System.Net.Http.Headers.HttpHeaders:TryAddWithoutValidation (System.Net.Http.Headers.HeaderDescriptor,string) bool System.Net.Http.Headers.HttpHeaders:TryAddWithoutValidation (System.Net.Http.Headers.HeaderDescriptor,System.Collections.Generic.IEnumerable`1) bool System.Net.Http.Headers.HttpHeaders:TryGetAndParseHeaderInfo (System.Net.Http.Headers.HeaderDescriptor,System.Net.Http.Headers.HttpHeaders/HeaderStoreItemInfo&) bool System.Net.Http.Headers.HttpHeaders:TryGetHeaderDescriptor (string,System.Net.Http.Headers.HeaderDescriptor&) @@ -759,9 +786,17 @@ Methods: bool System.Private.CoreLib.KeyCollection/Enumerator>:MoveNext () bool System.Private.CoreLib.ValueCollection/Enumerator:MoveNext () bool System.Reflection.Assembly:op_Inequality (System.Reflection.Assembly,System.Reflection.Assembly) + bool System.Reflection.AssemblyNameParser:IsAttribute (string,string) bool System.Reflection.AssemblyNameParser:IsWhiteSpace (char) + bool System.Reflection.AssemblyNameParser:TryGetNextToken (string&,System.Reflection.AssemblyNameParser/Token&) + bool System.Reflection.AssemblyNameParser:TryParse (System.Reflection.AssemblyNameParser/AssemblyNameParts&) + bool System.Reflection.AssemblyNameParser:TryParseCulture (string,string&) + bool System.Reflection.AssemblyNameParser:TryParsePKT (string,bool,byte[]&) + bool System.Reflection.AssemblyNameParser:TryParseVersion (string,System.Version&) bool System.Reflection.ConstructorInfo:op_Inequality (System.Reflection.ConstructorInfo,System.Reflection.ConstructorInfo) bool System.Reflection.CustomAttribute:AttrTypeMatches (System.Type,System.Type) + bool System.Reflection.CustomAttribute:IsDefined (System.Reflection.ICustomAttributeProvider,System.Type,bool) + bool System.Reflection.CustomAttribute:IsDefinedInternal (System.Reflection.ICustomAttributeProvider,System.Type) bool System.Reflection.CustomAttribute:IsUserCattrProvider (object) bool System.Reflection.MethodBase:get_IsPublic () bool System.Reflection.MethodBase:get_IsSpecialName () @@ -772,11 +807,11 @@ Methods: bool System.Reflection.ParameterInfo:get_IsIn () bool System.Reflection.ParameterInfo:get_IsOptional () bool System.Reflection.ParameterInfo:get_IsOut () + bool System.Reflection.RuntimeAssembly:get_IsCollectible () + bool System.Reflection.RuntimeConstructorInfo:IsDefined (System.Type,bool) bool System.Reflection.RuntimeMethodInfo:g__IsDisallowedByRefType|79_0 (System.Type) bool System.Reflection.RuntimeMethodInfo:get_ContainsGenericParameters () bool System.Reflection.RuntimeMethodInfo:get_IsGenericMethod () - bool System.Reflection.RuntimePropertyInfo:get_CanRead () - bool System.Reflection.RuntimePropertyInfo:get_CanWrite () bool System.Reflection.SignatureTypeExtensions:MatchesParameterTypeExactly (System.Type,System.Reflection.ParameterInfo) bool System.Resources.FastResourceComparer:Equals (string,string) bool System.Resources.ManifestBasedResourceGroveler:CanUseDefaultResourceClasses (string,string) @@ -793,8 +828,6 @@ Methods: bool System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1/ConfiguredTaskAwaiter:get_IsCompleted () bool System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1/ConfiguredTaskAwaiter:GetResult () bool System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1/ConfiguredTaskAwaiter:get_IsCompleted () - bool System.Runtime.CompilerServices.RuntimeFeature:get_IsDynamicCodeCompiled () - bool System.Runtime.CompilerServices.RuntimeFeature:get_IsDynamicCodeSupported () bool System.Runtime.CompilerServices.RuntimeHelpers:SufficientExecutionStack () bool System.Runtime.CompilerServices.RuntimeHelpers:TryEnsureSufficientExecutionStack () bool System.Runtime.InteropServices.MemoryMarshal:TryGetArray (System.ReadOnlyMemory`1,System.ArraySegment`1&) @@ -805,6 +838,7 @@ Methods: bool System.RuntimeType:FilterApplyMethodInfo (System.Reflection.RuntimeMethodInfo,System.Reflection.BindingFlags,System.Reflection.CallingConventions,System.Type[]) bool System.RuntimeType:get_ContainsGenericParameters () bool System.RuntimeType:get_IsActualEnum () + bool System.RuntimeType:get_IsActualValueType () bool System.RuntimeType:get_IsByRefLike () bool System.RuntimeType:get_IsConstructedGenericType () bool System.RuntimeType:get_IsEnum () @@ -815,7 +849,6 @@ Methods: bool System.RuntimeType:get_IsNullableOfT () bool System.RuntimeType:HasElementTypeImpl () bool System.RuntimeType:IsArrayImpl () - bool System.RuntimeType:IsAssignableFrom (System.Reflection.TypeInfo) bool System.RuntimeType:IsAssignableFrom (System.Type) bool System.RuntimeType:IsByRefImpl () bool System.RuntimeType:IsDelegate () @@ -839,16 +872,13 @@ Methods: bool System.RuntimeTypeHandle:IsGenericVariable (System.RuntimeType) bool System.RuntimeTypeHandle:IsInstanceOfType (System.Runtime.CompilerServices.QCallTypeHandle,object) bool System.RuntimeTypeHandle:IsInstanceOfType (System.RuntimeType,object) - bool System.RuntimeTypeHandle:IsInterface (System.RuntimeType) bool System.RuntimeTypeHandle:IsPointer (System.RuntimeType) bool System.RuntimeTypeHandle:IsPrimitive (System.RuntimeType) bool System.RuntimeTypeHandle:IsSubclassOf (System.RuntimeType,System.RuntimeType) bool System.RuntimeTypeHandle:IsValueType (System.RuntimeType) bool System.RuntimeTypeHandle:type_is_assignable_from (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.QCallTypeHandle) - bool System.SpanHelpers:NonPackedContainsValueType (int16&,int16,int) bool System.SpanHelpers:SequenceEqual (byte&,byte&,uintptr) bool System.String:Contains (char,System.StringComparison) - bool System.String:Contains (char) bool System.String:Contains (string) bool System.String:EndsWith (string,System.StringComparison) bool System.String:Equals (object) @@ -870,6 +900,7 @@ Methods: bool System.Threading.CancellationTokenSource:TransitionToCancellationRequested () bool System.Threading.CancellationTokenSource/Registrations:Unregister (long,System.Threading.CancellationTokenSource/CallbackNode) bool System.Threading.EventWaitHandle:Set () + bool System.Threading.Lock:get_IsSingleProcessor () bool System.Threading.LowLevelLifoSemaphore:Wait (int,bool) bool System.Threading.LowLevelLifoSemaphore:WaitCore (int) bool System.Threading.LowLevelLifoSemaphore:WaitForSignal (int) @@ -910,14 +941,13 @@ Methods: bool System.Threading.TimerQueueTimer:Change (uint,uint) bool System.Threading.WaitHandle:WaitOne () bool System.Threading.WaitHandle:WaitOne (int) - bool System.Threading.WaitHandle:WaitOneNoCheck (int) + bool System.Threading.WaitHandle:WaitOneNoCheck (int,bool,object,System.Diagnostics.Tracing.NativeRuntimeEventSource/WaitHandleWaitSourceMap) bool System.Threading.WaitSubsystem/ThreadWaitInfo:TrySignalToSatisfyWait (System.Threading.WaitSubsystem/ThreadWaitInfo/WaitedListNode,bool) bool System.Threading.WaitSubsystem/WaitableObject:get_IsAbandonedMutex () bool System.Type:get_HasElementType () bool System.Type:get_IsAbstract () bool System.Type:get_IsArray () bool System.Type:get_IsByRef () - bool System.Type:get_IsClass () bool System.Type:get_IsInterface () bool System.Type:get_IsPointer () bool System.Type:get_IsPrimitive () @@ -927,15 +957,18 @@ Methods: bool System.Type:op_Inequality (System.Type,System.Type) bool System.UInt16:TryParse (System.ReadOnlySpan`1,System.Globalization.NumberStyles,System.IFormatProvider,uint16&) bool System.Uri:CheckForUnicodeOrEscapedUnreserved (string) - bool System.Uri:Equals (object) + bool System.Uri:Equals (System.Uri) bool System.Uri:get_DisablePathAndQueryCanonicalization () bool System.Uri:get_IsDefaultPort () bool System.Uri:op_Equality (System.Uri,System.Uri) bool System.Uri:op_Inequality (System.Uri,System.Uri) bool System.UriHelper:IsLWS (char) + bool System.ValueTuple`2>:Equals (System.ValueTuple`2>) bool System.ValueTuple`3:Equals (System.ValueTuple`3) bool System.WeakReference:get_IsAlive () bool Xamarin.Android.Net.AndroidMessageHandler:get_decompress_here () + bool Xamarin.Android.Net.AndroidMessageHandler:get_HasClientCertificates () + bool Xamarin.Android.Net.AndroidMessageHandler:get_HasTrustedCerts () bool Xamarin.Android.Net.AndroidMessageHandler:HandleRedirect (System.Net.HttpStatusCode,Java.Net.HttpURLConnection,Xamarin.Android.Net.AndroidMessageHandler/RequestRedirectionState,bool&) bool Xamarin.Android.Net.AndroidMessageHandler:IsErrorStatusCode (System.Net.HttpStatusCode) byte System.IO.BinaryReader:ReadByte () @@ -949,7 +982,7 @@ Methods: byte[] System.Net.Http.QPack.QPackEncoder:EncodeLiteralHeaderFieldWithStaticNameReferenceToArray (int) byte[] System.ReadOnlySpan`1:ToArray () byte[] System.Reflection.AssemblyNameHelpers:ComputePublicKeyToken (byte[]) - byte[] System.Reflection.AssemblyNameParser:ParsePKT (string,bool) + byte[] System.Text.Encoding:GetBytes (string) byte* System.IO.UnmanagedMemoryStream:get_PositionPointer () byte* System.Private.CoreLib.Interop/Sys:g____PInvoke|48_0 () byte* System.Text.Unicode.Utf8Utility:GetPointerToFirstInvalidByte (byte*,int,int&,int&) @@ -1027,6 +1060,7 @@ Methods: double Microsoft.Maui.Platform.ContextExtensions:GetThemeAttributePixels (Android.Content.Context,int) double Microsoft.Maui.Platform.MeasureSpecExtensions:ToDouble (int,Android.Content.Context) double Microsoft.Maui.Primitives.Dimension:ResolveMinimum (double) + double System.Collections.Generic.List`1:get_Item (int) double System.Int32:System.IConvertible.ToDouble (System.IFormatProvider) double System.Math:Ceiling (double) double System.Math:Pow (double,double) @@ -1067,6 +1101,7 @@ Methods: int Android.Runtime.AndroidTypeManager:CountMethods (System.ReadOnlySpan`1) int Android.Runtime.IdentityHashTargets:get_Count () int Android.Runtime.InputStreamInvoker:Read (byte[],int,int) + int Android.Runtime.JavaList:get_Count () int Android.Runtime.JNIEnv:_GetArrayLength (intptr) int Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PP_I (_JniMarshal_PP_I,intptr,intptr) int Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPI_I (_JniMarshal_PPI_I,intptr,intptr,int) @@ -1125,6 +1160,8 @@ Methods: int Java.Interop.JniPeerMembers/JniStaticMethods:InvokeInt32Method (string,Java.Interop.JniArgumentValue*) int Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager:GetArrayInfo (System.Type,System.Type&) int Java.IO.InputStream:Read (byte[],int,int) + int Microsoft.Extensions.DependencyInjection.ActivatorUtilities:g__GetMaxArgCount|4_0 (Microsoft.Extensions.DependencyInjection.ActivatorUtilities/<>c__DisplayClass4_0&) + int Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorMatcher:Match (object[],Microsoft.Extensions.DependencyInjection.IServiceProviderIsService) int Microsoft.Extensions.DependencyInjection.ServiceCollection:get_Count () int Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/ServiceDescriptorCacheItem:get_Count () int Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey:GetHashCode () @@ -1150,7 +1187,6 @@ Methods: int Microsoft.Maui.Controls.Platform.MultiPageFragmentStateAdapter`1:get_ItemCount () int Microsoft.Maui.Controls.ReadOnlyCastingList`2:get_Count () int Microsoft.Maui.Controls.ResourceDictionary:get_Count () - int Microsoft.Maui.Controls.SetterSpecificity:CompareTo (Microsoft.Maui.Controls.SetterSpecificity) int Microsoft.Maui.Controls.VisualElement:get_ZIndex () int Microsoft.Maui.Controls.VisualState:GetHashCode () int Microsoft.Maui.Controls.VisualStateGroup:GetHashCode () @@ -1168,24 +1204,24 @@ Methods: int Microsoft.Maui.ViewHandlerExtensions:MakeMeasureSpecExact (Android.Views.View,double) int System.AppContextConfigHelper:GetInt32Config (string,int,bool) int System.AppContextConfigHelper:GetInt32Config (string,string,int,bool) - int System.Array:BinarySearch (Microsoft.Maui.Controls.SetterSpecificity[],int,int,Microsoft.Maui.Controls.SetterSpecificity,System.Collections.Generic.IComparer`1) int System.Array:GetLength (int) int System.Array:GetLengthInternal (System.Runtime.CompilerServices.ObjectHandleOnStack,int) int System.Array:GetLowerBound (int) int System.Array:GetLowerBoundInternal (System.Runtime.CompilerServices.ObjectHandleOnStack,int) - int System.Array:IndexOf (Android.Graphics.Drawables.Drawable[],Android.Graphics.Drawables.Drawable) - int System.Array:IndexOf (Microsoft.Maui.Hosting.FontDescriptor[],Microsoft.Maui.Hosting.FontDescriptor,int,int) + int System.Array:IndexOf (System.Type[],System.Type,int,int) + int System.Array:IndexOf (System.Type[],System.Type) + int System.Array:IndexOf (System.ValueTuple`2>[],System.ValueTuple`2>,int,int) int System.Array:LastIndexOf (System.Delegate[],System.Delegate,int,int) int System.Array:LastIndexOf (System.Delegate[],System.Delegate) int System.ArraySegment`1:get_Count () int System.ArraySegment`1:get_Offset () int System.Buffers.Any5SearchValues`2:IndexOfAny (System.ReadOnlySpan`1) - int System.Buffers.Latin1CharSearchValues:IndexOfAny (char&,int) - int System.Buffers.Latin1CharSearchValues:IndexOfAny (char&,int) - int System.Buffers.Latin1CharSearchValues:IndexOfAny (System.ReadOnlySpan`1) - int System.Buffers.Latin1CharSearchValues:IndexOfAnyExcept (System.ReadOnlySpan`1) - int System.Buffers.Latin1CharSearchValues:LastIndexOfAny (char&,int) - int System.Buffers.Latin1CharSearchValues:LastIndexOfAny (System.ReadOnlySpan`1) + int System.Buffers.BitmapCharSearchValues:IndexOfAny (char&,int) + int System.Buffers.BitmapCharSearchValues:IndexOfAny (char&,int) + int System.Buffers.BitmapCharSearchValues:IndexOfAny (System.ReadOnlySpan`1) + int System.Buffers.BitmapCharSearchValues:IndexOfAnyExcept (System.ReadOnlySpan`1) + int System.Buffers.BitmapCharSearchValues:LastIndexOfAny (char&,int) + int System.Buffers.BitmapCharSearchValues:LastIndexOfAny (System.ReadOnlySpan`1) int System.Buffers.SharedArrayPool`1:get_Id () int System.Buffers.SharedArrayPoolStatics:GetMaxArraysPerPartition () int System.Buffers.SharedArrayPoolStatics:GetPartitionCount () @@ -1208,25 +1244,24 @@ Methods: int System.Collections.Generic.Dictionary`2:Initialize (int) int System.Collections.Generic.Dictionary`2:Initialize (int) int System.Collections.Generic.Dictionary`2>:Initialize (int) - int System.Collections.Generic.EqualityComparer`1:IndexOf (Microsoft.Maui.Hosting.FontDescriptor[],Microsoft.Maui.Hosting.FontDescriptor,int,int) int System.Collections.Generic.EqualityComparer`1:LastIndexOf (System.Delegate[],System.Delegate,int,int) int System.Collections.Generic.EqualityComparer`1:System.Collections.IEqualityComparer.GetHashCode (object) - int System.Collections.Generic.GenericArraySortHelper`1:BinarySearch (Microsoft.Maui.Controls.SetterSpecificity[],int,int,Microsoft.Maui.Controls.SetterSpecificity,System.Collections.Generic.IComparer`1) - int System.Collections.Generic.GenericArraySortHelper`1:BinarySearch (Microsoft.Maui.Controls.SetterSpecificity[],int,int,Microsoft.Maui.Controls.SetterSpecificity) + int System.Collections.Generic.EqualityComparer`1:IndexOf (System.Type[],System.Type,int,int) + int System.Collections.Generic.EqualityComparer`1>>:IndexOf (System.ValueTuple`2>[],System.ValueTuple`2>,int,int) + int System.Collections.Generic.GenericComparer`1:Compare (double,double) int System.Collections.Generic.GenericComparer`1:Compare (int,int) + int System.Collections.Generic.HashSet`1:FindItemIndex (string) int System.Collections.Generic.HashSet`1:Initialize (int) - int System.Collections.Generic.HashSet`1:FindItemIndex (System.Type) + int System.Collections.Generic.List`1:GetNewCapacity (int) int System.Collections.Generic.List`1:get_Count () int System.Collections.Generic.List`1:IndexOf (Microsoft.Maui.Hosting.FontDescriptor) int System.Collections.Generic.List`1:EnsureCapacity (int) int System.Collections.Generic.List`1:get_Item (int) + int System.Collections.Generic.List`1>>:IndexOf (System.ValueTuple`2>) int System.Collections.Generic.List`1>:RemoveAll (System.Predicate`1>) int System.Collections.Generic.NonRandomizedStringEqualityComparer/OrdinalComparer:GetHashCode (string) int System.Collections.Generic.NonRandomizedStringEqualityComparer/OrdinalIgnoreCaseComparer:GetHashCode (string) int System.Collections.Generic.ObjectEqualityComparer`1:GetHashCode (System.Type) - int System.Collections.Generic.SortedList`2/ValueList:get_Count () - int System.Collections.Generic.SortedList`2:IndexOfKey (Microsoft.Maui.Controls.SetterSpecificity) - int System.Collections.Generic.SortedList`2:IndexOfKey (Microsoft.Maui.Controls.SetterSpecificity) int System.Collections.HashHelpers:ExpandPrime (int) int System.Collections.HashHelpers:GetPrime (int) int System.Collections.HashHelpers:GetPrime (int) @@ -1239,6 +1274,7 @@ Methods: int System.Collections.Specialized.SingleItemReadOnlyList:get_Count () int System.Environment:FindAndParseNextNumber (string,int&) int System.Environment:get_CurrentManagedThreadId () + int System.Environment:get_ProcessorCount () int System.Environment:get_TickCount () int System.Environment:GetProcessorCount () int System.Globalization.CultureData:get_LCID () @@ -1271,15 +1307,15 @@ Methods: int System.IO.UnmanagedMemoryStream:Read (System.Span`1) int System.IO.UnmanagedMemoryStream:ReadByte () int System.IO.UnmanagedMemoryStream:ReadCore (System.Span`1) - int System.Linq.EnumerableSorter`2:CompareAnyKeys_DefaultComparer_NoNext_Ascending (int,int) + int System.Linq.Enumerable/EnumerableSorter`2:CompareAnyKeys_DefaultComparer_NoNext_Ascending (int,int) int System.Marvin:ComputeHash32 (byte&,uint,uint,uint) int System.MemoryExtensions:Split (System.ReadOnlySpan`1,System.Span`1,char,System.StringSplitOptions) int System.MemoryExtensions:SplitCore (System.ReadOnlySpan`1,System.Span`1,System.ReadOnlySpan`1,System.ReadOnlySpan`1,bool,System.StringSplitOptions) int System.MemoryExtensions:ToLowerInvariant (System.ReadOnlySpan`1,System.Span`1) + int System.Net.Http.<>z__ReadOnlyArray`1:System.Collections.Generic.ICollection.get_Count () int System.Net.Http.Headers.HeaderUtilities:GetNextNonEmptyOrWhitespaceIndex (string,int,bool,bool&) int System.Net.Http.Headers.Int64NumberHeaderParser:GetParsedValueLength (string,int,object,object&) int System.Net.Http.HttpRuleParser:GetNumberLength (string,int,bool) - int System.Net.Http.HttpRuleParser:GetTokenLength (string,int) int System.Net.Http.HttpRuleParser:GetWhitespaceLength (string,int) int System.Net.Primitives.Interop/Sys:GetDomainName (byte*,int) int System.Nullable`1:get_Value () @@ -1310,10 +1346,11 @@ Methods: int System.Resources.ResourceReader:ReadUnalignedI4 (int*) int System.Runtime.CompilerServices.ConditionalWeakTable`2/Container:FindEntry (System.Type,object&) int System.Runtime.CompilerServices.RuntimeHelpers:InternalGetHashCode (object) - int System.Runtime.CompilerServices.RuntimeHelpers:InternalTryGetHashCode (object) int System.Runtime.InteropServices.Marshal:GetLastPInvokeError () int System.Runtime.InteropServices.Marshal:GetLastSystemError () + int System.Runtime.Intrinsics.Vector128`1:System.Runtime.Intrinsics.ISimdVector,T>.IndexOfLastMatch (System.Runtime.Intrinsics.Vector128`1) int System.RuntimeType:GetHashCode () + int System.SpanHelpers:g__SimdImpl|91_0 (int16&,int16,int) int System.SpanHelpers:IndexOf (char&,int,char&,int) int System.SpanHelpers:IndexOfAnyValueType (int16&,int16,int16,int16,int16,int) int System.SpanHelpers:IndexOfAnyValueType (int16&,int16,int16,int16,int16,int16,int) @@ -1322,11 +1359,11 @@ Methods: int System.SpanHelpers:LastIndexOfValueType (int16&,int16,int) int System.SpanHelpers:NonPackedIndexOfAnyInRangeUnsignedNumber (uint16&,uint16,uint16,int) int System.SpanHelpers:NonPackedIndexOfAnyValueType (int16&,int16,int16,int) - int System.SpanHelpers:NonPackedIndexOfAnyValueType (int16&,int16,int16,int16,int) int System.SpanHelpers:NonPackedIndexOfValueType (int16&,int16,int) int System.SpanHelpers:SequenceCompareTo (byte&,int,byte&,int) int System.String:Compare (string,string,System.StringComparison) int System.String:CompareOrdinal (string,string) + int System.String:CompareOrdinalHelper (string,string) int System.String:GetHashCode () int System.String:GetNonRandomizedHashCode () int System.String:GetNonRandomizedHashCodeOrdinalIgnoreCase () @@ -1337,12 +1374,12 @@ Methods: int System.String:IndexOf (string,System.StringComparison) int System.String:strlen (byte*) int System.String:wcslen (char*) + int System.Text.ASCIIEncoding:GetByteCount (string) + int System.Text.ASCIIEncoding:GetByteCountFast (char*,int,System.Text.EncoderFallback,int&) + int System.Text.ASCIIEncoding:GetBytes (string,int,int,byte[],int) int System.Text.ASCIIEncoding:GetBytes (System.ReadOnlySpan`1,System.Span`1) int System.Text.ASCIIEncoding:GetBytesFast (char*,int,byte*,int,int&) - int System.Text.DecoderNLS:GetChars (byte[],int,int,char[],int,bool) - int System.Text.DecoderNLS:GetChars (byte[],int,int,char[],int) - int System.Text.DecoderNLS:GetChars (byte*,int,char*,int,bool) - int System.Text.Encoding:GetChars (byte*,int,char*,int,System.Text.DecoderNLS) + int System.Text.EncoderReplacementFallback:get_MaxCharCount () int System.Text.UTF8Encoding:GetBytes (System.ReadOnlySpan`1,System.Span`1) int System.Text.UTF8Encoding:GetBytesFast (char*,int,byte*,int,int&) int System.Text.UTF8Encoding:GetCharCount (byte*,int) @@ -1363,7 +1400,7 @@ Methods: int System.Threading.Thread:GetSmallId () int System.Threading.ThreadLocal`1/IdManager:GetId (bool) int System.Threading.ThreadLocal`1:GetNewTableSize (int) - int System.Threading.WaitHandle:WaitOneCore (intptr,int) + int System.Threading.WaitHandle:WaitOneCore (intptr,int,bool) int System.Threading.WaitSubsystem:Wait (intptr,int,bool) int System.Threading.WaitSubsystem:Wait (System.Threading.WaitSubsystem/WaitableObject,int,bool,bool) int System.Threading.WaitSubsystem/ThreadWaitInfo:ProcessSignaledWaitState () @@ -1381,11 +1418,13 @@ Methods: int[] System.Globalization.CultureData:get_NumberGroupSizes () int[] System.Globalization.CultureData:GetLocaleInfoCoreUserOverride (System.Globalization.CultureData/LocaleGroupingData) int[] System.Globalization.CultureData:IcuGetLocaleInfo (System.Globalization.CultureData/LocaleGroupingData) - int[] System.Linq.EnumerableSorter`1:ComputeMap (Microsoft.Maui.IView[],int) - int[] System.Linq.EnumerableSorter`1:Sort (Microsoft.Maui.IView[],int) - int[] System.Linq.OrderedEnumerable`1:SortedMap (System.Linq.Buffer`1) + int[] System.Linq.Enumerable/EnumerableSorter`1:ComputeMap (Microsoft.Maui.IView[],int) + int[] System.Linq.Enumerable/EnumerableSorter`1:Sort (Microsoft.Maui.IView[],int) + int[] System.Linq.Enumerable/OrderedIterator`1:SortedMap (Microsoft.Maui.IView[]) int16 System.AppContextConfigHelper:GetInt16Config (string,int16,bool) int16 System.AppContextConfigHelper:GetInt16Config (string,string,int16,bool) + int16 System.Threading.Lock:DetermineMaxSpinCount () + int16 System.Threading.Lock:DetermineMinSpinCountForAdaptiveSpin () int16 System.Threading.PortableThreadPool:get_MinThreadsGoal () int16 System.Threading.PortableThreadPool:get_TargetThreadsGoalForBlockingAdjustment () int16 System.Threading.PortableThreadPool/WorkerThread:DetermineThreadsToKeepAlive () @@ -1429,31 +1468,23 @@ Methods: intptr Android.Runtime.JNIEnv:StartCreateInstance (string,string,Android.Runtime.JValue[]) intptr Android.Runtime.JNIEnv:StartCreateInstance (string,string,Android.Runtime.JValue*) intptr Android.Runtime.JNIEnv:ToLocalJniHandle (Android.Runtime.IJavaObject) - intptr Android.Runtime.JNIEnv/<>c:b__119_9 (System.Array) + intptr Android.Runtime.JNIEnv/<>c:b__121_9 (System.Array) intptr Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPI_L (_JniMarshal_PPI_L,intptr,intptr,int) intptr Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPLI_L (_JniMarshal_PPLI_L,intptr,intptr,intptr,int) intptr Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPLLL_L (_JniMarshal_PPLLL_L,intptr,intptr,intptr,intptr,intptr) intptr Android.Runtime.RuntimeNativeMethods:_monodroid_get_identity_hash_code (intptr,intptr) intptr Android.Runtime.RuntimeNativeMethods:monodroid_TypeManager_get_java_class_name (intptr) - intptr Android.Util.IAttributeSetInvoker:get_java_class_ref () - intptr Android.Util.IAttributeSetInvoker:Validate (intptr) - intptr Android.Views.IWindowManagerInvoker:get_java_class_ref () - intptr Android.Views.IWindowManagerInvoker:Validate (intptr) intptr AndroidX.Fragment.App.Fragment:n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_ (intptr,intptr,intptr,intptr,intptr) intptr AndroidX.RecyclerView.Widget.RecyclerView/Adapter:n_OnCreateViewHolder_Landroid_view_ViewGroup_I (intptr,intptr,intptr,int) intptr AndroidX.ViewPager2.Adapter.FragmentStateAdapter:n_CreateFragment_I (intptr,intptr,int) intptr Java.Interop.JavaConvert:ToLocalJniHandle (object) intptr Java.Interop.JavaConvert:WithLocalJniHandle (string,System.Func`2) - intptr Java.Interop.JavaConvert/<>c:<.cctor>b__20_29 (object) + intptr Java.Interop.JavaConvert/<>c:<.cctor>b__21_29 (object) intptr Java.Interop.JniRuntime:_AttachCurrentThread (string,Java.Interop.JniObjectReference) intptr Java.Interop.JniRuntime:get_InvocationPointer () intptr Java.Interop.JniType:RawGetStaticMethodID (intptr,string,string,intptr&) - intptr Java.Lang.ICharSequenceInvoker:get_java_class_ref () - intptr Java.Lang.ICharSequenceInvoker:Validate (intptr) intptr Java.Lang.Object:get_Handle () intptr Java.Lang.Object:Java.Interop.IJavaObjectEx.ToLocalJniHandle () - intptr Java.Util.IIteratorInvoker:get_java_class_ref () - intptr Java.Util.IIteratorInvoker:Validate (intptr) intptr Mono.RuntimeGPtrArrayHandle:get_Item (int) intptr Mono.RuntimeGPtrArrayHandle:Lookup (int) intptr Mono.SafeGPtrArrayHandle:get_Item (int) @@ -1479,7 +1510,6 @@ Methods: intptr System.RuntimeType:GetMethodsByName_native (System.Runtime.CompilerServices.QCallTypeHandle,intptr,System.Reflection.BindingFlags,System.RuntimeType/MemberListType) intptr System.RuntimeType:GetPropertiesByName_native (System.Runtime.CompilerServices.QCallTypeHandle,intptr,System.Reflection.BindingFlags,System.RuntimeType/MemberListType) intptr System.Threading.LowLevelLifoSemaphore:InitInternal () - intptr System.Threading.WaitSubsystem/HandleManager:NewHandle (System.Threading.WaitSubsystem/WaitableObject) intptr& System.Collections.Generic.Dictionary`2:FindValue (string) Java.Interop.IJavaPeerable Android.Runtime.AndroidValueManager:PeekPeer (Java.Interop.JniObjectReference) Java.Interop.IJavaPeerable Java.Interop.TypeManager:CreateInstance (intptr,Android.Runtime.JniHandleOwnership,System.Type) @@ -1487,6 +1517,7 @@ Methods: Java.Interop.IJavaPeerable Java.Lang.Object:GetObject (intptr,Android.Runtime.JniHandleOwnership,System.Type) Java.Interop.IJavaPeerable Java.Lang.Object:PeekObject (intptr,System.Type) Java.Interop.JavaVMInterface Java.Interop.JniRuntime:CreateInvoker (intptr) + Java.Interop.JavaVMInterface System.Runtime.InteropServices.Marshal:PtrToStructure (intptr) Java.Interop.JniEnvironmentInfo Java.Interop.JniEnvironment/<>c:<.cctor>b__35_0 () Java.Interop.JniEnvironmentInfo System.Threading.ThreadLocal`1:get_Value () Java.Interop.JniEnvironmentInfo System.Threading.ThreadLocal`1:GetValueSlow () @@ -1597,13 +1628,14 @@ Methods: Java.Net.URL Java.Net.URLConnection:get_URL () Java.Net.URLConnection Java.Net.URL:OpenConnection () Java.Security.KeyStore Java.Security.KeyStore:GetInstance (string) - Java.Security.KeyStore Xamarin.Android.Net.AndroidMessageHandler:g__InitializeKeyStore|161_0 (bool&) Java.Security.KeyStore Xamarin.Android.Net.AndroidMessageHandler:ConfigureKeyStore (Java.Security.KeyStore) + Java.Security.KeyStore Xamarin.Android.Net.AndroidMessageHandler:GetConfiguredKeyStoreInstance () Java.Util.IIterator Android.Runtime.JavaList:Iterator () Java.Util.IIterator Android.Runtime.JavaSet:Iterator () Java.Util.IIterator AndroidX.Navigation.NavGraph:Iterator () Javax.Net.Ssl.IHostnameVerifier Xamarin.Android.Net.AndroidMessageHandler:GetSSLHostnameVerifier (Javax.Net.Ssl.HttpsURLConnection) Javax.Net.Ssl.KeyManagerFactory Xamarin.Android.Net.AndroidMessageHandler:ConfigureKeyManagerFactory (Java.Security.KeyStore) + Javax.Net.Ssl.KeyManagerFactory Xamarin.Android.Net.AndroidMessageHandler:GetConfiguredKeyManagerFactory (Java.Security.KeyStore) Javax.Net.Ssl.SSLSocketFactory Xamarin.Android.Net.AndroidMessageHandler:ConfigureCustomSSLSocketFactory (Javax.Net.Ssl.HttpsURLConnection) Javax.Net.Ssl.TrustManagerFactory Xamarin.Android.Net.AndroidMessageHandler:ConfigureTrustManagerFactory (Java.Security.KeyStore) long Android.Runtime.JNINativeWrapper:Wrap_JniMarshal_PPI_J (_JniMarshal_PPI_J,intptr,intptr,int) @@ -1618,15 +1650,19 @@ Methods: long System.Diagnostics.Stopwatch:QueryPerformanceCounter () long System.Environment:get_TickCount64 () long System.IO.MemoryStream:Seek (long,System.IO.SeekOrigin) + long System.IO.MemoryStream:SeekCore (long,int) long System.IO.UnmanagedMemoryStream:get_Length () long System.IO.UnmanagedMemoryStream:get_Position () long System.IO.UnmanagedMemoryStream:Seek (long,System.IO.SeekOrigin) + long System.Math:BigMul (long,long,long&) long System.Net.Http.HttpContent/LimitArrayPoolWriteStream:get_Length () long System.Nullable`1:get_Value () long System.Private.CoreLib.Interop/Sys:GetSystemTimeAsTicks () long System.Runtime.InteropServices.Marshal:ReadInt64 (intptr,int) long System.Threading.ThreadInt64PersistentCounter:get_Count () long System.Threading.TimerQueue:get_TickCount64 () + Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorInfoEx[] Microsoft.Extensions.DependencyInjection.ActivatorUtilities:CreateConstructorInfoExs (System.Type) + Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorInfoEx[] Microsoft.Extensions.DependencyInjection.ActivatorUtilities:GetOrAddConstructors (System.Type) Microsoft.Extensions.DependencyInjection.IServiceCollection Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions:Add (Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Type,System.Func`2,Microsoft.Extensions.DependencyInjection.ServiceLifetime) Microsoft.Extensions.DependencyInjection.IServiceCollection Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions:Add (Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Type,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) Microsoft.Extensions.DependencyInjection.IServiceCollection Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions:AddScoped (Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Func`2) @@ -1653,7 +1689,6 @@ Methods: Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Extensions.DependencyInjection.ServiceDescriptor:Transient () Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/ServiceDescriptorCacheItem:get_Item (int) Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/ServiceDescriptorCacheItem:get_Last () - Microsoft.Extensions.DependencyInjection.ServiceDescriptor Microsoft.Maui.Hosting.Internal.MauiFactory:GetServiceDescriptor (System.Type) Microsoft.Extensions.DependencyInjection.ServiceDescriptor System.Collections.Generic.List`1:get_Item (int) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain/ChainItemInfo& System.Collections.Generic.Dictionary`2:FindValue (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory Microsoft.Extensions.DependencyInjection.ServiceProvider:get_CallSiteFactory () @@ -1687,21 +1722,19 @@ Methods: Microsoft.Maui.ApplicationModel.AppTheme Microsoft.Maui.ApplicationModel.AppInfoImplementation:get_RequestedTheme () Microsoft.Maui.ApplicationModel.AppTheme Microsoft.Maui.ApplicationModel.AppInfoImplementation:GetRequestedTheme () Microsoft.Maui.ApplicationModel.AppTheme Microsoft.Maui.Controls.Application:get_RequestedTheme () + Microsoft.Maui.ApplicationModel.AppTheme Microsoft.Maui.Controls.Application:get_UserAppTheme () Microsoft.Maui.ApplicationModel.IActivityStateManager Microsoft.Maui.ApplicationModel.ActivityStateManager:get_Default () Microsoft.Maui.ApplicationModel.IAppActions Microsoft.Maui.ApplicationModel.AppActions:get_Current () Microsoft.Maui.ApplicationModel.IAppInfo Microsoft.Maui.ApplicationModel.AppInfo:get_Current () Microsoft.Maui.ApplicationModel.IPlatformAppActions Microsoft.Maui.ApplicationModel.AppActionsExtensions:AsPlatform (Microsoft.Maui.ApplicationModel.IAppActions) Microsoft.Maui.ApplicationModel.LayoutDirection Microsoft.Maui.ApplicationModel.AppInfoImplementation:get_RequestedLayoutDirection () Microsoft.Maui.ApplicationModel.LayoutDirection Microsoft.Maui.ApplicationModel.AppInfoImplementation:GetLayoutDirection () - Microsoft.Maui.ApplicationModel.Permissions/NetworkState System.Activator:CreateInstance () Microsoft.Maui.Aspect Microsoft.Maui.Controls.Image:get_Aspect () Microsoft.Maui.Controls.Application Microsoft.Maui.Controls.Page:FindApplication (Microsoft.Maui.Controls.Element) Microsoft.Maui.Controls.Application Microsoft.Maui.Controls.Window:get_Application () Microsoft.Maui.Controls.BackButtonBehavior Microsoft.Maui.Controls.Shell:GetBackButtonBehavior (Microsoft.Maui.Controls.BindableObject) Microsoft.Maui.Controls.BindableObject Microsoft.Maui.Controls.MergedStyle:get_Target () Microsoft.Maui.Controls.BindableObject Microsoft.Maui.Controls.Shell:GetBindableObjectWithFlyoutItemTemplate (Microsoft.Maui.Controls.BindableObject) - Microsoft.Maui.Controls.BindableObject/BindablePropertyContext[] System.Collections.Generic.EnumerableHelpers:ToArray (System.Collections.Generic.IEnumerable`1) - Microsoft.Maui.Controls.BindableObject/BindablePropertyContext[] System.Linq.Enumerable:ToArray (System.Collections.Generic.IEnumerable`1) Microsoft.Maui.Controls.BindableObject/SetValueArgs System.Collections.Generic.Queue`1:Dequeue () Microsoft.Maui.Controls.BindableProperty Microsoft.Maui.Controls.BindableProperty:Create (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindablePropertyBindingChanging,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) Microsoft.Maui.Controls.BindableProperty Microsoft.Maui.Controls.BindableProperty:Create (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) @@ -1714,16 +1747,16 @@ Methods: Microsoft.Maui.Controls.BindablePropertyKey Microsoft.Maui.Controls.BindableProperty:CreateAttachedReadOnly (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) Microsoft.Maui.Controls.BindablePropertyKey Microsoft.Maui.Controls.BindableProperty:CreateReadOnly (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.AppThemeBinding:Clone () - Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.Binding:Clone () + Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors:Create1934409943 (System.Func`2,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.IValueConverter,object,string,object,object,object) + Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors:Create839423058 (System.Func`2,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.IValueConverter,object,string,object,object,object) + Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors:Create860667569 (System.Func`2,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.IValueConverter,object,string,object,object,object) + Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.Internals.TypedBinding`2:Clone () + Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.SetterSpecificityList`1:get_Item (Microsoft.Maui.Controls.SetterSpecificity) + Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.SetterSpecificityList`1:GetClearedValue () + Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.SetterSpecificityList`1:GetValue () Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.Xaml.AppThemeBindingExtension:Microsoft.Maui.Controls.Xaml.IMarkupExtension.ProvideValue (System.IServiceProvider) + Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.Xaml.BindingExtension:.ProvideValue>g__CreateBinding|40_0 (Microsoft.Maui.Controls.Xaml.BindingExtension/<>c__DisplayClass40_0&) Microsoft.Maui.Controls.BindingBase Microsoft.Maui.Controls.Xaml.BindingExtension:Microsoft.Maui.Controls.Xaml.IMarkupExtension.ProvideValue (System.IServiceProvider) - Microsoft.Maui.Controls.BindingBase Microsoft.Maui.EnumerableExtensions:Last (System.Collections.Generic.IList`1) - Microsoft.Maui.Controls.BindingBase System.Collections.Generic.SortedList`2/ValueList:get_Item (int) - Microsoft.Maui.Controls.BindingBase System.Collections.Generic.SortedList`2:get_Item (Microsoft.Maui.Controls.SetterSpecificity) - Microsoft.Maui.Controls.BindingBase System.Collections.Generic.SortedList`2:GetValueAtIndex (int) - Microsoft.Maui.Controls.BindingBase System.Linq.Enumerable:ElementAt (System.Collections.Generic.IEnumerable`1,int) - Microsoft.Maui.Controls.BindingBase System.Linq.Enumerable:LastOrDefault (System.Collections.Generic.IEnumerable`1) - Microsoft.Maui.Controls.BindingBase System.Linq.Enumerable:TryGetLast (System.Collections.Generic.IEnumerable`1,bool&) Microsoft.Maui.Controls.Brush Microsoft.Maui.Controls.Brush:get_Default () Microsoft.Maui.Controls.Brush Microsoft.Maui.Controls.Brush:op_Implicit (Microsoft.Maui.Graphics.Color) Microsoft.Maui.Controls.Brush Microsoft.Maui.Controls.NavigationPage:get_BarBackground () @@ -1733,13 +1766,12 @@ Methods: Microsoft.Maui.Controls.ColumnDefinition Microsoft.Maui.Controls.DefinitionCollection`1:get_Item (int) Microsoft.Maui.Controls.ColumnDefinitionCollection Microsoft.Maui.Controls.Grid:get_ColumnDefinitions () Microsoft.Maui.Controls.ControlTemplate Microsoft.Maui.Controls.TemplatedPage:get_ControlTemplate () - Microsoft.Maui.Controls.DataTemplate Microsoft.Maui.Controls.BaseShellItem:CreateDefaultFlyoutItemCell (string,string) + Microsoft.Maui.Controls.DataTemplate Microsoft.Maui.Controls.BaseShellItem:CreateDefaultFlyoutItemCell (Microsoft.Maui.Controls.BindableObject) Microsoft.Maui.Controls.DataTemplate Microsoft.Maui.Controls.Internals.DataTemplateExtensions:SelectDataTemplate (Microsoft.Maui.Controls.DataTemplate,object,Microsoft.Maui.Controls.BindableObject) Microsoft.Maui.Controls.DataTemplate Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRecyclerAdapter:get_DefaultItemTemplate () Microsoft.Maui.Controls.DataTemplate Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRecyclerAdapter:GetDataTemplate (int) Microsoft.Maui.Controls.DataTemplate Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.GetFlyoutItemDataTemplate (Microsoft.Maui.Controls.BindableObject) Microsoft.Maui.Controls.DataTemplate Microsoft.Maui.Controls.ShellContent:get_ContentTemplate () - Microsoft.Maui.Controls.DependencyService/DependencyType System.Collections.Generic.List`1/Enumerator:get_Current () Microsoft.Maui.Controls.DependencyService/DependencyType System.Linq.Enumerable:FirstOrDefault (System.Collections.Generic.IEnumerable`1,System.Func`2) Microsoft.Maui.Controls.DependencyService/DependencyType System.Linq.Enumerable:TryGetFirst (System.Collections.Generic.IEnumerable`1,System.Func`2,bool&) Microsoft.Maui.Controls.EffectiveFlowDirection Microsoft.Maui.Controls.BaseShellItem:Microsoft.Maui.Controls.IFlowDirectionController.get_EffectiveFlowDirection () @@ -1749,8 +1781,8 @@ Methods: Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element:get_Parent () Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element:get_ParentOverride () Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element:get_RealParent () - Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element/d__101`1:System.Collections.Generic.IEnumerator.get_Current () - Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element/d__112:System.Collections.Generic.IEnumerator.get_Current () + Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element/d__103`1:System.Collections.Generic.IEnumerator.get_Current () + Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Element/d__114:System.Collections.Generic.IEnumerator.get_Current () Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Shell:GetVisiblePage () Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.Shell:WalkToPage (Microsoft.Maui.Controls.Element) Microsoft.Maui.Controls.Element Microsoft.Maui.Controls.TemplatedPage:Microsoft.Maui.Controls.IControlTemplated.get_TemplateRoot () @@ -1766,6 +1798,7 @@ Methods: Microsoft.Maui.Controls.HideSoftInputOnTappedChangedManager Microsoft.Maui.ElementHandlerExtensions:GetService (Microsoft.Maui.IElementHandler) Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.BaseShellItem:get_FlyoutIcon () Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.BaseShellItem:get_Icon () + Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.BaseShellItem/<>c:b__83_4 (Microsoft.Maui.Controls.BaseShellItem) Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.Button:get_ImageSource () Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.Image:get_Source () Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.ImageSource:FromFile (string) @@ -1775,6 +1808,8 @@ Methods: Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:GetFlyoutIcon (Microsoft.Maui.Controls.BackButtonBehavior,Microsoft.Maui.Controls.Page) Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.Shell:get_FlyoutBackgroundImage () Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.Shell:get_FlyoutIcon () + Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.ShellSection/<>c:b__59_1 (Microsoft.Maui.Controls.BaseShellItem) + Microsoft.Maui.Controls.ImageSource Microsoft.Maui.Controls.ShellSection/<>c:b__59_2 (Microsoft.Maui.Controls.BaseShellItem) Microsoft.Maui.Controls.IMessagingCenter Microsoft.Maui.Controls.MessagingCenter:get_Instance () Microsoft.Maui.Controls.INavigation Microsoft.Maui.Controls.NavigableElement:get_Navigation () Microsoft.Maui.Controls.Internals.INameScope Microsoft.Maui.Controls.Internals.NameScope:GetNameScope (Microsoft.Maui.Controls.BindableObject) @@ -1796,17 +1831,17 @@ Methods: Microsoft.Maui.Controls.IVisual Microsoft.Maui.Controls.VisualMarker:get_MatchParent () Microsoft.Maui.Controls.Label System.Linq.Enumerable:First (System.Collections.Generic.IEnumerable`1) Microsoft.Maui.Controls.Label System.Linq.Enumerable:TryGetFirst (System.Collections.Generic.IEnumerable`1,bool&) + Microsoft.Maui.Controls.Label System.Linq.Enumerable:TryGetFirstNonIterator (System.Collections.Generic.IEnumerable`1,bool&) Microsoft.Maui.Controls.LayoutOptions Microsoft.Maui.Controls.View:get_HorizontalOptions () Microsoft.Maui.Controls.LayoutOptions Microsoft.Maui.Controls.View:get_VerticalOptions () Microsoft.Maui.Controls.MenuItemCollection Microsoft.Maui.Controls.ShellContent:get_MenuItems () Microsoft.Maui.Controls.NavigatingStepRequestList Microsoft.Maui.Controls.Internals.NavigationProxy/<>c:<.ctor>b__33_0 () - Microsoft.Maui.Controls.NavigatingStepRequestList System.Lazy`1:CreateValue () - Microsoft.Maui.Controls.NavigatingStepRequestList System.Lazy`1:get_Value () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Application:get_MainPage () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.CastingEnumerator`2:get_Current () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.MenuItemTracker`1:get_Target () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.MultiPage`1:get_CurrentPage () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.NavigationPage:get_CurrentPage () + Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_CurrentPage () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_CurrentPlatformPage () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Shell:get_CurrentPage () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Shell:GetCurrentShellPage () @@ -1815,6 +1850,7 @@ Methods: Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.ShellSection:Microsoft.Maui.Controls.IShellSectionController.get_PresentedPage () Microsoft.Maui.Controls.Page Microsoft.Maui.Controls.Window:get_Page () Microsoft.Maui.Controls.Page System.Linq.Enumerable:FirstOrDefault (System.Collections.Generic.IEnumerable`1) + Microsoft.Maui.Controls.Platform.AdapterItemKey Microsoft.Maui.Controls.Platform.MultiPageFragmentStateAdapter`1:GetItemByItemId (long) Microsoft.Maui.Controls.Platform.AdapterItemKey Microsoft.Maui.Controls.Platform.MultiPageFragmentStateAdapter`1:GetItemIdByPosition (int) Microsoft.Maui.Controls.Platform.Compatibility.IShellBottomNavViewAppearanceTracker Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:CreateBottomNavViewAppearanceTracker (Microsoft.Maui.Controls.ShellItem) Microsoft.Maui.Controls.Platform.Compatibility.IShellBottomNavViewAppearanceTracker Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.Controls.Platform.Compatibility.IShellContext.CreateBottomNavViewAppearanceTracker (Microsoft.Maui.Controls.ShellItem) @@ -1840,18 +1876,16 @@ Methods: Microsoft.Maui.Controls.PlatformConfigurationRegistry`1 Microsoft.Maui.Controls.TabbedPage:<.ctor>b__38_0 () Microsoft.Maui.Controls.ReadOnlyCastingList`2 Microsoft.Maui.Controls.NavigationPage/MauiNavigationImpl:<.ctor>b__1_0 () Microsoft.Maui.Controls.ResourceDictionary Microsoft.Maui.Controls.Application:get_Resources () - Microsoft.Maui.Controls.ResourceDictionary Microsoft.Maui.Controls.ResourceDictionary/<>c__DisplayClass8_0:b__0 (System.Type) + Microsoft.Maui.Controls.ResourceDictionary Microsoft.Maui.Controls.ResourceDictionary/<>c__9`1<__XamlGeneratedCode__.__TypeA6EB4B27A3A00AE8>:b__9_0 (System.Type) Microsoft.Maui.Controls.ResourceDictionary Microsoft.Maui.Controls.VisualElement:get_Resources () Microsoft.Maui.Controls.ResourceDictionary System.Collections.ObjectModel.Collection`1:get_Item (int) Microsoft.Maui.Controls.ResourceDictionary System.Runtime.CompilerServices.ConditionalWeakTable`2:GetValue (System.Type,System.Runtime.CompilerServices.ConditionalWeakTable`2/CreateValueCallback) Microsoft.Maui.Controls.ResourceDictionary System.Runtime.CompilerServices.ConditionalWeakTable`2:GetValueLocked (System.Type,System.Runtime.CompilerServices.ConditionalWeakTable`2/CreateValueCallback) Microsoft.Maui.Controls.RowDefinitionCollection Microsoft.Maui.Controls.Grid:get_RowDefinitions () Microsoft.Maui.Controls.SearchHandler Microsoft.Maui.Controls.Shell:GetSearchHandler (Microsoft.Maui.Controls.BindableObject) - Microsoft.Maui.Controls.SetterSpecificity System.Collections.Generic.SortedList`2/KeyList:get_Item (int) - Microsoft.Maui.Controls.SetterSpecificity System.Collections.Generic.SortedList`2/KeyList:get_Item (int) - Microsoft.Maui.Controls.SetterSpecificity System.Collections.Generic.SortedList`2:GetKeyAtIndex (int) - Microsoft.Maui.Controls.SetterSpecificity System.Collections.Generic.SortedList`2:GetKeyAtIndex (int) - Microsoft.Maui.Controls.SetterSpecificity System.Linq.Enumerable:ElementAt (System.Collections.Generic.IEnumerable`1,int) + Microsoft.Maui.Controls.SetterSpecificity Microsoft.Maui.Controls.SetterSpecificity:CopyStyle (byte,uint16,byte,byte) + Microsoft.Maui.Controls.SetterSpecificity Microsoft.Maui.Controls.SetterSpecificityList`1:GetClearedSpecificity () + Microsoft.Maui.Controls.SetterSpecificity Microsoft.Maui.Controls.SetterSpecificityList`1:GetSpecificity () Microsoft.Maui.Controls.Shadow Microsoft.Maui.Controls.VisualElement:get_Shadow () Microsoft.Maui.Controls.Shapes.Geometry Microsoft.Maui.Controls.VisualElement:get_Clip () Microsoft.Maui.Controls.Shell Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.Controls.Platform.Compatibility.IShellContext.get_Shell () @@ -1882,8 +1916,6 @@ Methods: Microsoft.Maui.Controls.Style Microsoft.Maui.Controls.Style:GetBasedOnResource (Microsoft.Maui.Controls.BindableObject) Microsoft.Maui.Controls.Style System.Linq.Enumerable:FirstOrDefault (System.Collections.Generic.IEnumerable`1,System.Func`2) Microsoft.Maui.Controls.Style System.Linq.Enumerable:TryGetFirst (System.Collections.Generic.IEnumerable`1,System.Func`2,bool&) - Microsoft.Maui.Controls.Style System.Linq.Enumerable/Iterator`1:get_Current () - Microsoft.Maui.Controls.Style[] System.Linq.Enumerable:GetEmptyIfEmpty (System.Collections.Generic.IEnumerable`1) Microsoft.Maui.Controls.TabbedPage Microsoft.Maui.Controls.Configuration`2:get_Element () Microsoft.Maui.Controls.View Microsoft.Maui.Controls.ContentPage:get_Content () Microsoft.Maui.Controls.View Microsoft.Maui.Controls.NavigationPage:GetTitleView (Microsoft.Maui.Controls.BindableObject) @@ -1908,7 +1940,6 @@ Methods: Microsoft.Maui.Controls.VisualState Microsoft.Maui.Controls.WatchAddList`1:get_Item (int) Microsoft.Maui.Controls.VisualStateGroup Microsoft.Maui.Controls.VisualStateGroup:Clone () Microsoft.Maui.Controls.VisualStateGroup Microsoft.Maui.Controls.VisualStateGroupList:get_Item (int) - Microsoft.Maui.Controls.Window Microsoft.Maui.Controls.Application:CreateWindow (Microsoft.Maui.IActivationState) Microsoft.Maui.Controls.Window Microsoft.Maui.Controls.BaseShellItem:Microsoft.Maui.Controls.IWindowController.get_Window () Microsoft.Maui.Controls.Window Microsoft.Maui.Controls.VisualElement:get_Window () Microsoft.Maui.Controls.Window Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.Controls.IWindowController.get_Window () @@ -2013,7 +2044,6 @@ Methods: Microsoft.Maui.Graphics.Rect Microsoft.Maui.Platform.ActivityExtensions:GetWindowFrame (Android.App.Activity) Microsoft.Maui.Graphics.Rect Microsoft.Maui.Platform.ContextExtensions:FromPixels (Android.Content.Context,Android.Graphics.Rect) Microsoft.Maui.Graphics.Rect Microsoft.Maui.Platform.ContextExtensions:ToCrossPlatformRectInReferenceFrame (Android.Content.Context,int,int,int,int) - Microsoft.Maui.Graphics.Rect System.Collections.Generic.List`1:get_Item (int) Microsoft.Maui.Graphics.Size Microsoft.Maui.Controls.Compatibility.Layout:CrossPlatformArrange (Microsoft.Maui.Graphics.Rect) Microsoft.Maui.Graphics.Size Microsoft.Maui.Controls.Compatibility.Layout:Microsoft.Maui.IView.Measure (double,double) Microsoft.Maui.Graphics.Size Microsoft.Maui.Controls.ContentPage:Microsoft.Maui.ICrossPlatformLayout.CrossPlatformArrange (Microsoft.Maui.Graphics.Rect) @@ -2054,6 +2084,8 @@ Methods: Microsoft.Maui.Graphics.Size Microsoft.Maui.ViewHandlerExtensions:MeasureVirtualView (Microsoft.Maui.IPlatformViewHandler,int,int,System.Func`3) Microsoft.Maui.GridLength Microsoft.Maui.Controls.ColumnDefinition:get_Width () Microsoft.Maui.GridLength Microsoft.Maui.GridLength:op_Implicit (double) + Microsoft.Maui.HandlerDisconnectPolicy Microsoft.Maui.Controls.Element:Microsoft.Maui.IHandlerDisconnectPolicies.get_DisconnectPolicy () + Microsoft.Maui.HandlerDisconnectPolicy Microsoft.Maui.Controls.HandlerProperties:GetDisconnectPolicy (Microsoft.Maui.Controls.BindableObject) Microsoft.Maui.Handlers.IImageHandler Microsoft.Maui.Platform.ImageSourcePartSetter`1:get_Handler () Microsoft.Maui.Handlers.IImageHandler Microsoft.Maui.WeakReferenceExtensions:GetTargetOrDefault (System.WeakReference`1) Microsoft.Maui.Handlers.ToolbarHandler/ProcessBackClick Microsoft.Maui.Handlers.ToolbarHandler:get_BackNavigationClick () @@ -2061,16 +2093,23 @@ Methods: Microsoft.Maui.Hosting.IFontCollection Microsoft.Maui.Hosting.FontCollectionExtensions:AddFont (Microsoft.Maui.Hosting.IFontCollection,string,string) Microsoft.Maui.Hosting.IImageSourceServiceCollection Microsoft.Maui.Hosting.ImageSourceServiceCollectionExtensions:AddService (Microsoft.Maui.Hosting.IImageSourceServiceCollection,System.Func`2>) Microsoft.Maui.Hosting.IImageSourceServiceCollection Microsoft.Maui.Hosting.ImageSourcesMauiAppBuilderExtensions/<>c:b__1_1 (System.IServiceProvider) - Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:AddMauiControlsHandlers (Microsoft.Maui.Hosting.IMauiHandlersCollection) + Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping:GetInstance (Microsoft.Maui.Hosting.IImageSourceServiceCollection) + Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping/<>c:b__1_0 (Microsoft.Maui.Hosting.IImageSourceServiceCollection) + Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:AddControlsHandlers (Microsoft.Maui.Hosting.IMauiHandlersCollection) + Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/<>c:b__1_1 (System.IServiceProvider) Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions:AddHandler (Microsoft.Maui.Hosting.IMauiHandlersCollection,System.Type,System.Type) Microsoft.Maui.Hosting.IMauiHandlersCollection Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions:AddHandler (Microsoft.Maui.Hosting.IMauiHandlersCollection) Microsoft.Maui.Hosting.IMauiInitializeService System.SZGenericArrayEnumerator`1:get_Current () - Microsoft.Maui.Hosting.Internal.MauiHandlersCollection Microsoft.Maui.Hosting.Internal.MauiHandlersFactory:CreateHandlerCollection (System.Collections.Generic.IEnumerable`1) + Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:GetInstance (Microsoft.Maui.Hosting.IMauiHandlersCollection) + Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet/<>c:b__1_0 (Microsoft.Maui.Hosting.IMauiHandlersCollection) + Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet System.Collections.Concurrent.ConcurrentDictionary`2:GetOrAdd (Microsoft.Maui.Hosting.IMauiHandlersCollection,System.Func`2) Microsoft.Maui.Hosting.MauiApp Microsoft.Maui.Hosting.MauiAppBuilder:Build () Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:ConfigureImageSourceHandlers (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:RemapForControls (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:SetupDefaults (Microsoft.Maui.Hosting.MauiAppBuilder) + Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:SetupXamlDefaults (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:UseMauiApp (Microsoft.Maui.Hosting.MauiAppBuilder) + Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Controls.Hosting.AppHostBuilderExtensions:UseMauiPrimaryApp (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Hosting.AppHostBuilderExtensions:ConfigureAnimations (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Hosting.AppHostBuilderExtensions:ConfigureDispatching (Microsoft.Maui.Hosting.MauiAppBuilder) Microsoft.Maui.Hosting.MauiAppBuilder Microsoft.Maui.Hosting.EssentialsExtensions:UseEssentials (Microsoft.Maui.Hosting.MauiAppBuilder) @@ -2104,6 +2143,7 @@ Methods: Microsoft.Maui.IFontManager Microsoft.Maui.Hosting.FontsMauiAppBuilderExtensions/<>c:b__1_2 (System.IServiceProvider) Microsoft.Maui.IFontRegistrar Microsoft.Maui.Hosting.FontsMauiAppBuilderExtensions/<>c:b__1_1 (System.IServiceProvider) Microsoft.Maui.IGridColumnDefinition Microsoft.Maui.Controls.ReadOnlyCastingList`2:get_Item (int) + Microsoft.Maui.IImage Microsoft.Maui.Handlers.ImageHandler:Microsoft.Maui.Handlers.IImageHandler.get_VirtualView () Microsoft.Maui.IImageSource Microsoft.Maui.Controls.Button:Microsoft.Maui.IImageSourcePart.get_Source () Microsoft.Maui.IImageSource Microsoft.Maui.Controls.Image:Microsoft.Maui.IImageSourcePart.get_Source () Microsoft.Maui.IImageSourcePart Microsoft.Maui.Platform.ImageSourcePartSetter`1:get_ImageSourcePart () @@ -2115,11 +2155,11 @@ Methods: Microsoft.Maui.IImageSourceServiceProvider Microsoft.Maui.ElementHandlerExtensions:GetRequiredService (Microsoft.Maui.IElementHandler) Microsoft.Maui.IImageSourceServiceProvider Microsoft.Maui.Hosting.ImageSourcesMauiAppBuilderExtensions/<>c:b__1_0 (System.IServiceProvider) Microsoft.Maui.IImageSourceServiceResult System.Runtime.CompilerServices.TaskAwaiter`1:GetResult () - Microsoft.Maui.IMauiContext Microsoft.Maui.ActivationState:get_Context () Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.IElementHandler.get_MauiContext () Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRecyclerAdapter:get_MauiContext () Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRenderer:get_MauiContext () Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer:get_MauiContext () + Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.Platform.ModalNavigationManager:get_WindowMauiContext () Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.TabbedPage:get_MauiContext () Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.Toolbar:get_MauiContext () Microsoft.Maui.IMauiContext Microsoft.Maui.Controls.ViewExtensions:FindMauiContext (Microsoft.Maui.Controls.Element,bool) @@ -2131,6 +2171,8 @@ Methods: Microsoft.Maui.IMauiHandlersFactory Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/<>c:b__1_0 (System.IServiceProvider) Microsoft.Maui.IMauiHandlersFactory Microsoft.Maui.MauiContext:<.ctor>b__6_0 () Microsoft.Maui.IMauiHandlersFactory Microsoft.Maui.MauiContext:get_Handlers () + Microsoft.Maui.IMauiHandlersFactory System.Lazy`1:CreateValue () + Microsoft.Maui.IMauiHandlersFactory System.Lazy`1:get_Value () Microsoft.Maui.IPersistedState Microsoft.Maui.ActivationState:get_State () Microsoft.Maui.IShadow Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.IView.get_Shadow () Microsoft.Maui.IToolbar Microsoft.Maui.Controls.NavigationPage:FindMyToolbar () @@ -2150,8 +2192,8 @@ Methods: Microsoft.Maui.IView Microsoft.Maui.Handlers.ViewHandler`2:Microsoft.Maui.IViewHandler.get_VirtualView () Microsoft.Maui.IView Microsoft.Maui.HotReload.MauiHotReloadHelper:GetReplacedView (Microsoft.Maui.HotReload.IHotReloadableView) Microsoft.Maui.IView Microsoft.Maui.Platform.StackNavigationManager:get_CurrentPage () - Microsoft.Maui.IView System.Linq.OrderedEnumerable`1/d__4:System.Collections.Generic.IEnumerator.get_Current () - Microsoft.Maui.IView[] System.Collections.Generic.EnumerableHelpers:ToArray (System.Collections.Generic.IEnumerable`1,int&) + Microsoft.Maui.IView[] System.Linq.Enumerable:ICollectionToArray (System.Collections.Generic.ICollection`1) + Microsoft.Maui.IView[] System.Linq.Enumerable:ToArray (System.Collections.Generic.IEnumerable`1) Microsoft.Maui.IViewHandler Microsoft.Maui.Controls.VisualElement:get_Handler () Microsoft.Maui.IVisualDiagnosticsOverlay Microsoft.Maui.Controls.Window:get_VisualDiagnosticsOverlay () Microsoft.Maui.IWindow Microsoft.Maui.Controls.Application:Microsoft.Maui.IApplication.CreateWindow (Microsoft.Maui.IActivationState) @@ -2167,7 +2209,7 @@ Methods: Microsoft.Maui.Layouts.ILayoutManager Microsoft.Maui.Controls.Layout:GetLayoutManagerFromFactory (Microsoft.Maui.Controls.Layout) Microsoft.Maui.Layouts.ILayoutManager Microsoft.Maui.Controls.VerticalStackLayout:CreateLayoutManager () Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnCreate Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions/d__3`1:System.Collections.Generic.IEnumerator.get_Current () - Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnCreate System.Linq.Enumerable/d__41`1:System.Collections.Generic.IEnumerator.get_Current () + Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnCreate System.Linq.Enumerable/Iterator`1:get_Current () Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions:OnBackPressed (Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder,Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnBackPressed) Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions:OnConfigurationChanged (Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder,Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnConfigurationChanged) Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder Microsoft.Maui.LifecycleEvents.AndroidLifecycleBuilderExtensions:OnCreate (Microsoft.Maui.LifecycleEvents.IAndroidLifecycleBuilder,Microsoft.Maui.LifecycleEvents.AndroidLifecycle/OnCreate) @@ -2245,12 +2287,13 @@ Methods: Microsoft.Win32.SafeHandles.SafeWaitHandle System.Threading.WaitSubsystem:NewHandle (System.Threading.WaitSubsystem/WaitableObject) Mono.MonoAssemblyName* System.Reflection.AssemblyName:GetNativeName (intptr) object Android.Runtime.AndroidEnvironment:GetHttpMessageHandler () - object Android.Runtime.JNIEnv/<>c:b__70_8 (System.Type,intptr,int) - object Android.Runtime.JNIEnv/<>c:b__70_9 (System.Type,intptr,int) - object Java.Interop.JavaConvert/<>c:<.cctor>b__20_9 (intptr,Android.Runtime.JniHandleOwnership) + object Android.Runtime.JNIEnv/<>c:b__72_8 (System.Type,intptr,int) + object Android.Runtime.JNIEnv/<>c:b__72_9 (System.Type,intptr,int) + object Java.Interop.JavaConvert/<>c:<.cctor>b__21_9 (intptr,Android.Runtime.JniHandleOwnership) object Java.Interop.TypeManager:CreateProxy (System.Type,intptr,Android.Runtime.JniHandleOwnership) + object Microsoft.Extensions.DependencyInjection.ActivatorUtilities:CreateInstance (System.IServiceProvider,System.Type,object[]) + object Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorMatcher:CreateInstance (System.IServiceProvider) object Microsoft.Extensions.DependencyInjection.KeyedService:get_AnyKey () - object Microsoft.Extensions.DependencyInjection.ServiceDescriptor:get_ImplementationInstance () object Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory/<>c:b__16_0 (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier) object Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver:Resolve (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope) object Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver:VisitCache (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite,Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope,Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverLock) @@ -2276,32 +2319,39 @@ Methods: object Microsoft.Extensions.DependencyInjection.ServiceProvider/<>c:b__33_1 (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope) object Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions:GetRequiredService (System.IServiceProvider,System.Type) object Microsoft.Maui.Controls.AppThemeBinding:GetValue () - object Microsoft.Maui.Controls.BaseShellItem/<>c__DisplayClass81_0:b__0 () + object Microsoft.Maui.Controls.BaseShellItem/<>c__DisplayClass83_0:b__0 () object Microsoft.Maui.Controls.BindableObject:get_BindingContext () object Microsoft.Maui.Controls.BindableObject:GetValue (Microsoft.Maui.Controls.BindableProperty) object Microsoft.Maui.Controls.BindableProperty:GetDefaultValue (Microsoft.Maui.Controls.BindableObject) - object Microsoft.Maui.Controls.Binding:GetSourceValue (object,System.Type) object Microsoft.Maui.Controls.BindingBase:GetSourceValue (object,System.Type) - object Microsoft.Maui.Controls.Element/d__101`1:System.Collections.IEnumerator.get_Current () + object Microsoft.Maui.Controls.Element/d__103`1:System.Collections.IEnumerator.get_Current () object Microsoft.Maui.Controls.ElementTemplate:CreateContent () object Microsoft.Maui.Controls.FlyoutPage:GetDefaultValue (Microsoft.Maui.Controls.BindableObject) object Microsoft.Maui.Controls.FontElement:FontSizeDefaultValueCreator (Microsoft.Maui.Controls.BindableObject) + object Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c:b__33_2 (Microsoft.Maui.Controls.BaseShellItem) + object Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c:b__34_2 (Microsoft.Maui.Controls.BaseShellItem) + object Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c:b__30_2 (Microsoft.Maui.Controls.Element) + object Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c:b__49_2 (Microsoft.Maui.Controls.BaseShellItem) + object Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c:b__47_2 (Microsoft.Maui.Controls.BaseShellItem) + object Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c:b__48_2 (Microsoft.Maui.Controls.BaseShellItem) + object Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c:b__35_2 (Microsoft.Maui.Controls.BaseShellItem) object Microsoft.Maui.Controls.Grid/<>c:<.cctor>b__59_1 (Microsoft.Maui.Controls.BindableObject) object Microsoft.Maui.Controls.Grid/<>c:<.cctor>b__59_3 (Microsoft.Maui.Controls.BindableObject) object Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.IElementHandler.get_PlatformView () object Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.IViewHandler.get_ContainerView () object Microsoft.Maui.Controls.Internals.DataTemplateExtensions:CreateContent (Microsoft.Maui.Controls.DataTemplate,object,Microsoft.Maui.Controls.BindableObject) + object Microsoft.Maui.Controls.Internals.TypedBinding`2:GetSourceValue (object,System.Type) object Microsoft.Maui.Controls.ObservableWrapper`2:System.Collections.IList.get_Item (int) object Microsoft.Maui.Controls.PaddingElement:PaddingDefaultValueCreator (Microsoft.Maui.Controls.BindableObject) object Microsoft.Maui.Controls.Routing:CreateDefaultRoute (Microsoft.Maui.Controls.BindableObject) - object Microsoft.Maui.Controls.SetterSpecificityList:GetClearedValue (Microsoft.Maui.Controls.SetterSpecificity) + object Microsoft.Maui.Controls.SetterSpecificityList`1:GetClearedValue (Microsoft.Maui.Controls.SetterSpecificity) object Microsoft.Maui.Controls.Shell/<>c:<.cctor>b__313_0 (Microsoft.Maui.Controls.BindableObject) object Microsoft.Maui.Controls.Shell/<>c:<.cctor>b__313_1 (Microsoft.Maui.Controls.BindableObject) object Microsoft.Maui.Controls.ShellContent:get_Content () - object Microsoft.Maui.Controls.ShellContent/<>c__DisplayClass19_0:b__0 () - object Microsoft.Maui.Controls.ShellContent/<>c:<.cctor>b__40_0 (Microsoft.Maui.Controls.BindableObject) - object Microsoft.Maui.Controls.ShellItem/<>c:<.cctor>b__40_0 (Microsoft.Maui.Controls.BindableObject) - object Microsoft.Maui.Controls.ShellSection/<>c:<.cctor>b__103_0 (Microsoft.Maui.Controls.BindableObject) + object Microsoft.Maui.Controls.ShellContent/<>c__DisplayClass20_0:b__0 () + object Microsoft.Maui.Controls.ShellContent/<>c:<.cctor>b__45_0 (Microsoft.Maui.Controls.BindableObject) + object Microsoft.Maui.Controls.ShellItem/<>c:<.cctor>b__41_0 (Microsoft.Maui.Controls.BindableObject) + object Microsoft.Maui.Controls.ShellSection/<>c:<.cctor>b__104_0 (Microsoft.Maui.Controls.BindableObject) object Microsoft.Maui.Controls.VisualElement:CoerceInputTransparentProperty (Microsoft.Maui.Controls.BindableObject,object) object Microsoft.Maui.Controls.VisualElement:CoerceIsEnabledProperty (Microsoft.Maui.Controls.BindableObject,object) object Microsoft.Maui.Controls.VisualElement/<>c:<.cctor>b__426_0 (Microsoft.Maui.Controls.BindableObject,object) @@ -2309,6 +2359,8 @@ Methods: object Microsoft.Maui.Controls.VisualStateManager/<>c:<.cctor>b__8_0 (Microsoft.Maui.Controls.BindableObject) object Microsoft.Maui.Controls.Xaml.Internals.SimpleValueTargetProvider:Microsoft.Maui.Controls.Xaml.IProvideValueTarget.get_TargetObject () object Microsoft.Maui.Controls.Xaml.Internals.SimpleValueTargetProvider:Microsoft.Maui.Controls.Xaml.IProvideValueTarget.get_TargetProperty () + object Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider:Microsoft.Maui.Controls.Xaml.IProvideValueTarget.get_TargetObject () + object Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider:Microsoft.Maui.Controls.Xaml.IProvideValueTarget.get_TargetProperty () object Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider:GetService (System.Type) object Microsoft.Maui.Controls.Xaml.OnIdiomExtension:GetValue () object Microsoft.Maui.Controls.Xaml.OnIdiomExtension:ProvideValue (System.IServiceProvider) @@ -2326,8 +2378,6 @@ Methods: object Microsoft.Maui.Handlers.ViewHandler:OnCreatePlatformElement () object Microsoft.Maui.Handlers.ViewHandler`2:Microsoft.Maui.IElementHandler.get_PlatformView () object Microsoft.Maui.Hosting.Internal.MauiFactory:CreateInstance (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) - object Microsoft.Maui.Hosting.Internal.MauiFactory:GetService (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) - object Microsoft.Maui.Hosting.Internal.MauiFactory:GetService (System.Type,Microsoft.Extensions.DependencyInjection.ServiceDescriptor,System.Collections.Generic.IEnumerable`1) object Microsoft.Maui.Hosting.Internal.MauiFactory:GetService (System.Type) object Microsoft.Maui.MauiContext/<>c__11`1:b__11_0 (object) object Microsoft.Maui.MauiContext/<>c__12`1:b__12_0 (object) @@ -2338,8 +2388,7 @@ Methods: object System.AppContext:GetData (string) object System.Array:Clone () object System.Collections.Concurrent.ConcurrentDictionary`2:GetOrAdd (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,System.Func`2) - object System.Collections.Generic.List`1/Enumerator:System.Collections.IEnumerator.get_Current () - object System.Collections.Generic.SortedList`2:get_Item (Microsoft.Maui.Controls.SetterSpecificity) + object System.Collections.Generic.List`1/Enumerator:System.Collections.IEnumerator.get_Current () object System.Collections.Hashtable:get_Item (object) object System.Collections.Specialized.SingleItemReadOnlyList:get_Item (int) object System.Collections.Specialized.SingleItemReadOnlyList/d__15:System.Collections.IEnumerator.get_Current () @@ -2355,6 +2404,11 @@ Methods: object System.Net.Http.Headers.HttpHeaders/HeaderStoreItemInfo:GetSingleParsedValue () object System.Object:MemberwiseClone () object System.Reflection.ConstructorInfo:Invoke (object[]) + object System.Reflection.ConstructorInvoker:InterpretedInvoke (object,intptr*) + object System.Reflection.ConstructorInvoker:Invoke (System.Span`1) + object System.Reflection.ConstructorInvoker:InvokeDirectByRef (object,object,object,object) + object System.Reflection.ConstructorInvoker:InvokeDirectByRefWithFewArgs (System.Span`1) + object System.Reflection.ConstructorInvoker:InvokeImpl (object,object,object,object) object System.Reflection.MethodBase:Invoke (object,object[]) object System.Reflection.MethodBaseInvoker:InterpretedInvoke_Constructor (object,intptr*) object System.Reflection.MethodBaseInvoker:InterpretedInvoke_Method (object,intptr*) @@ -2377,7 +2431,6 @@ Methods: object System.Runtime.DependentHandle:UnsafeGetTargetAndDependent (object&) object System.Runtime.InteropServices.GCHandle:get_Target () object System.Runtime.InteropServices.GCHandle:InternalGet (intptr) - object System.Runtime.InteropServices.Marshal:PtrToStructure (intptr,System.Type) object System.RuntimeType:CreateInstanceDefaultCtor (bool,bool) object System.RuntimeType:CreateInstanceForAnotherGenericParameter (System.Type,System.RuntimeType,System.RuntimeType) object System.RuntimeType:CreateInstanceInternal (System.Runtime.CompilerServices.QCallTypeHandle) @@ -2388,6 +2441,7 @@ Methods: object System.Threading.ThreadInt64PersistentCounter:CreateThreadLocalCountObject () object System.Threading.ThreadPool:GetOrCreateThreadLocalCompletionCountObject () object System.Threading.ThreadPoolWorkQueue:Dequeue (System.Threading.ThreadPoolWorkQueueThreadLocals,bool&) + object System.Threading.ThreadPoolWorkQueue:DequeueWithPriorityAlternation (System.Threading.ThreadPoolWorkQueue,System.Threading.ThreadPoolWorkQueueThreadLocals,bool&) object System.Threading.ThreadPoolWorkQueue/WorkStealingQueue:LocalPop () object System.Threading.ThreadPoolWorkQueue/WorkStealingQueue:LocalPopCore () object System.Threading.ThreadPoolWorkQueue/WorkStealingQueue:TrySteal (bool&) @@ -2402,7 +2456,7 @@ Methods: object[] System.Reflection.RuntimeParameterInfo:GetPseudoCustomAttributes () object& System.Collections.Generic.Dictionary`2:FindValue (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey) object& System.Collections.Generic.Dictionary`2:FindValue (string) - object& System.Net.Http.Headers.HttpHeaders:g__GrowEntriesAndAddDefault|73_0 (System.Net.Http.Headers.HeaderDescriptor) + object& System.Net.Http.Headers.HttpHeaders:g__GrowEntriesAndAddDefault|74_0 (System.Net.Http.Headers.HeaderDescriptor) object& System.Net.Http.Headers.HttpHeaders:GetValueRefOrAddDefault (System.Net.Http.Headers.HeaderDescriptor) object& System.Net.Http.Headers.HttpHeaders:GetValueRefOrNullRef (System.Net.Http.Headers.HeaderDescriptor) single Android.Util.DisplayMetrics:get_Density () @@ -2430,6 +2484,8 @@ Methods: string Android.Runtime.AndroidTypeManager:GetReplacementTypeCore (string) string Android.Runtime.AndroidTypeManager:GetSimpleReference (System.Type) string Android.Runtime.JavaArray`1/d__13:System.Collections.Generic.IEnumerator.get_Current () + string Android.Runtime.JavaList`1:get_Item (int) + string Android.Runtime.JavaList`1:InternalGet (int) string Android.Runtime.JNIEnv:GetCharSequence (intptr,Android.Runtime.JniHandleOwnership) string Android.Runtime.JNIEnv:GetClassNameFromInstance (intptr) string Android.Runtime.JNIEnv:GetJniName (System.Type) @@ -2453,6 +2509,9 @@ Methods: string Microsoft.Maui.ApplicationModel.AppInfoImplementation/<>c:<.cctor>b__23_0 () string Microsoft.Maui.Controls.BaseShellItem:get_Route () string Microsoft.Maui.Controls.BaseShellItem:get_Title () + string Microsoft.Maui.Controls.BaseShellItem/<>c:b__83_1 (Microsoft.Maui.Controls.Element) + string Microsoft.Maui.Controls.BaseShellItem/<>c:b__83_5 (Microsoft.Maui.Controls.BaseShellItem) + string Microsoft.Maui.Controls.BaseShellItem/<>c:b__83_7 (Microsoft.Maui.Controls.BaseShellItem) string Microsoft.Maui.Controls.BindableObjectExtensions:GetPropertyIfSet (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,string) string Microsoft.Maui.Controls.Button:get_FontFamily () string Microsoft.Maui.Controls.Button:get_Text () @@ -2464,6 +2523,7 @@ Methods: string Microsoft.Maui.Controls.NavigationPageToolbar:get_Title () string Microsoft.Maui.Controls.NavigationPageToolbar:GetTitle () string Microsoft.Maui.Controls.Page:get_Title () + string Microsoft.Maui.Controls.PropertyChangingEventArgs:get_PropertyName () string Microsoft.Maui.Controls.RequestDefinition:MakeUriString (System.Collections.Generic.List`1) string Microsoft.Maui.Controls.RouteRequestBuilder:g__GetUserSegment|27_1 (Microsoft.Maui.Controls.BaseShellItem) string Microsoft.Maui.Controls.RouteRequestBuilder:get_NextSegment () @@ -2473,6 +2533,7 @@ Methods: string Microsoft.Maui.Controls.SemanticProperties:GetDescription (Microsoft.Maui.Controls.BindableObject) string Microsoft.Maui.Controls.SemanticProperties:GetHint (Microsoft.Maui.Controls.BindableObject) string Microsoft.Maui.Controls.Shell:get_Route () + string Microsoft.Maui.Controls.ShellSection/<>c:b__59_0 (Microsoft.Maui.Controls.BaseShellItem) string Microsoft.Maui.Controls.ShellUriHandler:FormatUri (string) string Microsoft.Maui.Controls.Toolbar:get_Title () string Microsoft.Maui.Controls.Window:get_Title () @@ -2523,7 +2584,7 @@ Methods: string System.IO.Path:GetFileNameWithoutExtension (string) string System.IO.Path:JoinInternal (System.ReadOnlySpan`1,System.ReadOnlySpan`1) string System.IO.PathInternal:NormalizeDirectorySeparators (string) - string System.Linq.Extensions/d__5`1:System.Collections.Generic.IEnumerator.get_Current () + string System.Linq.Extensions/d__6`1:System.Collections.Generic.IEnumerator.get_Current () string System.Net.CookieContainer:CreateFqdnMyDomain () string System.Net.CookieContainer:GetCookieHeader (System.Uri,string&) string System.Net.CookieContainer:GetCookieHeader (System.Uri) @@ -2538,8 +2599,7 @@ Methods: string System.ReadOnlySpan`1:ToString () string System.Reflection.AssemblyName:get_CultureName () string System.Reflection.AssemblyName:get_FullName () - string System.Reflection.AssemblyNameFormatter:ComputeDisplayName (string,System.Version,string,byte[],System.Reflection.AssemblyNameFlags,System.Reflection.AssemblyContentType) - string System.Reflection.AssemblyNameParser:ParseCulture (string) + string System.Reflection.AssemblyNameFormatter:ComputeDisplayName (string,System.Version,string,byte[],System.Reflection.AssemblyNameFlags,System.Reflection.AssemblyContentType,byte[]) string System.Reflection.RuntimeAssembly:get_Location () string System.Reflection.RuntimeAssembly:GetInfo (System.Reflection.RuntimeAssembly/AssemblyInfoKind) string System.Reflection.RuntimeMethodInfo:get_Name () @@ -2562,11 +2622,10 @@ Methods: string System.String:Concat (string,string,string) string System.String:Concat (string,string) string System.String:Concat (System.ReadOnlySpan`1,System.ReadOnlySpan`1,System.ReadOnlySpan`1) - string System.String:Create (int,intptr,System.Buffers.SpanAction`2) + string System.String:Create (int,System.ReadOnlySpan`1,System.Buffers.SpanAction`2>) string System.String:CreateStringForSByteConstructor (byte*,int) string System.String:CreateStringFromEncoding (byte*,int,System.Text.Encoding) string System.String:CreateTrimmedString (int,int) - string System.String:Ctor (char[],int,int) string System.String:Ctor (char*,int,int) string System.String:Ctor (char*) string System.String:Ctor (sbyte*) @@ -2583,6 +2642,7 @@ Methods: string System.String:Trim () string System.String:TrimEnd (char) string System.String:TrimHelper (char*,int,System.Text.TrimType) + string System.Text.Encoding:GetString (System.ReadOnlySpan`1) string System.Text.ValueStringBuilder:ToString () string System.Text.ValueStringBuilder:ToString () string System.Threading.Tasks.Task`1:get_Result () @@ -2623,8 +2683,9 @@ Methods: System.Action`2 Microsoft.Maui.PropertyMapper:GetProperty (string) System.Action`3 Microsoft.Maui.CommandMapper:GetCommand (string) System.Array Android.Runtime.JNIEnv:_GetArray (intptr,System.Type) + System.Array Android.Runtime.JNIEnv:ArrayCreateInstance (System.Type,int) System.Array Android.Runtime.JNIEnv:GetArray (intptr,Android.Runtime.JniHandleOwnership,System.Type) - System.Array Android.Runtime.JNIEnv/<>c:b__96_12 (System.Type,intptr,int) + System.Array Android.Runtime.JNIEnv/<>c:b__98_12 (System.Type,intptr,int) System.Array Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver:g__CreateArray|12_0 (System.Type,int) System.Array System.Array:CreateInstance (System.Type,int) System.Array System.Array:InternalCreate (System.RuntimeType,int,int*,int*) @@ -2633,25 +2694,25 @@ Methods: System.Attribute System.Attribute:GetCustomAttribute (System.Reflection.MemberInfo,System.Type) System.Attribute System.Reflection.CustomAttributeExtensions:GetCustomAttribute (System.Reflection.Assembly,System.Type) System.Attribute System.Reflection.CustomAttributeExtensions:GetCustomAttribute (System.Reflection.MemberInfo,System.Type) - System.Attribute[] System.Attribute:GetCustomAttributes (System.Reflection.Assembly,System.Type) System.Attribute[] System.Reflection.CustomAttribute:GetCustomAttributesInternal (System.Reflection.ICustomAttributeProvider,System.Type,bool) System.AttributeUsageAttribute System.Reflection.CustomAttribute:RetrieveAttributeUsage (System.Type) System.AttributeUsageAttribute System.Reflection.CustomAttribute:RetrieveAttributeUsageNoCache (System.Type) System.Buffers.ArrayPool`1 System.Buffers.ArrayPool`1:get_Shared () System.Buffers.ArrayPool`1 System.Buffers.ArrayPool`1:get_Shared () + System.Buffers.OperationStatus System.Text.Ascii:ChangeCase (System.ReadOnlySpan`1,System.Span`1,int&) System.Buffers.OperationStatus System.Text.Ascii:ChangeCase (System.ReadOnlySpan`1,System.Span`1,int&) System.Buffers.OperationStatus System.Text.Unicode.Utf8Utility:TranscodeToUtf16 (byte*,int,char*,int,byte*&,char*&) System.Buffers.OperationStatus System.Text.Unicode.Utf8Utility:TranscodeToUtf8 (char*,int,byte*,int,char*&,byte*&) System.Buffers.SearchValues`1 System.Buffers.SearchValues:Create (System.ReadOnlySpan`1) System.Buffers.SearchValues`1 System.Buffers.SearchValues:Create (System.ReadOnlySpan`1) - System.Buffers.SharedArrayPool`1/Partitions System.Buffers.SharedArrayPool`1:CreatePerCorePartitions (int) - System.Buffers.SharedArrayPool`1/ThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () - System.Buffers.SharedArrayPool`1/ThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Buffers.SharedArrayPoolPartitions System.Buffers.SharedArrayPool`1:CreatePerCorePartitions (int) + System.Buffers.SharedArrayPoolThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () + System.Buffers.SharedArrayPoolThreadLocalArray[] System.Buffers.SharedArrayPool`1:InitializeTlsBucketsAndTrimming () System.Buffers.Utilities/MemoryPressure System.Buffers.Utilities:GetMemoryPressure () + System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:CreateComparer () + System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:get_Default () System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:CreateComparer () System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:get_Default () - System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:CreateComparer () - System.Collections.Generic.Comparer`1 System.Collections.Generic.Comparer`1:get_Default () System.Collections.Generic.Dictionary`2/Enumerator System.Collections.Generic.Dictionary`2:GetEnumerator () System.Collections.Generic.Dictionary`2/Enumerator> System.Collections.Generic.Dictionary`2>:GetEnumerator () System.Collections.Generic.Dictionary`2/Enumerator System.Collections.Generic.Dictionary`2:GetEnumerator () @@ -2659,7 +2720,7 @@ Methods: System.Collections.Generic.Dictionary`2/KeyCollection/Enumerator> System.Collections.Generic.Dictionary`2/KeyCollection>:GetEnumerator () System.Collections.Generic.Dictionary`2/KeyCollection> System.Collections.Generic.Dictionary`2>:get_Keys () System.Collections.Generic.Dictionary`2/ValueCollection/Enumerator System.Collections.Generic.Dictionary`2/ValueCollection:GetEnumerator () - System.Collections.Generic.Dictionary`2/ValueCollection System.Collections.Generic.Dictionary`2:get_Values () + System.Collections.Generic.Dictionary`2/ValueCollection System.Collections.Generic.Dictionary`2:get_Values () System.Collections.Generic.Dictionary`2> System.Runtime.Loader.AssemblyLoadContext:get_AllContexts () System.Collections.Generic.Dictionary`2> Microsoft.Maui.Controls.Element:get_DynamicResources () System.Collections.Generic.Dictionary`2 Microsoft.Maui.Controls.ShellRouteParameters:ParseQueryString (string) @@ -2679,12 +2740,11 @@ Methods: System.Collections.Generic.EqualityComparer`1 System.Collections.Generic.EqualityComparer`1:CreateComparer () System.Collections.Generic.EqualityComparer`1 System.Collections.Generic.EqualityComparer`1:CreateComparer () System.Collections.Generic.EqualityComparer`1> System.Collections.Generic.EqualityComparer`1>:CreateComparer () + System.Collections.Generic.EqualityComparer`1>> System.Collections.Generic.EqualityComparer`1>>:CreateComparer () System.Collections.Generic.EqualityComparer`1> System.Collections.Generic.EqualityComparer`1>:CreateComparer () - System.Collections.Generic.HashSet`1/Enumerator System.Collections.Generic.HashSet`1:GetEnumerator () + System.Collections.Generic.HashSet`1/Enumerator System.Collections.Generic.HashSet`1:GetEnumerator () System.Collections.Generic.HashSet`1 Microsoft.Maui.PropertyMapper:PopulateKeys () System.Collections.Generic.IArraySortHelper`1 System.Collections.Generic.ArraySortHelper`1:CreateArraySortHelper () - System.Collections.Generic.IArraySortHelper`1 System.Collections.Generic.ArraySortHelper`1:CreateArraySortHelper () - System.Collections.Generic.IArraySortHelper`1 System.Collections.Generic.ArraySortHelper`1:get_Default () System.Collections.Generic.ICollection`1 Microsoft.Maui.Controls.ResourceDictionary:get_MergedDictionaries () System.Collections.Generic.ICollection`1 Android.Runtime.JavaDictionary`2>:get_Keys () System.Collections.Generic.IComparer`1 Microsoft.Maui.Controls.MenuBarTracker:CreateComparer () @@ -2699,31 +2759,27 @@ Methods: System.Collections.Generic.IEnumerable`1 System.Linq.Enumerable:Where (System.Collections.Generic.IEnumerable`1,System.Func`2) System.Collections.Generic.IEnumerable`1 System.Linq.Enumerable:Select (System.Collections.Generic.IEnumerable`1,System.Func`2) System.Collections.Generic.IEnumerable`1 Microsoft.Maui.Controls.StyleSheets.StyleSheetExtensions:GetStyleSheets (Microsoft.Maui.Controls.IResourcesProvider) - System.Collections.Generic.IEnumerable`1 System.Reflection.CustomAttributeExtensions:GetCustomAttributes (System.Reflection.Assembly) System.Collections.Generic.IEnumerable`1 Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions:GetRequiredService (System.IServiceProvider) System.Collections.Generic.IEnumerable`1 Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions:GetServices (System.IServiceProvider) System.Collections.Generic.IEnumerable`1 Microsoft.Maui.Platform.ElementExtensions:GetParentsPath (Microsoft.Maui.IElement) System.Collections.Generic.IEnumerable`1 Microsoft.Maui.LifecycleEvents.LifecycleEventService:GetEventDelegates (string) System.Collections.Generic.IEnumerable`1 Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions:GetLifecycleEventDelegates (System.IServiceProvider,string) System.Collections.Generic.IEnumerable`1 System.Linq.Enumerable:OfType (System.Collections.IEnumerable) - System.Collections.Generic.IEnumerable`1 System.Linq.Enumerable:OfTypeIterator (System.Collections.IEnumerable) System.Collections.Generic.IEnumerable`1 Microsoft.Maui.Controls.Xaml.Internals.SimpleValueTargetProvider:Microsoft.Maui.Controls.Xaml.IProvideParentValues.get_ParentObjects () System.Collections.Generic.IEnumerable`1 Microsoft.Maui.Handlers.AndroidBatchPropertyMapper`2:GetKeys () System.Collections.Generic.IEnumerable`1 Microsoft.Maui.PropertyMapper:GetKeys () - System.Collections.Generic.IEnumerable`1 System.Reflection.CustomAttributeExtensions:GetCustomAttributes (System.Reflection.Assembly,System.Type) System.Collections.Generic.IEnumerable`1> Microsoft.Maui.Controls.ResourceDictionary:get_MergedResources () System.Collections.Generic.IEnumerable`1> Microsoft.Maui.Controls.ResourcesExtensions:GetMergedResources (Microsoft.Maui.Controls.IElementDefinition) System.Collections.Generic.IEnumerable`1> System.Diagnostics.Metrics.Instrument:get_Tags () + System.Collections.Generic.IEnumerator`1 Android.Runtime.JavaList`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 System.Collections.ObjectModel.Collection`1:GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Collections.Generic.List`1:System.Collections.Generic.IEnumerable.GetEnumerator () - System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.Element/d__101`1:System.Collections.Generic.IEnumerable.GetEnumerator () - System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.Element/d__112:System.Collections.Generic.IEnumerable.GetEnumerator () + System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.Element/d__103`1:System.Collections.Generic.IEnumerable.GetEnumerator () + System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.Element/d__114:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.ViewExtensions/d__22:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 System.Collections.ObjectModel.ReadOnlyCollection`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.NavigatingStepRequestList:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.MenuItemTracker`1/d__7:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.ReadOnlyCastingList`2:GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Linq.Enumerable/Iterator`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.ObservableWrapper`2:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.ShellElementCollection`1:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.StyleSheets.StyleSheetExtensions/d__0:System.Collections.Generic.IEnumerable.GetEnumerator () @@ -2734,25 +2790,17 @@ Methods: System.Collections.Generic.IEnumerator`1 System.Array:InternalArray__IEnumerable_GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Platform.ElementExtensions/d__11:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Controls.Layout:GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Linq.OrderedEnumerable`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions/d__3`1:System.Collections.Generic.IEnumerable.GetEnumerator () - System.Collections.Generic.IEnumerator`1 System.Linq.Enumerable/d__41`1:System.Collections.Generic.IEnumerable.GetEnumerator () + System.Collections.Generic.IEnumerator`1 System.Linq.Enumerable/Iterator`1:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Android.Runtime.JavaArray`1:GetEnumerator () - System.Collections.Generic.IEnumerator`1 Android.Runtime.JavaList`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 Android.Runtime.JavaSet`1:GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.Handlers.AndroidBatchPropertyMapper`2/d__2:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 Microsoft.Maui.PropertyMapper/d__17:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 System.Collections.Generic.HashSet`1:System.Collections.Generic.IEnumerable.GetEnumerator () System.Collections.Generic.IEnumerator`1 System.Linq.Extensions:ToEnumerator_Dispose (Java.Util.IIterator) System.Collections.Generic.IEnumerator`1> System.Runtime.CompilerServices.ConditionalWeakTable`2:System.Collections.Generic.IEnumerable>.GetEnumerator () - System.Collections.Generic.IEnumerator`1> System.Array:InternalArray__IEnumerable_GetEnumerator () - System.Collections.Generic.IEnumerator`1> System.Collections.Generic.EnumerableHelpers:GetEmptyEnumerator () - System.Collections.Generic.IEnumerator`1> System.Collections.Generic.SortedList`2:GetEnumerator () - System.Collections.Generic.IEnumerator`1> System.Collections.Generic.SortedList`2:System.Collections.Generic.IEnumerable>.GetEnumerator () - System.Collections.Generic.IEnumerator`1> System.Collections.Generic.SortedList`2:GetEnumerator () - System.Collections.Generic.IEnumerator`1> System.Collections.Generic.SortedList`2:System.Collections.Generic.IEnumerable>.GetEnumerator () System.Collections.Generic.IEnumerator`1> Microsoft.Maui.Controls.ResourceDictionary:GetEnumerator () - System.Collections.Generic.IEnumerator`1> Microsoft.Maui.Controls.ResourceDictionary/d__42:System.Collections.Generic.IEnumerable>.GetEnumerator () + System.Collections.Generic.IEnumerator`1> Microsoft.Maui.Controls.ResourceDictionary/d__46:System.Collections.Generic.IEnumerable>.GetEnumerator () System.Collections.Generic.IEnumerator`1> Microsoft.Maui.Controls.ShellNavigationQueryParameters:GetEnumerator () System.Collections.Generic.IEnumerator`1> System.Collections.Generic.Dictionary`2:System.Collections.Generic.IEnumerable>.GetEnumerator () System.Collections.Generic.IEnumerator`1> System.Collections.Generic.List`1>:System.Collections.Generic.IEnumerable.GetEnumerator () @@ -2761,7 +2809,6 @@ Methods: System.Collections.Generic.IEqualityComparer`1 System.Collections.Generic.NonRandomizedStringEqualityComparer:GetStringComparer (object) System.Collections.Generic.IList`1 AndroidX.Fragment.App.FragmentManager:get_Fragments () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.Style:get_Behaviors () - System.Collections.Generic.IList`1 System.Collections.Generic.SortedList`2:get_Values () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.Compatibility.Layout:get_LogicalChildrenInternalBackingStore () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.Element:get_LogicalChildrenInternalBackingStore () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.TemplatedPage:Microsoft.Maui.Controls.IControlTemplated.get_InternalChildren () @@ -2770,8 +2817,6 @@ Methods: System.Collections.Generic.IList`1 Microsoft.Maui.Controls.MenuBarTracker:GetMenuItems (Microsoft.Maui.Controls.Page) System.Collections.Generic.IList`1 Microsoft.Maui.Controls.MenuItemTracker`1:get_ToolbarItems () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.MultiPage`1:get_Children () - System.Collections.Generic.IList`1 System.Collections.Generic.SortedList`2:get_Keys () - System.Collections.Generic.IList`1 System.Collections.Generic.SortedList`2:get_Keys () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.ShellSection:get_Items () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.Shell:get_Items () System.Collections.Generic.IList`1 Microsoft.Maui.Controls.ShellItem:get_Items () @@ -2783,7 +2828,7 @@ Methods: System.Collections.Generic.IList`1 Android.Runtime.JavaDictionary`2>:Get (string) System.Collections.Generic.IList`1 Android.Runtime.JavaDictionary`2>:get_Item (string) System.Collections.Generic.IList`1 Android.Runtime.JavaList`1:FromJniHandle (intptr,Android.Runtime.JniHandleOwnership) - System.Collections.Generic.IList`1 Microsoft.Maui.Controls.NavigableElement:Microsoft.Maui.Controls.StyleSheets.IStyleSelectable.get_Classes () + System.Collections.Generic.IList`1 Microsoft.Maui.Controls.StyleableElement:Microsoft.Maui.Controls.StyleSheets.IStyleSelectable.get_Classes () System.Collections.Generic.IList`1> System.Collections.ObjectModel.ReadOnlyCollection`1>:get_Items () System.Collections.Generic.IReadOnlyCollection`1 Microsoft.Maui.PropertyMapper:get_UpdateKeys () System.Collections.Generic.IReadOnlyList`1 Microsoft.Maui.Controls.Element:get_LogicalChildrenInternal () @@ -2804,21 +2849,12 @@ Methods: System.Collections.Generic.IReadOnlyList`1 Microsoft.Maui.Controls.Element:Microsoft.Maui.IVisualTreeElement.GetVisualChildren () System.Collections.Generic.IReadOnlyList`1 Microsoft.Maui.Controls.Application:Microsoft.Maui.IApplication.get_Windows () System.Collections.Generic.IReadOnlyList`1 Microsoft.Maui.Platform.WindowExtensions:GetWindows () - System.Collections.Generic.KeyValuePair`2 System.Collections.Generic.SortedList`2/Enumerator:get_Current () - System.Collections.Generic.KeyValuePair`2 System.Linq.Enumerable:Last (System.Collections.Generic.IEnumerable`1>) - System.Collections.Generic.KeyValuePair`2 System.Linq.Enumerable:LastOrDefault (System.Collections.Generic.IEnumerable`1>) - System.Collections.Generic.KeyValuePair`2 System.Linq.Enumerable:TryGetLast (System.Collections.Generic.IEnumerable`1>,bool&) - System.Collections.Generic.KeyValuePair`2 Microsoft.Maui.Controls.SetterSpecificityList:GetSpecificityAndValue () - System.Collections.Generic.KeyValuePair`2 System.Collections.Generic.SortedList`2/Enumerator:get_Current () - System.Collections.Generic.KeyValuePair`2 System.Linq.Enumerable:Last (System.Collections.Generic.IEnumerable`1>) - System.Collections.Generic.KeyValuePair`2 System.Linq.Enumerable:TryGetLast (System.Collections.Generic.IEnumerable`1>,bool&) - System.Collections.Generic.KeyValuePair`2 System.Nullable`1>:get_Value () - System.Collections.Generic.KeyValuePair`2 Microsoft.Maui.Controls.ResourceDictionary/d__42:System.Collections.Generic.IEnumerator>.get_Current () + System.Collections.Generic.KeyValuePair`2 Microsoft.Maui.Controls.SetterSpecificityList`1:GetSpecificityAndValue () + System.Collections.Generic.KeyValuePair`2 Microsoft.Maui.Controls.ResourceDictionary/d__46:System.Collections.Generic.IEnumerator>.get_Current () System.Collections.Generic.KeyValuePair`2 System.Collections.Generic.Dictionary`2/Enumerator:get_Current () System.Collections.Generic.KeyValuePair`2 System.Collections.Generic.List`1/Enumerator>:get_Current () - System.Collections.Generic.KeyValuePair`2[] System.Collections.Generic.EnumerableHelpers:ToArray (System.Collections.Generic.IEnumerable`1>) + System.Collections.Generic.KeyValuePair`2[] System.Linq.Enumerable:ICollectionToArray (System.Collections.Generic.ICollection`1>) System.Collections.Generic.KeyValuePair`2[] System.Linq.Enumerable:ToArray (System.Collections.Generic.IEnumerable`1>) - System.Collections.Generic.List`1/Enumerator System.Collections.Generic.List`1:GetEnumerator () System.Collections.Generic.List`1/Enumerator System.Collections.Generic.List`1:GetEnumerator () System.Collections.Generic.List`1/Enumerator> System.Collections.Generic.List`1>:GetEnumerator () System.Collections.Generic.List`1/Enumerator> System.Collections.Generic.List`1>:GetEnumerator () @@ -2831,21 +2867,19 @@ Methods: System.Collections.Generic.List`1> Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.GenerateFlyoutGrouping () System.Collections.Generic.List`1> Microsoft.Maui.Controls.ShellFlyoutItemsManager:GenerateFlyoutGrouping () System.Collections.Generic.List`1 System.Threading.TimerQueue:InitializeScheduledTimerManager_Locked () - System.Collections.Generic.List`1 Microsoft.Maui.Hosting.Internal.MauiFactory:GetServiceBaseTypes (System.Type) System.Collections.Generic.List`1> Microsoft.Maui.Controls.Handlers.TabbedPageManager:CreateTabList () System.Collections.Generic.List`1> Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRenderer:CreateTabList (Microsoft.Maui.Controls.ShellItem) - System.Collections.Generic.SortedList`2/KeyList System.Collections.Generic.SortedList`2:GetKeyListHelper () - System.Collections.Generic.SortedList`2/KeyList System.Collections.Generic.SortedList`2:GetKeyListHelper () - System.Collections.Generic.SortedList`2/ValueList System.Collections.Generic.SortedList`2:GetValueListHelper () + System.Collections.Generic.Stack`1/Enumerator System.Collections.Generic.Stack`1:GetEnumerator () System.Collections.IEnumerable Microsoft.Maui.Controls.Internals.TemplatedItemsList`2, Microsoft.Maui.Controls.Page>:GetItemsViewSource () System.Collections.IEnumerable Microsoft.Maui.Controls.MultiPage`1:get_ItemsSource () - System.Collections.IEnumerator Microsoft.Maui.Controls.Element/d__101`1:System.Collections.IEnumerable.GetEnumerator () + System.Collections.IEnumerator Microsoft.Maui.Controls.Element/d__103`1:System.Collections.IEnumerable.GetEnumerator () System.Collections.IEnumerator Microsoft.Maui.Controls.Layout:System.Collections.IEnumerable.GetEnumerator () - System.Collections.IEnumerator System.Collections.Generic.List`1:System.Collections.IEnumerable.GetEnumerator () + System.Collections.IEnumerator System.Collections.Generic.List`1:System.Collections.IEnumerable.GetEnumerator () System.Collections.IEnumerator System.Collections.ObjectModel.ReadOnlyCollection`1:System.Collections.IEnumerable.GetEnumerator () System.Collections.IEnumerator System.Collections.Specialized.ReadOnlyList:GetEnumerator () System.Collections.IEnumerator System.Collections.Specialized.SingleItemReadOnlyList:GetEnumerator () System.Collections.ObjectModel.ObservableCollection`1 Microsoft.Maui.Controls.Compatibility.Layout:get_InternalChildren () + System.Collections.ObjectModel.ObservableCollection`1 Microsoft.Maui.Controls.Page:get_InternalChildren () System.Collections.ObjectModel.ReadOnlyCollection`1 System.Collections.Generic.List`1:AsReadOnly () System.Collections.ObjectModel.ReadOnlyCollection`1 Microsoft.Maui.Controls.ShellSection:Microsoft.Maui.Controls.IShellSectionController.GetItems () System.Collections.ObjectModel.ReadOnlyCollection`1 Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.GetItems () @@ -2980,13 +3014,13 @@ Methods: System.Delegate System.Delegate:Remove (System.Delegate,System.Delegate) System.Delegate System.MulticastDelegate:CombineImpl (System.Delegate) System.Delegate System.MulticastDelegate:RemoveImpl (System.Delegate) - System.Diagnostics.Metrics.Histogram`1 System.Diagnostics.Metrics.Meter:CreateHistogram (string,string,string,System.Collections.Generic.IEnumerable`1>) - System.Diagnostics.Metrics.Histogram`1 System.Diagnostics.Metrics.Meter:CreateHistogram (string,string,string) + System.Diagnostics.Metrics.Histogram`1 System.Diagnostics.Metrics.Meter:CreateHistogram (string,string,string,System.Collections.Generic.IEnumerable`1>,System.Diagnostics.Metrics.InstrumentAdvice`1) System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter:GetCachedInstrument (System.Collections.Generic.List`1,System.Type,string,string,System.Collections.Generic.IEnumerable`1>) System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter:GetOrCreateInstrument (System.Type,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Func`1) System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter:GetOrCreateInstrument (System.Type,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Func`1) - System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter/<>c__DisplayClass35_0`1:b__0 () - System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter/<>c__DisplayClass37_0`1:b__0 () + System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter/<>c__DisplayClass39_0`1:b__0 () + System.Diagnostics.Metrics.Instrument System.Diagnostics.Metrics.Meter/<>c__DisplayClass41_0`1:b__0 () + System.Diagnostics.Metrics.InstrumentAdvice`1 System.Net.Http.DiagnosticsHelper:get_ShortHistogramAdvice () System.Diagnostics.Metrics.Meter System.Net.Http.Metrics.MetricsHandler/SharedMeter:get_Instance () System.Diagnostics.Metrics.UpDownCounter`1 System.Diagnostics.Metrics.Meter:CreateUpDownCounter (string,string,string,System.Collections.Generic.IEnumerable`1>) System.Diagnostics.Metrics.UpDownCounter`1 System.Diagnostics.Metrics.Meter:CreateUpDownCounter (string,string,string) @@ -3034,6 +3068,8 @@ Methods: System.IDisposable Microsoft.Maui.Platform.ViewExtensions:OnUnloaded (Android.Views.View,System.Action) System.IDisposable Microsoft.Maui.Platform.ViewExtensions:OnUnloaded (Microsoft.Maui.IElement,System.Action) System.IDisposable& System.Collections.Generic.Dictionary`2:FindValue (intptr) + System.Int128 System.Int128:op_Addition (System.Int128,System.Int128) + System.Int128 System.Math:BigMul (long,long) System.IO.Stream Android.Runtime.InputStreamInvoker:FromJniHandle (intptr,Android.Runtime.JniHandleOwnership) System.IO.Stream Java.Net.URLConnection:get_InputStream () System.IO.Stream System.IO.BinaryReader:get_BaseStream () @@ -3048,8 +3084,8 @@ Methods: System.IServiceProvider Microsoft.Maui.MauiApplication:Microsoft.Maui.IPlatformApplication.get_Services () System.IServiceProvider Microsoft.Maui.MauiContext:get_Services () System.LazyHelper System.LazyHelper:Create (System.Threading.LazyThreadSafetyMode,bool) - System.Linq.EnumerableSorter`1 System.Linq.OrderedEnumerable`1:GetEnumerableSorter () - System.Linq.EnumerableSorter`1 System.Linq.OrderedEnumerable`2:GetEnumerableSorter (System.Linq.EnumerableSorter`1) + System.Linq.Enumerable/EnumerableSorter`1 System.Linq.Enumerable/OrderedIterator`2:GetEnumerableSorter (System.Linq.Enumerable/EnumerableSorter`1) + System.Linq.Enumerable/Iterator`1 System.Linq.Enumerable/Iterator`1:GetEnumerator () System.Linq.IOrderedEnumerable`1 Microsoft.Maui.Handlers.LayoutExtensions:OrderByZIndex (Microsoft.Maui.ILayout) System.Linq.IOrderedEnumerable`1 System.Linq.Enumerable:OrderBy (System.Collections.Generic.IEnumerable`1,System.Func`2) System.MulticastDelegate System.Delegate:AllocDelegateLike_internal (System.Delegate) @@ -3086,6 +3122,7 @@ Methods: System.Number/ParsingStatus System.Number:TryParseBinaryIntegerStyle (System.ReadOnlySpan`1,System.Globalization.NumberStyles,System.Globalization.NumberFormatInfo,uint16&) System.Numerics.Matrix3x2 System.Numerics.Matrix3x2:CreateScale (single,single) System.Numerics.Matrix3x2 System.Numerics.Matrix3x2:op_Multiply (System.Numerics.Matrix3x2,System.Numerics.Matrix3x2) + System.Numerics.Vector2 System.Numerics.Vector2:Create (single,single) System.OperatingSystem System.Environment:get_OSVersion () System.OperatingSystem System.Environment:GetOperatingSystem (string) System.OperatingSystem System.Environment:GetOSVersion () @@ -3098,32 +3135,29 @@ Methods: System.ReadOnlySpan`1 System.Globalization.IcuLocaleData:get_NameIndexToNumericData () System.ReadOnlySpan`1 System.Globalization.IcuLocaleData:GetCultureName (int) System.ReadOnlySpan`1 System.HexConverter:get_CharToHexLookup () - System.ReadOnlySpan`1 System.IO.BinaryReader:InternalRead (int) + System.ReadOnlySpan`1 System.IO.BinaryReader:InternalRead (System.Span`1) System.ReadOnlySpan`1 System.IO.Path:GetFileName (System.ReadOnlySpan`1) System.ReadOnlySpan`1 System.IO.Path:GetFileNameWithoutExtension (System.ReadOnlySpan`1) System.ReadOnlySpan`1 System.IO.Path:GetPathRoot (System.ReadOnlySpan`1) System.ReadOnlySpan`1 System.IO.Path:TrimEndingDirectorySeparator (System.ReadOnlySpan`1) System.ReadOnlySpan`1 System.IO.PathInternal:TrimEndingDirectorySeparator (System.ReadOnlySpan`1) - System.ReadOnlySpan`1 System.MemoryExtensions:g__TrimFallback|219_0 (System.ReadOnlySpan`1) + System.ReadOnlySpan`1 System.MemoryExtensions:g__TrimFallback|231_0 (System.ReadOnlySpan`1) System.ReadOnlySpan`1 System.Runtime.CompilerServices.DefaultInterpolatedStringHandler:get_Text () System.ReadOnlySpan`1 System.Collections.Generic.ValueListBuilder`1:AsSpan () + System.ReadOnlySpan`1 System.Reflection.MethodBase:GetParametersAsSpan () System.Reflection.Assembly System.Reflection.Assembly:InternalLoad (string,System.Threading.StackCrawlMark&,intptr) System.Reflection.Assembly System.Reflection.Assembly:Load (System.Reflection.AssemblyName,System.Threading.StackCrawlMark&,System.Runtime.Loader.AssemblyLoadContext) System.Reflection.Assembly System.Reflection.RuntimeAssembly:InternalGetSatelliteAssembly (System.Reflection.Assembly,System.Globalization.CultureInfo,System.Version,bool) System.Reflection.Assembly System.Resources.ManifestBasedResourceGroveler:GetSatelliteAssembly (System.Globalization.CultureInfo) System.Reflection.Assembly System.Resources.ManifestBasedResourceGroveler:InternalGetSatelliteAssembly (System.Reflection.Assembly,System.Globalization.CultureInfo,System.Version) System.Reflection.Assembly System.Runtime.Loader.AssemblyLoadContext:LoadFromAssemblyName (System.Reflection.AssemblyName) - System.Reflection.Assembly System.Runtime.Loader.AssemblyLoadContext:MonoResolveUsingResolveSatelliteAssembly (intptr,string) - System.Reflection.Assembly System.Runtime.Loader.AssemblyLoadContext:ResolveSatelliteAssembly (System.Reflection.AssemblyName) System.Reflection.Assembly System.RuntimeType:get_Assembly () System.Reflection.AssemblyContentType System.Reflection.AssemblyName:get_ContentType () System.Reflection.AssemblyName System.Reflection.Assembly:GetName () System.Reflection.AssemblyName System.Reflection.AssemblyName:Create (intptr,string) System.Reflection.AssemblyName System.Reflection.RuntimeAssembly:GetName (bool) - System.Reflection.AssemblyNameParser/AssemblyNameParts System.Reflection.AssemblyNameParser:Parse () System.Reflection.AssemblyNameParser/AssemblyNameParts System.Reflection.AssemblyNameParser:Parse (string) - System.Reflection.AssemblyNameParser/Token System.Reflection.AssemblyNameParser:GetNextToken () - System.Reflection.AssemblyNameParser/Token System.Reflection.AssemblyNameParser:GetNextToken (string&) + System.Reflection.AssemblyNameParser/AssemblyNameParts System.Reflection.AssemblyNameParser:Parse (System.ReadOnlySpan`1) System.Reflection.Binder System.Type:get_DefaultBinder () System.Reflection.BindingFlags System.Reflection.RuntimePropertyInfo:FilterPreCalculate (bool,bool,bool) System.Reflection.BindingFlags System.Reflection.RuntimePropertyInfo:get_BindingFlags () @@ -3138,6 +3172,8 @@ Methods: System.Reflection.ConstructorInfo[] System.RuntimeType:GetConstructors (System.Reflection.BindingFlags) System.Reflection.ConstructorInfo[] System.RuntimeType/ListBuilder`1:ToArray () System.Reflection.ConstructorInfo[] System.Type:GetConstructors () + System.Reflection.ConstructorInvoker Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorInfoEx:get_Invoker () + System.Reflection.ConstructorInvoker System.Reflection.ConstructorInvoker:Create (System.Reflection.ConstructorInfo) System.Reflection.CorElementType System.Enum:InternalGetCorElementType () System.Reflection.CorElementType System.Enum:InternalGetCorElementType (System.Runtime.CompilerServices.QCallTypeHandle) System.Reflection.CorElementType System.RuntimeType:GetCorElementType () @@ -3155,14 +3191,12 @@ Methods: System.Reflection.MethodBase System.Reflection.RuntimeMethodInfo:GetMethodFromHandleInternalType_native (intptr,intptr,bool) System.Reflection.MethodBase System.Reflection.RuntimeMethodInfo:GetMethodFromHandleNoGenericCheck (System.RuntimeMethodHandle,System.RuntimeTypeHandle) System.Reflection.MethodBase System.Reflection.RuntimeMethodInfo:GetMethodFromHandleNoGenericCheck (System.RuntimeMethodHandle) - System.Reflection.MethodInfo Microsoft.Maui.Controls.Xaml.TypeConversionExtensions:GetImplicitConversionOperator (System.Type,System.Type,System.Type) + System.Reflection.MethodInfo Microsoft.Maui.Controls.TypeConversionHelper:g__GetImplicitConversionOperator|3_0 (System.Type,System.Type,System.Type) System.Reflection.MethodInfo System.Delegate:get_Method () System.Reflection.MethodInfo System.Delegate:GetCandidateMethod (System.RuntimeType,System.Type,string,System.Reflection.BindingFlags,bool) System.Reflection.MethodInfo System.Delegate:GetDelegateInvokeMethod (System.RuntimeType) System.Reflection.MethodInfo System.Delegate:GetMethodImpl () System.Reflection.MethodInfo System.MulticastDelegate:GetMethodImpl () - System.Reflection.MethodInfo System.Reflection.PropertyInfo:get_GetMethod () - System.Reflection.MethodInfo System.Reflection.PropertyInfo:get_SetMethod () System.Reflection.MethodInfo System.Reflection.RuntimeMethodInfo:GetBaseMethod () System.Reflection.MethodInfo System.Reflection.RuntimePropertyInfo:GetGetMethod (bool) System.Reflection.MethodInfo System.Reflection.RuntimePropertyInfo:GetSetMethod (bool) @@ -3173,26 +3207,28 @@ Methods: System.Reflection.MethodInfo System.Type:GetMethod (string,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type[],System.Reflection.ParameterModifier[]) System.Reflection.MethodInfo System.Type:GetMethod (string,System.Reflection.BindingFlags) System.Reflection.MethodInfo System.Type:GetMethod (string) + System.Reflection.MethodInfo[] System.RuntimeType:GetMethods (System.Reflection.BindingFlags) System.Reflection.Module System.RuntimeType:get_Module () System.Reflection.MonoMethodInfo System.Reflection.MonoMethodInfo:GetMethodInfo (intptr) System.Reflection.ParameterAttributes System.Reflection.ParameterInfo:get_Attributes () - System.Reflection.ParameterInfo[] System.Reflection.MethodBase:GetParametersNoCopy () System.Reflection.ParameterInfo[] System.Reflection.MonoMethodInfo:get_parameter_info (intptr,System.Reflection.MemberInfo) System.Reflection.ParameterInfo[] System.Reflection.MonoMethodInfo:GetParametersInfo (intptr,System.Reflection.MemberInfo) System.Reflection.ParameterInfo[] System.Reflection.RuntimeConstructorInfo:GetParameters () System.Reflection.ParameterInfo[] System.Reflection.RuntimeConstructorInfo:GetParametersInternal () + System.Reflection.ParameterInfo[] System.Reflection.RuntimeMethodInfo:GetParameters () System.Reflection.ParameterInfo[] System.Reflection.RuntimeMethodInfo:GetParametersInternal () System.Reflection.PropertyInfo System.Reflection.CustomAttribute:GetBasePropertyDefinition (System.Reflection.RuntimePropertyInfo) System.Reflection.PropertyInfo System.Reflection.RuntimePropertyInfo:GetPropertyFromHandle (Mono.RuntimePropertyHandle,System.RuntimeTypeHandle) System.Reflection.PropertyInfo System.Reflection.RuntimePropertyInfo:internal_from_handle_type (intptr,intptr) System.Reflection.PropertyInfo System.Reflection.RuntimeReflectionExtensions:GetRuntimeProperty (System.Type,string) - System.Reflection.PropertyInfo System.Reflection.TypeInfo:GetDeclaredProperty (string) System.Reflection.PropertyInfo System.RuntimeType:GetPropertyImpl (string,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[]) System.Reflection.PropertyInfo System.Type:GetProperty (string,System.Reflection.BindingFlags) System.Reflection.PropertyInfo System.Type:GetProperty (string) System.Reflection.RuntimeAssembly System.Reflection.RuntimeAssembly:InternalLoad (System.Reflection.AssemblyName,System.Threading.StackCrawlMark&,System.Runtime.Loader.AssemblyLoadContext) System.Reflection.RuntimeAssembly System.Runtime.Loader.AssemblyLoadContext:InvokeResolveEvent (System.ResolveEventHandler,System.Reflection.RuntimeAssembly,string) + System.Reflection.RuntimeAssembly System.Runtime.Loader.AssemblyLoadContext:MonoResolveUsingResolveSatelliteAssembly (intptr,string) System.Reflection.RuntimeAssembly System.Runtime.Loader.AssemblyLoadContext:OnAssemblyResolve (System.Reflection.RuntimeAssembly,string) + System.Reflection.RuntimeAssembly System.Runtime.Loader.AssemblyLoadContext:ResolveSatelliteAssembly (System.Reflection.AssemblyName) System.Reflection.RuntimeAssembly System.RuntimeTypeHandle:GetAssembly (System.RuntimeType) System.Reflection.RuntimeConstructorInfo System.RuntimeType:GetDefaultConstructor () System.Reflection.RuntimeConstructorInfo[] System.RuntimeType:GetConstructors_internal (System.Reflection.BindingFlags,System.RuntimeType) @@ -3234,7 +3270,6 @@ Methods: System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (System.Net.Http.HttpContent/d__63&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.IAsyncStateMachineBox System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:GetStateMachineBox (System.Net.Http.StreamToStreamCopy/<g__DisposeSourceAsync|1_0>d&,System.Threading.Tasks.Task`1&) System.Runtime.CompilerServices.TaskAwaiter`1 System.Threading.Tasks.Task`1:GetAwaiter () - System.Runtime.InteropServices.GCHandle System.Runtime.InteropServices.GCHandle:Alloc (object,System.Runtime.InteropServices.GCHandleType) System.Runtime.Loader.AssemblyLoadContext System.Runtime.Loader.AssemblyLoadContext:GetAssemblyLoadContext (intptr) System.Runtime.Loader.AssemblyLoadContext System.Runtime.Loader.AssemblyLoadContext:GetLoadContext (System.Reflection.Assembly) System.RuntimeType System.RuntimeType:GetBaseType () @@ -3251,8 +3286,6 @@ Methods: System.RuntimeType/TypeCache System.RuntimeType:get_Cache () System.RuntimeTypeHandle System.RuntimeType:get_TypeHandle () System.Span`1 System.Text.ValueUtf8Converter:ConvertAndTerminateString (System.ReadOnlySpan`1) - System.Span`1 System.Runtime.InteropServices.CollectionsMarshal:AsSpan (System.Collections.Generic.List`1) - System.Text.Decoder System.Text.UTF8Encoding:GetDecoder () System.Text.Encoding System.Text.Encoding:get_UTF8 () System.Threading.CancellationToken Microsoft.Maui.ImageSourceServiceResultManager:BeginLoad () System.Threading.CancellationToken Microsoft.Maui.ImageSourceServiceResultManager:get_Token () @@ -3279,7 +3312,10 @@ Methods: System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__Core|27_0>d>:get_Context () System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1d__63>:get_Context () System.Threading.ExecutionContext& System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1/AsyncStateMachineBox`1g__DisposeSourceAsync|1_0>d>:get_Context () - System.Threading.LowLevelLifoSemaphoreBase/Counts System.Threading.LowLevelLifoSemaphoreBase/Counts:InterlockedCompareExchange (System.Threading.LowLevelLifoSemaphoreBase/Counts,System.Threading.LowLevelLifoSemaphoreBase/Counts) + System.Threading.Lock/State System.Threading.Lock/State:CompareExchange (System.Threading.Lock,System.Threading.Lock/State,System.Threading.Lock/State) + System.Threading.Lock/ThreadId System.Threading.Lock:EnterAndGetCurrentThreadId () + System.Threading.Lock/ThreadId System.Threading.Lock:TryEnterSlow (int,System.Threading.Lock/ThreadId) + System.Threading.LowLevelLifoSemaphore/Counts System.Threading.LowLevelLifoSemaphore/Counts:InterlockedCompareExchange (System.Threading.LowLevelLifoSemaphore/Counts,System.Threading.LowLevelLifoSemaphore/Counts) System.Threading.PortableThreadPool/ThreadCounts System.Threading.PortableThreadPool/ThreadCounts:InterlockedCompareExchange (System.Threading.PortableThreadPool/ThreadCounts,System.Threading.PortableThreadPool/ThreadCounts) System.Threading.SemaphoreSlim System.IO.Stream:EnsureAsyncActiveSemaphoreInitialized () System.Threading.SynchronizationContext Android.App.Application:get_SynchronizationContext () @@ -3317,7 +3353,6 @@ Methods: System.Threading.Tasks.Task System.Threading.Tasks.Task:Run (System.Action,System.Threading.CancellationToken) System.Threading.Tasks.Task System.Threading.Tasks.Task:WhenAll (System.Collections.Generic.IEnumerable`1) System.Threading.Tasks.Task System.Threading.Tasks.Task:WhenAll (System.ReadOnlySpan`1) - System.Threading.Tasks.Task System.Threading.Tasks.Task:WhenAll (System.Threading.Tasks.Task[]) System.Threading.Tasks.Task Xamarin.Android.Net.AndroidMessageHandler:ConnectAsync (Java.Net.HttpURLConnection,System.Threading.CancellationToken) System.Threading.Tasks.Task Xamarin.Android.Net.AndroidMessageHandler:SetupRequest (System.Net.Http.HttpRequestMessage,Java.Net.HttpURLConnection) System.Threading.Tasks.Task/ContingentProperties System.Threading.Tasks.Task:EnsureContingentPropertiesInitializedUnsafe () @@ -3377,11 +3412,9 @@ Methods: System.Threading.WaitSubsystem/WaitableObject System.Threading.WaitSubsystem/WaitableObject:NewEvent (bool,System.Threading.EventResetMode) System.Threading.WaitSubsystem/WaitableObject[] System.Threading.WaitSubsystem/ThreadWaitInfo:GetWaitedObjectArray (int) System.TimeProvider System.TimeProvider:get_System () - System.TimeSpan System.TimeSpan:FromHours (double) - System.TimeSpan System.TimeSpan:FromMilliseconds (double) - System.TimeSpan System.TimeSpan:FromSeconds (double) - System.TimeSpan System.TimeSpan:Interval (double,double) - System.TimeSpan System.TimeSpan:IntervalFromDoubleTicks (double) + System.TimeSpan System.TimeSpan:FromHours (int) + System.TimeSpan System.TimeSpan:FromMilliseconds (long,long) + System.TimeSpan System.TimeSpan:FromSeconds (long) System.Type Android.Animation.ValueAnimator:get_ThresholdType () System.Type Android.App.Application:get_ThresholdType () System.Type Android.App.UiModeManager:get_ThresholdType () @@ -3400,6 +3433,8 @@ Methods: System.Type Android.Graphics.Paint:get_ThresholdType () System.Type Android.Net.ConnectivityManager:get_ThresholdType () System.Type Android.Net.NetworkInfo:get_ThresholdType () + System.Type Android.Runtime.AndroidEnvironment:g__TypeGetType|26_0 (string) + System.Type Android.Runtime.JNIEnvInit:g__TypeGetType|13_0 (string) System.Type Android.Runtime.XAPeerMembers:GetThresholdType (Java.Interop.IJavaPeerable) System.Type Android.Text.TextPaint:get_ThresholdType () System.Type Android.Views.Display:get_ThresholdType () @@ -3439,6 +3474,8 @@ Methods: System.Type Google.Android.Material.Button.MaterialButton:get_ThresholdType () System.Type Google.Android.Material.Tabs.TabLayout:get_ThresholdType () System.Type Google.Android.Material.Tabs.TabLayout/Tab:get_ThresholdType () + System.Type Java.Interop.JavaConvert:g__MakeGenericType|2_0 (System.Type,System.Type[]) + System.Type Java.Interop.JavaObjectExtensions:g__AssemblyGetType|10_0 (System.Reflection.Assembly,string) System.Type Java.Interop.JavaObjectExtensions:GetInvokerType (System.Type) System.Type Java.Interop.JniRuntime/JniTypeManager:GetUnderlyingType (System.Type,int&) System.Type Java.Interop.TypeManager:GetJavaToManagedType (string) @@ -3448,18 +3485,17 @@ Methods: System.Type Java.Lang.Object:GetThresholdType () System.Type Java.Net.URL:get_ThresholdType () System.Type Javax.Net.Ssl.HttpsURLConnectionInvoker:get_ThresholdType () - System.Type Microsoft.Extensions.DependencyInjection.ServiceDescriptor:get_ImplementationType () System.Type Microsoft.Extensions.DependencyInjection.ServiceDescriptor:GetImplementationType () System.Type Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceDescriptorExtensions:GetImplementationType (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) System.Type Microsoft.Maui.Controls.DependencyService:FindImplementor (System.Type) System.Type Microsoft.Maui.Controls.Style:get_TargetType () System.Type Microsoft.Maui.Controls.Xaml.TypeConversionExtensions:GetConverterType (System.ComponentModel.TypeConverterAttribute) - System.Type Microsoft.Maui.Controls.Xaml.XamlResourceIdAttribute:GetTypeForPath (System.Reflection.Assembly,string) - System.Type Microsoft.Maui.Hosting.ImageSourceServiceProvider:b__9_0 (System.Type) - System.Type Microsoft.Maui.Hosting.ImageSourceServiceProvider:GetImageSourceServiceType (System.Type) + System.Type Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping:FindImageSourceServiceType (System.Type) + System.Type Microsoft.Maui.Hosting.Internal.MauiHandlersFactory:GetVirtualViewHandlerServiceType (System.Type) + System.Type Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:ResolveVirtualViewFromTypeSet (System.Type,System.Collections.Generic.HashSet`1) + System.Type Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:ResolveVirtualViewToRegisteredHandlerServiceType (System.Type) System.Type Microsoft.Maui.PlatformAppCompatTextView:get_ThresholdType () System.Type Microsoft.Maui.PlatformContentViewGroup:get_ThresholdType () - System.Type System.Collections.Concurrent.ConcurrentDictionary`2:GetOrAdd (System.Type,System.Func`2) System.Type System.Nullable:GetUnderlyingType (System.Type) System.Type System.Reflection.Assembly:GetType (string) System.Type System.Reflection.Assembly:InternalGetType (System.Reflection.Module,string,bool,bool) @@ -3473,7 +3509,6 @@ Methods: System.Type System.Reflection.RuntimePropertyInfo:get_DeclaringType () System.Type System.Reflection.RuntimePropertyInfo:get_PropertyType () System.Type System.Reflection.RuntimePropertyInfo:get_ReflectedType () - System.Type System.Reflection.TypeInfo:AsType () System.Type System.RuntimeType:get_BaseType () System.Type System.RuntimeType:get_UnderlyingSystemType () System.Type System.RuntimeType:GetElementType () @@ -3486,7 +3521,6 @@ Methods: System.Type System.Type:GetType (string) System.Type[] Java.Interop.TypeManager:GetParameterTypes (string) System.Type[] System.RuntimeType:GetGenericArguments () - System.Type[] System.RuntimeType:GetInterfaces () System.Type[] System.Type:get_GenericTypeArguments () System.TypeCode System.RuntimeType:GetTypeCodeImpl () System.Uri Microsoft.Maui.Controls.ShellNavigationState:TrimDownImplicitAndDefaultPaths (System.Uri) @@ -3504,15 +3538,23 @@ Methods: System.ValueTuple`2[] Microsoft.Maui.Controls.BindableObject:GetValues (Microsoft.Maui.Controls.BindableProperty[]) System.ValueTuple`2[] Microsoft.Maui.Controls.BindableObject:GetValues (Microsoft.Maui.Controls.BindableProperty[]) System.ValueTuple`2 System.Threading.PortableThreadPool/HillClimbing:Update (int,double,int) + System.ValueTuple`2 System.Collections.Generic.List`1>:get_Item (int) + System.ValueTuple`2 Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c__DisplayClass33_0:b__1 (Microsoft.Maui.Controls.BaseShellItem) + System.ValueTuple`2 Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c__DisplayClass48_0:b__1 (Microsoft.Maui.Controls.BaseShellItem) + System.ValueTuple`2 Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c__DisplayClass49_0:b__1 (Microsoft.Maui.Controls.BaseShellItem) System.ValueTuple`2 System.Collections.Generic.List`1>:get_Item (int) + System.ValueTuple`2 Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c__DisplayClass30_0:b__1 (Microsoft.Maui.Controls.Element) + System.ValueTuple`2 Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c__DisplayClass34_0:b__1 (Microsoft.Maui.Controls.BaseShellItem) + System.ValueTuple`2 Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c__DisplayClass35_0:b__1 (Microsoft.Maui.Controls.BaseShellItem) + System.ValueTuple`2 Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c__DisplayClass47_0:b__1 (Microsoft.Maui.Controls.BaseShellItem) System.ValueTuple`2[] Microsoft.Maui.ApplicationModel.Permissions/NetworkState:get_RequiredPermissions () System.ValueTuple`2[] System.Collections.Generic.List`1>:ToArray () + System.ValueTuple`2& System.Collections.Generic.Dictionary`2>:FindValue (Microsoft.Maui.Controls.BindableProperty) System.ValueTuple`2& System.Collections.Generic.Dictionary`2>:FindValue (string) System.ValueTuple`3 Microsoft.Maui.Platform.MauiRippleDrawableExtensions:GetStrokeProperties (Microsoft.Maui.IButtonStroke,Android.Content.Context,bool) System.ValueTuple`3 System.Collections.Generic.List`1>:get_Item (int) System.ValueTuple`3& System.Collections.Generic.Dictionary`2>:FindValue (string) System.ValueTuple`3 System.Net.Http.HttpClient:PrepareCancellationTokenSource (System.Threading.CancellationToken) - System.Version System.Reflection.AssemblyNameParser:ParseVersion (string) System.Version System.Resources.ResourceManager:GetSatelliteContractVersion (System.Reflection.Assembly) System.Version System.Resources.ResourceManager/ResourceManagerMediator:ObtainSatelliteContractVersion (System.Reflection.Assembly) System.WeakReference`1 Android.Runtime.IdentityHashTargets:CreateWeakReference (Java.Interop.IJavaPeerable) @@ -3523,7 +3565,9 @@ Methods: uint System.HashCode:GenerateGlobalSeed () uint System.HashCode:MixEmptyState () uint System.Private.CoreLib.GateThread/DelayHelper:GetNextDelay (int) + uint System.Private.CoreLib.Interop/Sys:TryGetUInt32OSThreadId () uint System.Threading.TimerQueueTimer:GetMilliseconds (System.TimeSpan,string) + uintptr System.Text.Ascii:ChangeCase (uint16*,byte*,uintptr) uintptr System.Text.Ascii:ChangeCase (uint16*,uint16*,uintptr) uintptr System.Text.Ascii:GetIndexOfFirstNonAsciiByte_Vector (byte*,uintptr) uintptr System.Text.Ascii:NarrowUtf16ToAscii (char*,byte*,uintptr) @@ -3541,7 +3585,7 @@ Methods: void Android.Animation.ValueAnimator:add_Update (System.EventHandler`1) void Android.Animation.ValueAnimator:AddUpdateListener (Android.Animation.ValueAnimator/IAnimatorUpdateListener) void Android.Animation.ValueAnimator:SetInterpolator (Android.Animation.ITimeInterpolator) - void Android.Animation.ValueAnimator/<>c__DisplayClass143_0:b__0 (Android.Animation.ValueAnimator/IAnimatorUpdateListenerImplementor) + void Android.Animation.ValueAnimator/<>c__DisplayClass148_0:b__0 (Android.Animation.ValueAnimator/IAnimatorUpdateListenerImplementor) void Android.Animation.ValueAnimator/IAnimatorUpdateListenerImplementor:.ctor (object) void Android.Animation.ValueAnimator/IAnimatorUpdateListenerImplementor:OnAnimationUpdate (Android.Animation.ValueAnimator) void Android.Animation.ValueAnimator/IAnimatorUpdateListenerInvoker:.cctor () @@ -3582,6 +3626,8 @@ Methods: void Android.App.SyncContext/<>c__DisplayClass2_0:b__0 () void Android.App.UiModeManager:.cctor () void Android.App.UiModeManager:.ctor (intptr,Android.Runtime.JniHandleOwnership) + void Android.Content.ContentProvider:.cctor () + void Android.Content.ContentProvider:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.Content.Context:.cctor () void Android.Content.Context:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.Content.ContextWrapper:.cctor () @@ -3695,10 +3741,10 @@ Methods: void Android.Runtime.AndroidObjectReferenceManager:CreatedLocalReference (Java.Interop.JniObjectReference,int&) void Android.Runtime.AndroidObjectReferenceManager:DeleteGlobalReference (Java.Interop.JniObjectReference&) void Android.Runtime.AndroidObjectReferenceManager:DeleteLocalReference (Java.Interop.JniObjectReference&,int&) - void Android.Runtime.AndroidRuntime:.ctor (intptr,intptr,bool,intptr,intptr,bool) + void Android.Runtime.AndroidRuntime:.ctor (intptr,intptr,intptr,intptr,bool) void Android.Runtime.AndroidRuntimeInternal:.cctor () void Android.Runtime.AndroidRuntimeInternal:WaitForBridgeProcessing () - void Android.Runtime.AndroidRuntimeOptions:.ctor (intptr,intptr,bool,intptr,intptr,bool) + void Android.Runtime.AndroidRuntimeOptions:.ctor (intptr,intptr,intptr,intptr,bool) void Android.Runtime.AndroidTypeManager:.cctor () void Android.Runtime.AndroidTypeManager:.ctor (bool) void Android.Runtime.AndroidTypeManager:RegisterNativeMembers (Java.Interop.JniType,System.Type,System.ReadOnlySpan`1) @@ -3714,6 +3760,7 @@ Methods: void Android.Runtime.IdentityHashTargets:RemoveAt (int) void Android.Runtime.InputStreamInvoker:.ctor (Java.IO.InputStream) void Android.Runtime.InputStreamInvoker:Close () + void Android.Runtime.InputStreamInvoker:Dispose (bool) void Android.Runtime.JavaArray`1/d__13:System.IDisposable.Dispose () void Android.Runtime.JavaArray`1:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.Runtime.JavaDictionary:.cctor () @@ -3790,7 +3837,6 @@ Methods: void Android.Views.Display:GetRealMetrics (Android.Util.DisplayMetrics) void Android.Views.IWindowManagerInvoker:.cctor () void Android.Views.IWindowManagerInvoker:.ctor (intptr,Android.Runtime.JniHandleOwnership) - void Android.Views.IWindowManagerInvoker:Dispose (bool) void Android.Views.LayoutInflater:.cctor () void Android.Views.LayoutInflater:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.Views.LayoutInflaterInvoker:.cctor () @@ -3823,6 +3869,7 @@ Methods: void Android.Views.View:OnLayout (bool,int,int,int,int) void Android.Views.View:OnMeasure (int,int) void Android.Views.View:OnSizeChanged (int,int,int,int) + void Android.Views.View:remove_FocusChange (System.EventHandler`1) void Android.Views.View:remove_LayoutChange (System.EventHandler`1) void Android.Views.View:remove_Touch (System.EventHandler`1) void Android.Views.View:remove_ViewAttachedToWindow (System.EventHandler`1) @@ -3859,19 +3906,21 @@ Methods: void Android.Views.View:SetOnHoverListener (Android.Views.View/IOnHoverListener) void Android.Views.View:SetOnTouchListener (Android.Views.View/IOnTouchListener) void Android.Views.View:SetPadding (int,int,int,int) - void Android.Views.View/<>c__DisplayClass2962_0:b__0 (Android.Views.View/IOnAttachStateChangeListenerImplementor) - void Android.Views.View/<>c__DisplayClass2963_0:b__0 (Android.Views.View/IOnAttachStateChangeListener) - void Android.Views.View/<>c__DisplayClass2963_0:b__1 (Android.Views.View/IOnAttachStateChangeListenerImplementor) - void Android.Views.View/<>c__DisplayClass2965_0:b__0 (Android.Views.View/IOnAttachStateChangeListenerImplementor) - void Android.Views.View/<>c__DisplayClass2966_0:b__0 (Android.Views.View/IOnAttachStateChangeListener) - void Android.Views.View/<>c__DisplayClass2966_0:b__1 (Android.Views.View/IOnAttachStateChangeListenerImplementor) - void Android.Views.View/<>c__DisplayClass2970_0:b__0 (Android.Views.View/IOnLayoutChangeListenerImplementor) - void Android.Views.View/<>c__DisplayClass2971_0:b__0 (Android.Views.View/IOnLayoutChangeListener) - void Android.Views.View/<>c__DisplayClass2971_0:b__1 (Android.Views.View/IOnLayoutChangeListenerImplementor) - void Android.Views.View/<>c__DisplayClass2994_0:b__0 (Android.Views.View/IOnClickListenerImplementor) - void Android.Views.View/<>c__DisplayClass3047_0:b__0 (Android.Views.View/IOnTouchListenerImplementor) - void Android.Views.View/<>c__DisplayClass3052_0:b__0 (Android.Views.View/IOnFocusChangeListener) - void Android.Views.View/<>c__DisplayClass3052_0:b__1 (Android.Views.View/IOnFocusChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3029_0:b__0 (Android.Views.View/IOnAttachStateChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3030_0:b__0 (Android.Views.View/IOnAttachStateChangeListener) + void Android.Views.View/<>c__DisplayClass3030_0:b__1 (Android.Views.View/IOnAttachStateChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3032_0:b__0 (Android.Views.View/IOnAttachStateChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3033_0:b__0 (Android.Views.View/IOnAttachStateChangeListener) + void Android.Views.View/<>c__DisplayClass3033_0:b__1 (Android.Views.View/IOnAttachStateChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3037_0:b__0 (Android.Views.View/IOnLayoutChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3038_0:b__0 (Android.Views.View/IOnLayoutChangeListener) + void Android.Views.View/<>c__DisplayClass3038_0:b__1 (Android.Views.View/IOnLayoutChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3061_0:b__0 (Android.Views.View/IOnClickListenerImplementor) + void Android.Views.View/<>c__DisplayClass3114_0:b__0 (Android.Views.View/IOnTouchListenerImplementor) + void Android.Views.View/<>c__DisplayClass3119_0:b__0 (Android.Views.View/IOnFocusChangeListener) + void Android.Views.View/<>c__DisplayClass3119_0:b__1 (Android.Views.View/IOnFocusChangeListenerImplementor) + void Android.Views.View/<>c__DisplayClass3120_0:b__0 (Android.Views.View/IOnFocusChangeListener) + void Android.Views.View/<>c__DisplayClass3120_0:b__1 (Android.Views.View/IOnFocusChangeListenerImplementor) void Android.Views.View/IOnAttachStateChangeListenerImplementor:.ctor (object) void Android.Views.View/IOnAttachStateChangeListenerImplementor:OnViewAttachedToWindow (Android.Views.View) void Android.Views.View/IOnAttachStateChangeListenerImplementor:OnViewDetachedFromWindow (Android.Views.View) @@ -3902,12 +3951,15 @@ Methods: void Android.Views.ViewGroup:AddView (Android.Views.View) void Android.Views.ViewGroup:Layout (int,int,int,int) void Android.Views.ViewGroup:n_OnLayout_ZIIII (intptr,intptr,bool,int,int,int,int) + void Android.Views.ViewGroup:remove_ChildViewAdded (System.EventHandler`1) void Android.Views.ViewGroup:RemoveAllViews () void Android.Views.ViewGroup:RemoveView (Android.Views.View) void Android.Views.ViewGroup:SetClipChildren (bool) void Android.Views.ViewGroup:SetClipToPadding (bool) void Android.Views.ViewGroup:SetOnHierarchyChangeListener (Android.Views.ViewGroup/IOnHierarchyChangeListener) void Android.Views.ViewGroup/<>c__DisplayClass554_0:b__0 (Android.Views.ViewGroup/IOnHierarchyChangeListenerImplementor) + void Android.Views.ViewGroup/<>c__DisplayClass555_0:b__0 (Android.Views.ViewGroup/IOnHierarchyChangeListener) + void Android.Views.ViewGroup/<>c__DisplayClass555_0:b__1 (Android.Views.ViewGroup/IOnHierarchyChangeListenerImplementor) void Android.Views.ViewGroup/ChildViewAddedEventArgs:.ctor (Android.Views.View,Android.Views.View) void Android.Views.ViewGroup/IOnHierarchyChangeListenerImplementor:.ctor (object) void Android.Views.ViewGroup/IOnHierarchyChangeListenerImplementor:OnChildViewAdded (Android.Views.View,Android.Views.View) @@ -3963,6 +4015,7 @@ Methods: void Android.Widget.TextView:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Android.Widget.TextView:set_Ellipsize (Android.Text.TextUtils/TruncateAt) void Android.Widget.TextView:set_Gravity (Android.Views.GravityFlags) + void Android.Widget.TextView:set_JustificationMode (Android.Text.JustificationMode) void Android.Widget.TextView:set_LetterSpacing (single) void Android.Widget.TextView:set_PaintFlags (Android.Graphics.PaintFlags) void Android.Widget.TextView:set_Text (string) @@ -3981,6 +4034,8 @@ Methods: void AndroidX.AppCompat.App.ActionBarDrawerToggle:SyncState () void AndroidX.AppCompat.App.AppCompatActivity:.cctor () void AndroidX.AppCompat.App.AppCompatActivity:.ctor () + void AndroidX.AppCompat.App.AppCompatDelegate:.cctor () + void AndroidX.AppCompat.App.AppCompatDelegate:set_DefaultNightMode (int) void AndroidX.AppCompat.Content.Res.AppCompatResources:.cctor () void AndroidX.AppCompat.Graphics.Drawable.DrawerArrowDrawable:.cctor () void AndroidX.AppCompat.Graphics.Drawable.DrawerArrowDrawable:.ctor (Android.Content.Context) @@ -4027,6 +4082,8 @@ Methods: void AndroidX.CoordinatorLayout.Widget.CoordinatorLayout/LayoutParams:set_Gravity (int) void AndroidX.Core.App.ComponentActivity:.cctor () void AndroidX.Core.App.ComponentActivity:.ctor (intptr,Android.Runtime.JniHandleOwnership) + void AndroidX.Core.Content.FileProvider:.cctor () + void AndroidX.Core.Content.FileProvider:.ctor () void AndroidX.Core.View.AccessibilityDelegateCompat:.cctor () void AndroidX.Core.View.AccessibilityDelegateCompat:.ctor () void AndroidX.Core.View.AccessibilityDelegateCompat:.ctor (intptr,Android.Runtime.JniHandleOwnership) @@ -4037,9 +4094,12 @@ Methods: void AndroidX.Core.Widget.NestedScrollView:.cctor () void AndroidX.Core.Widget.NestedScrollView:.ctor (Android.Content.Context,Android.Util.IAttributeSet,int) void AndroidX.Core.Widget.NestedScrollView:add_ScrollChange (System.EventHandler`1) + void AndroidX.Core.Widget.NestedScrollView:remove_ScrollChange (System.EventHandler`1) void AndroidX.Core.Widget.NestedScrollView:set_FillViewport (bool) void AndroidX.Core.Widget.NestedScrollView:SetOnScrollChangeListener (AndroidX.Core.Widget.NestedScrollView/IOnScrollChangeListener) void AndroidX.Core.Widget.NestedScrollView/<>c__DisplayClass158_0:b__0 (AndroidX.Core.Widget.NestedScrollView/IOnScrollChangeListenerImplementor) + void AndroidX.Core.Widget.NestedScrollView/<>c__DisplayClass159_0:b__0 (AndroidX.Core.Widget.NestedScrollView/IOnScrollChangeListener) + void AndroidX.Core.Widget.NestedScrollView/<>c__DisplayClass159_0:b__1 (AndroidX.Core.Widget.NestedScrollView/IOnScrollChangeListenerImplementor) void AndroidX.Core.Widget.NestedScrollView/IOnScrollChangeListenerImplementor:.ctor (object) void AndroidX.Core.Widget.NestedScrollView/IOnScrollChangeListenerInvoker:.cctor () void AndroidX.Core.Widget.TextViewCompat:.cctor () @@ -4052,12 +4112,22 @@ Methods: void AndroidX.DrawerLayout.Widget.DrawerLayout:add_DrawerStateChanged (System.EventHandler`1) void AndroidX.DrawerLayout.Widget.DrawerLayout:AddDrawerListener (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListener) void AndroidX.DrawerLayout.Widget.DrawerLayout:CloseDrawer (Android.Views.View) + void AndroidX.DrawerLayout.Widget.DrawerLayout:remove_DrawerClosed (System.EventHandler`1) + void AndroidX.DrawerLayout.Widget.DrawerLayout:remove_DrawerOpened (System.EventHandler`1) + void AndroidX.DrawerLayout.Widget.DrawerLayout:remove_DrawerSlide (System.EventHandler`1) + void AndroidX.DrawerLayout.Widget.DrawerLayout:remove_DrawerStateChanged (System.EventHandler`1) + void AndroidX.DrawerLayout.Widget.DrawerLayout:RemoveDrawerListener (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListener) void AndroidX.DrawerLayout.Widget.DrawerLayout:SetDrawerLockMode (int) void AndroidX.DrawerLayout.Widget.DrawerLayout:SetScrimColor (int) void AndroidX.DrawerLayout.Widget.DrawerLayout/<>c__DisplayClass193_0:b__0 (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor) + void AndroidX.DrawerLayout.Widget.DrawerLayout/<>c__DisplayClass194_0:b__1 (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor) void AndroidX.DrawerLayout.Widget.DrawerLayout/<>c__DisplayClass196_0:b__0 (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor) + void AndroidX.DrawerLayout.Widget.DrawerLayout/<>c__DisplayClass197_0:b__1 (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor) void AndroidX.DrawerLayout.Widget.DrawerLayout/<>c__DisplayClass199_0:b__0 (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor) + void AndroidX.DrawerLayout.Widget.DrawerLayout/<>c__DisplayClass200_0:b__1 (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor) void AndroidX.DrawerLayout.Widget.DrawerLayout/<>c__DisplayClass202_0:b__0 (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor) + void AndroidX.DrawerLayout.Widget.DrawerLayout/<>c__DisplayClass203_0:b__0 (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListener) + void AndroidX.DrawerLayout.Widget.DrawerLayout/<>c__DisplayClass203_0:b__1 (AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor) void AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerImplementor:.ctor (object) void AndroidX.DrawerLayout.Widget.DrawerLayout/IDrawerListenerInvoker:.cctor () void AndroidX.DrawerLayout.Widget.DrawerLayout/LayoutParams:.cctor () @@ -4081,6 +4151,7 @@ Methods: void AndroidX.Fragment.App.FragmentManager:.cctor () void AndroidX.Fragment.App.FragmentManager:.ctor (intptr,Android.Runtime.JniHandleOwnership) void AndroidX.Fragment.App.FragmentManager:RegisterFragmentLifecycleCallbacks (AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks,bool) + void AndroidX.Fragment.App.FragmentManager:UnregisterFragmentLifecycleCallbacks (AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:.cctor () void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:.ctor () void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:n_OnFragmentAttached_Landroidx_fragment_app_FragmentManager_Landroidx_fragment_app_Fragment_Landroid_content_Context_ (intptr,intptr,intptr,intptr,intptr) @@ -4088,6 +4159,7 @@ Methods: void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:n_OnFragmentPreAttached_Landroidx_fragment_app_FragmentManager_Landroidx_fragment_app_Fragment_Landroid_content_Context_ (intptr,intptr,intptr,intptr,intptr) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:n_OnFragmentPreCreated_Landroidx_fragment_app_FragmentManager_Landroidx_fragment_app_Fragment_Landroid_os_Bundle_ (intptr,intptr,intptr,intptr,intptr) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:n_OnFragmentResumed_Landroidx_fragment_app_FragmentManager_Landroidx_fragment_app_Fragment_ (intptr,intptr,intptr,intptr) + void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:n_OnFragmentSaveInstanceState_Landroidx_fragment_app_FragmentManager_Landroidx_fragment_app_Fragment_Landroid_os_Bundle_ (intptr,intptr,intptr,intptr,intptr) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:n_OnFragmentStarted_Landroidx_fragment_app_FragmentManager_Landroidx_fragment_app_Fragment_ (intptr,intptr,intptr,intptr) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:n_OnFragmentViewCreated_Landroidx_fragment_app_FragmentManager_Landroidx_fragment_app_Fragment_Landroid_view_View_Landroid_os_Bundle_ (intptr,intptr,intptr,intptr,intptr,intptr) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:n_OnFragmentViewDestroyed_Landroidx_fragment_app_FragmentManager_Landroidx_fragment_app_Fragment_ (intptr,intptr,intptr,intptr) @@ -4095,6 +4167,7 @@ Methods: void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:OnFragmentCreated (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.OS.Bundle) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:OnFragmentPreAttached (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.Content.Context) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:OnFragmentPreCreated (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.OS.Bundle) + void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:OnFragmentSaveInstanceState (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.OS.Bundle) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:OnFragmentStarted (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:OnFragmentViewCreated (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.Views.View,Android.OS.Bundle) void AndroidX.Fragment.App.FragmentManager/FragmentLifecycleCallbacks:OnFragmentViewDestroyed (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment) @@ -4121,6 +4194,7 @@ Methods: void AndroidX.Navigation.NavController:.cctor () void AndroidX.Navigation.NavController:.ctor (intptr,Android.Runtime.JniHandleOwnership) void AndroidX.Navigation.NavController:AddOnDestinationChangedListener (AndroidX.Navigation.NavController/IOnDestinationChangedListener) + void AndroidX.Navigation.NavController:RemoveOnDestinationChangedListener (AndroidX.Navigation.NavController/IOnDestinationChangedListener) void AndroidX.Navigation.NavController:SetGraph (AndroidX.Navigation.NavGraph,Android.OS.Bundle) void AndroidX.Navigation.NavController/IOnDestinationChangedListenerInvoker:.cctor () void AndroidX.Navigation.NavController/IOnDestinationChangedListenerInvoker:n_OnDestinationChanged_Landroidx_navigation_NavController_Landroidx_navigation_NavDestination_Landroid_os_Bundle_ (intptr,intptr,intptr,intptr,intptr) @@ -4300,7 +4374,6 @@ Methods: void Java.Interop.JniRuntime:AssertValid () void Java.Interop.JniRuntime:set_InvocationPointer (intptr) void Java.Interop.JniRuntime:set_JniVersion (Java.Interop.JniVersion) - void Java.Interop.JniRuntime:set_NewObjectRequired (bool) void Java.Interop.JniRuntime:set_ObjectReferenceManager (Java.Interop.JniRuntime/JniObjectReferenceManager) void Java.Interop.JniRuntime:set_TrackIDs (bool) void Java.Interop.JniRuntime:set_TypeManager (Java.Interop.JniRuntime/JniTypeManager) @@ -4330,11 +4403,14 @@ Methods: void Java.Interop.JniType:Initialize (Java.Interop.JniObjectReference&,Java.Interop.JniObjectReferenceOptions) void Java.Interop.JniType:RegisterNativeMethods (Java.Interop.JniNativeMethodRegistration[]) void Java.Interop.JniType:RegisterWithRuntime () + void Java.Interop.JniTypeManager/JniPrimitiveArrayInfo:.ctor (string,System.Type,System.Type[]) void Java.Interop.JniTypeSignature:.ctor (string,int,bool) void Java.Interop.ManagedPeer:.cctor () void Java.Interop.ManagedPeer:Init () void Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager:.cctor () void Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager:set_PackageNamingPolicy (Java.Interop.Tools.TypeNameMappings.PackageNamingPolicy) + void Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager/<>c:.cctor () + void Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager/<>c:.ctor () void Java.Interop.TypeManager:.cctor () void Java.Interop.TypeManager:Activate (intptr,System.Reflection.ConstructorInfo,object[]) void Java.Interop.TypeManager:n_Activate (intptr,intptr,intptr,intptr,intptr,intptr) @@ -4391,12 +4467,13 @@ Methods: void Java.Security.KeyStore:Load (System.IO.Stream,char[]) void Java.Util.IIteratorInvoker:.cctor () void Java.Util.IIteratorInvoker:.ctor (intptr,Android.Runtime.JniHandleOwnership) - void Java.Util.IIteratorInvoker:Dispose (bool) void Javax.Net.Ssl.HttpsURLConnection:.cctor () void Javax.Net.Ssl.HttpsURLConnection:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Javax.Net.Ssl.HttpsURLConnectionInvoker:.cctor () void Javax.Net.Ssl.HttpsURLConnectionInvoker:.ctor (intptr,Android.Runtime.JniHandleOwnership) void Javax.Net.Ssl.HttpsURLConnectionInvoker:Connect () + void Microsoft.Extensions.DependencyInjection.ActivatorUtilities:.cctor () + void Microsoft.Extensions.DependencyInjection.ActivatorUtilities/ConstructorInfoEx:.ctor (System.Reflection.ConstructorInfo) void Microsoft.Extensions.DependencyInjection.DependencyInjectionEventSource:.cctor () void Microsoft.Extensions.DependencyInjection.DependencyInjectionEventSource:.ctor () void Microsoft.Extensions.DependencyInjection.DependencyInjectionEventSource:ServiceProviderBuilt (Microsoft.Extensions.DependencyInjection.ServiceProvider) @@ -4498,7 +4575,6 @@ Methods: void Microsoft.Maui.Controls.Application:OnStart () void Microsoft.Maui.Controls.Application:RemapForControls () void Microsoft.Maui.Controls.Application:SendStart () - void Microsoft.Maui.Controls.Application:set_MainPage (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.Application:set_Resources (Microsoft.Maui.Controls.ResourceDictionary) void Microsoft.Maui.Controls.AppThemeBinding:.ctor () void Microsoft.Maui.Controls.AppThemeBinding:Apply (bool) @@ -4523,7 +4599,7 @@ Methods: void Microsoft.Maui.Controls.BarElement:.cctor () void Microsoft.Maui.Controls.BaseShellItem:.cctor () void Microsoft.Maui.Controls.BaseShellItem:.ctor () - void Microsoft.Maui.Controls.BaseShellItem:<.ctor>b__20_0 (object,System.Collections.Specialized.NotifyCollectionChangedEventArgs) + void Microsoft.Maui.Controls.BaseShellItem:<.ctor>b__21_0 (object,System.Collections.Specialized.NotifyCollectionChangedEventArgs) void Microsoft.Maui.Controls.BaseShellItem:Microsoft.Maui.Controls.IFlowDirectionController.set_EffectiveFlowDirection (Microsoft.Maui.Controls.EffectiveFlowDirection) void Microsoft.Maui.Controls.BaseShellItem:Microsoft.Maui.Controls.IPropertyPropagationController.PropagatePropertyChanged (string) void Microsoft.Maui.Controls.BaseShellItem:Microsoft.Maui.Controls.IVisualController.set_EffectiveVisual (Microsoft.Maui.Controls.IVisual) @@ -4537,15 +4613,19 @@ Methods: void Microsoft.Maui.Controls.BaseShellItem:SendAppearing () void Microsoft.Maui.Controls.BaseShellItem:set_Route (string) void Microsoft.Maui.Controls.BaseShellItem:UpdateFlyoutItemStyles (Microsoft.Maui.Controls.Grid,Microsoft.Maui.Controls.StyleSheets.IStyleSelectable) - void Microsoft.Maui.Controls.BaseShellItem/<>c__DisplayClass81_1:b__1 (object,System.EventArgs) + void Microsoft.Maui.Controls.BaseShellItem/<>c__DisplayClass83_1:b__6 (object,System.EventArgs) + void Microsoft.Maui.Controls.BaseShellItem/<>c:.cctor () + void Microsoft.Maui.Controls.BaseShellItem/<>c:.ctor () void Microsoft.Maui.Controls.BindableObject:.cctor () void Microsoft.Maui.Controls.BindableObject:.ctor () void Microsoft.Maui.Controls.BindableObject:add_BindingContextChanged (System.EventHandler) void Microsoft.Maui.Controls.BindableObject:add_PropertyChanged (System.ComponentModel.PropertyChangedEventHandler) - void Microsoft.Maui.Controls.BindableObject:ApplyBindings (bool,bool) + void Microsoft.Maui.Controls.BindableObject:add_PropertyChanging (Microsoft.Maui.Controls.PropertyChangingEventHandler) + void Microsoft.Maui.Controls.BindableObject:ApplyBindings (bool) void Microsoft.Maui.Controls.BindableObject:BindingContextPropertyChanged (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.BindableObject:ClearValue (Microsoft.Maui.Controls.BindableProperty,Microsoft.Maui.Controls.SetterSpecificity) void Microsoft.Maui.Controls.BindableObject:ClearValueCore (Microsoft.Maui.Controls.BindableProperty,Microsoft.Maui.Controls.SetterSpecificity) + void Microsoft.Maui.Controls.BindableObject:OnBindablePropertySet (Microsoft.Maui.Controls.BindableProperty,object,object,bool,bool) void Microsoft.Maui.Controls.BindableObject:OnBindingContextChanged () void Microsoft.Maui.Controls.BindableObject:OnPropertyChanged (string) void Microsoft.Maui.Controls.BindableObject:OnPropertyChanging (string) @@ -4572,13 +4652,11 @@ Methods: void Microsoft.Maui.Controls.BindableObjectExtensions:PropagateBindingContext (Microsoft.Maui.Controls.BindableObject,System.Collections.Generic.IEnumerable`1,System.Action`2) void Microsoft.Maui.Controls.BindableObjectExtensions:PropagateBindingContext (Microsoft.Maui.Controls.BindableObject,System.Collections.Generic.IEnumerable`1) void Microsoft.Maui.Controls.BindableObjectExtensions:RefreshPropertyValue (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,object) - void Microsoft.Maui.Controls.BindableObjectExtensions:SetBinding (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,string,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.IValueConverter,string) void Microsoft.Maui.Controls.BindableProperty:.cctor () void Microsoft.Maui.Controls.BindableProperty:.ctor (string,System.Type,System.Type,object,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.BindableProperty/ValidateValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangedDelegate,Microsoft.Maui.Controls.BindableProperty/BindingPropertyChangingDelegate,Microsoft.Maui.Controls.BindableProperty/CoerceValueDelegate,Microsoft.Maui.Controls.BindableProperty/BindablePropertyBindingChanging,bool,Microsoft.Maui.Controls.BindableProperty/CreateDefaultValueDelegate) void Microsoft.Maui.Controls.BindablePropertyKey:.ctor (Microsoft.Maui.Controls.BindableProperty) void Microsoft.Maui.Controls.Binding:.cctor () void Microsoft.Maui.Controls.Binding:.ctor (string,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.IValueConverter,object,string,object) - void Microsoft.Maui.Controls.Binding:Apply (bool) void Microsoft.Maui.Controls.Binding:Apply (object,Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,bool,Microsoft.Maui.Controls.SetterSpecificity) void Microsoft.Maui.Controls.Binding:set_Converter (Microsoft.Maui.Controls.IValueConverter) void Microsoft.Maui.Controls.Binding:set_ConverterParameter (object) @@ -4586,28 +4664,19 @@ Methods: void Microsoft.Maui.Controls.Binding:set_Path (string) void Microsoft.Maui.Controls.Binding:set_Source (object) void Microsoft.Maui.Controls.Binding:set_UpdateSourceEventName (string) - void Microsoft.Maui.Controls.Binding:Unapply (bool) void Microsoft.Maui.Controls.BindingBase:.cctor () void Microsoft.Maui.Controls.BindingBase:.ctor () void Microsoft.Maui.Controls.BindingBase:set_Mode (Microsoft.Maui.Controls.BindingMode) void Microsoft.Maui.Controls.BindingExpression:.cctor () void Microsoft.Maui.Controls.BindingExpression:.ctor (Microsoft.Maui.Controls.BindingBase,string) - void Microsoft.Maui.Controls.BindingExpression:Apply (bool) void Microsoft.Maui.Controls.BindingExpression:Apply (object,Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,Microsoft.Maui.Controls.SetterSpecificity) void Microsoft.Maui.Controls.BindingExpression:ApplyCore (object,Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,bool,Microsoft.Maui.Controls.SetterSpecificity) - void Microsoft.Maui.Controls.BindingExpression:ClearAncestryChangeSubscriptions (int) void Microsoft.Maui.Controls.BindingExpression:ParsePath () - void Microsoft.Maui.Controls.BindingExpression:SetupPart (System.Reflection.TypeInfo,Microsoft.Maui.Controls.BindingExpression/BindingExpressionPart) - void Microsoft.Maui.Controls.BindingExpression:Unapply () void Microsoft.Maui.Controls.BindingExpression/BindingExpressionPart:.ctor (Microsoft.Maui.Controls.BindingExpression,string,bool) - void Microsoft.Maui.Controls.BindingExpression/BindingExpressionPart:Finalize () - void Microsoft.Maui.Controls.BindingExpression/BindingExpressionPart:PropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) - void Microsoft.Maui.Controls.BindingExpression/BindingExpressionPart:Subscribe (System.ComponentModel.INotifyPropertyChanged) - void Microsoft.Maui.Controls.BindingExpression/BindingExpressionPart:Unsubscribe () - void Microsoft.Maui.Controls.BindingExpression/WeakPropertyChangedProxy:.ctor (System.ComponentModel.INotifyPropertyChanged,System.ComponentModel.PropertyChangedEventHandler) void Microsoft.Maui.Controls.BindingExpression/WeakPropertyChangedProxy:OnPropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) void Microsoft.Maui.Controls.BindingExpression/WeakPropertyChangedProxy:Subscribe (System.ComponentModel.INotifyPropertyChanged,System.ComponentModel.PropertyChangedEventHandler) void Microsoft.Maui.Controls.BindingExpression/WeakPropertyChangedProxy:Unsubscribe () + void Microsoft.Maui.Controls.BindingExpressionHelper:.cctor () void Microsoft.Maui.Controls.Border:.cctor () void Microsoft.Maui.Controls.Border/<>c:.cctor () void Microsoft.Maui.Controls.Border/<>c:.ctor () @@ -4630,7 +4699,7 @@ Methods: void Microsoft.Maui.Controls.Button:set_Text (string) void Microsoft.Maui.Controls.Button/<>c:.cctor () void Microsoft.Maui.Controls.Button/<>c:.ctor () - void Microsoft.Maui.Controls.Button/<>c:<.cctor>b__166_1 (Microsoft.Maui.Controls.BindableObject,object,object) + void Microsoft.Maui.Controls.Button/<>c:<.cctor>b__165_1 (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.Button/ButtonContentLayout:.ctor (Microsoft.Maui.Controls.Button/ButtonContentLayout/ImagePosition,double) void Microsoft.Maui.Controls.ButtonElement:.cctor () void Microsoft.Maui.Controls.CastingEnumerator`2:Dispose () @@ -4655,10 +4724,10 @@ Methods: void Microsoft.Maui.Controls.Compatibility.Layout:InternalChildrenOnCollectionChanged (object,System.Collections.Specialized.NotifyCollectionChangedEventArgs) void Microsoft.Maui.Controls.Compatibility.Layout:InvalidateLayout () void Microsoft.Maui.Controls.Compatibility.Layout:InvalidateMeasureOverride () - void Microsoft.Maui.Controls.Compatibility.Layout:LayoutChildIntoBoundingRegion (Microsoft.Maui.Controls.VisualElement,Microsoft.Maui.Graphics.Rect) void Microsoft.Maui.Controls.Compatibility.Layout:OnChildMeasureInvalidated () void Microsoft.Maui.Controls.Compatibility.Layout:OnChildMeasureInvalidated (Microsoft.Maui.Controls.VisualElement,Microsoft.Maui.Controls.Internals.InvalidationTrigger) void Microsoft.Maui.Controls.Compatibility.Layout:OnChildMeasureInvalidated (object,System.EventArgs) + void Microsoft.Maui.Controls.Compatibility.Layout:OnChildMeasureInvalidatedInternal (Microsoft.Maui.Controls.VisualElement,Microsoft.Maui.Controls.Internals.InvalidationTrigger) void Microsoft.Maui.Controls.Compatibility.Layout:OnInternalAdded (Microsoft.Maui.Controls.View) void Microsoft.Maui.Controls.Compatibility.Layout:OnSizeAllocated (double,double) void Microsoft.Maui.Controls.Compatibility.Layout:UpdateChildrenLayout () @@ -4718,6 +4787,7 @@ Methods: void Microsoft.Maui.Controls.Element:MapAutomationPropertiesIsInAccessibleTree (Microsoft.Maui.IElementHandler,Microsoft.Maui.IElement) void Microsoft.Maui.Controls.Element:Microsoft.Maui.Controls.IElementDefinition.AddResourcesChangedListener (System.Action`2) void Microsoft.Maui.Controls.Element:Microsoft.Maui.Controls.IElementDefinition.RemoveResourcesChangedListener (System.Action`2) + void Microsoft.Maui.Controls.Element:OnBindablePropertySet (Microsoft.Maui.Controls.BindableProperty,object,object,bool,bool) void Microsoft.Maui.Controls.Element:OnBindingContextChanged () void Microsoft.Maui.Controls.Element:OnChildAdded (Microsoft.Maui.Controls.Element) void Microsoft.Maui.Controls.Element:OnChildRemoved (Microsoft.Maui.Controls.Element,int) @@ -4759,11 +4829,11 @@ Methods: void Microsoft.Maui.Controls.Element:SetupChildren () void Microsoft.Maui.Controls.Element:SetValueFromRenderer (Microsoft.Maui.Controls.BindableProperty,object) void Microsoft.Maui.Controls.Element:SetValueFromRenderer (Microsoft.Maui.Controls.BindablePropertyKey,object) - void Microsoft.Maui.Controls.Element:UpdateHandlerValue (string) - void Microsoft.Maui.Controls.Element/d__101`1:.ctor (int) - void Microsoft.Maui.Controls.Element/d__101`1:System.IDisposable.Dispose () - void Microsoft.Maui.Controls.Element/d__112:.ctor (int) - void Microsoft.Maui.Controls.Element/d__112:System.IDisposable.Dispose () + void Microsoft.Maui.Controls.Element:UpdateHandlerValue (string,bool) + void Microsoft.Maui.Controls.Element/d__103`1:.ctor (int) + void Microsoft.Maui.Controls.Element/d__103`1:System.IDisposable.Dispose () + void Microsoft.Maui.Controls.Element/d__114:.ctor (int) + void Microsoft.Maui.Controls.Element/d__114:System.IDisposable.Dispose () void Microsoft.Maui.Controls.ElementCollection`1:.ctor (System.Collections.ObjectModel.ObservableCollection`1) void Microsoft.Maui.Controls.ElementEventArgs:.ctor (Microsoft.Maui.Controls.Element) void Microsoft.Maui.Controls.ElementTemplate:.ctor (System.Func`1) @@ -4795,6 +4865,12 @@ Methods: void Microsoft.Maui.Controls.Frame:.cctor () void Microsoft.Maui.Controls.Frame/<>c:.cctor () void Microsoft.Maui.Controls.Frame/<>c:.ctor () + void Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors:SetBinding1138676086 (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,System.Func`2,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.IValueConverter,object,string,object,object,object) + void Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors:SetBinding114022620 (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,System.Func`2,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.IValueConverter,object,string,object,object,object) + void Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors:SetBinding1635156915 (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,System.Func`2,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.IValueConverter,object,string,object,object,object) + void Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors:SetBinding570983195 (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,System.Func`2,Microsoft.Maui.Controls.BindingMode,Microsoft.Maui.Controls.IValueConverter,object,string,object,object,object) + void Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c:.cctor () + void Microsoft.Maui.Controls.Generated.GeneratedBindingInterceptors/<>c:.ctor () void Microsoft.Maui.Controls.GestureRecognizer:.ctor () void Microsoft.Maui.Controls.Grid:.cctor () void Microsoft.Maui.Controls.Grid:.ctor () @@ -4818,9 +4894,11 @@ Methods: void Microsoft.Maui.Controls.GroupableItemsView:.cctor () void Microsoft.Maui.Controls.GroupableItemsView:.ctor () void Microsoft.Maui.Controls.HandlerChangingEventArgs:.ctor (Microsoft.Maui.IElementHandler,Microsoft.Maui.IElementHandler) + void Microsoft.Maui.Controls.HandlerProperties:.cctor () void Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:.cctor () void Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:.ctor () void Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.Controls.IAppearanceObserver.OnAppearanceChanged (Microsoft.Maui.Controls.ShellAppearance) + void Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.IElementHandler.DisconnectHandler () void Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.IElementHandler.Invoke (string,object) void Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.IElementHandler.SetMauiContext (Microsoft.Maui.IMauiContext) void Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:Microsoft.Maui.IElementHandler.SetVirtualView (Microsoft.Maui.IElement) @@ -4830,6 +4908,7 @@ Methods: void Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:SetVirtualView (Microsoft.Maui.Controls.Shell) void Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer:SwitchFragment (AndroidX.Fragment.App.FragmentManager,Android.Views.View,Microsoft.Maui.Controls.ShellItem,bool) void Microsoft.Maui.Controls.Handlers.TabbedPageManager:.ctor (Microsoft.Maui.IMauiContext) + void Microsoft.Maui.Controls.Handlers.TabbedPageManager:b__52_0 (Microsoft.Maui.Controls.Element) void Microsoft.Maui.Controls.Handlers.TabbedPageManager:NotifyDataSetChanged () void Microsoft.Maui.Controls.Handlers.TabbedPageManager:OnChildrenCollectionChanged (object,System.Collections.Specialized.NotifyCollectionChangedEventArgs) void Microsoft.Maui.Controls.Handlers.TabbedPageManager:OnLayoutChanged (object,Android.Views.View/LayoutChangeEventArgs) @@ -4843,6 +4922,7 @@ Methods: void Microsoft.Maui.Controls.Handlers.TabbedPageManager:SetTabLayout () void Microsoft.Maui.Controls.Handlers.TabbedPageManager:SetupBottomNavigationView () void Microsoft.Maui.Controls.Handlers.TabbedPageManager:SetupPage (Microsoft.Maui.Controls.Page) + void Microsoft.Maui.Controls.Handlers.TabbedPageManager:TeardownPage (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.Handlers.TabbedPageManager:UpdateBarBackground () void Microsoft.Maui.Controls.Handlers.TabbedPageManager:UpdateBarBackgroundColor () void Microsoft.Maui.Controls.Handlers.TabbedPageManager:UpdateBarTextColor () @@ -4909,6 +4989,18 @@ Methods: void Microsoft.Maui.Controls.Internals.TemplatedItemsList`2, Microsoft.Maui.Controls.Page>:BindableOnPropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) void Microsoft.Maui.Controls.Internals.TemplatedItemsList`2, Microsoft.Maui.Controls.Page>:OnListProxyChanged (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.Internals.TemplatedItemsList`2, Microsoft.Maui.Controls.Page>:set_ListProxy (Microsoft.Maui.Controls.IListProxy) + void Microsoft.Maui.Controls.Internals.TypedBinding`2/PropertyChangedProxy:.ctor (System.Func`2,string,Microsoft.Maui.Controls.BindingBase) + void Microsoft.Maui.Controls.Internals.TypedBinding`2/PropertyChangedProxy:Finalize () + void Microsoft.Maui.Controls.Internals.TypedBinding`2/PropertyChangedProxy:OnPropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) + void Microsoft.Maui.Controls.Internals.TypedBinding`2/PropertyChangedProxy:set_Part (System.ComponentModel.INotifyPropertyChanged) + void Microsoft.Maui.Controls.Internals.TypedBinding`2:.ctor (System.Func`2>,System.Action`2,System.Tuple`2, string>[]) + void Microsoft.Maui.Controls.Internals.TypedBinding`2:Apply (bool) + void Microsoft.Maui.Controls.Internals.TypedBinding`2:Apply (object,Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,bool,Microsoft.Maui.Controls.SetterSpecificity) + void Microsoft.Maui.Controls.Internals.TypedBinding`2:ApplyCore (object,Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,bool,Microsoft.Maui.Controls.SetterSpecificity) + void Microsoft.Maui.Controls.Internals.TypedBinding`2:ApplyToResolvedSource (object,Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.BindableProperty,bool,Microsoft.Maui.Controls.SetterSpecificity) + void Microsoft.Maui.Controls.Internals.TypedBinding`2:Subscribe (Microsoft.Maui.Controls.BaseShellItem) + void Microsoft.Maui.Controls.Internals.TypedBinding`2:Unapply (bool) + void Microsoft.Maui.Controls.Internals.TypedBinding`2:Unsubscribe () void Microsoft.Maui.Controls.ItemsLayout:.cctor () void Microsoft.Maui.Controls.ItemsLayout:.ctor (Microsoft.Maui.Controls.ItemsLayoutOrientation) void Microsoft.Maui.Controls.ItemsLayout:set_SnapPointsAlignment (Microsoft.Maui.Controls.SnapPointsAlignment) @@ -5014,6 +5106,7 @@ Methods: void Microsoft.Maui.Controls.MessagingCenter/MaybeWeakReference:.ctor (object,object) void Microsoft.Maui.Controls.MessagingCenter/Sender:.ctor (string,System.Type,System.Type) void Microsoft.Maui.Controls.MessagingCenter/Subscription:.ctor (object,object,System.Reflection.MethodInfo,Microsoft.Maui.Controls.MessagingCenter/Filter) + void Microsoft.Maui.Controls.MultiBinding:.cctor () void Microsoft.Maui.Controls.MultiPage`1:.cctor () void Microsoft.Maui.Controls.MultiPage`1:.ctor () void Microsoft.Maui.Controls.MultiPage`1:add_PagesChanged (System.Collections.Specialized.NotifyCollectionChangedEventHandler) @@ -5022,18 +5115,13 @@ Methods: void Microsoft.Maui.Controls.MultiPage`1:OnCurrentPageChanged () void Microsoft.Maui.Controls.MultiPage`1:OnPagesChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs) void Microsoft.Maui.Controls.MultiPage`1:OnPropertyChanged (string) + void Microsoft.Maui.Controls.MultiPage`1:remove_PagesChanged (System.Collections.Specialized.NotifyCollectionChangedEventHandler) void Microsoft.Maui.Controls.MultiPage`1:set_CurrentPage (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.MultiPage`1:SetIndex (Microsoft.Maui.Controls.Page,int) void Microsoft.Maui.Controls.NavigableElement:.cctor () void Microsoft.Maui.Controls.NavigableElement:.ctor () void Microsoft.Maui.Controls.NavigableElement:OnParentSet () - void Microsoft.Maui.Controls.NavigableElement:set_class (System.Collections.Generic.IList`1) void Microsoft.Maui.Controls.NavigableElement:set_Navigation (Microsoft.Maui.Controls.INavigation) - void Microsoft.Maui.Controls.NavigableElement:set_Style (Microsoft.Maui.Controls.Style) - void Microsoft.Maui.Controls.NavigableElement:set_StyleClass (System.Collections.Generic.IList`1) - void Microsoft.Maui.Controls.NavigableElement/<>c:.cctor () - void Microsoft.Maui.Controls.NavigableElement/<>c:.ctor () - void Microsoft.Maui.Controls.NavigableElement/<>c:<.cctor>b__22_0 (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.NavigatingStepRequestList:.ctor () void Microsoft.Maui.Controls.NavigatingStepRequestList:Clear () void Microsoft.Maui.Controls.NavigationPage:.cctor () @@ -5043,14 +5131,13 @@ Methods: void Microsoft.Maui.Controls.NavigationPage:b__101_1 () void Microsoft.Maui.Controls.NavigationPage:FireAppearing (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.NavigationPage:Init () - void Microsoft.Maui.Controls.NavigationPage:LayoutChildren (double,double,double,double) void Microsoft.Maui.Controls.NavigationPage:Microsoft.Maui.IStackNavigation.NavigationFinished (System.Collections.Generic.IReadOnlyList`1) void Microsoft.Maui.Controls.NavigationPage:Microsoft.Maui.IStackNavigation.RequestNavigation (Microsoft.Maui.NavigationRequest) void Microsoft.Maui.Controls.NavigationPage:OnCurrentPageChanged (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.NavigationPage:OnHandlerChangedCore () void Microsoft.Maui.Controls.NavigationPage:OnWindowChanged (object,System.EventArgs) void Microsoft.Maui.Controls.NavigationPage:PushPage (Microsoft.Maui.Controls.Page) - void Microsoft.Maui.Controls.NavigationPage:SendNavigated (Microsoft.Maui.Controls.Page) + void Microsoft.Maui.Controls.NavigationPage:SendNavigated (Microsoft.Maui.Controls.Page,Microsoft.Maui.Controls.NavigationType) void Microsoft.Maui.Controls.NavigationPage:set_CurrentPage (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.NavigationPage:set_RootPage (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.NavigationPage:SyncToNavigationStack (System.Collections.Generic.IReadOnlyList`1) @@ -5063,7 +5150,6 @@ Methods: void Microsoft.Maui.Controls.NavigationPageToolbar:Disconnect () void Microsoft.Maui.Controls.NavigationPageToolbar:OnPageAppearing (object,System.EventArgs) void Microsoft.Maui.Controls.NavigationPageToolbar:OnPagePropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) - void Microsoft.Maui.Controls.NavigationPageToolbar:OnPropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) void Microsoft.Maui.Controls.NavigationPageToolbar:OnToolbarItemsChanged (object,System.EventArgs) void Microsoft.Maui.Controls.NavigationPageToolbar:set_BarTextColor (Microsoft.Maui.Graphics.Color) void Microsoft.Maui.Controls.NavigationPageToolbar:set_IconColor (Microsoft.Maui.Graphics.Color) @@ -5086,15 +5172,16 @@ Methods: void Microsoft.Maui.Controls.Page:FlushPendingActions (object,System.EventArgs) void Microsoft.Maui.Controls.Page:ForceLayout () void Microsoft.Maui.Controls.Page:InternalChildrenOnCollectionChanged (object,System.Collections.Specialized.NotifyCollectionChangedEventArgs) - void Microsoft.Maui.Controls.Page:LayoutChildren (double,double,double,double) void Microsoft.Maui.Controls.Page:OnAppearing () void Microsoft.Maui.Controls.Page:OnChildMeasureInvalidated (Microsoft.Maui.Controls.VisualElement,Microsoft.Maui.Controls.Internals.InvalidationTrigger) void Microsoft.Maui.Controls.Page:OnChildMeasureInvalidated (object,System.EventArgs) + void Microsoft.Maui.Controls.Page:OnChildMeasureInvalidatedInternal (Microsoft.Maui.Controls.VisualElement,Microsoft.Maui.Controls.Internals.InvalidationTrigger) void Microsoft.Maui.Controls.Page:OnDisappearing () void Microsoft.Maui.Controls.Page:OnNavigatedTo (Microsoft.Maui.Controls.NavigatedToEventArgs) void Microsoft.Maui.Controls.Page:OnParentSet () void Microsoft.Maui.Controls.Page:OnSizeAllocated (double,double) void Microsoft.Maui.Controls.Page:remove_Appearing (System.EventHandler) + void Microsoft.Maui.Controls.Page:remove_Disappearing (System.EventHandler) void Microsoft.Maui.Controls.Page:remove_NavigatedFrom (System.EventHandler`1) void Microsoft.Maui.Controls.Page:remove_NavigatedTo (System.EventHandler`1) void Microsoft.Maui.Controls.Page:SendAppearing () @@ -5111,6 +5198,7 @@ Methods: void Microsoft.Maui.Controls.Picker:RemapForControls () void Microsoft.Maui.Controls.PlaceholderElement:.cctor () void Microsoft.Maui.Controls.Platform.AdapterItemKey:.ctor (Microsoft.Maui.Controls.Page,System.Action`1) + void Microsoft.Maui.Controls.Platform.AdapterItemKey:Disconnect () void Microsoft.Maui.Controls.Platform.AdapterItemKey:OnHandlerChanged (object,System.EventArgs) void Microsoft.Maui.Controls.Platform.AdapterItemKey:OnHandlerChanging (object,Microsoft.Maui.Controls.HandlerChangingEventArgs) void Microsoft.Maui.Controls.Platform.AdapterItemKey:SetToStableView () @@ -5149,6 +5237,7 @@ Methods: void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutLayout:.ctor (Android.Content.Context,Android.Util.IAttributeSet) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutLayout:OnLayout (bool,int,int,int,int) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRecyclerAdapter:.ctor (Microsoft.Maui.Controls.Platform.Compatibility.IShellContext,System.Action`1) + void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRecyclerAdapter:Disconnect () void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRecyclerAdapter:OnBindViewHolder (AndroidX.RecyclerView.Widget.RecyclerView/ViewHolder,int) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRecyclerAdapter/AdapterListItem:.ctor (Microsoft.Maui.Controls.Element,bool) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRecyclerAdapter/ElementViewHolder:.ctor (Microsoft.Maui.Controls.View,Android.Views.View,Android.Views.View,System.Action`1,Microsoft.Maui.Controls.Shell) @@ -5159,6 +5248,7 @@ Methods: void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer:.ctor (Microsoft.Maui.Controls.Platform.Compatibility.IShellContext,Android.Content.Context) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer:AddFlyoutContentToLayoutIfNeeded (Microsoft.Maui.FlyoutBehavior) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer:AttachFlyout (Microsoft.Maui.Controls.Platform.Compatibility.IShellContext,Android.Views.View) + void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer:Disconnect () void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer:Microsoft.Maui.Controls.IAppearanceObserver.OnAppearanceChanged (Microsoft.Maui.Controls.ShellAppearance) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer:Microsoft.Maui.Controls.IFlyoutBehaviorObserver.OnFlyoutBehaviorChanged (Microsoft.Maui.FlyoutBehavior) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer:Microsoft.Maui.Controls.Platform.Compatibility.IShellFlyoutRenderer.AttachFlyout (Microsoft.Maui.Controls.Platform.Compatibility.IShellContext,Android.Views.View) @@ -5168,6 +5258,7 @@ Methods: void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer:UpdateFlyoutSize (Android.Views.View) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer:UpdateScrim (Microsoft.Maui.Controls.Brush) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutTemplatedContentRenderer:.ctor (Microsoft.Maui.Controls.Platform.Compatibility.IShellContext) + void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutTemplatedContentRenderer:Disconnect () void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutTemplatedContentRenderer:DisconnectRecyclerView () void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutTemplatedContentRenderer:LoadView (Microsoft.Maui.Controls.Platform.Compatibility.IShellContext) void Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutTemplatedContentRenderer:OnFlyoutViewLayoutChanging () @@ -5196,6 +5287,7 @@ Methods: void Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRenderer:SetupMenu (Android.Views.IMenu,int,Microsoft.Maui.Controls.ShellItem) void Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRenderer:UpdateTabBarVisibility () void Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRendererBase:.ctor (Microsoft.Maui.Controls.Platform.Compatibility.IShellContext) + void Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRendererBase:Disconnect () void Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRendererBase:HookChildEvents (Microsoft.Maui.Controls.ShellSection) void Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRendererBase:HookEvents (Microsoft.Maui.Controls.ShellItem) void Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRendererBase:Microsoft.Maui.Controls.Platform.Compatibility.IShellItemRenderer.set_ShellItem (Microsoft.Maui.Controls.ShellItem) @@ -5213,6 +5305,7 @@ Methods: void Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer:HookEvents () void Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer:Microsoft.Maui.Controls.IAppearanceObserver.OnAppearanceChanged (Microsoft.Maui.Controls.ShellAppearance) void Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer:OnPageSelected (int) + void Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer:OnShellContentPropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) void Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer:OnShellItemPropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) void Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer:set_ShellSection (Microsoft.Maui.Controls.ShellSection) void Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer:SetAppearance (Microsoft.Maui.Controls.ShellAppearance) @@ -5225,7 +5318,7 @@ Methods: void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarAppearanceTracker:SetAppearance (AndroidX.AppCompat.Widget.Toolbar,Microsoft.Maui.Controls.Platform.Compatibility.IShellToolbarTracker,Microsoft.Maui.Controls.ShellAppearance) void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarAppearanceTracker:SetColors (AndroidX.AppCompat.Widget.Toolbar,Microsoft.Maui.Controls.Platform.Compatibility.IShellToolbarTracker,Microsoft.Maui.Graphics.Color,Microsoft.Maui.Graphics.Color,Microsoft.Maui.Graphics.Color) void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:.ctor (Microsoft.Maui.Controls.Platform.Compatibility.IShellContext,AndroidX.AppCompat.Widget.Toolbar,AndroidX.DrawerLayout.Widget.DrawerLayout) - void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:<.ctor>b__23_0 (Microsoft.Maui.Controls.Platform.GenericGlobalLayoutListener,Android.Views.View) + void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:<.ctor>b__25_0 (Microsoft.Maui.Controls.Platform.GenericGlobalLayoutListener,Android.Views.View) void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:ApplyToolbarChanges (Microsoft.Maui.Controls.Toolbar,Microsoft.Maui.Controls.Toolbar) void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:HandleShellPropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:Microsoft.Maui.Controls.IFlyoutBehaviorObserver.OnFlyoutBehaviorChanged (Microsoft.Maui.FlyoutBehavior) @@ -5245,7 +5338,7 @@ Methods: void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:UpdateToolbarIconAccessibilityText (AndroidX.AppCompat.Widget.Toolbar,Microsoft.Maui.Controls.Shell) void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:UpdateToolbarItems () void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker:UpdateToolbarItems (AndroidX.AppCompat.Widget.Toolbar,Microsoft.Maui.Controls.Page) - void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker/d__52:MoveNext () + void Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker/d__54:MoveNext () void Microsoft.Maui.Controls.Platform.Compatibility.ShellViewRenderer:.ctor (Android.Content.Context,Microsoft.Maui.Controls.View,Microsoft.Maui.IMauiContext) void Microsoft.Maui.Controls.Platform.Compatibility.ShellViewRenderer:OnViewSet (Microsoft.Maui.IView) void Microsoft.Maui.Controls.Platform.Compatibility.ShellViewRenderer:set_View (Microsoft.Maui.IView) @@ -5275,21 +5368,25 @@ Methods: void Microsoft.Maui.Controls.Platform.GesturePlatformManager:UpdateIsEnabled () void Microsoft.Maui.Controls.Platform.GesturePlatformManager:UpdatePointer () void Microsoft.Maui.Controls.Platform.ModalNavigationManager:.ctor (Microsoft.Maui.Controls.Window) - void Microsoft.Maui.Controls.Platform.ModalNavigationManager:<.ctor>b__32_0 (object,System.ComponentModel.PropertyChangedEventArgs) - void Microsoft.Maui.Controls.Platform.ModalNavigationManager:b__31_0 (object,System.EventArgs) + void Microsoft.Maui.Controls.Platform.ModalNavigationManager:<.ctor>b__36_0 (object,System.ComponentModel.PropertyChangedEventArgs) + void Microsoft.Maui.Controls.Platform.ModalNavigationManager:b__35_0 (object,System.EventArgs) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:ClearModalPages (bool,bool) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:DisconnectPlatformPageWatchingForLoaded () void Microsoft.Maui.Controls.Platform.ModalNavigationManager:InitializePlatform () void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnCurrentPageHandlerChanged (object,System.EventArgs) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnCurrentPlatformPageLoaded (object,System.EventArgs) + void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnPlatformWindowHandlerChanging (object,Microsoft.Maui.Controls.HandlerChangingEventArgs) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnWindowHandlerChanging (object,Microsoft.Maui.Controls.HandlerChangingEventArgs) + void Microsoft.Maui.Controls.Platform.ModalNavigationManager:OnWindowPropertyChanging (object,Microsoft.Maui.Controls.PropertyChangingEventArgs) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:SettingNewPage () void Microsoft.Maui.Controls.Platform.ModalNavigationManager:SyncModalStackWhenPlatformIsReady (string) void Microsoft.Maui.Controls.Platform.ModalNavigationManager:SyncPlatformModalStack (string) - void Microsoft.Maui.Controls.Platform.ModalNavigationManager/<>c__DisplayClass50_0:b__1 () - void Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__50:MoveNext () - void Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__41:MoveNext () + void Microsoft.Maui.Controls.Platform.ModalNavigationManager/<>c__DisplayClass55_0:b__1 () + void Microsoft.Maui.Controls.Platform.ModalNavigationManager/<>c__DisplayClass55_1:b__2 () + void Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__55:MoveNext () + void Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__45:MoveNext () void Microsoft.Maui.Controls.Platform.MultiPageFragmentStateAdapter`1:.ctor (Microsoft.Maui.Controls.MultiPage`1,AndroidX.Fragment.App.FragmentManager,Microsoft.Maui.IMauiContext) + void Microsoft.Maui.Controls.Platform.MultiPageFragmentStateAdapter`1:b__13_0 (Microsoft.Maui.Controls.Platform.AdapterItemKey) void Microsoft.Maui.Controls.Platform.MultiPageFragmentStateAdapter`1:CheckItemKeys () void Microsoft.Maui.Controls.Platform.PointerGestureHandler:.ctor (System.Func`1,System.Func`1) void Microsoft.Maui.Controls.Platform.PointerGestureHandler:SetupHandlerForPointer () @@ -5298,6 +5395,7 @@ Methods: void Microsoft.Maui.Controls.Platform.TextViewExtensions:UpdateLineBreakMode (Android.Widget.TextView,Microsoft.Maui.Controls.Label) void Microsoft.Maui.Controls.Platform.TextViewExtensions:UpdateMaxLines (Android.Widget.TextView,Microsoft.Maui.Controls.Label) void Microsoft.Maui.Controls.Platform.TextViewExtensions:UpdateText (Android.Widget.TextView,Microsoft.Maui.Controls.Label) + void Microsoft.Maui.Controls.Platform.ToolbarExtensions:DisposeMenuItems (AndroidX.AppCompat.Widget.Toolbar,System.Collections.Generic.IEnumerable`1,System.ComponentModel.PropertyChangedEventHandler) void Microsoft.Maui.Controls.Platform.ToolbarExtensions:UpdateBackButton (AndroidX.AppCompat.Widget.Toolbar,Microsoft.Maui.Controls.Toolbar) void Microsoft.Maui.Controls.Platform.ToolbarExtensions:UpdateBarBackground (AndroidX.AppCompat.Widget.Toolbar,Microsoft.Maui.Controls.Toolbar) void Microsoft.Maui.Controls.Platform.ToolbarExtensions:UpdateBarTextColor (AndroidX.AppCompat.Widget.Toolbar,Microsoft.Maui.Controls.Toolbar) @@ -5323,14 +5421,13 @@ Methods: void Microsoft.Maui.Controls.ProgressBar:.cctor () void Microsoft.Maui.Controls.ProgressBar/<>c:.cctor () void Microsoft.Maui.Controls.ProgressBar/<>c:.ctor () + void Microsoft.Maui.Controls.PropertyChangingEventArgs:.ctor (string) void Microsoft.Maui.Controls.RadioButton:.cctor () void Microsoft.Maui.Controls.RadioButton:RemapForControls () void Microsoft.Maui.Controls.RadioButton/<>c:.cctor () void Microsoft.Maui.Controls.RadioButton/<>c:.ctor () void Microsoft.Maui.Controls.RefreshView:.cctor () void Microsoft.Maui.Controls.RefreshView:RemapForControls () - void Microsoft.Maui.Controls.RefreshView/<>c:.cctor () - void Microsoft.Maui.Controls.RefreshView/<>c:.ctor () void Microsoft.Maui.Controls.ReorderableItemsView:.cctor () void Microsoft.Maui.Controls.ReorderableItemsView:.ctor () void Microsoft.Maui.Controls.RequestDefinition:.ctor (Microsoft.Maui.Controls.RouteRequestBuilder,Microsoft.Maui.Controls.Shell) @@ -5347,13 +5444,16 @@ Methods: void Microsoft.Maui.Controls.ResourceDictionary:remove_ValuesChanged (System.EventHandler`1) void Microsoft.Maui.Controls.ResourceDictionary:set_Item (string,object) void Microsoft.Maui.Controls.ResourceDictionary:set_Source (System.Uri) - void Microsoft.Maui.Controls.ResourceDictionary:SetAndLoadSource (System.Uri,string,System.Reflection.Assembly,System.Xml.IXmlLineInfo) + void Microsoft.Maui.Controls.ResourceDictionary:SetAndCreateSource (System.Uri) + void Microsoft.Maui.Controls.ResourceDictionary:SetSource (System.Uri,Microsoft.Maui.Controls.ResourceDictionary) void Microsoft.Maui.Controls.ResourceDictionary:System.Collections.Generic.ICollection>.CopyTo (System.Collections.Generic.KeyValuePair`2[],int) - void Microsoft.Maui.Controls.ResourceDictionary/d__42:.ctor (int) - void Microsoft.Maui.Controls.ResourceDictionary/d__42:<>m__Finally1 () - void Microsoft.Maui.Controls.ResourceDictionary/d__42:<>m__Finally2 () - void Microsoft.Maui.Controls.ResourceDictionary/d__42:<>m__Finally3 () - void Microsoft.Maui.Controls.ResourceDictionary/d__42:System.IDisposable.Dispose () + void Microsoft.Maui.Controls.ResourceDictionary/<>c__9`1<__XamlGeneratedCode__.__TypeA6EB4B27A3A00AE8>:.cctor () + void Microsoft.Maui.Controls.ResourceDictionary/<>c__9`1<__XamlGeneratedCode__.__TypeA6EB4B27A3A00AE8>:.ctor () + void Microsoft.Maui.Controls.ResourceDictionary/d__46:.ctor (int) + void Microsoft.Maui.Controls.ResourceDictionary/d__46:<>m__Finally1 () + void Microsoft.Maui.Controls.ResourceDictionary/d__46:<>m__Finally2 () + void Microsoft.Maui.Controls.ResourceDictionary/d__46:<>m__Finally3 () + void Microsoft.Maui.Controls.ResourceDictionary/d__46:System.IDisposable.Dispose () void Microsoft.Maui.Controls.RouteRequestBuilder:.cctor () void Microsoft.Maui.Controls.RouteRequestBuilder:.ctor (System.Collections.Generic.List`1) void Microsoft.Maui.Controls.RouteRequestBuilder:AddMatch (string,string,object) @@ -5384,11 +5484,13 @@ Methods: void Microsoft.Maui.Controls.Setter:Apply (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.SetterSpecificity) void Microsoft.Maui.Controls.Setter:UnApply (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.SetterSpecificity) void Microsoft.Maui.Controls.SetterSpecificity:.cctor () - void Microsoft.Maui.Controls.SetterSpecificity:.ctor (int,int,int,int,int,int,int,int) - void Microsoft.Maui.Controls.SetterSpecificity:.ctor (int,int,int,int) - void Microsoft.Maui.Controls.SetterSpecificityList:Remove (Microsoft.Maui.Controls.SetterSpecificity) - void Microsoft.Maui.Controls.SetterSpecificityList:set_Item (Microsoft.Maui.Controls.SetterSpecificity,object) - void Microsoft.Maui.Controls.SetterSpecificityList:SetValue (Microsoft.Maui.Controls.SetterSpecificity,object) + void Microsoft.Maui.Controls.SetterSpecificity:.ctor (byte,uint16,byte,byte,uint16,byte,byte,byte) + void Microsoft.Maui.Controls.SetterSpecificity:.ctor (uint16,byte,byte,byte) + void Microsoft.Maui.Controls.SetterSpecificity:.ctor (ulong) + void Microsoft.Maui.Controls.SetterSpecificityList`1:.ctor () + void Microsoft.Maui.Controls.SetterSpecificityList`1:.ctor (int) + void Microsoft.Maui.Controls.SetterSpecificityList`1:Remove (Microsoft.Maui.Controls.SetterSpecificity) + void Microsoft.Maui.Controls.SetterSpecificityList`1:set_Item (Microsoft.Maui.Controls.SetterSpecificity,object) void Microsoft.Maui.Controls.Shadow:.cctor () void Microsoft.Maui.Controls.Shapes.Rectangle:.cctor () void Microsoft.Maui.Controls.Shapes.Rectangle:.ctor () @@ -5415,6 +5517,7 @@ Methods: void Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.AddAppearanceObserver (Microsoft.Maui.Controls.IAppearanceObserver,Microsoft.Maui.Controls.Element) void Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.AddFlyoutBehaviorObserver (Microsoft.Maui.Controls.IFlyoutBehaviorObserver) void Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.AppearanceChanged (Microsoft.Maui.Controls.Element,bool) + void Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.remove_FlyoutItemsChanged (System.EventHandler) void Microsoft.Maui.Controls.Shell:Microsoft.Maui.Controls.IShellController.UpdateCurrentState (Microsoft.Maui.Controls.ShellNavigationSource) void Microsoft.Maui.Controls.Shell:NotifyFlyoutBehaviorObservers () void Microsoft.Maui.Controls.Shell:OnCurrentItemChanged (Microsoft.Maui.Controls.BindableObject,object,object) @@ -5447,9 +5550,11 @@ Methods: void Microsoft.Maui.Controls.ShellContent:.cctor () void Microsoft.Maui.Controls.ShellContent:.ctor () void Microsoft.Maui.Controls.ShellContent:ApplyQueryAttributes (Microsoft.Maui.Controls.ShellRouteParameters) + void Microsoft.Maui.Controls.ShellContent:EvaluateDisconnect () void Microsoft.Maui.Controls.ShellContent:Microsoft.Maui.Controls.IShellContentController.add_IsPageVisibleChanged (System.EventHandler) void Microsoft.Maui.Controls.ShellContent:OnChildAdded (Microsoft.Maui.Controls.Element) void Microsoft.Maui.Controls.ShellContent:OnPagePropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) + void Microsoft.Maui.Controls.ShellContent:OnPropertyChanged (string) void Microsoft.Maui.Controls.ShellContent:SendAppearing () void Microsoft.Maui.Controls.ShellContent:SendPageAppearing (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.ShellContent:set_ContentCache (Microsoft.Maui.Controls.Page) @@ -5476,6 +5581,7 @@ Methods: void Microsoft.Maui.Controls.ShellFlyoutItemsManager:g__IncrementGroup|14_2 (Microsoft.Maui.Controls.ShellFlyoutItemsManager/<>c__DisplayClass14_0&) void Microsoft.Maui.Controls.ShellFlyoutItemsManager:add_FlyoutItemsChanged (System.EventHandler) void Microsoft.Maui.Controls.ShellFlyoutItemsManager:CheckIfFlyoutItemsChanged () + void Microsoft.Maui.Controls.ShellFlyoutItemsManager:remove_FlyoutItemsChanged (System.EventHandler) void Microsoft.Maui.Controls.ShellFlyoutItemsManager:SyncFlyoutItemsToReadOnlyCollection () void Microsoft.Maui.Controls.ShellFlyoutItemsManager/ReadOnlyObservableCollectionWithSource`1>:.ctor () void Microsoft.Maui.Controls.ShellFlyoutItemsManager/ReadOnlyObservableCollectionWithSource`1>:.ctor (System.Collections.ObjectModel.ObservableCollection`1>) @@ -5574,6 +5680,13 @@ Methods: void Microsoft.Maui.Controls.Style:set_BasedOn (Microsoft.Maui.Controls.Style) void Microsoft.Maui.Controls.Style:set_BaseResourceKey (string) void Microsoft.Maui.Controls.Style:UnApplyCore (Microsoft.Maui.Controls.BindableObject,Microsoft.Maui.Controls.Style) + void Microsoft.Maui.Controls.StyleableElement:.cctor () + void Microsoft.Maui.Controls.StyleableElement:.ctor () + void Microsoft.Maui.Controls.StyleableElement:set_class (System.Collections.Generic.IList`1) + void Microsoft.Maui.Controls.StyleableElement:set_StyleClass (System.Collections.Generic.IList`1) + void Microsoft.Maui.Controls.StyleableElement/<>c:.cctor () + void Microsoft.Maui.Controls.StyleableElement/<>c:.ctor () + void Microsoft.Maui.Controls.StyleableElement/<>c:<.cctor>b__14_0 (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.StyleSheets.StyleSheetExtensions/d__0:.ctor (int) void Microsoft.Maui.Controls.StyleSheets.StyleSheetExtensions/d__0:System.IDisposable.Dispose () void Microsoft.Maui.Controls.SwipeItem:.cctor () @@ -5586,7 +5699,7 @@ Methods: void Microsoft.Maui.Controls.TabbedPage:.ctor () void Microsoft.Maui.Controls.TabbedPage:g__OnPagePropertyChanged|42_2 (object,System.ComponentModel.PropertyChangedEventArgs) void Microsoft.Maui.Controls.TabbedPage:g__WireUnwireChanges|42_1 (bool) - void Microsoft.Maui.Controls.TabbedPage:LayoutChildren (double,double,double,double) + void Microsoft.Maui.Controls.TabbedPage:DisconnectHandler () void Microsoft.Maui.Controls.TabbedPage:MapBarBackground (Microsoft.Maui.Handlers.ITabbedViewHandler,Microsoft.Maui.Controls.TabbedPage) void Microsoft.Maui.Controls.TabbedPage:MapBarBackgroundColor (Microsoft.Maui.Handlers.ITabbedViewHandler,Microsoft.Maui.Controls.TabbedPage) void Microsoft.Maui.Controls.TabbedPage:MapBarTextColor (Microsoft.Maui.Handlers.ITabbedViewHandler,Microsoft.Maui.Controls.TabbedPage) @@ -5613,7 +5726,6 @@ Methods: void Microsoft.Maui.Controls.TimePicker:RemapForControls () void Microsoft.Maui.Controls.TimePicker/<>c:.cctor () void Microsoft.Maui.Controls.TimePicker/<>c:.ctor () - void Microsoft.Maui.Controls.Toolbar:.cctor () void Microsoft.Maui.Controls.Toolbar:.ctor (Microsoft.Maui.IElement) void Microsoft.Maui.Controls.Toolbar:add_PropertyChanged (System.ComponentModel.PropertyChangedEventHandler) void Microsoft.Maui.Controls.Toolbar:MapBackButtonTitle (Microsoft.Maui.Handlers.IToolbarHandler,Microsoft.Maui.Controls.Toolbar) @@ -5659,7 +5771,6 @@ Methods: void Microsoft.Maui.Controls.View:MarginPropertyChanged (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.View:OnBindingContextChanged () void Microsoft.Maui.Controls.View:OnHandlerChangedCore () - void Microsoft.Maui.Controls.View:set_Margin (Microsoft.Maui.Thickness) void Microsoft.Maui.Controls.View/<>c:.cctor () void Microsoft.Maui.Controls.View/<>c:.ctor () void Microsoft.Maui.Controls.View/<>c:<.cctor>b__56_0 (Microsoft.Maui.Controls.BindableObject,object,object) @@ -5671,7 +5782,6 @@ Methods: void Microsoft.Maui.Controls.VisualElement:add__platformContainerViewChanged (System.EventHandler) void Microsoft.Maui.Controls.VisualElement:add__windowChanged (System.EventHandler) void Microsoft.Maui.Controls.VisualElement:add_Loaded (System.EventHandler) - void Microsoft.Maui.Controls.VisualElement:add_MeasureInvalidated (System.EventHandler) void Microsoft.Maui.Controls.VisualElement:add_SizeChanged (System.EventHandler) void Microsoft.Maui.Controls.VisualElement:BatchCommit () void Microsoft.Maui.Controls.VisualElement:ChangeVisualState () @@ -5699,6 +5809,7 @@ Methods: void Microsoft.Maui.Controls.VisualElement:Microsoft.Maui.IView.InvalidateMeasure () void Microsoft.Maui.Controls.VisualElement:OnBindingContextChanged () void Microsoft.Maui.Controls.VisualElement:OnChildAdded (Microsoft.Maui.Controls.Element) + void Microsoft.Maui.Controls.VisualElement:OnChildMeasureInvalidatedInternal (Microsoft.Maui.Controls.VisualElement,Microsoft.Maui.Controls.Internals.InvalidationTrigger) void Microsoft.Maui.Controls.VisualElement:OnConstraintChanged (Microsoft.Maui.Controls.LayoutConstraint,Microsoft.Maui.Controls.LayoutConstraint) void Microsoft.Maui.Controls.VisualElement:OnHandlerChangedCore () void Microsoft.Maui.Controls.VisualElement:OnIsPlatformEnabledChanged () @@ -5728,7 +5839,7 @@ Methods: void Microsoft.Maui.Controls.VisualElement:SetEffectiveFlowDirection (Microsoft.Maui.Controls.EffectiveFlowDirection,bool) void Microsoft.Maui.Controls.VisualElement:SizeAllocated (double,double) void Microsoft.Maui.Controls.VisualElement:UpdateBoundsComponents (Microsoft.Maui.Graphics.Rect) - void Microsoft.Maui.Controls.VisualElement:UpdateHandlerValue (string) + void Microsoft.Maui.Controls.VisualElement:UpdateHandlerValue (string,bool) void Microsoft.Maui.Controls.VisualElement:UpdatePlatformUnloadedLoadedWiring (Microsoft.Maui.Controls.Window,Microsoft.Maui.Controls.Window) void Microsoft.Maui.Controls.VisualElement:UpdateSemanticsFromMapper () void Microsoft.Maui.Controls.VisualElement/<>c:.cctor () @@ -5767,7 +5878,6 @@ Methods: void Microsoft.Maui.Controls.Window:.ctor (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.Window:add_Activated (System.EventHandler) void Microsoft.Maui.Controls.Window:add_Destroying (System.EventHandler) - void Microsoft.Maui.Controls.Window:add_Resumed (System.EventHandler) void Microsoft.Maui.Controls.Window:FinishedAddingWindowToApplication (Microsoft.Maui.Controls.Application) void Microsoft.Maui.Controls.Window:MapWindowSoftInputModeAdjust (Microsoft.Maui.Handlers.IWindowHandler,Microsoft.Maui.IWindow) void Microsoft.Maui.Controls.Window:Microsoft.Maui.Controls.IFlowDirectionController.set_EffectiveFlowDirection (Microsoft.Maui.Controls.EffectiveFlowDirection) @@ -5789,13 +5899,16 @@ Methods: void Microsoft.Maui.Controls.Window:set_Page (Microsoft.Maui.Controls.Page) void Microsoft.Maui.Controls.Window:SetEffectiveFlowDirection (Microsoft.Maui.Controls.EffectiveFlowDirection,bool) void Microsoft.Maui.Controls.Window:ShellPropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) - void Microsoft.Maui.Controls.Window:UpdateHandlerValue (string) + void Microsoft.Maui.Controls.Window:UpdateHandlerValue (string,bool) void Microsoft.Maui.Controls.Window/<>c:.cctor () void Microsoft.Maui.Controls.Window/<>c:.ctor () - void Microsoft.Maui.Controls.Window/<>c:<.cctor>b__220_0 (Microsoft.Maui.Controls.BindableObject,object,object) + void Microsoft.Maui.Controls.Window/<>c:<.cctor>b__224_0 (Microsoft.Maui.Controls.BindableObject,object,object) void Microsoft.Maui.Controls.Window/NavigationImpl:.ctor (Microsoft.Maui.Controls.Window) + void Microsoft.Maui.Controls.Xaml.:.cctor () void Microsoft.Maui.Controls.Xaml.Diagnostics.ResourceDictionaryDiagnostics:OnStaticResourceResolved (Microsoft.Maui.Controls.ResourceDictionary,string,object,object) void Microsoft.Maui.Controls.Xaml.Internals.SimpleValueTargetProvider:.ctor (object[],object,Microsoft.Maui.Controls.Internals.INameScope[],bool) + void Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider:.ctor (object,object) + void Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider:.cctor () void Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider:.ctor () void Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider:Add (System.Type,object) void Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider:set_IValueConverterProvider (Microsoft.Maui.Controls.Xaml.IValueConverterProvider) @@ -5803,8 +5916,8 @@ Methods: void Microsoft.Maui.Controls.Xaml.Internals.XamlTypeResolver:.ctor (System.Xml.IXmlNamespaceResolver,System.Reflection.Assembly) void Microsoft.Maui.Controls.Xaml.Internals.XmlNamespaceResolver:.ctor () void Microsoft.Maui.Controls.Xaml.Internals.XmlNamespaceResolver:Add (string,string) + void Microsoft.Maui.Controls.Xaml.ResourceDictionaryHotReloadHelper:Init () void Microsoft.Maui.Controls.Xaml.TypeConversionExtensions:.cctor () - void Microsoft.Maui.Controls.Xaml.XamlResourceIdAttribute:.ctor (string,string,System.Type) void Microsoft.Maui.Controls.Xaml.XmlLineInfo:.ctor (int,int) void Microsoft.Maui.Converters.ThicknessTypeConverter:.ctor () void Microsoft.Maui.Devices.DeviceDisplay:add_MainDisplayInfoChanged (System.EventHandler`1) @@ -5896,9 +6009,11 @@ Methods: void Microsoft.Maui.Handlers.AndroidBatchPropertyMapper`2:.ctor (Microsoft.Maui.IPropertyMapper[]) void Microsoft.Maui.Handlers.ApplicationHandler:.cctor () void Microsoft.Maui.Handlers.ApplicationHandler:.ctor () + void Microsoft.Maui.Handlers.ApplicationHandler:MapAppTheme (Microsoft.Maui.Handlers.ApplicationHandler,Microsoft.Maui.IApplication) void Microsoft.Maui.Handlers.ButtonHandler:.cctor () void Microsoft.Maui.Handlers.ButtonHandler:.ctor () void Microsoft.Maui.Handlers.ButtonHandler:ConnectHandler (Google.Android.Material.Button.MaterialButton) + void Microsoft.Maui.Handlers.ButtonHandler:DisconnectHandler (Google.Android.Material.Button.MaterialButton) void Microsoft.Maui.Handlers.ButtonHandler:MapBackground (Microsoft.Maui.Handlers.IButtonHandler,Microsoft.Maui.IButton) void Microsoft.Maui.Handlers.ButtonHandler:MapCharacterSpacing (Microsoft.Maui.Handlers.IButtonHandler,Microsoft.Maui.ITextStyle) void Microsoft.Maui.Handlers.ButtonHandler:MapCornerRadius (Microsoft.Maui.Handlers.IButtonHandler,Microsoft.Maui.IButton) @@ -5917,26 +6032,31 @@ Methods: void Microsoft.Maui.Handlers.CheckBoxHandler:.cctor () void Microsoft.Maui.Handlers.ContentViewHandler:.cctor () void Microsoft.Maui.Handlers.ContentViewHandler:.ctor (Microsoft.Maui.IPropertyMapper,Microsoft.Maui.CommandMapper) + void Microsoft.Maui.Handlers.ContentViewHandler:DisconnectHandler (Microsoft.Maui.Platform.ContentViewGroup) void Microsoft.Maui.Handlers.ContentViewHandler:MapContent (Microsoft.Maui.Handlers.IContentViewHandler,Microsoft.Maui.IContentView) void Microsoft.Maui.Handlers.ContentViewHandler:SetVirtualView (Microsoft.Maui.IView) void Microsoft.Maui.Handlers.ContentViewHandler:UpdateContent (Microsoft.Maui.Handlers.IContentViewHandler) - void Microsoft.Maui.Handlers.DatePickerHandler:.cctor () void Microsoft.Maui.Handlers.EditorHandler:.cctor () void Microsoft.Maui.Handlers.ElementHandler:.cctor () void Microsoft.Maui.Handlers.ElementHandler:.ctor (Microsoft.Maui.IPropertyMapper,Microsoft.Maui.CommandMapper) void Microsoft.Maui.Handlers.ElementHandler:ConnectHandler (object) + void Microsoft.Maui.Handlers.ElementHandler:DisconnectHandler (object) void Microsoft.Maui.Handlers.ElementHandler:Invoke (string,object) + void Microsoft.Maui.Handlers.ElementHandler:Microsoft.Maui.IElementHandler.DisconnectHandler () void Microsoft.Maui.Handlers.ElementHandler:SetMauiContext (Microsoft.Maui.IMauiContext) void Microsoft.Maui.Handlers.ElementHandler:SetVirtualView (Microsoft.Maui.IElement) void Microsoft.Maui.Handlers.ElementHandler:UpdateValue (string) void Microsoft.Maui.Handlers.ElementHandler`2:.ctor (Microsoft.Maui.IPropertyMapper,Microsoft.Maui.CommandMapper) void Microsoft.Maui.Handlers.ElementHandler`2:ConnectHandler (Android.App.Application) void Microsoft.Maui.Handlers.ElementHandler`2:OnConnectHandler (object) + void Microsoft.Maui.Handlers.ElementHandler`2:DisconnectHandler (Google.Android.Material.AppBar.MaterialToolbar) + void Microsoft.Maui.Handlers.ElementHandler`2:OnDisconnectHandler (object) void Microsoft.Maui.Handlers.EntryHandler:.cctor () void Microsoft.Maui.Handlers.FlyoutViewHandler:.cctor () void Microsoft.Maui.Handlers.FlyoutViewHandler:.ctor () void Microsoft.Maui.Handlers.FlyoutViewHandler:b__11_1 (AndroidX.Fragment.App.FragmentManager) void Microsoft.Maui.Handlers.FlyoutViewHandler:ConnectHandler (Android.Views.View) + void Microsoft.Maui.Handlers.FlyoutViewHandler:DisconnectHandler (Android.Views.View) void Microsoft.Maui.Handlers.FlyoutViewHandler:DrawerLayoutAttached (object,Android.Views.View/ViewAttachedToWindowEventArgs) void Microsoft.Maui.Handlers.FlyoutViewHandler:LayoutAsFlyout () void Microsoft.Maui.Handlers.FlyoutViewHandler:LayoutViews () @@ -5954,12 +6074,16 @@ Methods: void Microsoft.Maui.Handlers.FlyoutViewHandler:UpdateIsPresented () void Microsoft.Maui.Handlers.ImageHandler:.cctor () void Microsoft.Maui.Handlers.ImageHandler:.ctor () + void Microsoft.Maui.Handlers.ImageHandler:ConnectHandler (Android.Widget.ImageView) + void Microsoft.Maui.Handlers.ImageHandler:DisconnectHandler (Android.Widget.ImageView) void Microsoft.Maui.Handlers.ImageHandler:MapAspect (Microsoft.Maui.Handlers.IImageHandler,Microsoft.Maui.IImage) void Microsoft.Maui.Handlers.ImageHandler:MapBackground (Microsoft.Maui.Handlers.IImageHandler,Microsoft.Maui.IImage) void Microsoft.Maui.Handlers.ImageHandler:MapIsAnimationPlaying (Microsoft.Maui.Handlers.IImageHandler,Microsoft.Maui.IImage) void Microsoft.Maui.Handlers.ImageHandler:MapSource (Microsoft.Maui.Handlers.IImageHandler,Microsoft.Maui.IImage) + void Microsoft.Maui.Handlers.ImageHandler:OnPlatformViewAttachedToWindow (Microsoft.Maui.Handlers.IImageHandler) + void Microsoft.Maui.Handlers.ImageHandler:OnPlatformViewAttachedToWindow (object,Android.Views.View/ViewAttachedToWindowEventArgs) void Microsoft.Maui.Handlers.ImageHandler:PlatformArrange (Microsoft.Maui.Graphics.Rect) - void Microsoft.Maui.Handlers.ImageHandler/d__8:MoveNext () + void Microsoft.Maui.Handlers.ImageHandler/d__9:MoveNext () void Microsoft.Maui.Handlers.ImageHandler/ImageImageSourcePartSetter:.ctor (Microsoft.Maui.Handlers.IImageHandler) void Microsoft.Maui.Handlers.ImageHandler/ImageImageSourcePartSetter:SetImageSource (Android.Graphics.Drawables.Drawable) void Microsoft.Maui.Handlers.LabelHandler:.cctor () @@ -5978,6 +6102,8 @@ Methods: void Microsoft.Maui.Handlers.LayoutExtensions/<>c:.ctor () void Microsoft.Maui.Handlers.LayoutHandler:.cctor () void Microsoft.Maui.Handlers.LayoutHandler:.ctor () + void Microsoft.Maui.Handlers.LayoutHandler:Clear (Microsoft.Maui.Platform.LayoutViewGroup) + void Microsoft.Maui.Handlers.LayoutHandler:DisconnectHandler (Microsoft.Maui.Platform.LayoutViewGroup) void Microsoft.Maui.Handlers.LayoutHandler:MapBackground (Microsoft.Maui.ILayoutHandler,Microsoft.Maui.ILayout) void Microsoft.Maui.Handlers.LayoutHandler:MapClipsToBounds (Microsoft.Maui.ILayoutHandler,Microsoft.Maui.ILayout) void Microsoft.Maui.Handlers.LayoutHandler:MapInputTransparent (Microsoft.Maui.ILayoutHandler,Microsoft.Maui.ILayout) @@ -5985,6 +6111,7 @@ Methods: void Microsoft.Maui.Handlers.NavigationViewHandler:.cctor () void Microsoft.Maui.Handlers.NavigationViewHandler:.ctor () void Microsoft.Maui.Handlers.NavigationViewHandler:ConnectHandler (Android.Views.View) + void Microsoft.Maui.Handlers.NavigationViewHandler:OnDisconnectHandler (Android.Views.View) void Microsoft.Maui.Handlers.NavigationViewHandler:OnLayoutChanged (object,Android.Views.View/LayoutChangeEventArgs) void Microsoft.Maui.Handlers.NavigationViewHandler:OnViewAttachedToWindow (object,Android.Views.View/ViewAttachedToWindowEventArgs) void Microsoft.Maui.Handlers.NavigationViewHandler:OnViewDetachedFromWindow (object,Android.Views.View/ViewDetachedFromWindowEventArgs) @@ -5995,10 +6122,10 @@ Methods: void Microsoft.Maui.Handlers.PageHandler:MapTitle (Microsoft.Maui.Handlers.IPageHandler,Microsoft.Maui.IContentView) void Microsoft.Maui.Handlers.PickerHandler:.cctor () void Microsoft.Maui.Handlers.RadioButtonHandler:.cctor () - void Microsoft.Maui.Handlers.RefreshViewHandler:.cctor () void Microsoft.Maui.Handlers.ScrollViewHandler:.cctor () void Microsoft.Maui.Handlers.ScrollViewHandler:.ctor () void Microsoft.Maui.Handlers.ScrollViewHandler:ConnectHandler (Microsoft.Maui.Platform.MauiScrollView) + void Microsoft.Maui.Handlers.ScrollViewHandler:DisconnectHandler (Microsoft.Maui.Platform.MauiScrollView) void Microsoft.Maui.Handlers.ScrollViewHandler:InsertInsetView (Microsoft.Maui.Handlers.IScrollViewHandler,Microsoft.Maui.IScrollView,Android.Views.View,Microsoft.Maui.ICrossPlatformLayout) void Microsoft.Maui.Handlers.ScrollViewHandler:MapContent (Microsoft.Maui.Handlers.IScrollViewHandler,Microsoft.Maui.IScrollView) void Microsoft.Maui.Handlers.ScrollViewHandler:MapHorizontalScrollBarVisibility (Microsoft.Maui.Handlers.IScrollViewHandler,Microsoft.Maui.IScrollView) @@ -6010,10 +6137,10 @@ Methods: void Microsoft.Maui.Handlers.SwipeViewHandler:.cctor () void Microsoft.Maui.Handlers.TabbedViewHandler:.cctor () void Microsoft.Maui.Handlers.TabbedViewHandler:.ctor () - void Microsoft.Maui.Handlers.TimePickerHandler:.cctor () void Microsoft.Maui.Handlers.ToolbarHandler:.cctor () void Microsoft.Maui.Handlers.ToolbarHandler:.ctor () void Microsoft.Maui.Handlers.ToolbarHandler:MapTitle (Microsoft.Maui.Handlers.IToolbarHandler,Microsoft.Maui.IToolbar) + void Microsoft.Maui.Handlers.ToolbarHandler:OnDisconnectHandler (object) void Microsoft.Maui.Handlers.ToolbarHandler:SetupToolbar () void Microsoft.Maui.Handlers.ToolbarHandler:SetupWithDrawerLayout (AndroidX.DrawerLayout.Widget.DrawerLayout) void Microsoft.Maui.Handlers.ToolbarHandler:SetupWithNavController (AndroidX.Navigation.NavController,Microsoft.Maui.Platform.StackNavigationManager) @@ -6021,6 +6148,7 @@ Methods: void Microsoft.Maui.Handlers.ViewHandler:.cctor () void Microsoft.Maui.Handlers.ViewHandler:.ctor (Microsoft.Maui.IPropertyMapper,Microsoft.Maui.CommandMapper) void Microsoft.Maui.Handlers.ViewHandler:ConnectingHandler (Android.Views.View) + void Microsoft.Maui.Handlers.ViewHandler:DisconnectingHandler (Android.Views.View) void Microsoft.Maui.Handlers.ViewHandler:MapAutomationId (Microsoft.Maui.IViewHandler,Microsoft.Maui.IView) void Microsoft.Maui.Handlers.ViewHandler:MapBackground (Microsoft.Maui.IViewHandler,Microsoft.Maui.IView) void Microsoft.Maui.Handlers.ViewHandler:MapBorderView (Microsoft.Maui.IViewHandler,Microsoft.Maui.IView) @@ -6046,13 +6174,16 @@ Methods: void Microsoft.Maui.Handlers.ViewHandler:MapToolTip (Microsoft.Maui.IViewHandler,Microsoft.Maui.IView) void Microsoft.Maui.Handlers.ViewHandler:MapWidth (Microsoft.Maui.IViewHandler,Microsoft.Maui.IView) void Microsoft.Maui.Handlers.ViewHandler:OnConnectHandler (object) + void Microsoft.Maui.Handlers.ViewHandler:OnDisconnectHandler (object) void Microsoft.Maui.Handlers.ViewHandler:set_HasContainer (bool) void Microsoft.Maui.Handlers.ViewHandler`2:.ctor (Microsoft.Maui.IPropertyMapper,Microsoft.Maui.CommandMapper) void Microsoft.Maui.Handlers.ViewHandler`2:ConnectHandler (Microsoft.Maui.Platform.ContentViewGroup) void Microsoft.Maui.Handlers.ViewHandler`2:OnConnectHandler (Android.Views.View) void Microsoft.Maui.Handlers.ViewHandler`2:SetVirtualView (Microsoft.Maui.IElement) void Microsoft.Maui.Handlers.ViewHandler`2:SetVirtualView (Microsoft.Maui.IView) + void Microsoft.Maui.Handlers.ViewHandler`2:OnDisconnectHandler (Android.Views.View) void Microsoft.Maui.Handlers.ViewHandler`2:PlatformArrange (Microsoft.Maui.Graphics.Rect) + void Microsoft.Maui.Handlers.ViewHandler`2:DisconnectHandler (Android.Views.View) void Microsoft.Maui.Handlers.WebViewHandler:.cctor () void Microsoft.Maui.Handlers.WindowHandler:.cctor () void Microsoft.Maui.Handlers.WindowHandler:.ctor () @@ -6088,6 +6219,8 @@ Methods: void Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/<>c:.cctor () void Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/<>c:.ctor () void Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/HandlerRegistration:AddRegistration (Microsoft.Maui.Hosting.IMauiHandlersCollection) + void Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions/HandlerServiceBuilder:.ctor (System.Collections.Generic.IEnumerable`1) + void Microsoft.Maui.Hosting.ImageSourceServiceCollectionExtensions:AddImageSourceMapping (Microsoft.Maui.Hosting.IImageSourceServiceCollection) void Microsoft.Maui.Hosting.ImageSourceServiceProvider:.cctor () void Microsoft.Maui.Hosting.ImageSourceServiceProvider:.ctor (Microsoft.Maui.Hosting.IImageSourceServiceCollection,System.IServiceProvider) void Microsoft.Maui.Hosting.ImageSourcesMauiAppBuilderExtensions/<>c:.cctor () @@ -6095,21 +6228,31 @@ Methods: void Microsoft.Maui.Hosting.ImageSourcesMauiAppBuilderExtensions/<>c:b__0_0 (Microsoft.Maui.Hosting.IImageSourceServiceCollection) void Microsoft.Maui.Hosting.ImageSourcesMauiAppBuilderExtensions/ImageSourceRegistration:AddRegistration (Microsoft.Maui.Hosting.IImageSourceServiceCollection) void Microsoft.Maui.Hosting.ImageSourcesMauiAppBuilderExtensions/ImageSourceServiceBuilder:.ctor (System.Collections.Generic.IEnumerable`1) + void Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping:.cctor () + void Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping:.ctor () + void Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping:Add () + void Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping/<>c:.cctor () + void Microsoft.Maui.Hosting.ImageSourceToImageSourceServiceTypeMapping/<>c:.ctor () void Microsoft.Maui.Hosting.Internal.FontCollection:.ctor () void Microsoft.Maui.Hosting.Internal.FontCollection:Add (Microsoft.Maui.Hosting.FontDescriptor) - void Microsoft.Maui.Hosting.Internal.MauiFactory:.cctor () void Microsoft.Maui.Hosting.Internal.MauiFactory:.ctor (Microsoft.Maui.Hosting.IMauiServiceCollection) - void Microsoft.Maui.Hosting.Internal.MauiHandlersCollection:.ctor () - void Microsoft.Maui.Hosting.Internal.MauiHandlersFactory:.ctor (System.Collections.Generic.IEnumerable`1) + void Microsoft.Maui.Hosting.Internal.MauiHandlersFactory:.ctor (Microsoft.Maui.Hosting.IMauiHandlersCollection) void Microsoft.Maui.Hosting.Internal.MauiServiceCollection:.ctor () void Microsoft.Maui.Hosting.Internal.MauiServiceCollection:Add (Microsoft.Extensions.DependencyInjection.ServiceDescriptor) + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:.cctor () + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:.ctor () + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet:Add (System.Type) + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet/<>c:.cctor () + void Microsoft.Maui.Hosting.Internal.RegisteredHandlerServiceTypeSet/<>c:.ctor () void Microsoft.Maui.Hosting.MauiAppBuilder:.ctor (bool) void Microsoft.Maui.Hosting.MauiAppBuilder:ConfigureDefaultLogging () void Microsoft.Maui.Hosting.MauiAppBuilder/<>c:.cctor () void Microsoft.Maui.Hosting.MauiAppBuilder/<>c:.ctor () void Microsoft.Maui.Hosting.MauiAppBuilder/NullLogger`1:.ctor () + void Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions:RegisterHandlerServiceType (Microsoft.Maui.Hosting.IMauiHandlersCollection,System.Type) void Microsoft.Maui.HotReload.MauiHotReloadHelper:.cctor () - void Microsoft.Maui.HotReload.MauiHotReloadHelper:RegisterHandlers (Microsoft.Maui.Hosting.IMauiHandlersCollection) + void Microsoft.Maui.ImageSourceServiceResultManager:CompleteLoad (System.IDisposable) + void Microsoft.Maui.ImageSourceServiceResultManager:Reset () void Microsoft.Maui.Layouts.GridLayoutManager/Cell:.ctor (int,int,int,int,int,Microsoft.Maui.Layouts.GridLayoutManager/GridLengthType,Microsoft.Maui.Layouts.GridLayoutManager/GridLengthType) void Microsoft.Maui.Layouts.GridLayoutManager/Definition:.ctor (Microsoft.Maui.GridLength) void Microsoft.Maui.Layouts.GridLayoutManager/Definition:set_Size (double) @@ -6189,6 +6332,7 @@ Methods: void Microsoft.Maui.Platform.ActivityExtensions:UpdateX (Android.App.Activity,Microsoft.Maui.IWindow) void Microsoft.Maui.Platform.ActivityExtensions:UpdateY (Android.App.Activity,Microsoft.Maui.IWindow) void Microsoft.Maui.Platform.ApplicationExtensions:CreatePlatformWindow (Android.App.Activity,Microsoft.Maui.IApplication,Android.OS.Bundle) + void Microsoft.Maui.Platform.ApplicationExtensions:UpdateNightMode (Microsoft.Maui.IApplication) void Microsoft.Maui.Platform.ButtonExtensions:UpdateBackground (Google.Android.Material.Button.MaterialButton,Microsoft.Maui.IButton) void Microsoft.Maui.Platform.ButtonExtensions:UpdateButtonBackground (Google.Android.Material.Button.MaterialButton,Microsoft.Maui.IButton) void Microsoft.Maui.Platform.ButtonExtensions:UpdateButtonStroke (Google.Android.Material.Button.MaterialButton,Microsoft.Maui.IButton) @@ -6216,7 +6360,8 @@ Methods: void Microsoft.Maui.Platform.ElementExtensions/d__11:System.IDisposable.Dispose () void Microsoft.Maui.Platform.ImageSourcePartExtensions/d__0:MoveNext () void Microsoft.Maui.Platform.ImageSourcePartLoader:.ctor (Microsoft.Maui.Platform.IImageSourcePartSetter) - void Microsoft.Maui.Platform.ImageSourcePartLoader/d__10:MoveNext () + void Microsoft.Maui.Platform.ImageSourcePartLoader:Reset () + void Microsoft.Maui.Platform.ImageSourcePartLoader/d__14:MoveNext () void Microsoft.Maui.Platform.ImageSourcePartSetter`1:.ctor (Microsoft.Maui.Handlers.IImageHandler) void Microsoft.Maui.Platform.ImageViewExtensions:UpdateAspect (Android.Widget.ImageView,Microsoft.Maui.IImage) void Microsoft.Maui.Platform.ImageViewExtensions:UpdateIsAnimationPlaying (Android.Graphics.Drawables.Drawable,Microsoft.Maui.IImageSourcePart) @@ -6245,6 +6390,7 @@ Methods: void Microsoft.Maui.Platform.MauiScrollView:SetVerticalScrollBarVisibility (Microsoft.Maui.ScrollBarVisibility) void Microsoft.Maui.Platform.MauiTextView:.ctor (Android.Content.Context) void Microsoft.Maui.Platform.MauiTextView:add_LayoutChanged (System.EventHandler`1) + void Microsoft.Maui.Platform.MauiTextView:remove_LayoutChanged (System.EventHandler`1) void Microsoft.Maui.Platform.NavigationRootManager:add_RootViewChanged (System.EventHandler) void Microsoft.Maui.Platform.NavigationRootManager:ClearPlatformParts () void Microsoft.Maui.Platform.NavigationRootManager:Connect (Microsoft.Maui.IView,Microsoft.Maui.IMauiContext) @@ -6263,6 +6409,7 @@ Methods: void Microsoft.Maui.Platform.StackNavigationManager:ApplyNavigationRequest (Microsoft.Maui.NavigationRequest) void Microsoft.Maui.Platform.StackNavigationManager:CheckForFragmentChange () void Microsoft.Maui.Platform.StackNavigationManager:Connect (Microsoft.Maui.IView) + void Microsoft.Maui.Platform.StackNavigationManager:Disconnect () void Microsoft.Maui.Platform.StackNavigationManager:NavigationFinished (Microsoft.Maui.IStackNavigation) void Microsoft.Maui.Platform.StackNavigationManager:OnDestinationChanged (AndroidX.Navigation.NavController,AndroidX.Navigation.NavDestination,Android.OS.Bundle) void Microsoft.Maui.Platform.StackNavigationManager:OnNavigationHostViewAdded (object,Android.Views.ViewGroup/ChildViewAddedEventArgs) @@ -6275,11 +6422,13 @@ Methods: void Microsoft.Maui.Platform.StackNavigationManager/<>c__DisplayClass63_0:b__0 (AndroidX.Navigation.Fragment.FragmentNavigator/Destination) void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:.ctor (Microsoft.Maui.Platform.StackNavigationManager,AndroidX.Navigation.NavController,AndroidX.Fragment.App.FragmentManager) void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:AndroidX.Navigation.NavController.IOnDestinationChangedListener.OnDestinationChanged (AndroidX.Navigation.NavController,AndroidX.Navigation.NavDestination,Android.OS.Bundle) + void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:Disconnect () void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:OnFragmentAttached (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.Content.Context) void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:OnFragmentCreated (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.OS.Bundle) void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:OnFragmentPreAttached (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.Content.Context) void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:OnFragmentPreCreated (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.OS.Bundle) void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:OnFragmentResumed (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment) + void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:OnFragmentSaveInstanceState (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.OS.Bundle) void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:OnFragmentStarted (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment) void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:OnFragmentViewCreated (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment,Android.Views.View,Android.OS.Bundle) void Microsoft.Maui.Platform.StackNavigationManager/Callbacks:OnFragmentViewDestroyed (AndroidX.Fragment.App.FragmentManager,AndroidX.Fragment.App.Fragment) @@ -6361,6 +6510,7 @@ Methods: void Microsoft.Maui.PropertyMapperExtensions/<>c__DisplayClass1_0`2:g__newMethod|0 (Microsoft.Maui.IElementHandler,Microsoft.Maui.IElement) void Microsoft.Maui.PropertyMapperExtensions/<>c__DisplayClass2_0`2:b__0 (Microsoft.Maui.Handlers.ApplicationHandler,Microsoft.Maui.Controls.Application,System.Action`2) void Microsoft.Maui.PropertyMapperExtensions/<>c__DisplayClass4_0`2:b__0 (Microsoft.Maui.IElementHandler,Microsoft.Maui.IElement,System.Action`2) + void Microsoft.Maui.Storage.FileProvider:.ctor () void Microsoft.Maui.TaskExtensions:FireAndForget (System.Threading.Tasks.Task,Microsoft.Extensions.Logging.ILogger,string) void Microsoft.Maui.TaskExtensions:FireAndForget (System.Threading.Tasks.Task,Microsoft.Maui.Handlers.IImageHandler,string) void Microsoft.Maui.TaskExtensions:FireAndForget (System.Threading.Tasks.Task,System.Action`1) @@ -6375,11 +6525,15 @@ Methods: void Microsoft.Maui.Thickness:set_Left (double) void Microsoft.Maui.Thickness:set_Right (double) void Microsoft.Maui.Thickness:set_Top (double) + void Microsoft.Maui.ViewExtensions:g__BuildFlatList|0_0 (Microsoft.Maui.IView,System.Collections.Generic.List`1) + void Microsoft.Maui.ViewExtensions:DisconnectHandlers (Microsoft.Maui.IView) void Microsoft.Maui.ViewHandlerExtensions:PlatformArrangeHandler (Microsoft.Maui.IViewHandler,Microsoft.Maui.Graphics.Rect) void Microsoft.Maui.ViewHandlerExtensions:PrepareForTextViewArrange (Microsoft.Maui.IViewHandler,Microsoft.Maui.Graphics.Rect) void Microsoft.Maui.VisualDiagnostics:.cctor () void Microsoft.Maui.VisualDiagnostics:OnChildAdded (Microsoft.Maui.IVisualTreeElement,Microsoft.Maui.IVisualTreeElement) void Microsoft.Maui.VisualDiagnostics:OnChildRemoved (Microsoft.Maui.IVisualTreeElement,Microsoft.Maui.IVisualTreeElement,int) + void Microsoft.Maui.VisualDiagnostics/<>c:.cctor () + void Microsoft.Maui.VisualDiagnostics/<>c:.ctor () void Microsoft.Maui.VisualDiagnosticsOverlay:.ctor (Microsoft.Maui.IWindow) void Microsoft.Maui.VisualDiagnosticsOverlay:HandleUIChange () void Microsoft.Maui.VisualDiagnosticsOverlay:RemoveScrollableElementHandler () @@ -6393,10 +6547,10 @@ Methods: void Microsoft.Maui.WeakEventManager/Subscription:.ctor (System.WeakReference,System.Reflection.MethodInfo) void Microsoft.Maui.WeakList`1/<>c:.cctor () void Microsoft.Maui.WeakList`1/<>c:.ctor () - void Microsoft.Maui.WeakList`1:.ctor () void Microsoft.Maui.WeakList`1:Add (Microsoft.Maui.Controls.BindableObject) void Microsoft.Maui.WeakList`1:CleanupIfNeeded () void Microsoft.Maui.WeakList`1:Remove (Microsoft.Maui.Controls.BindableObject) + void Microsoft.Maui.WeakList`1:.ctor () void Microsoft.Maui.WindowExtensions:UpdateTitle (Android.App.Activity,Microsoft.Maui.IWindow) void Microsoft.Maui.WindowExtensions:UpdateWindowSoftInputModeAdjust (Microsoft.Maui.IWindow,Android.Views.SoftInput) void Microsoft.Maui.WindowOverlay:.ctor (Microsoft.Maui.IWindow) @@ -6408,14 +6562,14 @@ Methods: void Microsoft.Maui.WindowOverlay:remove_Tapped (System.EventHandler`1) void Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid:.ctor (bool) void Microsoft.Win32.SafeHandles.SafeWaitHandle:.ctor () + void modreq System.Diagnostics.Metrics.InstrumentAdvice`1:set_HistogramBucketBoundaries (System.Runtime.CompilerServices.IsExternalInit) System.Diagnostics.Metrics.InstrumentAdvice`1:set_HistogramBucketBoundaries (System.Collections.Generic.IReadOnlyList`1) void Mono.RuntimeGPtrArrayHandle:DestroyAndFree (Mono.RuntimeGPtrArrayHandle&) void Mono.RuntimeGPtrArrayHandle:GPtrArrayFree (Mono.RuntimeStructs/GPtrArray*) void Mono.SafeGPtrArrayHandle:Dispose () void Mono.SafeStringMarshal:Dispose () void Mono.SafeStringMarshal:GFree (intptr) - void System.AppContext:Setup (char**,char**,int) + void System.AppContext:Setup (char**,uint*,char**,uint*,int) void System.ArgumentException:ThrowIfNullOrEmpty (string,string) - void System.ArgumentException:ThrowIfNullOrWhiteSpace (string,string) void System.ArgumentOutOfRangeException:ThrowIfGreaterThan (int,int,string) void System.ArgumentOutOfRangeException:ThrowIfGreaterThan (long,long,string) void System.ArgumentOutOfRangeException:ThrowIfLessThan (int,int,string) @@ -6431,6 +6585,7 @@ Methods: void System.Array:Copy (System.Array,System.Array,int) void System.Array:CopySlow (System.Array,int,System.Array,int,int,bool) void System.Array:GetValueImpl (System.Runtime.CompilerServices.ObjectHandleOnStack,System.Runtime.CompilerServices.ObjectHandleOnStack,int) + void System.Array:InternalArray__ICollection_CopyTo (double[],int) void System.Array:InternalArray__ICollection_CopyTo (string[],int) void System.Array:InternalCreate (System.Array&,intptr,int,int*,int*) void System.Array:InternalSetValue (object,intptr) @@ -6442,8 +6597,8 @@ Methods: void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () - void System.Array/EmptyArray`1>:.cctor () void System.Array/EmptyArray`1>>:.cctor () + void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () void System.Array/EmptyArray`1:.cctor () @@ -6451,12 +6606,10 @@ Methods: void System.ArraySegment`1:.cctor () void System.ArraySegment`1:.ctor (byte[],int,int) void System.ArraySegment`1:.ctor (byte[]) - void System.AttributeUsageAttribute:.cctor () void System.AttributeUsageAttribute:.ctor (System.AttributeTargets) void System.BitConverter:.cctor () void System.Boolean:.cctor () void System.Buffer:BulkMoveWithWriteBarrier (byte&,byte&,uintptr,intptr) - void System.Buffer:Memmove (byte&,byte&,uintptr) void System.Buffers.Any5SearchValues`2:.ctor (System.ReadOnlySpan`1) void System.Buffers.AnyByteSearchValues:.ctor (System.ReadOnlySpan`1) void System.Buffers.ArrayPool`1:.cctor () @@ -6465,21 +6618,22 @@ Methods: void System.Buffers.ArrayPool`1:.ctor () void System.Buffers.ArrayPoolEventSource:.cctor () void System.Buffers.ArrayPoolEventSource:.ctor () + void System.Buffers.BitmapCharSearchValues:.ctor (System.ReadOnlySpan`1,int) void System.Buffers.BitVector256:Set (int) - void System.Buffers.IndexOfAnyAsciiSearcher:ComputeBitmap256 (System.ReadOnlySpan`1,System.Runtime.Intrinsics.Vector256`1&,System.Runtime.Intrinsics.Vector256`1&,System.Buffers.BitVector256&) - void System.Buffers.Latin1CharSearchValues:.ctor (System.ReadOnlySpan`1) + void System.Buffers.IndexOfAnyAsciiSearcher:ComputeAnyByteState (System.ReadOnlySpan`1,System.Buffers.IndexOfAnyAsciiSearcher/AnyByteState&) + void System.Buffers.IndexOfAnyAsciiSearcher/AnyByteState:.ctor (System.Runtime.Intrinsics.Vector128`1,System.Runtime.Intrinsics.Vector128`1,System.Buffers.BitVector256) void System.Buffers.SharedArrayPool`1/<>c:.cctor () void System.Buffers.SharedArrayPool`1/<>c:.ctor () void System.Buffers.SharedArrayPool`1/<>c:.cctor () void System.Buffers.SharedArrayPool`1/<>c:.ctor () - void System.Buffers.SharedArrayPool`1/Partition:.ctor () - void System.Buffers.SharedArrayPool`1/Partition:Trim (int,int,System.Buffers.Utilities/MemoryPressure,int) - void System.Buffers.SharedArrayPool`1/Partitions:.ctor () - void System.Buffers.SharedArrayPool`1/Partitions:Trim (int,int,System.Buffers.Utilities/MemoryPressure,int) void System.Buffers.SharedArrayPool`1:.ctor () void System.Buffers.SharedArrayPool`1:Return (byte[],bool) void System.Buffers.SharedArrayPool`1:.ctor () void System.Buffers.SharedArrayPool`1:Return (char[],bool) + void System.Buffers.SharedArrayPoolPartitions:.ctor () + void System.Buffers.SharedArrayPoolPartitions:Trim (int,int,System.Buffers.Utilities/MemoryPressure) + void System.Buffers.SharedArrayPoolPartitions/Partition:.ctor () + void System.Buffers.SharedArrayPoolPartitions/Partition:Trim (int,int,System.Buffers.Utilities/MemoryPressure) void System.Buffers.SharedArrayPoolStatics:.cctor () void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey,Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) void System.Collections.Concurrent.ConcurrentDictionary`2/Node:.ctor (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier,Microsoft.Extensions.DependencyInjection.ServiceProvider/ServiceAccessor,int,System.Collections.Concurrent.ConcurrentDictionary`2/Node) @@ -6525,7 +6679,6 @@ Methods: void System.Collections.Concurrent.ConcurrentQueue`1:.ctor () void System.Collections.Concurrent.ConcurrentQueue`1:Enqueue (object) void System.Collections.Concurrent.ConcurrentQueueSegment`1:.ctor (int) - void System.Collections.Generic.ArraySortHelper`1:.cctor () void System.Collections.Generic.ArraySortHelper`1:.cctor () void System.Collections.Generic.ArraySortHelper`1:InsertionSort (System.Span`1,System.Comparison`1) void System.Collections.Generic.ArraySortHelper`1:IntroSort (System.Span`1,int,System.Comparison`1) @@ -6538,8 +6691,8 @@ Methods: void System.Collections.Generic.Dictionary`2/Enumerator:.ctor (System.Collections.Generic.Dictionary`2,int) void System.Collections.Generic.Dictionary`2/Enumerator:Dispose () void System.Collections.Generic.Dictionary`2/KeyCollection>:.ctor (System.Collections.Generic.Dictionary`2>) - void System.Collections.Generic.Dictionary`2/ValueCollection:.ctor (System.Collections.Generic.Dictionary`2) void System.Collections.Generic.Dictionary`2/ValueCollection:CopyTo (Microsoft.Maui.Controls.BindableObject/BindablePropertyContext[],int) + void System.Collections.Generic.Dictionary`2/ValueCollection:.ctor (System.Collections.Generic.Dictionary`2) void System.Collections.Generic.Dictionary`2:.ctor () void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2:Add (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCacheKey,object) @@ -6558,6 +6711,8 @@ Methods: void System.Collections.Generic.Dictionary`2>:Resize () void System.Collections.Generic.Dictionary`2>:Resize (int,bool) void System.Collections.Generic.Dictionary`2>:set_Item (Microsoft.Maui.Controls.BindableProperty,System.ValueTuple`2) + void System.Collections.Generic.Dictionary`2:.ctor () + void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2:.ctor () void System.Collections.Generic.Dictionary`2:.ctor (int,System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2:Clear () @@ -6615,9 +6770,8 @@ Methods: void System.Collections.Generic.Dictionary`2>:.ctor (System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.Dictionary`2:.ctor () void System.Collections.Generic.EnumEqualityComparer`1:.ctor () - void System.Collections.Generic.GenericArraySortHelper`1:.ctor () void System.Collections.Generic.GenericArraySortHelper`1:.ctor () - void System.Collections.Generic.GenericComparer`1:.ctor () + void System.Collections.Generic.GenericComparer`1:.ctor () void System.Collections.Generic.GenericComparer`1:.ctor () void System.Collections.Generic.GenericEqualityComparer`1:.ctor () void System.Collections.Generic.GenericEqualityComparer`1:.ctor () @@ -6625,16 +6779,15 @@ Methods: void System.Collections.Generic.GenericEqualityComparer`1:.ctor () void System.Collections.Generic.GenericEqualityComparer`1:.ctor () void System.Collections.Generic.GenericEqualityComparer`1:.ctor () + void System.Collections.Generic.GenericEqualityComparer`1>>:.ctor () void System.Collections.Generic.GenericEqualityComparer`1>:.ctor () - void System.Collections.Generic.HashSet`1/Enumerator:.ctor (System.Collections.Generic.HashSet`1) void System.Collections.Generic.HashSet`1/Enumerator:Dispose () + void System.Collections.Generic.HashSet`1/Enumerator:.ctor (System.Collections.Generic.HashSet`1) + void System.Collections.Generic.HashSet`1:.ctor () void System.Collections.Generic.HashSet`1:.ctor (System.Collections.Generic.IEqualityComparer`1) void System.Collections.Generic.HashSet`1:Clear () void System.Collections.Generic.HashSet`1:Resize () void System.Collections.Generic.HashSet`1:Resize (int,bool) - void System.Collections.Generic.HashSet`1:.ctor () - void System.Collections.Generic.List`1/Enumerator:.ctor (System.Collections.Generic.List`1) - void System.Collections.Generic.List`1/Enumerator:Dispose () void System.Collections.Generic.List`1/Enumerator:.ctor (System.Collections.Generic.List`1) void System.Collections.Generic.List`1/Enumerator:Dispose () void System.Collections.Generic.List`1/Enumerator>:.ctor (System.Collections.Generic.List`1>) @@ -6658,10 +6811,10 @@ Methods: void System.Collections.Generic.List`1:Sort (int,int,System.Collections.Generic.IComparer`1) void System.Collections.Generic.List`1:Sort (System.Collections.Generic.IComparer`1) void System.Collections.Generic.List`1:Add (Microsoft.Maui.Controls.ResourceDictionary) + void System.Collections.Generic.List`1:GrowForInsertion (int,int) void System.Collections.Generic.List`1:Insert (int,Microsoft.Maui.Controls.ResourceDictionary) void System.Collections.Generic.List`1:AddRange (System.Collections.Generic.IEnumerable`1) void System.Collections.Generic.List`1:.cctor () - void System.Collections.Generic.List`1:.ctor (int) void System.Collections.Generic.List`1:.cctor () void System.Collections.Generic.List`1:.ctor () void System.Collections.Generic.List`1:AddWithResize (Microsoft.Maui.WeakEventManager/Subscription) @@ -6674,6 +6827,8 @@ Methods: void System.Collections.Generic.List`1>:AddWithResize (System.Collections.Generic.KeyValuePair`2) void System.Collections.Generic.List`1>:Grow (int) void System.Collections.Generic.List`1>:set_Capacity (int) + void System.Collections.Generic.List`1:.cctor () + void System.Collections.Generic.List`1:.ctor (System.Collections.Generic.IEnumerable`1) void System.Collections.Generic.List`1:.cctor () void System.Collections.Generic.List`1:.ctor () void System.Collections.Generic.List`1:AddWithResize (int) @@ -6690,11 +6845,13 @@ Methods: void System.Collections.Generic.List`1>:.ctor () void System.Collections.Generic.List`1>:AddWithResize (System.ValueTuple`2) void System.Collections.Generic.List`1>:Grow (int) + void System.Collections.Generic.List`1>:RemoveAt (int) void System.Collections.Generic.List`1>:set_Capacity (int) void System.Collections.Generic.List`1>>:.cctor () void System.Collections.Generic.List`1>>:.ctor () void System.Collections.Generic.List`1>>:AddWithResize (System.ValueTuple`2>) void System.Collections.Generic.List`1>>:Grow (int) + void System.Collections.Generic.List`1>>:RemoveAt (int) void System.Collections.Generic.List`1>>:set_Capacity (int) void System.Collections.Generic.List`1>:.cctor () void System.Collections.Generic.List`1>:.ctor () @@ -6721,23 +6878,9 @@ Methods: void System.Collections.Generic.Queue`1:MoveNext (int&) void System.Collections.Generic.Queue`1:SetCapacity (int) void System.Collections.Generic.Queue`1:.ctor (int) - void System.Collections.Generic.SortedList`2/Enumerator:.ctor (System.Collections.Generic.SortedList`2,int) - void System.Collections.Generic.SortedList`2/Enumerator:Dispose () - void System.Collections.Generic.SortedList`2/Enumerator:.ctor (System.Collections.Generic.SortedList`2,int) - void System.Collections.Generic.SortedList`2/Enumerator:Dispose () - void System.Collections.Generic.SortedList`2:.ctor () - void System.Collections.Generic.SortedList`2:EnsureCapacity (int) - void System.Collections.Generic.SortedList`2:Insert (int,Microsoft.Maui.Controls.SetterSpecificity,Microsoft.Maui.Controls.BindingBase) - void System.Collections.Generic.SortedList`2:RemoveAt (int) - void System.Collections.Generic.SortedList`2:set_Capacity (int) - void System.Collections.Generic.SortedList`2:set_Item (Microsoft.Maui.Controls.SetterSpecificity,Microsoft.Maui.Controls.BindingBase) - void System.Collections.Generic.SortedList`2:.ctor () - void System.Collections.Generic.SortedList`2:EnsureCapacity (int) - void System.Collections.Generic.SortedList`2:Insert (int,Microsoft.Maui.Controls.SetterSpecificity,object) - void System.Collections.Generic.SortedList`2:RemoveAt (int) - void System.Collections.Generic.SortedList`2:set_Capacity (int) - void System.Collections.Generic.SortedList`2:set_Item (Microsoft.Maui.Controls.SetterSpecificity,object) + void System.Collections.Generic.Stack`1/Enumerator:.ctor (System.Collections.Generic.Stack`1) void System.Collections.Generic.Stack`1:Clear () + void System.Collections.Generic.Stack`1:Clear () void System.Collections.Generic.ValueListBuilder`1:.ctor (System.Span`1) void System.Collections.Hashtable:.ctor () void System.Collections.Hashtable:.ctor (int,single) @@ -6766,7 +6909,8 @@ Methods: void System.Collections.ObjectModel.ObservableCollection`1>:System.ComponentModel.INotifyPropertyChanged.add_PropertyChanged (System.ComponentModel.PropertyChangedEventHandler) void System.Collections.ObjectModel.ReadOnlyCollection`1:.cctor () void System.Collections.ObjectModel.ReadOnlyCollection`1:.ctor (System.Collections.Generic.IList`1) - void System.Collections.ObjectModel.ReadOnlyObservableCollection`1>:.cctor () + void System.Collections.ObjectModel.ReadOnlyCollection`1:.cctor () + void System.Collections.ObjectModel.ReadOnlyCollection`1:.ctor (System.Collections.Generic.IList`1) void System.Collections.ObjectModel.ReadOnlyObservableCollection`1>:.ctor (System.Collections.ObjectModel.ObservableCollection`1>) void System.Collections.ObjectModel.ReadOnlyObservableCollection`1>:HandleCollectionChanged (object,System.Collections.Specialized.NotifyCollectionChangedEventArgs) void System.Collections.ObjectModel.ReadOnlyObservableCollection`1>:HandlePropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) @@ -6777,17 +6921,13 @@ Methods: void System.Collections.Specialized.NotifyCollectionChangedEventArgs:.ctor (System.Collections.Specialized.NotifyCollectionChangedAction) void System.Collections.Specialized.SingleItemReadOnlyList/d__15:System.IDisposable.Dispose () void System.ComponentModel.PropertyChangedEventArgs:.ctor (string) - void System.ComponentModel.TypeConverterAttribute:.cctor () - void System.ComponentModel.TypeConverterAttribute:.ctor () void System.ComponentModel.TypeConverterAttribute:.ctor (System.Type) void System.DateTime:.cctor () void System.DateTime:.ctor (int,int,int) void System.DateTime:.ctor (long,System.DateTimeKind) void System.DBNull:.cctor () void System.DBNull:.ctor () - void System.DefaultBinder:.cctor () - void System.DefaultBinder:.ctor () - void System.Diagnostics.Metrics.Histogram`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) + void System.Diagnostics.Metrics.Histogram`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Diagnostics.Metrics.InstrumentAdvice`1) void System.Diagnostics.Metrics.Instrument:.cctor () void System.Diagnostics.Metrics.Instrument:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) void System.Diagnostics.Metrics.Instrument:Publish () @@ -6795,8 +6935,10 @@ Methods: void System.Diagnostics.Metrics.Instrument:ValidateTypeParameter () void System.Diagnostics.Metrics.Instrument/<>c:.cctor () void System.Diagnostics.Metrics.Instrument/<>c:.ctor () - void System.Diagnostics.Metrics.Instrument`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) + void System.Diagnostics.Metrics.Instrument`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Diagnostics.Metrics.InstrumentAdvice`1) + void System.Diagnostics.Metrics.Instrument`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>,System.Diagnostics.Metrics.InstrumentAdvice`1) void System.Diagnostics.Metrics.Instrument`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) + void System.Diagnostics.Metrics.InstrumentAdvice`1:.ctor () void System.Diagnostics.Metrics.Meter:.cctor () void System.Diagnostics.Metrics.Meter:.ctor (string,string,System.Collections.Generic.IEnumerable`1>,object) void System.Diagnostics.Metrics.Meter:.ctor (string) @@ -6805,7 +6947,6 @@ Methods: void System.Diagnostics.Metrics.Meter/<>c:.ctor () void System.Diagnostics.Metrics.UpDownCounter`1:.ctor (System.Diagnostics.Metrics.Meter,string,string,string,System.Collections.Generic.IEnumerable`1>) void System.Diagnostics.Stopwatch:.cctor () - void System.Diagnostics.Tracing.EventSource:.cctor () void System.Diagnostics.Tracing.EventSource:.ctor () void System.Diagnostics.Tracing.EventSource:.ctor (System.Diagnostics.Tracing.EventSourceSettings,string[]) void System.Diagnostics.Tracing.EventSource:.ctor (System.Diagnostics.Tracing.EventSourceSettings) @@ -6898,34 +7039,40 @@ Methods: void System.IO.UnmanagedMemoryStream:EnsureReadable () void System.IO.UnmanagedMemoryStream:Initialize (byte*,long,long,System.IO.FileAccess) void System.IO.UnmanagedMemoryStream:set_Position (long) - void System.Lazy`1:ExecutionAndPublication (System.LazyHelper,bool) - void System.Lazy`1:ViaFactory (System.Threading.LazyThreadSafetyMode) + void System.Lazy`1:ExecutionAndPublication (System.LazyHelper,bool) + void System.Lazy`1:ViaFactory (System.Threading.LazyThreadSafetyMode) + void System.Lazy`1:.ctor (System.Func`1,System.Threading.LazyThreadSafetyMode,bool) + void System.Lazy`1:.ctor (System.Func`1) + void System.Lazy`1:ExecutionAndPublication (System.LazyHelper,bool) + void System.Lazy`1:ViaFactory (System.Threading.LazyThreadSafetyMode) void System.LazyHelper:.cctor () void System.LazyHelper:.ctor (System.LazyState) - void System.Linq.Buffer`1:.ctor (System.Collections.Generic.IEnumerable`1) - void System.Linq.Enumerable/d__41`1:.ctor (int) - void System.Linq.Enumerable/d__41`1:<>m__Finally1 () - void System.Linq.Enumerable/d__41`1:System.IDisposable.Dispose () - void System.Linq.Enumerable/Iterator`1:.ctor () - void System.Linq.Enumerable/Iterator`1:Dispose () - void System.Linq.Enumerable/SelectListIterator`2:.ctor (System.Collections.Generic.List`1,System.Func`2) - void System.Linq.Enumerable/WhereListIterator`1:.ctor (System.Collections.Generic.List`1,System.Func`2) + void System.Linq.Enumerable:FillIncrementing (System.Span`1,int) + void System.Linq.Enumerable/EnumerableSorter`1:.cctor () + void System.Linq.Enumerable/EnumerableSorter`1:.ctor () + void System.Linq.Enumerable/EnumerableSorter`2:.ctor (System.Func`2,System.Collections.Generic.IComparer`1,bool,System.Linq.Enumerable/EnumerableSorter`1) + void System.Linq.Enumerable/EnumerableSorter`2:ComputeKeys (Microsoft.Maui.IView[],int) + void System.Linq.Enumerable/EnumerableSorter`2:QuickSort (int[],int,int) + void System.Linq.Enumerable/Iterator`1:.ctor () + void System.Linq.Enumerable/Iterator`1:Dispose () + void System.Linq.Enumerable/ListSelectIterator`2:.ctor (System.Collections.Generic.List`1,System.Func`2) + void System.Linq.Enumerable/ListWhereIterator`1:.ctor (System.Collections.Generic.List`1,System.Func`2) + void System.Linq.Enumerable/OfTypeIterator`1:.ctor (System.Collections.IEnumerable) + void System.Linq.Enumerable/OfTypeIterator`1:Dispose () + void System.Linq.Enumerable/OrderedIterator`1:.ctor (System.Collections.Generic.IEnumerable`1) + void System.Linq.Enumerable/OrderedIterator`2:.ctor (System.Collections.Generic.IEnumerable`1,System.Func`2,System.Collections.Generic.IComparer`1,bool,System.Linq.Enumerable/OrderedIterator`1) + void System.Linq.Enumerable/OrderedIterator`2:Dispose () void System.Linq.EnumerableSorter`1/<>c:.cctor () void System.Linq.EnumerableSorter`1/<>c:.ctor () - void System.Linq.EnumerableSorter`1:.cctor () - void System.Linq.EnumerableSorter`1:.ctor () - void System.Linq.EnumerableSorter`2:.ctor (System.Func`2,System.Collections.Generic.IComparer`1,bool,System.Linq.EnumerableSorter`1) - void System.Linq.EnumerableSorter`2:ComputeKeys (Microsoft.Maui.IView[],int) - void System.Linq.EnumerableSorter`2:QuickSort (int[],int,int) void System.Linq.Extensions:.cctor () - void System.Linq.Extensions/d__5`1:<>m__Finally1 () - void System.Linq.Extensions/d__5`1:System.IDisposable.Dispose () - void System.Linq.OrderedEnumerable`1/d__4:System.IDisposable.Dispose () - void System.Linq.OrderedEnumerable`2:.ctor (System.Collections.Generic.IEnumerable`1,System.Func`2,System.Collections.Generic.IComparer`1,bool,System.Linq.OrderedEnumerable`1) + void System.Linq.Extensions/d__6`1:<>m__Finally1 () + void System.Linq.Extensions/d__6`1:System.IDisposable.Dispose () void System.Marvin:.cctor () void System.MemoryExtensions:Sort (System.Span`1,System.Comparison`1) void System.Net.CookieContainer:.cctor () void System.Net.CookieContainer:.ctor () + void System.Net.Http.<>z__ReadOnlyArray`1:System.Collections.Generic.ICollection.CopyTo (double[],int) + void System.Net.Http.DiagnosticsHelper:.cctor () void System.Net.Http.Headers.AltSvcHeaderParser:.cctor () void System.Net.Http.Headers.AltSvcHeaderParser:.ctor () void System.Net.Http.Headers.BaseHeaderParser:.ctor (bool) @@ -6943,6 +7090,7 @@ Methods: void System.Net.Http.Headers.HeaderUtilities:.cctor () void System.Net.Http.Headers.HeaderUtilities:CheckValidToken (string,string) void System.Net.Http.Headers.HttpContentHeaders:.ctor (System.Net.Http.HttpContent) + void System.Net.Http.Headers.HttpHeaderParser:.cctor () void System.Net.Http.Headers.HttpHeaderParser:.ctor (bool,string) void System.Net.Http.Headers.HttpHeaderParser:.ctor (bool) void System.Net.Http.Headers.HttpHeaders:.ctor (System.Net.Http.Headers.HttpHeaderType,System.Net.Http.Headers.HttpHeaderType) @@ -7006,6 +7154,10 @@ Methods: void System.Net.Http.HttpMessageInvoker:Dispose (bool) void System.Net.Http.HttpMethod:.cctor () void System.Net.Http.HttpMethod:.ctor (string,int) + void System.Net.Http.HttpMethod:Initialize (int) + void System.Net.Http.HttpMethod:set_IsConnect (bool) + void System.Net.Http.HttpMethod:set_IsHead (bool) + void System.Net.Http.HttpMethod:set_MustHaveRequestBody (bool) void System.Net.Http.HttpRequestMessage:.ctor (System.Net.Http.HttpMethod,string) void System.Net.Http.HttpRequestMessage:.ctor (System.Net.Http.HttpMethod,System.Uri) void System.Net.Http.HttpRequestMessage:set_Version (System.Version) @@ -7033,6 +7185,7 @@ Methods: void System.NullReferenceException:.ctor (string) void System.Number:.cctor () void System.Number/NumberBuffer:.ctor (System.Number/NumberBufferKind,System.Span`1) + void System.Numerics.Vector`1:.ctor (int) void System.OperatingSystem:.ctor (System.PlatformID,System.Version,string) void System.OperatingSystem:.ctor (System.PlatformID,System.Version) void System.OrdinalCaseSensitiveComparer:.cctor () @@ -7065,12 +7218,14 @@ Methods: void System.Reflection.AssemblyName:FillName (Mono.MonoAssemblyName*,string,bool,bool,bool) void System.Reflection.AssemblyNameFormatter:AppendQuoted (System.Text.ValueStringBuilder&,string) void System.Reflection.AssemblyNameParser:.ctor (System.ReadOnlySpan`1) - void System.Reflection.AssemblyNameParser:RecordNewSeenOrThrow (System.Reflection.AssemblyNameParser/AttributeKind&,System.Reflection.AssemblyNameParser/AttributeKind) void System.Reflection.AssemblyNameParser/AssemblyNameParts:.ctor (string,System.Version,string,System.Reflection.AssemblyNameFlags,byte[]) void System.Reflection.ConstructorInfo:.cctor () + void System.Reflection.ConstructorInvoker:.ctor (System.Reflection.RuntimeConstructorInfo,System.RuntimeType[]) + void System.Reflection.ConstructorInvoker:.ctor (System.Reflection.RuntimeConstructorInfo) void System.Reflection.CustomAttribute:.cctor () void System.Reflection.CustomAttribute/AttributeInfo:.ctor (System.AttributeUsageAttribute,int) void System.Reflection.Emit.OpCodes:.cctor () + void System.Reflection.MethodBase/StackAllocatedArguments:.ctor (object,object,object,object) void System.Reflection.MethodBaseInvoker:.ctor (System.Reflection.MethodBase,System.RuntimeType[]) void System.Reflection.MethodBaseInvoker:.ctor (System.Reflection.RuntimeConstructorInfo) void System.Reflection.MethodBaseInvoker:.ctor (System.Reflection.RuntimeMethodInfo) @@ -7096,7 +7251,6 @@ Methods: void System.Resources.ResourceManager:CommonAssemblyInit () void System.Resources.ResourceManager/ResourceManagerMediator:.ctor (System.Resources.ResourceManager) void System.Resources.ResourceReader:_ReadResources () - void System.Resources.ResourceReader:.cctor () void System.Resources.ResourceReader:.ctor (System.IO.Stream,System.Collections.Generic.Dictionary`2,bool) void System.Resources.ResourceReader:ReadResources () void System.Resources.ResourceReader:SkipString () @@ -7107,16 +7261,16 @@ Methods: void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.NavigationPage/d__100&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.BottomNavigationViewUtils/d__6&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.BottomNavigationViewUtils/d__4&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker/d__52&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__50&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__41&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.Compatibility.ShellToolbarTracker/d__54&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__55&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Platform.ModalNavigationManager/d__45&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Shell/<b__161_0>d&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.Shell/<g__SetCurrentItem|161_1>d&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Controls.ShellNavigationManager/d__14&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Devices.DeviceDisplayImplementation/Listener/d__2&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Handlers.ImageHandler/d__8&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Handlers.ImageHandler/d__9&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Platform.ImageSourcePartExtensions/d__0&) - void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Platform.ImageSourcePartLoader/d__10&) + void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.Platform.ImageSourcePartLoader/d__14&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.TaskExtensions/d__0`1&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (Microsoft.Maui.TaskExtensions/d__1&) void System.Runtime.CompilerServices.AsyncMethodBuilderCore:Start (System.IO.BufferedStream/d__68&) @@ -7214,7 +7368,7 @@ Methods: void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:AwaitUnsafeOnCompleted (System.Runtime.CompilerServices.TaskAwaiter`1&,System.Runtime.CompilerServices.IAsyncStateMachineBox) void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:AwaitUnsafeOnCompleted (System.Runtime.CompilerServices.TaskAwaiter`1&,System.Runtime.CompilerServices.IAsyncStateMachineBox) void System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetExistingTaskResult (System.Threading.Tasks.Task`1,System.Threading.Tasks.VoidTaskResult) - void System.Runtime.CompilerServices.AsyncVoidMethodBuilder:NotifySynchronizationContextOfCompletion () + void System.Runtime.CompilerServices.AsyncVoidMethodBuilder:NotifySynchronizationContextOfCompletion (System.Threading.SynchronizationContext) void System.Runtime.CompilerServices.AsyncVoidMethodBuilder:SetResult () void System.Runtime.CompilerServices.ConditionalWeakTable`2/Container:.ctor (System.Runtime.CompilerServices.ConditionalWeakTable`2,int[],System.Runtime.CompilerServices.ConditionalWeakTable`2/Entry[],int) void System.Runtime.CompilerServices.ConditionalWeakTable`2/Container:Finalize () @@ -7232,7 +7386,6 @@ Methods: void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler:AppendFormatted (string) void System.Runtime.CompilerServices.QCallAssembly:.ctor (System.Reflection.RuntimeAssembly&) void System.Runtime.CompilerServices.QCallTypeHandle:.ctor (System.RuntimeType&) - void System.Runtime.CompilerServices.RuntimeFeature:.cctor () void System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal (System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool) void System.Runtime.ConstrainedExecution.CriticalFinalizerObject:Finalize () void System.Runtime.DependentHandle:.ctor (object,object) @@ -7244,7 +7397,6 @@ Methods: void System.Runtime.InteropServices.Marshal:FreeCoTaskMem (intptr) void System.Runtime.InteropServices.Marshal:FreeHGlobal (intptr) void System.Runtime.InteropServices.Marshal:PtrToStructureHelper (intptr,object,bool) - void System.Runtime.InteropServices.Marshal:PtrToStructureInternal (intptr,object,bool) void System.Runtime.InteropServices.Marshal:SetLastPInvokeError (int) void System.Runtime.InteropServices.Marshal:SetLastSystemError (int) void System.Runtime.InteropServices.Marshal:ZeroFreeCoTaskMemUTF8 (intptr) @@ -7267,7 +7419,6 @@ Methods: void System.RuntimeType:FilterHelper (System.Reflection.BindingFlags,string&,bool,bool&,bool&,System.RuntimeType/MemberListType&) void System.RuntimeType:getFullName (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack,bool,bool) void System.RuntimeType:GetGenericArgumentsInternal (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack,bool) - void System.RuntimeType:GetInterfaces (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.RuntimeType:GetName (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.RuntimeType:make_byref_type (System.Runtime.CompilerServices.QCallTypeHandle,System.Runtime.CompilerServices.ObjectHandleOnStack) void System.RuntimeType:MakeGenericType (System.Type,System.Type[],System.Runtime.CompilerServices.ObjectHandleOnStack) @@ -7284,8 +7435,8 @@ Methods: void System.RuntimeTypeHandle:internal_from_name (intptr,System.Threading.StackCrawlMark&,System.Runtime.CompilerServices.ObjectHandleOnStack,bool,bool) void System.SpanHelpers:ClearWithoutReferences (byte&,uintptr) void System.SpanHelpers:ClearWithReferences (intptr&,uintptr) + void System.SpanHelpers:Memmove (byte&,byte&,uintptr) void System.StackOverflowException:.ctor (string) - void System.String:.ctor (char[],int,int) void System.String:.ctor (char*,int,int) void System.String:.ctor (char*) void System.String:.ctor (sbyte*) @@ -7295,12 +7446,8 @@ Methods: void System.String:MakeSeparatorListVectorized (System.ReadOnlySpan`1,System.Collections.Generic.ValueListBuilder`1&,char,char,char) void System.String:memcpy (byte*,byte*,int) void System.String:memset (byte*,int,int) - void System.SZGenericArrayEnumerator`1:.cctor () - void System.SZGenericArrayEnumerator`1:.ctor (Microsoft.Maui.Controls.DependencyService/DependencyType[],int) void System.SZGenericArrayEnumerator`1:.cctor () void System.SZGenericArrayEnumerator`1:.ctor (Microsoft.Maui.Hosting.IMauiInitializeService[],int) - void System.SZGenericArrayEnumerator`1>:.cctor () - void System.SZGenericArrayEnumerator`1>:.ctor (System.Collections.Generic.KeyValuePair`2[],int) void System.SZGenericArrayEnumerator`1>>:.cctor () void System.SZGenericArrayEnumerator`1>>:.ctor (System.Collections.Generic.KeyValuePair`2>[],int) void System.SZGenericArrayEnumerator`1>:.cctor () @@ -7311,8 +7458,6 @@ Methods: void System.Text.ASCIIEncoding:.ctor () void System.Text.ASCIIEncoding:SetDefaultFallbacks () void System.Text.ASCIIEncoding/ASCIIEncodingSealed:.ctor () - void System.Text.DecoderNLS:.ctor (System.Text.Encoding) - void System.Text.DecoderNLS:Reset () void System.Text.DecoderReplacementFallback:.cctor () void System.Text.DecoderReplacementFallback:.ctor () void System.Text.DecoderReplacementFallback:.ctor (string) @@ -7361,20 +7506,23 @@ Methods: void System.Threading.ExecutionContext:.ctor () void System.Threading.ExecutionContext:RunFromThreadPoolDispatchLoop (System.Threading.Thread,System.Threading.ExecutionContext,System.Threading.ContextCallback,object) void System.Threading.ExecutionContext:RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object) + void System.Threading.Lock:.cctor () + void System.Threading.Lock:.ctor () + void System.Threading.Lock:Exit (System.Threading.Lock/ThreadId) + void System.Threading.Lock/ThreadId:InitializeForCurrentThread () void System.Threading.LowLevelLifoSemaphore:.ctor (int,int,int,System.Action) void System.Threading.LowLevelLifoSemaphore:Create (int) + void System.Threading.LowLevelLifoSemaphore:Release (int) void System.Threading.LowLevelLifoSemaphore:ReleaseCore (int) void System.Threading.LowLevelLifoSemaphore:ReleaseInternal (intptr,int) - void System.Threading.LowLevelLifoSemaphoreBase:.ctor (int,int,int,System.Action) - void System.Threading.LowLevelLifoSemaphoreBase:Release (int) - void System.Threading.LowLevelLifoSemaphoreBase/Counts:AddUpToMaxCountOfWaitersSignaledToWake (uint) - void System.Threading.LowLevelLifoSemaphoreBase/Counts:DecrementCountOfWaitersSignaledToWake () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:DecrementSpinnerCount () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:DecrementWaiterCount () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:IncrementSpinnerCount () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:IncrementWaiterCount () - void System.Threading.LowLevelLifoSemaphoreBase/Counts:set_SignalCount (uint) - void System.Threading.LowLevelLifoSemaphoreBase/Counts:SetUInt32Value (uint,byte) + void System.Threading.LowLevelLifoSemaphore/Counts:AddUpToMaxCountOfWaitersSignaledToWake (uint) + void System.Threading.LowLevelLifoSemaphore/Counts:DecrementCountOfWaitersSignaledToWake () + void System.Threading.LowLevelLifoSemaphore/Counts:DecrementSpinnerCount () + void System.Threading.LowLevelLifoSemaphore/Counts:DecrementWaiterCount () + void System.Threading.LowLevelLifoSemaphore/Counts:IncrementSpinnerCount () + void System.Threading.LowLevelLifoSemaphore/Counts:IncrementWaiterCount () + void System.Threading.LowLevelLifoSemaphore/Counts:set_SignalCount (uint) + void System.Threading.LowLevelLifoSemaphore/Counts:SetUInt32Value (uint,byte) void System.Threading.LowLevelLock:.cctor () void System.Threading.LowLevelLock:.ctor () void System.Threading.LowLevelLock:Acquire () @@ -7388,7 +7536,7 @@ Methods: void System.Threading.LowLevelMonitor:Signal_ReleaseCore () void System.Threading.LowLevelMonitor:Wait () void System.Threading.LowLevelMonitor:WaitCore () - void System.Threading.LowLevelSpinWaiter:Wait (int,int,int) + void System.Threading.LowLevelSpinWaiter:Wait (int,int,bool) void System.Threading.Monitor:Exit (object) void System.Threading.Monitor:InternalExit (object) void System.Threading.PortableThreadPool:.cctor () @@ -7463,7 +7611,7 @@ Methods: void System.Threading.Tasks.Task:UnsafeSetContinuationForAwait (System.Runtime.CompilerServices.IAsyncStateMachineBox,bool) void System.Threading.Tasks.Task/<>c:.cctor () void System.Threading.Tasks.Task/<>c:.ctor () - void System.Threading.Tasks.Task/<>c:<.cctor>b__281_0 (object) + void System.Threading.Tasks.Task/<>c:<.cctor>b__292_0 (object) void System.Threading.Tasks.Task/ContingentProperties:SetCompleted () void System.Threading.Tasks.Task/ContingentProperties:UnregisterCancellationCallback () void System.Threading.Tasks.Task/DelayPromise:.cctor () @@ -7561,6 +7709,7 @@ Methods: void System.Threading.TimerQueue:DeleteTimer (System.Threading.TimerQueueTimer) void System.Threading.TimerQueue:FireNextTimers () void System.Threading.TimerQueue:LinkTimer (System.Threading.TimerQueueTimer) + void System.Threading.TimerQueue:MoveTimerToCorrectList (System.Threading.TimerQueueTimer,bool) void System.Threading.TimerQueue:System.Threading.IThreadPoolWorkItem.Execute () void System.Threading.TimerQueue:TimerThread () void System.Threading.TimerQueue:UnlinkTimer (System.Threading.TimerQueueTimer) @@ -7592,6 +7741,7 @@ Methods: void System.TimeSpan:.ctor (int,int,int,int,int,int) void System.TimeSpan:.ctor (int,int,int,int,int) void System.TimeSpan:.ctor (long) + void System.Tuple`2, System.String>:.ctor (System.Func`2,string) void System.Tuple`3:.ctor (string,System.Type,System.Type) void System.Tuple`4:.ctor (System.WeakReference,Microsoft.Maui.Controls.MessagingCenter/MaybeWeakReference,System.Reflection.MethodInfo,Microsoft.Maui.Controls.MessagingCenter/Filter) void System.Type:.cctor () @@ -7600,7 +7750,7 @@ Methods: void System.Uri:.cctor () void System.Uri:.ctor (string,System.UriKind) void System.Uri:.ctor (string) - void System.Uri:CheckAuthorityHelperHandleDnsIri (char*,int,int,bool,System.Uri/Flags&,bool&,string&,System.ParsingError&) + void System.Uri:CheckAuthorityHelperHandleDnsIri (char*,int,int,bool,System.Uri/Flags&,string&,System.ParsingError&) void System.Uri:CreateHostString () void System.Uri:CreateThis (string,bool,System.UriKind,System.UriCreationOptions&) void System.Uri:CreateUriInfo (System.Uri/Flags) @@ -7617,7 +7767,7 @@ Methods: void System.UriHelper:.cctor () void System.UriHelper/<>c:.cctor () void System.UriHelper/<>c:.ctor () - void System.UriHelper/<>c:b__0_0 (System.Span`1,intptr) + void System.UriHelper/<>c:b__0_0 (System.Span`1,System.ReadOnlySpan`1) void System.UriParser:.cctor () void System.UriParser:.ctor (System.UriSyntaxFlags) void System.UriParser/BuiltInUriParser:.ctor (string,int,System.UriSyntaxFlags) diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.cs.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.cs.resx index 027b175bbd99..f3d376a7aea5 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.cs.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.cs.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType očekává řetězcový literál, značku {{x:Type}} nebo {{x:Nul}l}. + x:DataType očekává řetězcový literál, značku {{x:Type}} nebo {{x:Null}}. Nedeklarovaná předpona xmlns: {0} diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.cs.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.cs.xlf index 7cbd7bf8dcc3..3102b6c43288 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.cs.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.cs.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. Šablona stylů nemůže obsahovat jak zdroj, tak obsah. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType očekává řetězcový literál, značku {{x:Type}} nebo {{x:Nul}l}. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType očekává řetězcový literál, značku {{x:Type}} nebo {{x:Null}}. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.de.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.de.resx index 5188c521bb24..4f983ad4ea95 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.de.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.de.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType erwartet ein Zeichenfolgenliteral, ein {{x:Type}}-Markup oder {{x:Nul}l}. + x:DataType erwartet ein Zeichenfolgenliteral, ein {{x:Type}}-Markup oder {{x:Null}}. Nicht deklariertes xmlns-Präfix "{0}". diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.de.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.de.xlf index 56eac6f37c17..4224295ffe50 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.de.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.de.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. Das StyleSheet kann nicht gleichzeitig eine Source-Eigenschaft und einen Inhalt aufweisen. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType erwartet ein Zeichenfolgenliteral, ein {{x:Type}}-Markup oder {{x:Nul}l}. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType erwartet ein Zeichenfolgenliteral, ein {{x:Type}}-Markup oder {{x:Null}}. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.es.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.es.resx index f175a0f30b1d..4407d399de75 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.es.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.es.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType espera un literal de cadena, una marca {{x:Type}} o {{x:Nul}l}. + x:DataType espera un literal de cadena, una marca {{x:Type}} o {{x:Null}}. Prefijo xmlns no declarado "{0}". diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.es.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.es.xlf index d015bba319da..79c6c50d24c2 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.es.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.es.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. StyleSheet no puede tener un origen y un contenido. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType espera un literal de cadena, una marca {{x:Type}} o {{x:Nul}l}. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType espera un literal de cadena, una marca {{x:Type}} o {{x:Null}}. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.fr.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.fr.resx index 793cec9e7c91..b77deb50442b 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.fr.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.fr.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType attend un littéral de chaîne, une balise {{x:Type}} ou {{x:Nul}l}. + x:DataType attend un littéral de chaîne, une balise {{x:Type}} ou {{x:Null}}. Préfixe xmlns non déclaré "{0}". diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.fr.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.fr.xlf index dd6e43501431..555138772ac6 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.fr.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.fr.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. StyleSheet ne peut pas avoir à la fois Source et un contenu. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType attend un littéral de chaîne, une balise {{x:Type}} ou {{x:Nul}l}. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType attend un littéral de chaîne, une balise {{x:Type}} ou {{x:Null}}. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.it.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.it.resx index 8648543cc726..52a2005ecd45 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.it.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.it.resx @@ -232,7 +232,7 @@ 0 is a type name - Con x:DataType è previsto un valore letterale stringa, un markup {{x:Type}} oppure {{x:Nul}l}. + Con x:DataType è previsto un valore letterale stringa, un markup {{x:Type}} oppure {{x:Null}}. Il prefisso xmlns "{0}" non è dichiarato. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.it.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.it.xlf index c43809468668..f912c2c74af4 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.it.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.it.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. Un elemento StyleSheet non può includere sia un elemento Source che contenuto. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - Con x:DataType è previsto un valore letterale stringa, un markup {{x:Type}} oppure {{x:Nul}l}. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + Con x:DataType è previsto un valore letterale stringa, un markup {{x:Type}} oppure {{x:Null}}. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ja.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ja.resx index ec5c7e2fcb48..0a13067bb8b7 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ja.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ja.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType には、文字列リテラル、{{x:Type}} マークアップ、または {{x:Nul}l} を指定する必要があります。 + x:DataType には、文字列リテラル、{{x:Type}} マークアップ、または {{x:Null}} を指定する必要があります。 宣言されていない xmlns プレフィックス "{0}" です。 diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ja.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ja.xlf index 6cb313abae99..49ade821c141 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ja.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ja.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. スタイルシートにソースとコンテンツの両方を含めることはできません。 @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType には、文字列リテラル、{{x:Type}} マークアップ、または {{x:Nul}l} を指定する必要があります。 + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType には、文字列リテラル、{{x:Type}} マークアップ、または {{x:Null}} を指定する必要があります。 diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ko.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ko.resx index 7dfd7de990ca..db6bb7d25bdf 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ko.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ko.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType에는 {{x:Type}} 태그 또는 {{x:Nul}l} 문자열 리터럴이 필요합니다. + x:DataType에는 {{x:Type}} 태그 또는 {{x:Null}} 문자열 리터럴이 필요합니다. 선언되지 않은 xmlns 접두사 "{0}"입니다. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ko.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ko.xlf index 91d664cd0a01..0337c609d5dc 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ko.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ko.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. 스타일 시트는 소스와 콘텐츠 중 하나만 포함할 수 있습니다. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType에는 {{x:Type}} 태그 또는 {{x:Nul}l} 문자열 리터럴이 필요합니다. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType에는 {{x:Type}} 태그 또는 {{x:Null}} 문자열 리터럴이 필요합니다. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pl.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pl.resx index e4a2cd6851bd..41f371ed3a59 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pl.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pl.resx @@ -232,7 +232,7 @@ 0 is a type name - Argument x:DataType oczekuje literału ciągu, znacznika {{x:Type}} lub {{x:Nul}l}. + Argument x:DataType oczekuje literału ciągu, znacznika {{x:Type}} lub {{x:Null}}. Niezadeklarowany prefiks xmlns „{0}”. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pl.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pl.xlf index d20887f84b42..4d7fb96464d9 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pl.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pl.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. Arkusz stylów nie może mieć zarówno źródła, jak i zawartości. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - Argument x:DataType oczekuje literału ciągu, znacznika {{x:Type}} lub {{x:Nul}l}. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + Argument x:DataType oczekuje literału ciągu, znacznika {{x:Type}} lub {{x:Null}}. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pt-BR.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pt-BR.resx index c27097e3c9f9..3e7fbc849da2 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pt-BR.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pt-BR.resx @@ -232,7 +232,7 @@ 0 is a type name - O x:DataType espera um literal de cadeia de caracteres, uma marcação {{x:Type}} ou um {{x:Nul}l}. + O x:DataType espera um literal de cadeia de caracteres, uma marcação {{x:Type}} ou um {{x:Null}}. Prefixo xmlns não declarado "{0}". diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pt-BR.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pt-BR.xlf index a3d8e626569a..77f0db8aa8ce 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pt-BR.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.pt-BR.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. A StyleSheet não pode ter uma Origem e também um conteúdo. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - O x:DataType espera um literal de cadeia de caracteres, uma marcação {{x:Type}} ou um {{x:Nul}l}. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + O x:DataType espera um literal de cadeia de caracteres, uma marcação {{x:Type}} ou um {{x:Null}}. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ru.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ru.resx index 5f57347ec0ab..b855ab08c224 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ru.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ru.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType ожидает строковый литерал, разметку {{x:Type}} или {{x:Nul}l}. + x:DataType ожидает строковый литерал, разметку {{x:Type}} или {{x:Null}}. Необъявленный префикс xmlns "{0}". diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ru.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ru.xlf index a556605f7e00..cc12599b2aaf 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ru.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.ru.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. Таблица стилей (StyleSheet) не может одновременно содержать источник (Source) и содержимое. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType ожидает строковый литерал, разметку {{x:Type}} или {{x:Nul}l}. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType ожидает строковый литерал, разметку {{x:Type}} или {{x:Null}}. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.tr.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.tr.resx index 0847f628082c..50b9144290e7 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.tr.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.tr.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType için bir dize sabit değeri, {{x:Type}} işaretlemesi veya {{x:Nul}l} bekleniyor. + x:DataType için bir dize sabit değeri, {{x:Type}} işaretlemesi veya {{x:Null}} bekleniyor. "{0}" xmlns ön eki bildirilmedi. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.tr.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.tr.xlf index e1eca33056a3..9af1cf8f24f5 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.tr.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.tr.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. StyleSheet, hem Source hem de içerik bulunduramaz. @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType için bir dize sabit değeri, {{x:Type}} işaretlemesi veya {{x:Nul}l} bekleniyor. + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType için bir dize sabit değeri, {{x:Type}} işaretlemesi veya {{x:Null}} bekleniyor. diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hans.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hans.resx index b4cf88160d17..e3708633dd31 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hans.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hans.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType 需要字符串文本、{{x:Type}} 标记或 {{x:Nul}l}。 + x:DataType 需要字符串文本、{{x:Type}} 标记或 {{x:Null}}。 xmlns 前缀“{0}”未经过声明。 diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hans.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hans.xlf index 0ed5bcfa3227..3c75ee388f75 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hans.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hans.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. 样式表不能同时具有源和内容。 @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType 需要字符串文本、{{x:Type}} 标记或 {{x:Nul}l}。 + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType 需要字符串文本、{{x:Type}} 标记或 {{x:Null}}。 diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hant.resx b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hant.resx index 5eb7d3939e92..519ff5b5cef6 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hant.resx +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hant.resx @@ -232,7 +232,7 @@ 0 is a type name - x:DataType 需要字串常值、{{x:Type}} 標記或 {{x:Nul}l}。 + x:DataType 需要字串常值、{{x:Type}} 標記或 {{x:Null}}。 未宣告的 xmlns 前置詞 "{0}"。 diff --git a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hant.xlf b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hant.xlf index 38e5bd1dc7f4..d22fa5b1ebf3 100644 --- a/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hant.xlf +++ b/src/Controls/src/Build.Tasks/xlf/ErrorMessages.zh-Hant.xlf @@ -143,7 +143,7 @@ - StyleSheet can not have both a Source and a content. + StyleSheet cannot have both a Source and a content. 樣式表不能同時有來源和內容。 @@ -158,8 +158,8 @@ 0 is a type name - x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}. - x:DataType 需要字串常值、{{x:Type}} 標記或 {{x:Nul}l}。 + x:DataType expects a string literal, an {{x:Type}} markup or {{x:Null}}. + x:DataType 需要字串常值、{{x:Type}} 標記或 {{x:Null}}。 diff --git a/src/Controls/src/Core/AppThemeBinding.cs b/src/Controls/src/Core/AppThemeBinding.cs index 15daeacce5cf..fe85f6a67bcc 100644 --- a/src/Controls/src/Core/AppThemeBinding.cs +++ b/src/Controls/src/Core/AppThemeBinding.cs @@ -107,7 +107,7 @@ void Set() target.SetDynamicResource(_targetProperty, dynamicResource.Key, specificity); else { - if (!BindingExpression.TryConvert(ref value, _targetProperty, _targetProperty.ReturnType, true)) + if (!BindingExpressionHelper.TryConvert(ref value, _targetProperty, _targetProperty.ReturnType, true)) { BindingDiagnostics.SendBindingFailure(this, null, target, _targetProperty, "AppThemeBinding", BindingExpression.CannotConvertTypeErrorMessage, value, _targetProperty.ReturnType); return; diff --git a/src/Controls/src/Core/Application/Application.Mapper.cs b/src/Controls/src/Core/Application/Application.Mapper.cs index 193eeb402091..e67bb20e1151 100644 --- a/src/Controls/src/Core/Application/Application.Mapper.cs +++ b/src/Controls/src/Core/Application/Application.Mapper.cs @@ -6,10 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class Application { - [Obsolete("Use ApplicationHandler.Mapper instead.")] - public static IPropertyMapper ControlsApplicationMapper = - new ControlsMapper(ApplicationHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.Application legacy behaviors diff --git a/src/Controls/src/Core/Application/Application.cs b/src/Controls/src/Core/Application/Application.cs index 4d0c7d73c0b3..ae9524897d65 100644 --- a/src/Controls/src/Core/Application/Application.cs +++ b/src/Controls/src/Core/Application/Application.cs @@ -85,6 +85,7 @@ public IAppLinks AppLinks /// public Page? MainPage { + [Obsolete("This property has been deprecated. For single-window applications, use Windows[0].Page. For multi-window applications, identify and use the appropriate Window object to access the desired Page. Additionally, each element features a Window property, accessible when it's part of the current window.")] get { if (Windows.Count == 0) @@ -92,6 +93,7 @@ public Page? MainPage return Windows[0].Page; } + [Obsolete("This property is deprecated. Initialize your application by overriding Application.CreateWindow rather than setting MainPage. To modify the root page in an active application, use Windows[0].Page for applications with a single window. For applications with multiple windows, use Application.Windows to identify and update the root page on the correct window. Additionally, each element features a Window property, accessible when it's part of the current window.")] set { if (MainPage == value) @@ -454,7 +456,9 @@ IWindow IApplication.CreateWindow(IActivationState? activationState) void IApplication.OpenWindow(IWindow window) { if (window is Window cwindow) + { OpenWindow(cwindow); + } } void IApplication.CloseWindow(IWindow window) @@ -462,6 +466,14 @@ void IApplication.CloseWindow(IWindow window) Handler?.Invoke(nameof(IApplication.CloseWindow), window); } + void IApplication.ActivateWindow(IWindow window) + { + if (window is Window cwindow) + { + ActivateWindow(cwindow); + } + } + internal void RemoveWindow(Window window) { // Do not attempt to close the "MainPage" window @@ -501,6 +513,11 @@ public virtual void CloseWindow(Window window) Handler?.Invoke(nameof(IApplication.CloseWindow), window); } + public virtual void ActivateWindow(Window window) + { + Handler?.Invoke(nameof(IApplication.ActivateWindow), window); + } + void IApplication.ThemeChanged() { PlatformAppTheme = AppInfo.RequestedTheme; @@ -514,7 +531,9 @@ protected virtual Window CreateWindow(IActivationState? activationState) return window; if (Windows.Count > 1) +#pragma warning disable CS0618 // Type or member is obsolete throw new NotImplementedException($"Either set {nameof(MainPage)} or override {nameof(Application.CreateWindow)}."); +#pragma warning restore CS0618 // Type or member is obsolete if (Windows.Count > 0) return Windows[0]; @@ -522,7 +541,9 @@ protected virtual Window CreateWindow(IActivationState? activationState) if (_singleWindowMainPage is not null) return new Window(_singleWindowMainPage); +#pragma warning disable CS0618 // Type or member is obsolete throw new NotImplementedException($"Either set {nameof(MainPage)} or override {nameof(Application.CreateWindow)}."); +#pragma warning restore CS0618 // Type or member is obsolete } internal void AddWindow(Window window) diff --git a/src/Controls/src/Core/BindableLayout/BindableLayout.cs b/src/Controls/src/Core/BindableLayout/BindableLayout.cs index 3ee825380163..7e7a50c20d23 100644 --- a/src/Controls/src/Core/BindableLayout/BindableLayout.cs +++ b/src/Controls/src/Core/BindableLayout/BindableLayout.cs @@ -232,7 +232,7 @@ static void SetBindableLayoutTemplate(BindableObject b, DataTemplate value) static readonly DataTemplate DefaultItemTemplate = new DataTemplate(() => { var label = new Label { HorizontalTextAlignment = TextAlignment.Center }; - label.SetBinding(Label.TextProperty, "."); + label.SetBinding(Label.TextProperty, static (object o) => o); return label; }); diff --git a/src/Controls/src/Core/BindableObject.cs b/src/Controls/src/Core/BindableObject.cs index 7bdb15610463..4d4dc99fdac2 100644 --- a/src/Controls/src/Core/BindableObject.cs +++ b/src/Controls/src/Core/BindableObject.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using Microsoft.Extensions.Logging; @@ -15,6 +16,7 @@ namespace Microsoft.Maui.Controls /// Provides a mechanism to propagate data changes from one object to another. Enables validation, type coercion, and an event system. /// /// The class provides a data storage mechanism that enables the application developer to synchronize data between objects in response to changes, for example, between the View and View Model in the MVVM design pattern. All of the visual elements in the Microsoft.Maui.Controls namespace inherit from class, so they can all be used to bind the data behind their user interface. + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)] public abstract class BindableObject : INotifyPropertyChanged, IDynamicResourceHandler { IDispatcher _dispatcher; @@ -35,6 +37,8 @@ public BindableObject() _dispatcher = Dispatching.Dispatcher.GetForCurrentThread(); } + internal ushort _triggerCount = 0; + internal Dictionary _triggerSpecificity = new Dictionary(); readonly Dictionary _properties = new Dictionary(4); bool _applying; WeakReference _inheritedContext; @@ -126,8 +130,9 @@ void ClearValueCore(BindableProperty property, SetterSpecificity specificity) var original = bpcontext.Values.GetSpecificityAndValue(); if (original.Key == SetterSpecificity.FromHandler) + { bpcontext.Values.Remove(SetterSpecificity.FromHandler); - + } var newValue = bpcontext.Values.GetClearedValue(specificity); var changed = !Equals(original.Value, newValue); @@ -142,12 +147,8 @@ void ClearValueCore(BindableProperty property, SetterSpecificity specificity) //there's some side effect implemented in CoerceValue (see IsEnabled) that we need to trigger here if (property.CoerceValue != null) property.CoerceValue(this, newValue); - - if (changed) - { - OnPropertyChanged(property.PropertyName); - property.PropertyChanged?.Invoke(this, original.Value, newValue); - } + + OnBindablePropertySet(property, original.Value, newValue, changed, changed); } /// @@ -168,7 +169,7 @@ public object GetValue(BindableProperty property) var context = property.DefaultValueCreator != null ? GetOrCreateContext(property) : GetContext(property); - return context == null ? property.DefaultValue : context.Values.GetSpecificityAndValue().Value; + return context == null ? property.DefaultValue : context.Values.GetValue(); } internal LocalValueEnumerator GetLocalValueEnumerator() => new LocalValueEnumerator(this); @@ -185,7 +186,7 @@ public bool MoveNext() { if (_propertiesEnumerator.MoveNext()) { - Current = new LocalValueEntry(_propertiesEnumerator.Current.Key, _propertiesEnumerator.Current.Value.Values.GetSpecificityAndValue().Value, _propertiesEnumerator.Current.Value.Attributes); + Current = new LocalValueEntry(_propertiesEnumerator.Current.Key, _propertiesEnumerator.Current.Value.Values.GetValue(), _propertiesEnumerator.Current.Value.Attributes); return true; } return false; @@ -224,7 +225,7 @@ internal LocalValueEntry(BindableProperty property, object value, BindableContex if (properties.TryGetValue(propArray[i], out var context)) { var pair = context.Values.GetSpecificityAndValue(); - resultArray[i].IsSet = pair.Key.CompareTo(SetterSpecificity.DefaultValue) != 0; + resultArray[i].IsSet = pair.Key != SetterSpecificity.DefaultValue; resultArray[i].Value = (T)pair.Value; } else @@ -250,7 +251,7 @@ public bool IsSet(BindableProperty targetProperty) return false; if ((bpcontext.Attributes & BindableContextAttributes.IsDefaultValueCreated) == BindableContextAttributes.IsDefaultValueCreated) return true; - return bpcontext.Values.GetSpecificityAndValue().Key.CompareTo(SetterSpecificity.DefaultValue) != 0; + return bpcontext.Values.GetSpecificity() != SetterSpecificity.DefaultValue; } @@ -266,7 +267,7 @@ public void RemoveBinding(BindableProperty property) var specificity = SetterSpecificity.FromBinding; if (context != null && context.Bindings.Count > 0) - specificity = context.Bindings.Last().Key; + specificity = context.Bindings.GetSpecificity(); RemoveBinding(property, specificity); } @@ -301,23 +302,25 @@ internal void SetBinding(BindableProperty targetProperty, BindingBase binding, S var context = GetOrCreateContext(targetProperty); //if the value is manually set (has highest specificity than FromBinding), we reassign the specificity so it'll get replaced when the binding is applied - var kvp = context.Values.GetSpecificityAndValue(); - if (kvp.Key.CompareTo(SetterSpecificity.FromBinding) > 0) + var currentSpecificity = context.Values.GetSpecificity(); + if (currentSpecificity > SetterSpecificity.FromBinding) { - context.Values.Remove(kvp.Key); - context.Values[SetterSpecificity.FromBinding] = kvp.Value; + var currentValue = context.Values.GetValue(); + + context.Values.Remove(currentSpecificity); + context.Values[SetterSpecificity.FromBinding] = currentValue; } BindingBase oldBinding = null; SetterSpecificity oldSpecificity = default; if (context.Bindings.Count > 0) { - var b_p = context.Bindings.Last(); + var b_p = context.Bindings.GetSpecificityAndValue(); oldSpecificity = b_p.Key; oldBinding = b_p.Value; } - if (oldBinding != null && specificity.CompareTo(oldSpecificity) < 0) + if (oldBinding != null && specificity < oldSpecificity) { context.Bindings[specificity] = binding; return; @@ -343,13 +346,13 @@ public static void SetInheritedBindingContext(BindableObject bindable, object va { // I wonder if we couldn't treat BindingContext with specificities BindablePropertyContext bpContext = bindable.GetContext(BindingContextProperty); - if (bpContext != null && bpContext.Values.GetSpecificityAndValue().Key.CompareTo(SetterSpecificity.ManualValueSetter) >= 0) + if (bpContext != null && bpContext.Values.GetSpecificity() >= SetterSpecificity.ManualValueSetter) return; if (ReferenceEquals(bindable._inheritedContext?.Target, value)) return; - var binding = bpContext?.Bindings.Values.LastOrDefault(); + var binding = bpContext?.Bindings.GetValue(); if (binding != null) { @@ -372,7 +375,7 @@ public static void SetInheritedBindingContext(BindableObject bindable, object va protected void ApplyBindings() { BindablePropertyContext bpContext = GetContext(BindingContextProperty); - var binding = bpContext?.Bindings.Values.LastOrDefault(); + var binding = bpContext?.Bindings.GetValue(); if (binding != null) { ApplyBinding(bpContext, fromBindingContextChanged: false); @@ -417,7 +420,7 @@ protected virtual void OnPropertyChanging([CallerMemberName] string propertyName protected void UnapplyBindings() { foreach (var context in _properties.Values) - context.Bindings.Values.LastOrDefault()?.Unapply(); + context.Bindings.GetValue()?.Unapply(); } internal bool GetIsBound(BindableProperty targetProperty) @@ -605,21 +608,20 @@ internal void SetValueCore(BindableProperty property, object value, SetValueFlag void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes, SetterSpecificity specificity, bool silent = false) { - var pair = context.Values.GetSpecificityAndValue(); - var original = pair.Value; - var originalSpecificity = pair.Key; + var specificityAndValue = context.Values.GetSpecificityAndValue(); + var original = specificityAndValue.Value; + var originalSpecificity = specificityAndValue.Key; //if the last value was set from handler, override it if (specificity != SetterSpecificity.FromHandler && originalSpecificity == SetterSpecificity.FromHandler) { context.Values.Remove(SetterSpecificity.FromHandler); - pair = context.Values.GetSpecificityAndValue(); - originalSpecificity = pair.Key; + originalSpecificity = context.Values.GetSpecificity(); } //We keep setter of lower specificity so we can unapply - if (specificity.CompareTo(originalSpecificity) < 0) + if (specificity < originalSpecificity) { context.Values[specificity] = value; return; @@ -628,8 +630,8 @@ void SetValueActual(BindableProperty property, BindablePropertyContext context, bool raiseOnEqual = (attributes & SetValueFlags.RaiseOnEqual) != 0; bool clearDynamicResources = (attributes & SetValueFlags.ClearDynamicResource) != 0; - bool clearOneWayBindings = (attributes & SetValueFlags.ClearOneWayBindings) != 0 && specificity != SetterSpecificity.FromHandler; - bool clearTwoWayBindings = (attributes & SetValueFlags.ClearTwoWayBindings) != 0 && specificity != SetterSpecificity.FromHandler; + // bool clearOneWayBindings = (attributes & SetValueFlags.ClearOneWayBindings) != 0 && specificity != SetterSpecificity.FromHandler; + // bool clearTwoWayBindings = (attributes & SetValueFlags.ClearTwoWayBindings) != 0 && specificity != SetterSpecificity.FromHandler; bool sameValue = ReferenceEquals(context.Property, BindingContextProperty) ? ReferenceEquals(value, original) : Equals(value, original); if (!silent && (!sameValue || raiseOnEqual)) @@ -646,7 +648,7 @@ void SetValueActual(BindableProperty property, BindablePropertyContext context, if ((context.Attributes & BindableContextAttributes.IsDynamicResource) != 0 && clearDynamicResources) RemoveDynamicResource(property); - BindingBase binding = context.Bindings.Values.LastOrDefault(); + BindingBase binding = context.Bindings.GetValue(); if (!silent && (!sameValue || raiseOnEqual)) { @@ -656,9 +658,20 @@ void SetValueActual(BindableProperty property, BindablePropertyContext context, binding.Apply(true); _applying = false; } + + OnBindablePropertySet(property, original, value, !sameValue, true); + } + else + { + OnBindablePropertySet(property, original, value, !sameValue, false); + } + } + private protected virtual void OnBindablePropertySet(BindableProperty property, object original, object value, bool didChange, bool willFirePropertyChanged) + { + if(willFirePropertyChanged) + { OnPropertyChanged(property.PropertyName); - property.PropertyChanged?.Invoke(this, original, value); } } @@ -689,7 +702,7 @@ void ApplyBinding(BindablePropertyContext context, bool fromBindingContextChange return; } - var kvp = bindings.LastOrDefault(); + var kvp = bindings.GetSpecificityAndValue(); var binding = kvp.Value; if (binding == null) @@ -726,7 +739,7 @@ BindablePropertyContext CreateAndAddContext(BindableProperty property) { var defaultValueCreator = property.DefaultValueCreator; var context = new BindablePropertyContext { Property = property }; - context.Values.SetValue(SetterSpecificity.DefaultValue, defaultValueCreator != null ? defaultValueCreator(this) : property.DefaultValue); + context.Values[SetterSpecificity.DefaultValue] = defaultValueCreator != null ? defaultValueCreator(this) : property.DefaultValue; if (defaultValueCreator != null) context.Attributes = BindableContextAttributes.IsDefaultValueCreated; @@ -748,7 +761,7 @@ void RemoveBinding(BindableProperty property, BindablePropertyContext context, S if (count == 0) return; //used to fail; - var currentbinding = context.Bindings.Values.Last(); + var currentbinding = context.Bindings.GetValue(); var binding = context.Bindings[specificity]; var isCurrent = binding == currentbinding; @@ -758,11 +771,11 @@ void RemoveBinding(BindableProperty property, BindablePropertyContext context, S currentbinding = null; if (count > 1) - currentbinding = context.Bindings.Values.ElementAt(count - 2); + currentbinding = context.Bindings.GetClearedValue(); property.BindingChanging?.Invoke(this, binding, currentbinding); - currentbinding?.Apply(BindingContext, this, property, false, context.Bindings.Keys.ElementAt(count - 2)); + currentbinding?.Apply(BindingContext, this, property, false, context.Bindings.GetClearedSpecificity()); } context.Bindings.Remove(specificity); @@ -808,7 +821,7 @@ void CoerceValue(BindableProperty property, bool checkAccess) if (bpcontext == null) return; - object currentValue = bpcontext.Values.GetSpecificityAndValue().Value; + object currentValue = bpcontext.Values.GetValue(); if (property.ValidateValue != null && !property.ValidateValue(this, currentValue)) throw new ArgumentException($"Value is an invalid value for {property.PropertyName}", nameof(currentValue)); @@ -830,11 +843,11 @@ internal sealed class BindablePropertyContext { public BindableContextAttributes Attributes; - public SortedList Bindings = new(); + public SetterSpecificityList Bindings = new(); public Queue DelayedSetters; public BindableProperty Property; - public readonly SetterSpecificityList Values = new(); + public readonly SetterSpecificityList Values = new(3); } diff --git a/src/Controls/src/Core/BindableObjectExtensions.cs b/src/Controls/src/Core/BindableObjectExtensions.cs index 2e1542542a87..668bde3aa9b5 100644 --- a/src/Controls/src/Core/BindableObjectExtensions.cs +++ b/src/Controls/src/Core/BindableObjectExtensions.cs @@ -1,6 +1,8 @@ #nullable disable using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.ComponentModel; using System.Linq; using Microsoft.Maui.Graphics; @@ -14,7 +16,7 @@ internal static void RefreshPropertyValue(this BindableObject self, BindableProp var ctx = self.GetContext(property); if (ctx != null && ctx.Bindings.Count > 0) { - var binding = ctx.Bindings.Last().Value; + var binding = ctx.Bindings.GetValue(); // support bound properties if (!ctx.Attributes.HasFlag(BindableObject.BindableContextAttributes.IsBeingSet)) @@ -48,6 +50,7 @@ internal static void PropagateBindingContext(this BindableObject self, IEnume } /// + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public static void SetBinding(this BindableObject self, BindableProperty targetProperty, string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null, string stringFormat = null) { @@ -60,6 +63,90 @@ public static void SetBinding(this BindableObject self, BindableProperty targetP self.SetBinding(targetProperty, binding); } +#nullable enable + /// + /// Creates a binding between a property on the source object and a property on the target object. + /// + /// + /// The following example illustrates the setting of a binding using the extension method. + /// + /// vm.Name); + /// label.BindingContext = vm; + /// + /// vm.Name = "Jane Doe"; + /// Debug.WriteLine(label.Text); // prints "Jane Doe" + /// ]]> + /// + /// Not all methods can be used to define a binding. The expression must be a simple property access expression. The following are examples of valid and invalid expressions: + /// + /// vm.Name; + /// static (PersonViewModel vm) => vm.Address?.Street; + /// + /// // Valid: Array and indexer access + /// static (PersonViewModel vm) => vm.PhoneNumbers[0]; + /// static (PersonViewModel vm) => vm.Config["Font"]; + /// + /// // Valid: Casts + /// static (Label label) => (label.BindingContext as PersonViewModel).Name; + /// static (Label label) => ((PersonViewModel)label.BindingContext).Name; + /// + /// // Invalid: Method calls + /// static (PersonViewModel vm) => vm.GetAddress(); + /// static (PersonViewModel vm) => vm.Address?.ToString(); + /// + /// // Invalid: Complex expressions + /// static (PersonViewModel vm) => vm.Address?.Street + " " + vm.Address?.City; + /// static (PersonViewModel vm) => $"Name: {vm.Name}"; + /// ]]> + /// + /// + /// The source type. + /// The property type. + /// The . + /// The on which to set a binding. + /// An getter method used to retrieve the source property. + /// The binding mode. This property is optional. Default is . + /// The converter. This parameter is optional. Default is . + /// An user-defined parameter to pass to the converter. This parameter is optional. Default is . + /// A String format. This parameter is optional. Default is . + /// An object used as the source for this binding. This parameter is optional. Default is . + /// The value to use instead of the default value for the property, if no specified value exists. + /// The value to supply for a bound property when the target of the binding is . + /// + public static void SetBinding( + this BindableObject self, + BindableProperty targetProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + if (!RuntimeFeature.AreBindingInterceptorsSupported) + { + throw new InvalidOperationException($"Call to SetBinding<{typeof(TSource)}, {typeof(TProperty)}> could not be intercepted because the feature has been disabled. Consider removing the DisableMauiAnalyzers property from your project file or set the _MauiBindingInterceptorsSupport property to true instead."); + } + + throw new InvalidOperationException($"Call to SetBinding<{typeof(TSource)}, {typeof(TProperty)}> was not intercepted."); + } +#nullable disable + public static T GetPropertyIfSet(this BindableObject bindableObject, BindableProperty bindableProperty, T returnIfNotSet) { if (bindableObject == null) diff --git a/src/Controls/src/Core/BindableProperty.cs b/src/Controls/src/Core/BindableProperty.cs index 51160490afd1..adfc7d020109 100644 --- a/src/Controls/src/Core/BindableProperty.cs +++ b/src/Controls/src/Core/BindableProperty.cs @@ -40,7 +40,7 @@ public sealed class BindableProperty public delegate bool ValidateValueDelegate(BindableObject bindable, TPropertyType value); - static readonly Dictionary KnownTypeConverters = new Dictionary + internal static readonly Dictionary KnownTypeConverters = new Dictionary { { typeof(Uri), new UriTypeConverter() }, { typeof(Easing), new Maui.Converters.EasingTypeConverter() }, @@ -48,14 +48,14 @@ public sealed class BindableProperty { typeof(ImageSource), new ImageSourceConverter() } }; - static readonly Dictionary KnownIValueConverters = new Dictionary + internal static readonly Dictionary KnownIValueConverters = new Dictionary { { typeof(string), new ToStringValueConverter() }, }; // more or less the encoding of this, without the need to reflect // http://msdn.microsoft.com/en-us/library/y5b434w4.aspx - static readonly Dictionary SimpleConvertTypes = new Dictionary + internal static readonly Dictionary SimpleConvertTypes = new Dictionary { { typeof(sbyte), new[] { typeof(string), typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } }, { typeof(byte), new[] { typeof(string), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } }, @@ -232,24 +232,10 @@ internal bool TryConvert(ref object value) if (returnType.IsAssignableFrom(valueType)) return true; - // Don't look for implicit conversion operators on BCL-types - if (ShouldCheckForImplicitConversionOperator(returnType)) + if (TypeConversionHelper.TryConvert(value, returnType, out var convertedValue)) { - var cast = returnType.GetImplicitConversionOperator(fromType: valueType, toType: returnType); - if (cast != null) - { - value = cast.Invoke(null, [value]); - return true; - } - } - if (ShouldCheckForImplicitConversionOperator(valueType)) - { - var cast = valueType.GetImplicitConversionOperator(fromType: valueType, toType: returnType); - if (cast != null) - { - value = cast.Invoke(null, [value]); - return true; - } + value = convertedValue; + return true; } if (KnownIValueConverters.TryGetValue(returnType, out IValueConverter valueConverter)) { @@ -260,9 +246,6 @@ internal bool TryConvert(ref object value) return false; } - static bool ShouldCheckForImplicitConversionOperator(Type type) => - type != typeof(string) && !SimpleConvertTypes.ContainsKey(type); - internal delegate void BindablePropertyBindingChanging(BindableObject bindable, BindingBase oldValue, BindingBase newValue); } } diff --git a/src/Controls/src/Core/BindablePropertyConverter.cs b/src/Controls/src/Core/BindablePropertyConverter.cs index b2b875aae5e9..3e258086d467 100644 --- a/src/Controls/src/Core/BindablePropertyConverter.cs +++ b/src/Controls/src/Core/BindablePropertyConverter.cs @@ -1,12 +1,12 @@ #nullable disable using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; using System.Xml; using Microsoft.Extensions.Logging; -using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Xaml; namespace Microsoft.Maui.Controls @@ -90,23 +90,40 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning($"Can't resolve {value}. Accepted syntax is Type.PropertyName."); return null; } - Type type = Type.GetType("Microsoft.Maui.Controls." + parts[0]); + Type type = GetControlType(parts[0]); return ConvertFrom(type, parts[1], null); } BindableProperty ConvertFrom(Type type, string propertyName, IXmlLineInfo lineinfo) { - string name = propertyName + "Property"; - FieldInfo bpinfo = type.GetField(fi => fi.Name == name && fi.IsStatic && fi.IsPublic && fi.FieldType == typeof(BindableProperty)); - if (bpinfo == null) + var name = propertyName + "Property"; + FieldInfo bpinfo = GetPropertyField(type, name); + if (bpinfo == null || bpinfo.FieldType != typeof(BindableProperty)) throw new XamlParseException($"Can't resolve {name} on {type.Name}", lineinfo); var bp = bpinfo.GetValue(null) as BindableProperty; - var isObsolete = bpinfo.GetCustomAttribute() != null; + var isObsolete = GetObsoleteAttribute(bpinfo) != null; if (bp.PropertyName != propertyName && !isObsolete) throw new XamlParseException($"The PropertyName of {type.Name}.{name} is not {propertyName}", lineinfo); return bp; } + [UnconditionalSuppressMessage("TrimAnalysis", "IL2045:AttributeRemoval", + Justification = "ObsoleteAttribute instances are removed by the trimmer in production builds.")] + static ObsoleteAttribute GetObsoleteAttribute(FieldInfo fieldInfo) + => fieldInfo.GetCustomAttribute(); + + [UnconditionalSuppressMessage("TrimAnalysis", "IL2057:TypeGetType", + Justification = "The converter is only used when parsing XAML at runtime. The developer will receive a warning " + + "saying that parsing XAML at runtime may not work as expected when trimming.")] + static Type GetControlType(string typeName) + => Type.GetType("Microsoft.Maui.Controls." + typeName); + + [UnconditionalSuppressMessage("TrimAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "The converter is only used when parsing XAML at runtime. The developer will receive a warning " + + "saying that parsing XAML at runtime may not work as expected when trimming.")] + static FieldInfo GetPropertyField(Type type, string fieldName) + => type.GetField(fieldName, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + Type FindTypeForVisualState(IProvideParentValues parentValueProvider, IXmlLineInfo lineInfo) { var parents = parentValueProvider.ParentObjects.ToList(); diff --git a/src/Controls/src/Core/Binding.cs b/src/Controls/src/Core/Binding.cs index bba97b4800d4..80810bc64f10 100644 --- a/src/Controls/src/Core/Binding.cs +++ b/src/Controls/src/Core/Binding.cs @@ -1,14 +1,14 @@ #nullable disable using System; -using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Globalization; -using System.Reflection; using Microsoft.Maui.Controls.Xaml.Diagnostics; namespace Microsoft.Maui.Controls { /// + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public sealed class Binding : BindingBase { public const string SelfPath = "."; @@ -92,7 +92,7 @@ public object Source } /// - public static readonly object DoNothing = new object(); + public static readonly object DoNothing = MultiBinding.DoNothing; // the instance was moved to MultiBinding because the Binding class is annotated with [RequiresUnreferencedCode] /// [EditorBrowsable(EditorBrowsableState.Never)] @@ -124,10 +124,16 @@ internal override void Apply(object context, BindableObject bindObj, BindablePro var isApplied = IsApplied; var bindingContext = src ?? Context ?? context; - if (DataType != null && bindingContext != null && !DataType.IsAssignableFrom(bindingContext.GetType())) + + // Do not check type mismatch if this is a binding with Source and compilation of bindings with Source is disabled + bool skipTypeMismatchCheck = Source is not null && !RuntimeFeature.IsXamlCBindingWithSourceCompilationEnabled; + if (!skipTypeMismatchCheck) { - BindingDiagnostics.SendBindingFailure(this, "Binding", "Mismatch between the specified x:DataType and the current binding context"); - bindingContext = null; + if (DataType != null && bindingContext != null && !DataType.IsAssignableFrom(bindingContext.GetType())) + { + BindingDiagnostics.SendBindingFailure(this, "Binding", $"Mismatch between the specified x:DataType ({DataType}) and the current binding context ({bindingContext.GetType()})."); + bindingContext = null; + } } base.Apply(bindingContext, bindObj, targetProperty, fromBindingContextChanged, specificity); @@ -135,9 +141,19 @@ internal override void Apply(object context, BindableObject bindObj, BindablePro if (src != null && isApplied && fromBindingContextChanged) return; - if (Source is RelativeBindingSource) + if (Source is RelativeBindingSource relativeBindingSource) { - ApplyRelativeSourceBinding(bindObj, targetProperty, specificity); + var relativeSourceTarget = RelativeSourceTargetOverride ?? bindObj as Element; + if (relativeSourceTarget is not Element) + { + var message = bindObj is not null + ? $"Cannot apply relative binding to {bindObj.GetType().FullName} because it is not a superclass of Element." + : "Cannot apply relative binding when the target object is null."; + + throw new InvalidOperationException(message); + } + + ApplyRelativeSourceBinding(relativeBindingSource, relativeSourceTarget, bindObj, targetProperty, specificity); } else { @@ -148,148 +164,10 @@ internal override void Apply(object context, BindableObject bindObj, BindablePro } #pragma warning disable RECS0165 // Asynchronous methods should return a Task instead of void - async void ApplyRelativeSourceBinding( - BindableObject targetObject, - BindableProperty targetProperty, SetterSpecificity specificity) + async void ApplyRelativeSourceBinding(RelativeBindingSource relativeSource, Element relativeSourceTarget, BindableObject targetObject, BindableProperty targetProperty, SetterSpecificity specificity) #pragma warning restore RECS0165 // Asynchronous methods should return a Task instead of void { - if (!(Source is RelativeBindingSource relativeSource)) - return; - - var relativeSourceTarget = RelativeSourceTargetOverride ?? targetObject as Element; - if (!(relativeSourceTarget is Element)) - throw new InvalidOperationException(); - - object resolvedSource = null; - switch (relativeSource.Mode) - { - case RelativeBindingSourceMode.Self: - resolvedSource = relativeSourceTarget; - break; - - case RelativeBindingSourceMode.TemplatedParent: - resolvedSource = await TemplateUtilities.FindTemplatedParentAsync(relativeSourceTarget); - break; - - case RelativeBindingSourceMode.FindAncestor: - case RelativeBindingSourceMode.FindAncestorBindingContext: - ApplyAncestorTypeBinding(targetObject, relativeSourceTarget, targetProperty, specificity); - return; - - default: - throw new InvalidOperationException(); - } - - _expression.Apply(resolvedSource, targetObject, targetProperty, specificity); - } - - void ApplyAncestorTypeBinding( - BindableObject actualTarget, - Element relativeSourceTarget, - BindableProperty targetProperty, - SetterSpecificity specificity, - Element currentElement = null, - int currentLevel = 0, - List chain = null, - object lastMatchingBctx = null) - { - currentElement = currentElement ?? relativeSourceTarget; - chain = chain ?? new List { relativeSourceTarget }; - - if (!(Source is RelativeBindingSource relativeSource)) - return; - - if (currentElement.RealParent is Application || - currentElement.RealParent == null) - { - // Couldn't find the desired ancestor type in the chain, but it may be added later, - // so apply with a null source for now. - _expression.Apply(null, actualTarget, targetProperty, specificity); - _expression.SubscribeToAncestryChanges( - chain, - relativeSource.Mode == RelativeBindingSourceMode.FindAncestorBindingContext, - rootIsSource: false); - } - else if (currentElement.RealParent != null) - { - chain.Add(currentElement.RealParent); - if (ElementFitsAncestorTypeAndLevel(currentElement.RealParent, ref currentLevel, ref lastMatchingBctx)) - { - object resolvedSource; - if (relativeSource.Mode == RelativeBindingSourceMode.FindAncestor) - resolvedSource = currentElement.RealParent; - else - resolvedSource = currentElement.RealParent?.BindingContext; - _expression.Apply(resolvedSource, actualTarget, targetProperty, specificity); - _expression.SubscribeToAncestryChanges( - chain, - relativeSource.Mode == RelativeBindingSourceMode.FindAncestorBindingContext, - rootIsSource: true); - } - else - { - ApplyAncestorTypeBinding( - actualTarget, - relativeSourceTarget, - targetProperty, - specificity, - currentElement.RealParent, - currentLevel, - chain, - lastMatchingBctx); - } - } - else - { - EventHandler onElementParentSet = null; - onElementParentSet = (sender, e) => - { - currentElement.ParentSet -= onElementParentSet; - ApplyAncestorTypeBinding( - actualTarget, - relativeSourceTarget, - targetProperty, - specificity, - currentElement, - currentLevel, - chain, - lastMatchingBctx); - }; - currentElement.ParentSet += onElementParentSet; - } - } - - bool ElementFitsAncestorTypeAndLevel(Element element, ref int level, ref object lastPotentialBctx) - { - if (!(Source is RelativeBindingSource relativeSource)) - return false; - - bool fitsElementType = - relativeSource.Mode == RelativeBindingSourceMode.FindAncestor && - relativeSource.AncestorType.IsAssignableFrom(element.GetType()); - - bool fitsBindingContextType = - element.BindingContext != null && - relativeSource.Mode == RelativeBindingSourceMode.FindAncestorBindingContext && - relativeSource.AncestorType.IsAssignableFrom(element.BindingContext.GetType()); - - if (!fitsElementType && !fitsBindingContextType) - return false; - - if (fitsBindingContextType) - { - if (!object.ReferenceEquals(lastPotentialBctx, element.BindingContext)) - { - lastPotentialBctx = element.BindingContext; - level++; - } - } - else - { - level++; - } - - return level >= relativeSource.AncestorLevel; + await relativeSource.Apply(_expression, relativeSourceTarget, targetObject, targetProperty, specificity); } internal override BindingBase Clone() @@ -335,7 +213,9 @@ internal override void Unapply(bool fromBindingContextChanged = false) base.Unapply(fromBindingContextChanged: fromBindingContextChanged); if (_expression != null) + { _expression.Unapply(); + } } } -} +} \ No newline at end of file diff --git a/src/Controls/src/Core/BindingBase.Create.cs b/src/Controls/src/Core/BindingBase.Create.cs new file mode 100644 index 000000000000..70971eb91d72 --- /dev/null +++ b/src/Controls/src/Core/BindingBase.Create.cs @@ -0,0 +1,39 @@ +using System; + +namespace Microsoft.Maui.Controls +{ + partial class BindingBase + { + /// + /// This factory method was added to simplify creating TypedBindingBase instances from lambda getters. + /// + /// The source type. + /// The property type. + /// An getter method used to retrieve the source property. + /// The binding mode. This property is optional. Default is . + /// The converter. This parameter is optional. Default is . + /// An user-defined parameter to pass to the converter. This parameter is optional. Default is . + /// A String format. This parameter is optional. Default is . + /// An object used as the source for this binding. This parameter is optional. Default is . + /// The value to use instead of the default value for the property, if no specified value exists. + /// The value to supply for a bound property when the target of the binding is . + /// + public static BindingBase Create( + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + if (!RuntimeFeature.AreBindingInterceptorsSupported) + { + throw new InvalidOperationException($"Call to Create<{typeof(TSource)}, {typeof(TProperty)}> could not be intercepted because the feature has been disabled. Consider removing the DisableMauiAnalyzers property from your project file or set the _MauiBindingInterceptorsSupport property to true instead."); + } + + throw new InvalidOperationException($"Call to Create<{typeof(TSource)}, {typeof(TProperty)}>() was not intercepted."); + } + } +} diff --git a/src/Controls/src/Core/BindingBase.cs b/src/Controls/src/Core/BindingBase.cs index 6874dc331eca..e0d00af93bba 100644 --- a/src/Controls/src/Core/BindingBase.cs +++ b/src/Controls/src/Core/BindingBase.cs @@ -3,12 +3,11 @@ using System.Collections; using System.Runtime.CompilerServices; using Microsoft.Extensions.Logging; -using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls { /// - public abstract class BindingBase + public abstract partial class BindingBase { static readonly ConditionalWeakTable SynchronizedCollections = new ConditionalWeakTable(); diff --git a/src/Controls/src/Core/BindingExpression.cs b/src/Controls/src/Core/BindingExpression.cs index bb82a68c15f9..5a061f567f57 100644 --- a/src/Controls/src/Core/BindingExpression.cs +++ b/src/Controls/src/Core/BindingExpression.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; @@ -12,6 +13,7 @@ namespace Microsoft.Maui.Controls { + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] internal sealed class BindingExpression { internal const string PropertyNotFoundErrorMessage = "'{0}' property not found on '{1}', target property: '{2}.{3}'"; @@ -154,7 +156,7 @@ void ApplyCore(object sourceObject, BindableObject target, BindableProperty prop else value = Binding.FallbackValue ?? property.GetDefaultValue(target); - if (!TryConvert(ref value, property, property.ReturnType, true)) + if (!BindingExpressionHelper.TryConvert(ref value, property, property.ReturnType, true)) { BindingDiagnostics.SendBindingFailure(Binding, current, target, property, "Binding", CannotConvertTypeErrorMessage, value, property.ReturnType); return; @@ -166,7 +168,7 @@ void ApplyCore(object sourceObject, BindableObject target, BindableProperty prop { object value = Binding.GetTargetValue(target.GetValue(property), part.SetterType); - if (!TryConvert(ref value, property, part.SetterType, false)) + if (!BindingExpressionHelper.TryConvert(ref value, property, part.SetterType, false)) { BindingDiagnostics.SendBindingFailure(Binding, current, target, property, "Binding", CannotConvertTypeErrorMessage, value, part.SetterType); return; @@ -219,8 +221,8 @@ void ParsePath() int lbIndex = part.IndexOf("[", StringComparison.Ordinal); if (lbIndex != -1) { - int rbIndex = part.LastIndexOf(']'); - if (rbIndex == -1) + int rbIndex = part.Length - 1; + if (part[rbIndex] != ']') throw new FormatException("Indexer did not contain closing bracket"); int argLength = rbIndex - lbIndex - 1; @@ -326,10 +328,10 @@ void SetupPart(TypeInfo sourceType, BindingExpressionPart part) } string indexerName = "Item"; - foreach (DefaultMemberAttribute attrib in sourceType.GetCustomAttributes(typeof(DefaultMemberAttribute), true)) + var defaultMemberAttribute = (DefaultMemberAttribute)sourceType.GetCustomAttribute(typeof(DefaultMemberAttribute), true); + if (defaultMemberAttribute != null) { - indexerName = attrib.MemberName; - break; + indexerName = defaultMemberAttribute.MemberName; } part.IndexerName = indexerName; @@ -366,27 +368,31 @@ void SetupPart(TypeInfo sourceType, BindingExpressionPart part) else { TypeInfo type = sourceType; - while (type != null && property == null) + do { property = type.GetDeclaredProperty(part.Content); - type = type.BaseType?.GetTypeInfo(); - } + } while (property == null && (type = type.BaseType?.GetTypeInfo()) != null); } if (property != null) { - if (property.CanRead && property.GetMethod.IsPublic && !property.GetMethod.IsStatic) - part.LastGetter = property.GetMethod; - if (property.CanWrite && property.SetMethod.IsPublic && !property.SetMethod.IsStatic) + var propertyType = property.PropertyType; + + if (property is { CanRead: true, GetMethod: { IsPublic: true, IsStatic: false } propertyGetMethod }) + { + part.LastGetter = propertyGetMethod; + } + + if (property is {CanWrite: true, SetMethod: {IsPublic: true, IsStatic: false} propertySetMethod}) { - part.LastSetter = property.SetMethod; - part.SetterType = property.PropertyType; + part.LastSetter = propertySetMethod; + part.SetterType = propertyType; if (Binding.AllowChaining) { FieldInfo bindablePropertyField = sourceType.GetDeclaredField(part.Content + "Property"); if (bindablePropertyField != null && bindablePropertyField.FieldType == typeof(BindableProperty) && sourceType.ImplementedInterfaces.Contains(typeof(IElementController))) { - MethodInfo setValueMethod = typeof(IElementController).GetMethod("SetValueFromRenderer", new[] { typeof(BindableProperty), typeof(object) }); + MethodInfo setValueMethod = typeof(IElementController).GetMethod(nameof(IElementController.SetValueFromRenderer), new[] { typeof(BindableProperty), typeof(object) }); if (setValueMethod != null) { part.LastSetter = setValueMethod; @@ -397,11 +403,9 @@ void SetupPart(TypeInfo sourceType, BindingExpressionPart part) } } - if (property != null - && part.NextPart != null - && property.PropertyType.IsGenericType) + if (part.NextPart != null && propertyType.IsGenericType && propertyType.IsValueType) { - Type genericTypeDefinition = property.PropertyType.GetGenericTypeDefinition(); + Type genericTypeDefinition = propertyType.GetGenericTypeDefinition(); if ((genericTypeDefinition == typeof(ValueTuple<>) || genericTypeDefinition == typeof(ValueTuple<,>) || genericTypeDefinition == typeof(ValueTuple<,,>) @@ -426,54 +430,6 @@ void SetupPart(TypeInfo sourceType, BindingExpressionPart part) } } - static readonly Type[] DecimalTypes = { typeof(float), typeof(decimal), typeof(double) }; - - internal static bool TryConvert(ref object value, BindableProperty targetProperty, Type convertTo, bool toTarget) - { - if (value == null) - return !convertTo.GetTypeInfo().IsValueType || Nullable.GetUnderlyingType(convertTo) != null; - try - { - if ((toTarget && targetProperty.TryConvert(ref value)) || (!toTarget && convertTo.IsInstanceOfType(value))) - return true; - } - catch (InvalidOperationException) - { //that's what TypeConverters ususally throw - return false; - } - - object original = value; - try - { - convertTo = Nullable.GetUnderlyingType(convertTo) ?? convertTo; - - var stringValue = value as string ?? string.Empty; - // see: https://bugzilla.xamarin.com/show_bug.cgi?id=32871 - // do not canonicalize "*.[.]"; "1." should not update bound BindableProperty - if (stringValue.EndsWith(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, StringComparison.Ordinal) && DecimalTypes.Contains(convertTo)) - { - value = original; - return false; - } - - // do not canonicalize "-0"; user will likely enter a period after "-0" - if (stringValue == "-0" && DecimalTypes.Contains(convertTo)) - { - value = original; - return false; - } - - value = Convert.ChangeType(value, convertTo, CultureInfo.CurrentCulture); - - return true; - } - catch (Exception ex) when (ex is InvalidCastException || ex is FormatException || ex is InvalidOperationException || ex is OverflowException) - { - value = original; - return false; - } - } - // SubscribeToAncestryChanges, ClearAncestryChangeSubscriptions, FindAncestryIndex, and // OnElementParentSet are used with RelativeSource ancestor-type bindings, to detect when // there has been an ancestry change requiring re-applying the binding, and to minimize diff --git a/src/Controls/src/Core/BindingExpressionHelper.cs b/src/Controls/src/Core/BindingExpressionHelper.cs new file mode 100644 index 000000000000..03b510b6877e --- /dev/null +++ b/src/Controls/src/Core/BindingExpressionHelper.cs @@ -0,0 +1,58 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; + +namespace Microsoft.Maui.Controls +{ + internal static class BindingExpressionHelper + { + static readonly Type[] DecimalTypes = { typeof(float), typeof(decimal), typeof(double) }; + + internal static bool TryConvert(ref object value, BindableProperty targetProperty, Type convertTo, bool toTarget) + { + if (value == null) + return !convertTo.GetTypeInfo().IsValueType || Nullable.GetUnderlyingType(convertTo) != null; + try + { + if ((toTarget && targetProperty.TryConvert(ref value)) || (!toTarget && convertTo.IsInstanceOfType(value))) + return true; + } + catch (InvalidOperationException) + { //that's what TypeConverters ususally throw + return false; + } + + object original = value; + try + { + convertTo = Nullable.GetUnderlyingType(convertTo) ?? convertTo; + + var stringValue = value as string ?? string.Empty; + // see: https://bugzilla.xamarin.com/show_bug.cgi?id=32871 + // do not canonicalize "*.[.]"; "1." should not update bound BindableProperty + if (stringValue.EndsWith(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, StringComparison.Ordinal) && DecimalTypes.Contains(convertTo)) + { + value = original; + return false; + } + + // do not canonicalize "-0"; user will likely enter a period after "-0" + if (stringValue == "-0" && DecimalTypes.Contains(convertTo)) + { + value = original; + return false; + } + + value = Convert.ChangeType(value, convertTo, CultureInfo.CurrentCulture); + + return true; + } + catch (Exception ex) when (ex is InvalidCastException || ex is FormatException || ex is InvalidOperationException || ex is OverflowException) + { + value = original; + return false; + } + } + } +} diff --git a/src/Controls/src/Core/BoxView/BoxView.cs b/src/Controls/src/Core/BoxView/BoxView.cs index fb2d89ec0be6..26effb280f9f 100644 --- a/src/Controls/src/Core/BoxView/BoxView.cs +++ b/src/Controls/src/Core/BoxView/BoxView.cs @@ -43,6 +43,7 @@ public IPlatformElementConfiguration On() where T : IConfigPlatfo return _platformConfigurationRegistry.Value.On(); } + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { return new SizeRequest(new Size(40, 40)); diff --git a/src/Controls/src/Core/Brush/Brush.cs b/src/Controls/src/Core/Brush/Brush.cs index f76062fc8ba6..d15666be22d4 100644 --- a/src/Controls/src/Core/Brush/Brush.cs +++ b/src/Controls/src/Core/Brush/Brush.cs @@ -189,6 +189,8 @@ public static bool IsNullOrEmpty(Brush brush) static ImmutableBrush darkGray; /// Gets a of the system-defined color . public static SolidColorBrush DarkGray => darkGray ??= new(Colors.DarkGray); + /// Gets a of the system-defined color . + public static SolidColorBrush DarkGrey => DarkGray; static ImmutableBrush darkGreen; /// Gets a of the system-defined color . public static SolidColorBrush DarkGreen => darkGreen ??= new(Colors.DarkGreen); @@ -222,6 +224,8 @@ public static bool IsNullOrEmpty(Brush brush) static ImmutableBrush darkSlateGray; /// Gets a of the system-defined color . public static SolidColorBrush DarkSlateGray => darkSlateGray ??= new(Colors.DarkSlateGray); + /// Gets a of the system-defined color . + public static SolidColorBrush DarkSlateGrey => DarkSlateGray; static ImmutableBrush darkTurquoise; /// Gets a of the system-defined color . public static SolidColorBrush DarkTurquoise => darkTurquoise ??= new(Colors.DarkTurquoise); @@ -237,6 +241,8 @@ public static bool IsNullOrEmpty(Brush brush) static ImmutableBrush dimGray; /// Gets a of the system-defined color . public static SolidColorBrush DimGray => dimGray ??= new(Colors.DimGray); + /// Gets a of the system-defined color . + public static SolidColorBrush DimGrey => DimGray; static ImmutableBrush dodgerBlue; /// Gets a of the system-defined color . public static SolidColorBrush DodgerBlue => dodgerBlue ??= new(Colors.DodgerBlue); @@ -267,6 +273,8 @@ public static bool IsNullOrEmpty(Brush brush) static ImmutableBrush gray; /// Gets a of the system-defined color . public static SolidColorBrush Gray => gray ??= new(Colors.Gray); + /// Gets a of the system-defined color . + public static SolidColorBrush Grey => Gray; static ImmutableBrush green; /// Gets a of the system-defined color . public static SolidColorBrush Green => green ??= new(Colors.Green); @@ -318,6 +326,8 @@ public static bool IsNullOrEmpty(Brush brush) static ImmutableBrush lightGray; /// Gets a of the system-defined color . public static SolidColorBrush LightGray => lightGray ??= new(Colors.LightGray); + /// Gets a of the system-defined color . + public static SolidColorBrush LightGrey => LightGray; static ImmutableBrush lightGreen; /// Gets a of the system-defined color . public static SolidColorBrush LightGreen => lightGreen ??= new(Colors.LightGreen); @@ -336,6 +346,8 @@ public static bool IsNullOrEmpty(Brush brush) static ImmutableBrush lightSlateGray; /// Gets a of the system-defined color . public static SolidColorBrush LightSlateGray => lightSlateGray ??= new(Colors.LightSlateGray); + /// Gets a of the system-defined color . + public static SolidColorBrush LightSlateGrey => LightSlateGray; static ImmutableBrush lightSteelBlue; /// Gets a of the system-defined color . public static SolidColorBrush LightSteelBlue => lightSteelBlue ??= new(Colors.LightSteelBlue); @@ -492,6 +504,8 @@ public static bool IsNullOrEmpty(Brush brush) static ImmutableBrush slateGray; /// Gets a of the system-defined color . public static SolidColorBrush SlateGray => slateGray ??= new(Colors.SlateGray); + /// Gets a of the system-defined color . + public static SolidColorBrush SlateGrey => SlateGray; static ImmutableBrush snow; /// Gets a of the system-defined color . public static SolidColorBrush Snow => snow ??= new(Colors.Snow); diff --git a/src/Controls/src/Core/Brush/BrushTypeConverter.cs b/src/Controls/src/Core/Brush/BrushTypeConverter.cs index 2aaaed93dff0..e1bd56a8f48e 100644 --- a/src/Controls/src/Core/Brush/BrushTypeConverter.cs +++ b/src/Controls/src/Core/Brush/BrushTypeConverter.cs @@ -30,13 +30,24 @@ public class BrushTypeConverter : TypeConverter readonly ColorTypeConverter _colorTypeConverter = new ColorTypeConverter(); public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - => sourceType == typeof(string); + => sourceType == typeof(string) + || sourceType == typeof(Color) + || sourceType == typeof(Paint); public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - => false; + => destinationType == typeof(Paint); public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { + if (value is Color colorValue) + { + return (Brush)colorValue; + } + else if (value is Paint paintValue) + { + return (Brush)paintValue; + } + var strValue = value?.ToString(); if (strValue != null) @@ -70,9 +81,15 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c return new SolidColorBrush(null); } - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - => throw new NotSupportedException(); + { + if (value is Brush brush && destinationType == typeof(Paint)) + { + return (Paint)brush; + } + + throw new NotSupportedException(); + } public class GradientBrushParser { diff --git a/src/Controls/src/Core/Button/Button.Mapper.cs b/src/Controls/src/Core/Button/Button.Mapper.cs index f31eebfb702e..e474d64366e6 100644 --- a/src/Controls/src/Core/Button/Button.Mapper.cs +++ b/src/Controls/src/Core/Button/Button.Mapper.cs @@ -12,12 +12,6 @@ public partial class Button { // IButton does not include the ContentType property, so we map it here to handle Image Positioning - /// - /// The property mapper that maps the abstract properties to the platform-specific methods for further processing. - /// - [Obsolete("Use ButtonHandler.Mapper instead.")] - public static IPropertyMapper ControlsButtonMapper = new ControlsMapper(ButtonHandler.Mapper); - internal new static void RemapForControls() { ButtonHandler.Mapper.ReplaceMapping(nameof(ContentLayout), MapContentLayout); diff --git a/src/Controls/src/Core/Compatibility/Android/PlatformSizeService.cs b/src/Controls/src/Core/Compatibility/Android/PlatformSizeService.cs deleted file mode 100644 index 53dae264a0ec..000000000000 --- a/src/Controls/src/Core/Compatibility/Android/PlatformSizeService.cs +++ /dev/null @@ -1,21 +0,0 @@ -#nullable disable -using Microsoft.Maui.Controls.Internals; - -[assembly: Microsoft.Maui.Controls.Dependency(typeof(Microsoft.Maui.Controls.Compatibility.Platform.Android.PlatformSizeService))] - -namespace Microsoft.Maui.Controls.Compatibility.Platform.Android -{ - class PlatformSizeService : IPlatformSizeService - { - public SizeRequest GetPlatformSize(VisualElement view, double widthConstraint, double heightConstraint) - { - if (widthConstraint > 0 && heightConstraint > 0) - { - return view.Handler?.GetDesiredSize(widthConstraint, heightConstraint) ?? - new SizeRequest(); - } - - return new SizeRequest(); - } - } -} \ No newline at end of file diff --git a/src/Controls/src/Core/Compatibility/Android/Renderers/MotionEventHelper.cs b/src/Controls/src/Core/Compatibility/Android/Renderers/MotionEventHelper.cs index 8e7bd27eb326..89669c1cf570 100644 --- a/src/Controls/src/Core/Compatibility/Android/Renderers/MotionEventHelper.cs +++ b/src/Controls/src/Core/Compatibility/Android/Renderers/MotionEventHelper.cs @@ -43,6 +43,7 @@ public void UpdateElement(VisualElement element) bool ShouldPassThroughElement() { +#pragma warning disable CS0618 // Type or member is obsolete if (_element is Layout layout) { if (!layout.InputTransparent) @@ -61,6 +62,7 @@ bool ShouldPassThroughElement() // This event isn't being bubbled up by a non-InputTransparent child layout return true; } +#pragma warning restore CS0618 // Type or member is obsolete if (_element.InputTransparent) { diff --git a/src/Controls/src/Core/Compatibility/ControlsMapper.cs b/src/Controls/src/Core/Compatibility/ControlsMapper.cs deleted file mode 100644 index 6ca265222c7f..000000000000 --- a/src/Controls/src/Core/Compatibility/ControlsMapper.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Microsoft.Maui.Controls.Compatibility -{ - [Obsolete("Delete this for .NET9")] - class ControlsMapper : IPropertyMapper - where TVirtualView : IElement - where TViewHandler : IElementHandler - { - IPropertyMapper _propertyMapper; - - public ControlsMapper(IPropertyMapper propertyMapper) : base() - { - _propertyMapper = propertyMapper; - } - - public void Add(string key, Action action) - { - _propertyMapper.ReplaceMapping(key, action); - } - - public IEnumerable GetKeys() - { - return _propertyMapper.GetKeys(); - } - - public Action? GetProperty(string key) - { - return _propertyMapper.GetProperty(key); - } - - public void UpdateProperties(IElementHandler elementHandler, IElement virtualView) - { - _propertyMapper.UpdateProperties(elementHandler, virtualView); - } - - public void UpdateProperty(IElementHandler elementHandler, IElement virtualView, string property) - { - _propertyMapper.UpdateProperty(elementHandler, virtualView, property); - } - } -} diff --git a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs index c5cdb322314d..2b7802aadfd3 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs @@ -14,6 +14,7 @@ namespace Microsoft.Maui.Controls.Handlers.Compatibility { + [Obsolete("Frame is obsolete as of .NET 9. Please use Border instead.")] public class FrameRenderer : CardView, IPlatformViewHandler { public static IPropertyMapper Mapper diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ListViewAdapter.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ListViewAdapter.cs index 960718e34fef..630a352ac9ff 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ListViewAdapter.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ListViewAdapter.cs @@ -763,7 +763,7 @@ Cell GetNewGroupHeaderCell(ITemplatedItemsList group) else { groupHeaderCell = new TextCell(); - groupHeaderCell.SetBinding(TextCell.TextProperty, nameof(group.Name)); + groupHeaderCell.SetBinding(TextCell.TextProperty, static (ITemplatedItemsList g) => g.Name); groupHeaderCell.BindingContext = group; } diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ListViewRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ListViewRenderer.cs index 9269bd273c45..e46f57a9892c 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ListViewRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ListViewRenderer.cs @@ -252,7 +252,9 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE * This will most likely cause the user to be frustrated that the ListView doesn't scroll :-) but at least now * it's consistent between platforms and for cases where it doesn't need to scroll (TableView). * */ +#pragma warning disable CS0618 // Type or member is obsolete public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) +#pragma warning restore CS0618 // Type or member is obsolete { if (double.IsInfinity(heightConstraint)) { diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/Tizen/CellContentFactory.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/Tizen/CellContentFactory.cs index cc4d8048a9a2..a087f1a06cee 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/Tizen/CellContentFactory.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/Tizen/CellContentFactory.cs @@ -1,5 +1,6 @@ #nullable disable using Microsoft.Maui.Graphics; +using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls.Handlers.Compatibility { @@ -73,8 +74,8 @@ static View CreateContent(SectionCell sectionCell) #pragma warning restore CS0612 // Type or member is obsolete }; - text.SetBinding(Label.TextProperty, new Binding("Text", source: sectionCell)); - text.SetBinding(Label.TextColorProperty, new Binding("TextColor", source: sectionCell)); + text.SetBinding(Label.TextProperty, static (SectionCell cell) => cell.Text, source: sectionCell); + text.SetBinding(Label.TextColorProperty, static (SectionCell cell) => cell.TextColor, source: sectionCell); var layout = new Controls.StackLayout { @@ -92,15 +93,15 @@ static View CreateContent(SectionCell sectionCell) static View CreateContent(TextCell textcell) { var text = new Label(); - text.SetBinding(Label.TextProperty, new Binding("Text", source: textcell)); - text.SetBinding(Label.TextColorProperty, new Binding("TextColor", source: textcell)); + text.SetBinding(Label.TextProperty, static (TextCell cell) => cell.Text, source: textcell); + text.SetBinding(Label.TextColorProperty, static (TextCell cell) => cell.TextColor, source: textcell); #pragma warning disable CS0612 // Type or member is obsolete text.FontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label)); #pragma warning restore CS0612 // Type or member is obsolete var detail = new Label(); - detail.SetBinding(Label.TextProperty, new Binding("Detail", source: textcell)); - detail.SetBinding(Label.TextColorProperty, new Binding("DetailColor", source: textcell)); + detail.SetBinding(Label.TextProperty, static (TextCell cell) => cell.Detail, source: textcell); + detail.SetBinding(Label.TextColorProperty, static (TextCell cell) => cell.DetailColor, source: textcell); #pragma warning disable CS0612 // Type or member is obsolete detail.FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)); #pragma warning restore CS0612 // Type or member is obsolete @@ -138,7 +139,7 @@ static View CreateContent(ImageCell imageCell) { Aspect = Aspect.AspectFit, }; - img.SetBinding(Image.SourceProperty, new Binding("ImageSource", source: imageCell)); + img.SetBinding(Image.SourceProperty, static (ImageCell cell) => cell.ImageSource, source: imageCell); layout.Add(img, 0, 0); layout.Add(textcell, 1, 0); return layout; @@ -147,15 +148,15 @@ static View CreateContent(ImageCell imageCell) static View CreateContent(EntryCell entryCell) { var entry = new Entry(); - entry.SetBinding(Entry.TextProperty, new Binding("Text", BindingMode.TwoWay, source: entryCell)); - entry.SetBinding(Entry.PlaceholderProperty, new Binding("Placeholder", source: entryCell)); - entry.SetBinding(InputView.KeyboardProperty, new Binding("Keyboard", source: entryCell)); - entry.SetBinding(Entry.HorizontalTextAlignmentProperty, new Binding("HorizontalTextAlignment", source: entryCell)); - entry.SetBinding(Entry.VerticalTextAlignmentProperty, new Binding("VerticalTextAlignment", source: entryCell)); + entry.SetBinding(Entry.TextProperty, static (EntryCell cell) => cell.Text, mode: BindingMode.TwoWay, source: entryCell); + entry.SetBinding(Entry.PlaceholderProperty, static (EntryCell cell) => cell.Placeholder, source: entryCell); + entry.SetBinding(InputView.KeyboardProperty, static (EntryCell cell) => cell.Keyboard, source: entryCell); + entry.SetBinding(Entry.HorizontalTextAlignmentProperty, static (EntryCell cell) => cell.HorizontalTextAlignment, source: entryCell); + entry.SetBinding(Entry.VerticalTextAlignmentProperty, static (EntryCell cell) => cell.VerticalTextAlignment, source: entryCell); var label = new Label(); - label.SetBinding(Label.TextProperty, new Binding("Label", source: entryCell)); - label.SetBinding(Label.TextColorProperty, new Binding("LabelColor", source: entryCell)); + label.SetBinding(Label.TextProperty, static (EntryCell cell) => cell.Label, source: entryCell); + label.SetBinding(Label.TextColorProperty, static (EntryCell cell) => cell.LabelColor, source: entryCell); #pragma warning disable CS0612 // Type or member is obsolete label.FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)); #pragma warning restore CS0612 // Type or member is obsolete @@ -182,14 +183,14 @@ static View CreateContent(SwitchCell switchCell) HorizontalOptions = LayoutOptions.StartAndExpand, }; #pragma warning restore CS0618 - text.SetBinding(Label.TextProperty, new Binding("Text", source: switchCell)); + text.SetBinding(Label.TextProperty, static (SwitchCell cell) => cell.Text, source: switchCell); var sw = new Switch { HorizontalOptions = LayoutOptions.End }; - sw.SetBinding(Switch.IsToggledProperty, new Binding("On", BindingMode.TwoWay, source: switchCell)); - sw.SetBinding(Switch.OnColorProperty, new Binding("OnColor", source: switchCell)); + sw.SetBinding(Switch.IsToggledProperty, static (SwitchCell cell) => cell.On, mode: BindingMode.TwoWay, source: switchCell); + sw.SetBinding(Switch.OnColorProperty, static (SwitchCell cell) => cell.OnColor, source: switchCell); var layout = new Controls.StackLayout { diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/Tizen/ListViewRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/Tizen/ListViewRenderer.cs index cbb5d00039b4..36ef06dc47ed 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/Tizen/ListViewRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/Tizen/ListViewRenderer.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Linq; using Microsoft.Maui.Controls.Handlers.Items; +using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Platform; using Tizen.NUI; using Tizen.UIExtensions.NUI; @@ -97,7 +98,7 @@ protected void UpdateAdaptor(bool initialize) template = new CellWrapperTemplate(new DataTemplate(() => { var label = new TextCell(); - label.SetBinding(TextCell.TextProperty, new Binding(".")); + label.SetBinding(TextCell.TextProperty, static (object source) => source); return label; }), Element); } diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/CellControl.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/CellControl.cs index 145a51ac231b..e39d4513e606 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/CellControl.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/CellControl.cs @@ -21,7 +21,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public class CellControl : ContentControl + public partial class CellControl : ContentControl { public static readonly DependencyProperty CellProperty = DependencyProperty.Register("Cell", typeof(object), typeof(CellControl), new PropertyMetadata(null, (o, e) => ((CellControl)o).SetSource((Cell)e.OldValue, (Cell)e.NewValue))); diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/EntryCellTextBox.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/EntryCellTextBox.cs index 3d34c10cdf31..6f421532aec4 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/EntryCellTextBox.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/EntryCellTextBox.cs @@ -5,7 +5,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public class EntryCellTextBox : TextBox + public partial class EntryCellTextBox : TextBox { protected override void OnKeyUp(KeyRoutedEventArgs e) { diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListGroupHeaderPresenter.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListGroupHeaderPresenter.cs index be7d1ad6b911..ee83a0a5977a 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListGroupHeaderPresenter.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListGroupHeaderPresenter.cs @@ -6,7 +6,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public class ListGroupHeaderPresenter : Microsoft.UI.Xaml.Controls.ContentPresenter + public partial class ListGroupHeaderPresenter : Microsoft.UI.Xaml.Controls.ContentPresenter { void OnTapped(object sender, TappedRoutedEventArgs tappedRoutedEventArgs) { diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListViewGroupStyleSelector.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListViewGroupStyleSelector.cs index 9ad927639fa7..a48b12cc09ff 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListViewGroupStyleSelector.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListViewGroupStyleSelector.cs @@ -3,7 +3,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public class ListViewGroupStyleSelector : GroupStyleSelector + public partial class ListViewGroupStyleSelector : GroupStyleSelector { protected override GroupStyle SelectGroupStyleCore(object group, uint level) { diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListViewRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListViewRenderer.cs index 1b5c24b9fd15..4be3421e0b41 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListViewRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListViewRenderer.cs @@ -30,7 +30,7 @@ namespace Microsoft.Maui.Controls.Handlers.Compatibility { - public class ListViewRenderer : ViewRenderer + public partial class ListViewRenderer : ViewRenderer { public static PropertyMapper Mapper = new PropertyMapper(VisualElementRendererMapper); @@ -57,7 +57,7 @@ public ListViewRenderer() : base(Mapper, CommandMapper) AutoPackage = false; } - internal sealed class ListViewTransparent : WListView + internal sealed partial class ListViewTransparent : WListView { internal ListViewRenderer ListViewRenderer { get; } public ListViewTransparent(ListViewRenderer listViewRenderer) : base() diff --git a/src/Controls/src/Core/Compatibility/Handlers/ListView/iOS/ListViewRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/ListView/iOS/ListViewRenderer.cs index ae7fd8cce6a7..01cbc54376b5 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/ListView/iOS/ListViewRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/ListView/iOS/ListViewRenderer.cs @@ -932,7 +932,7 @@ internal nfloat CalculateHeightForCell(UITableView tableView, Cell cell) // Let the EstimatedHeight method know to use this value. // Much more efficient than checking the value each time. //_useEstimatedRowHeight = true; - var height = (nfloat)req.Request.Height; + var height = (nfloat)req.Height; return height > 1 ? height : DefaultRowHeight; } diff --git a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs index f440a7b9693d..4b72db7ba14a 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs @@ -76,11 +76,13 @@ Page Current public event EventHandler ElementChanged; +#pragma warning disable CS0618 // Type or member is obsolete public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) { return VisualElementRenderer.GetDesiredSize(this, widthConstraint, heightConstraint, new Size(0, 0)); } +#pragma warning restore CS0618 // Type or member is obsolete public UIView NativeView { @@ -896,7 +898,7 @@ async Task UpdateFormsInnerNavigation(Page pageBeingRemoved) await (NavPage as INavigationPageController)?.RemoveAsyncInner(pageBeingRemoved, false, true); if (_uiRequestedPop) { - NavPage?.SendNavigatedFromHandler(pageBeingRemoved); + NavPage?.SendNavigatedFromHandler(pageBeingRemoved, NavigationType.Pop); } } @@ -1103,8 +1105,8 @@ public override void DidShowViewController(UINavigationController navigationCont if (r.Element is NavigationPage np && !_finishedWithInitialNavigation) { - _finishedWithInitialNavigation = true; - np.SendNavigatedFromHandler(null); + _finishedWithInitialNavigation = true; + np.SendNavigatedFromHandler(null, NavigationType.Push); } if (WaitingForNavigationToFinish) @@ -2014,7 +2016,7 @@ protected override void Dispose(bool disposing) if (disposing) { - if (_child != null) + if (_child?.IsConnected() == true) { (_child.ContainerView ?? _child.PlatformView).RemoveFromSuperview(); _child.DisconnectHandler(); diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellBottomNavViewAppearanceTracker.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellBottomNavViewAppearanceTracker.cs index fdf0fdadd90f..1f9d682d41d9 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellBottomNavViewAppearanceTracker.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellBottomNavViewAppearanceTracker.cs @@ -72,7 +72,9 @@ public virtual void SetAppearance(BottomNavigationView bottomView, IShellAppeara protected virtual void SetBackgroundColor(BottomNavigationView bottomView, Color color) { +#pragma warning disable XAOBS001 // Obsolete var menuView = bottomView.GetChildAt(0) as BottomNavigationMenuView; +#pragma warning restore XAOBS001 // Obsolete var oldBackground = bottomView.Background; var colorDrawable = oldBackground as ColorDrawable; var colorChangeRevealDrawable = oldBackground as ColorChangeRevealDrawable; @@ -96,7 +98,9 @@ protected virtual void SetBackgroundColor(BottomNavigationView bottomView, Color backgroundColor.FillColor = ColorStateList.ValueOf(newColor); backgroundColor.InitializeElevationOverlay(bottomView.Context); +#pragma warning disable CS0618 // Obsolete ViewCompat.SetBackground(bottomView, backgroundColor); +#pragma warning restore CS0618 // Obsolete } } else @@ -114,7 +118,9 @@ protected virtual void SetBackgroundColor(BottomNavigationView bottomView, Color var touchPoint = new Point(child.Left + (child.Right - child.Left) / 2, child.Top + (child.Bottom - child.Top) / 2); +#pragma warning disable CS0618 // Obsolete ViewCompat.SetBackground(bottomView, new ColorChangeRevealDrawable(lastColor, newColor, touchPoint)); +#pragma warning restore CS0618 // Obsolete } } diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs index 8bd0afcea041..0d0bc72d6b6a 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs @@ -127,6 +127,14 @@ protected virtual void LoadView(IShellContext shellContext) void InitialLoad(GenericGlobalLayoutListener listener, AView view) { + // This means the handler was disconnected before the flyout was loaded + if (_shellContext?.Shell is null) + { + listener.Invalidate(); + sfl.LayoutChanging -= OnFlyoutViewLayoutChanging; + return; + } + OnFlyoutViewLayoutChanging(); if (_flyoutContentView == null || ggll == null) diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSearchViewAdapter.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSearchViewAdapter.cs index 21c7da7e1530..e862fa891ea0 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSearchViewAdapter.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSearchViewAdapter.cs @@ -5,6 +5,7 @@ using Android.Views; using Android.Widget; using Java.Lang; +using Microsoft.Extensions.Logging; using Microsoft.Maui.Controls.Internals; using AView = Android.Views.View; @@ -66,7 +67,30 @@ DataTemplate DefaultTemplate _defaultTemplate = new DataTemplate(() => { var label = new Label(); - label.SetBinding(Label.TextProperty, _searchHandler.DisplayMemberName ?? "."); + + if (RuntimeFeature.IsShellSearchResultsRendererDisplayMemberNameSupported) + { +#pragma warning disable CS0618 +#if NET8_0 +#pragma warning disable IL2026 // FeatureGuardAttribute is not supported on .NET 8 +#endif + label.SetBinding(Label.TextProperty, _searchHandler.DisplayMemberName ?? "."); +#if NET8_0 +#pragma warning restore IL2026 // FeatureGuardAttribute is not supported on .NET 8 +#endif +#pragma warning restore CS0618 + } + else + { +#pragma warning disable CS0618 + if (_searchHandler.DisplayMemberName is not null) + { + Application.Current?.FindMauiContext()?.CreateLogger()?.LogError(TrimmerConstants.SearchHandlerDisplayMemberNameNotSupportedWarning); + throw new InvalidOperationException(TrimmerConstants.SearchHandlerDisplayMemberNameNotSupportedWarning); + } +#pragma warning restore CS0618 + } + label.HorizontalTextAlignment = TextAlignment.Center; label.VerticalTextAlignment = TextAlignment.Center; diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs index 198e7b84fb03..657b53f23e2b 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs @@ -68,11 +68,16 @@ void IFlyoutBehaviorObserver.OnFlyoutBehaviorChanged(FlyoutBehavior behavior) DrawerArrowDrawable _drawerArrowDrawable; FlyoutIconDrawerDrawable _flyoutIconDrawerDrawable; IToolbar _toolbar; - protected IMauiContext MauiContext => ShellContext.Shell.Handler.MauiContext; + protected IMauiContext MauiContext => _shell.Handler.MauiContext; + + Toolbar _shellRootToolBar; + Shell _shell; public ShellToolbarTracker(IShellContext shellContext, AToolbar toolbar, DrawerLayout drawerLayout) { ShellContext = shellContext ?? throw new ArgumentNullException(nameof(shellContext)); + _shell = shellContext.Shell; + _platformToolbar = toolbar ?? throw new ArgumentNullException(nameof(toolbar)); _drawerLayout = drawerLayout ?? throw new ArgumentNullException(nameof(drawerLayout)); _appBar = _platformToolbar.Parent.GetParentOfType(); @@ -80,7 +85,8 @@ public ShellToolbarTracker(IShellContext shellContext, AToolbar toolbar, DrawerL _globalLayoutListener = new GenericGlobalLayoutListener((_, _) => UpdateNavBarHasShadow(Page), _appBar); _platformToolbar.SetNavigationOnClickListener(this); ((IShellController)ShellContext.Shell).AddFlyoutBehaviorObserver(this); - ShellContext.Shell.Toolbar.PropertyChanged += OnToolbarPropertyChanged; + _shellRootToolBar = _shell.Toolbar; + _shellRootToolBar.PropertyChanged += OnToolbarPropertyChanged; ShellContext.Shell.Navigated += OnShellNavigated; ShellContext.Shell.PropertyChanged += HandleShellPropertyChanged; } @@ -162,7 +168,7 @@ void AView.IOnClickListener.OnClick(AView v) else if (CanNavigateBack) OnNavigateBack(); else - ShellContext.Shell.FlyoutIsPresented = !ShellContext.Shell.FlyoutIsPresented; + _shell.FlyoutIsPresented = !_shell.FlyoutIsPresented; } } @@ -181,9 +187,9 @@ protected override void Dispose(bool disposing) _backButtonBehavior.PropertyChanged -= OnBackButtonBehaviorChanged; ((IShellController)ShellContext.Shell)?.RemoveFlyoutBehaviorObserver(this); - ShellContext.Shell.Toolbar.PropertyChanged -= OnToolbarPropertyChanged; - ShellContext.Shell.Navigated -= OnShellNavigated; - ShellContext.Shell.PropertyChanged -= HandleShellPropertyChanged; + _shellRootToolBar.PropertyChanged -= OnToolbarPropertyChanged; + _shell.Navigated -= OnShellNavigated; + _shell.PropertyChanged -= HandleShellPropertyChanged; UpdateTitleView(ShellContext.AndroidContext, _platformToolbar, null); if (_searchView != null) @@ -212,6 +218,7 @@ protected override void Dispose(bool disposing) _platformToolbar = null; _appBar = null; _drawerLayout = null; + _shell = null; base.Dispose(disposing); } @@ -261,8 +268,8 @@ protected virtual void OnPageChanged(Page oldPage, Page newPage) UpdateNavBarHasShadow(newPage); UpdateTitleView(); - if (ShellContext.Shell.Toolbar is ShellToolbar shellToolbar && - newPage == ShellContext.Shell.GetCurrentShellPage()) + if (_shell.Toolbar is ShellToolbar shellToolbar && + newPage == _shell.GetCurrentShellPage()) { shellToolbar.ApplyChanges(); } @@ -274,8 +281,8 @@ void OnShellNavigated(object sender, ShellNavigatedEventArgs e) if (_disposed || Page == null) return; - if (ShellContext?.Shell?.Toolbar is ShellToolbar && - Page == ShellContext?.Shell?.GetCurrentShellPage()) + if (_shell?.Toolbar is ShellToolbar && + Page == _shell?.GetCurrentShellPage()) { UpdateLeftBarButtonItem(); UpdateTitleView(); @@ -402,7 +409,7 @@ protected virtual async void UpdateLeftBarButtonItem(Context context, AToolbar t var backButtonHandler = Shell.GetBackButtonBehavior(page); var text = backButtonHandler.GetPropertyIfSet(BackButtonBehavior.TextOverrideProperty, String.Empty); var command = backButtonHandler.GetPropertyIfSet(BackButtonBehavior.CommandProperty, null); - bool isEnabled = ShellContext.Shell.Toolbar.BackButtonEnabled; + bool isEnabled = _shell.Toolbar.BackButtonEnabled; var image = GetFlyoutIcon(backButtonHandler, page); var backButtonVisible = _toolbar.BackButtonVisible; @@ -496,7 +503,7 @@ protected virtual async void UpdateLeftBarButtonItem(Context context, AToolbar t //this needs to be set after SyncState - UpdateToolbarIconAccessibilityText(toolbar, ShellContext.Shell); + UpdateToolbarIconAccessibilityText(toolbar, _shell); _toolbar?.Handler?.UpdateValue(nameof(Toolbar.IconColor)); } @@ -604,10 +611,10 @@ void UpdateNavBarHasShadow(Page page) void OnToolbarPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (_toolbar != null && ShellContext?.Shell?.GetCurrentShellPage() == Page) + if (_toolbar != null && _shell?.GetCurrentShellPage() == Page) { ApplyToolbarChanges((Toolbar)sender, (Toolbar)_toolbar); - UpdateToolbarIconAccessibilityText(_platformToolbar, ShellContext.Shell); + UpdateToolbarIconAccessibilityText(_platformToolbar, _shell); } } @@ -617,7 +624,7 @@ protected virtual void UpdatePageTitle(AToolbar toolbar, Page page) protected virtual void UpdateTitleView(Context context, AToolbar toolbar, View titleView) { - if (_toolbar != null && ShellContext?.Shell?.GetCurrentShellPage() == Page) + if (_toolbar != null && _shell?.GetCurrentShellPage() == Page) _toolbar.Handler?.UpdateValue(nameof(Toolbar.TitleView)); } diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellItemRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellItemRenderer.cs index 537a91a9a240..48bc62a05ec2 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellItemRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellItemRenderer.cs @@ -59,6 +59,7 @@ void IAppearanceObserver.OnAppearanceChanged(ShellAppearance appearance) public ShellItemRenderer(IShellContext context) { + this.DisableiOS18ToolbarTabs(); _context = context; } diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellScrollViewTracker.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellScrollViewTracker.cs deleted file mode 100644 index 8640688ce1f6..000000000000 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellScrollViewTracker.cs +++ /dev/null @@ -1,212 +0,0 @@ -#nullable disable -using System; -using ObjCRuntime; -using UIKit; -using PointF = CoreGraphics.CGPoint; - -namespace Microsoft.Maui.Controls.Handlers.Compatibility -{ - [Obsolete("Scrolling is now handled by KeyboardAutoManagerScroll.")] - public class ShellScrollViewTracker : IDisposable, IShellContentInsetObserver - { - #region IShellContentInsetObserver - - void IShellContentInsetObserver.OnInsetChanged(Thickness inset, double tabThickness) - { - UpdateContentInset(inset, tabThickness); - } - - #endregion IShellContentInsetObserver - - bool _disposed; - bool _isInShell; - bool _isInItems; - IPlatformViewHandler _renderer; - UIScrollView _scrollView; - ShellSection _shellSection; - IShellSectionController ShellSectionController => _shellSection; - - public ShellScrollViewTracker(IPlatformViewHandler renderer) - { - _renderer = renderer; - - if (_renderer.PlatformView is UIScrollView scrollView) - _scrollView = scrollView; - else if (_renderer.PlatformView.Subviews.Length > 0 && _renderer.PlatformView.Subviews[0] is UIScrollView nestedScrollView) - _scrollView = nestedScrollView; - - if (_scrollView == null) - return; - - var parent = _renderer.VirtualView.Parent; - - while (!Application.IsApplicationOrWindowOrNull(parent)) - { - if (parent is ScrollView || parent is ListView || parent is TableView || parent is CollectionView) - break; - parent = parent.Parent; - - // Currently ShellContents are not pushable onto the stack so we know we are not being pushed - // on the stack if we are in a ShellContent - if (parent is ShellContent) - _isInItems = true; - - if (parent is ShellSection shellSection) - { - _isInShell = true; - _shellSection = shellSection; - ((IShellSectionController)_shellSection).AddContentInsetObserver(this); - - break; - } - } - - if (_isInShell) - UpdateVerticalBounce(); - } - - public void OnLayoutSubviews() - { - if (!_isInShell) - return; - - if (OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsMacCatalystVersionAtLeast(11) -#if TVOS - || OperatingSystem.IsTvOSVersionAtLeast(11) -#endif - ) - { - var newBounds = _scrollView.AdjustedContentInset.InsetRect(_scrollView.Bounds).ToRectangle(); - newBounds.X = 0; - newBounds.Y = 0; - if (_renderer.VirtualView is ScrollView scrollView) - scrollView.LayoutAreaOverride = newBounds; - } - } - - Thickness _lastInset; - double _tabThickness; - - public bool Reset() - { - if (!_isInShell) - return false; - - if (_lastInset == 0 && _tabThickness == 0) - return false; - - if (!(OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsTvOSVersionAtLeast(11))) - { - UpdateContentInset(_lastInset, _tabThickness); - return true; - } - - if (ShellSectionController.GetItems().Count > 1 && _isInItems) - { - UpdateContentInset(_lastInset, _tabThickness); - return true; - } - - return false; - } - - void UpdateContentInset(Thickness inset, double tabThickness) - { - _lastInset = inset; - _tabThickness = tabThickness; - if (OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsMacCatalystVersionAtLeast(11) -#if TVOS - || OperatingSystem.IsTvOSVersionAtLeast(11) -#endif - ) - { - if (ShellSectionController.GetItems().Count > 1 && _isInItems) - { - var top = (float)tabThickness; - - var delta = _scrollView.ContentInset.Top - top; - var newInset = new UIEdgeInsets(top, 0, 0, 0); - - if (newInset != _scrollView.ContentInset) - { - _scrollView.ContentInset = newInset; - - var currentOffset = _scrollView.ContentOffset; - _scrollView.ContentOffset = new PointF(currentOffset.X, currentOffset.Y + delta); - } - } - - _scrollView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Always; - } - else - { - var top = (float)(inset.Top); - - if (_isInItems) - top += (float)tabThickness; - - var delta = _scrollView.ContentInset.Top - top; - var newInset = new UIEdgeInsets(top, (float)inset.Left, (float)inset.Bottom, (float)inset.Right); - - if (newInset != _scrollView.ContentInset) - { - _scrollView.ContentInset = newInset; - - var currentOffset = _scrollView.ContentOffset; - _scrollView.ContentOffset = new PointF(currentOffset.X, currentOffset.Y + delta - inset.Bottom); - } - } - } - - void UpdateVerticalBounce() - { - // Normally we dont want to do this unless this scrollview is vertical and its - // element is the child of a Page with a SearchHandler that is collapsible. - // If we can't bounce in that case you may not be able to expose the handler. - // Also the hiding behavior only depends on scroll on iOS 11. In 10 and below - // the search goes in the TitleView so there is nothing to collapse/expand. - if (!(OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsTvOSVersionAtLeast(11)) || - (_renderer.VirtualView is ScrollView scrollView && scrollView.Orientation == ScrollOrientation.Horizontal)) - return; - - var parent = _renderer.VirtualView.Parent; - while (!Application.IsApplicationOrNull(parent)) - { - if (parent is Page page) - { - var searchHandler = Shell.GetSearchHandler(page); - if (searchHandler?.SearchBoxVisibility == SearchBoxVisibility.Collapsible) - _scrollView.AlwaysBounceVertical = true; - return; - } - parent = parent.Parent; - } - } - - #region IDisposable Support - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - (_shellSection as IShellSectionController)?.RemoveContentInsetObserver(this); - } - - _renderer = null; - _scrollView = null; - _shellSection = null; - - _disposed = true; - } - } - - #endregion IDisposable Support - } -} \ No newline at end of file diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSearchResultsRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSearchResultsRenderer.cs index d459b1b5f0ed..9079c6a6c6a3 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSearchResultsRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSearchResultsRenderer.cs @@ -3,6 +3,7 @@ using System.Collections.Specialized; using Foundation; using Microsoft.Maui.Controls.Internals; +using Microsoft.Extensions.Logging; using ObjCRuntime; using UIKit; @@ -37,7 +38,32 @@ DataTemplate DefaultTemplate return _defaultTemplate ?? (_defaultTemplate = new DataTemplate(() => { var label = new Label(); - label.SetBinding(Label.TextProperty, SearchHandler.DisplayMemberName ?? "."); + + if (RuntimeFeature.IsShellSearchResultsRendererDisplayMemberNameSupported) + { +#pragma warning disable CS0618 +#if NET8_0 +#pragma warning disable IL2026 // FeatureGuardAttribute is not supported on .NET 8 +#endif + label.SetBinding(Label.TextProperty, SearchHandler.DisplayMemberName ?? "."); +#if NET8_0 +#pragma warning restore IL2026 // FeatureGuardAttribute is not supported on .NET 8 +#endif +#pragma warning restore CS0618 + } + else + { +#pragma warning disable CS0618 + if (SearchHandler.DisplayMemberName is not null) + { + Application.Current?.FindMauiContext()?.CreateLogger()?.LogError(TrimmerConstants.SearchHandlerDisplayMemberNameNotSupportedWarning); + throw new InvalidOperationException(TrimmerConstants.SearchHandlerDisplayMemberNameNotSupportedWarning); + } +#pragma warning restore CS0618 + + label.SetBinding(Label.TextProperty, static (object o) => o); + } + label.HorizontalTextAlignment = TextAlignment.Center; label.VerticalTextAlignment = TextAlignment.Center; @@ -88,7 +114,9 @@ public override UITableViewCell GetCell(UITableView tableView, NSIndexPath index var template = SearchHandler.ItemTemplate; if (template == null) + { template = DefaultTemplate; + } var cellId = ((IDataTemplateController)template.SelectDataTemplate(context, _context.Shell)).IdString; diff --git a/src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs index 4720766995bc..1da384a6f17b 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs @@ -39,6 +39,7 @@ public class TabbedRenderer : UITabBarController, IPlatformViewHandler [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] public TabbedRenderer() { + this.DisableiOS18ToolbarTabs(); _viewHandlerWrapper = new ViewHandlerDelegator(Mapper, CommandMapper, this); } @@ -531,7 +532,7 @@ void UpdateiOS15TabBarAppearance() tabbed.IsSet(TabbedPage.UnselectedTabColorProperty) ? tabbed.UnselectedTabColor : null, tabbed.IsSet(TabbedPage.BarBackgroundColorProperty) ? tabbed.BarBackgroundColor : null, tabbed.IsSet(TabbedPage.BarTextColorProperty) ? tabbed.BarTextColor : null, - null); + tabbed.IsSet(TabbedPage.BarTextColorProperty) ? tabbed.BarTextColor : null); } #region IPlatformViewHandler diff --git a/src/Controls/src/Core/Compatibility/Handlers/TableView/Android/TableViewRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/TableView/Android/TableViewRenderer.cs index 9395c646e5b5..5172705c1df7 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/TableView/Android/TableViewRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/TableView/Android/TableViewRenderer.cs @@ -117,7 +117,9 @@ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) base.OnMeasure(widthMeasureSpec, heightMeasureSpec); } +#pragma warning disable CS0618 // Type or member is obsolete public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) +#pragma warning restore CS0618 // Type or member is obsolete { if (double.IsInfinity(heightConstraint)) { diff --git a/src/Controls/src/Core/Compatibility/Handlers/TableView/Windows/TableViewRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/TableView/Windows/TableViewRenderer.cs index 7789da8893c4..91f13c7e6fea 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/TableView/Windows/TableViewRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/TableView/Windows/TableViewRenderer.cs @@ -9,7 +9,7 @@ namespace Microsoft.Maui.Controls.Handlers.Compatibility { - public class TableViewRenderer : ViewRenderer + public partial class TableViewRenderer : ViewRenderer { bool _ignoreSelectionEvent; bool _disposed; diff --git a/src/Controls/src/Core/Compatibility/Handlers/Tizen/FrameRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Tizen/FrameRenderer.cs index be59266ddc16..e89fe93e83de 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Tizen/FrameRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Tizen/FrameRenderer.cs @@ -12,6 +12,7 @@ namespace Microsoft.Maui.Controls.Handlers.Compatibility { + [System.Obsolete("Frame is obsolete as of .NET 9. Please use Border instead.")] public class FrameRenderer : ContentViewGroup, IPlatformViewHandler, IMeasurable { public static IPropertyMapper Mapper diff --git a/src/Controls/src/Core/Compatibility/Handlers/VisualElementRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/VisualElementRenderer.cs index 680bc596cc19..b0f0a0dc40d5 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/VisualElementRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/VisualElementRenderer.cs @@ -158,12 +158,14 @@ Size IViewHandler.GetDesiredSize(double widthConstraint, double heightConstraint return size; } +#pragma warning disable CS0618 // Type or member is obsolete public virtual SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) { var minSize = MinimumSize(); var size = GetDesiredSize(this, widthConstraint, heightConstraint, minSize); return new SizeRequest(size, minSize); } +#pragma warning restore CS0618 // Type or member is obsolete #if TIZEN protected new virtual Size MinimumSize() diff --git a/src/Controls/src/Core/Compatibility/Handlers/Windows/FrameRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Windows/FrameRenderer.cs index 8b8ba15ae638..f4356f465496 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Windows/FrameRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Windows/FrameRenderer.cs @@ -11,7 +11,8 @@ namespace Microsoft.Maui.Controls.Handlers.Compatibility { - public class FrameRenderer : ViewRenderer + [Obsolete("Frame is obsolete as of .NET 9. Please use Border instead.")] + public partial class FrameRenderer : ViewRenderer { public static IPropertyMapper Mapper = new PropertyMapper(VisualElementRendererMapper) diff --git a/src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs index 76b7a3d43c4d..174042c26f0e 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs @@ -7,6 +7,7 @@ namespace Microsoft.Maui.Controls.Handlers.Compatibility { + [Obsolete("Frame is obsolete as of .NET 9. Please use Border instead.")] public class FrameRenderer : VisualElementRenderer { public static IPropertyMapper Mapper diff --git a/src/Controls/src/Core/Compatibility/Handlers/iOS/KeyboardInsetTracker.cs b/src/Controls/src/Core/Compatibility/Handlers/iOS/KeyboardInsetTracker.cs deleted file mode 100644 index 6d50fb683985..000000000000 --- a/src/Controls/src/Core/Compatibility/Handlers/iOS/KeyboardInsetTracker.cs +++ /dev/null @@ -1,118 +0,0 @@ -#nullable disable -using System; -using ObjCRuntime; -using UIKit; -using PointF = CoreGraphics.CGPoint; -using RectangleF = CoreGraphics.CGRect; - -namespace Microsoft.Maui.Controls.Handlers.Compatibility -{ - [Obsolete("Scrolling is now handled by KeyboardAutoManagerScroll.")] - internal sealed class KeyboardInsetTracker : IDisposable - { - readonly Func _fetchWindow; - readonly Action _setContentOffset; - readonly Action _setInsetAction; - readonly UIScrollView _targetView; - bool _disposed; - UIEdgeInsets _currentInset; - RectangleF _lastKeyboardRect; - ShellScrollViewTracker _shellScrollViewTracker; - - - public KeyboardInsetTracker(UIScrollView targetView, Func fetchWindow, Action setInsetAction) - : this(targetView, fetchWindow, setInsetAction, null) - { - } - - public KeyboardInsetTracker(UIScrollView targetView, Func fetchWindow, Action setInsetAction, Action setContentOffset) - : this(targetView, fetchWindow, setInsetAction, setContentOffset, null) - { - } - - public KeyboardInsetTracker(UIScrollView targetView, Func fetchWindow, Action setInsetAction, Action setContentOffset, IPlatformViewHandler renderer) - { - _setContentOffset = setContentOffset; - _targetView = targetView; - _fetchWindow = fetchWindow; - _setInsetAction = setInsetAction; - Controls.Compatibility.Platform.iOS.KeyboardObserver.KeyboardWillShow += OnKeyboardShown; - Controls.Compatibility.Platform.iOS.KeyboardObserver.KeyboardWillHide += OnKeyboardHidden; - if (renderer != null) - _shellScrollViewTracker = new ShellScrollViewTracker(renderer); - } - - public void Dispose() - { - if (_disposed) - return; - - _disposed = true; - - Controls.Compatibility.Platform.iOS.KeyboardObserver.KeyboardWillShow -= OnKeyboardShown; - Controls.Compatibility.Platform.iOS.KeyboardObserver.KeyboardWillHide -= OnKeyboardHidden; - - _shellScrollViewTracker?.Dispose(); - _shellScrollViewTracker = null; - } - - //This method allows us to update the insets if the Frame changes - internal void UpdateInsets() - { - //being called from LayoutSubviews but keyboard wasn't shown yet - if (_lastKeyboardRect.IsEmpty) - return; - - var window = _fetchWindow(); - // Code left verbose to make its operation more obvious - if (window == null) - { - // we are not currently displayed and can safely ignore this - // most likely this renderer is on a page which is currently not displayed (e.g. in NavController) - return; - } - - var field = Controls.Compatibility.Platform.iOS.UIViewExtensions.FindFirstResponder(_targetView); - - //the view that is triggering the keyboard is not inside our UITableView? - //if (field == null) - // return; - - var boundsSize = _targetView.Frame.Size; - - //since our keyboard frame is RVC CoordinateSpace, lets convert it to our targetView CoordinateSpace - var rect = _targetView.Superview.ConvertRectFromView(_lastKeyboardRect, null); - //let's see how much does it cover our target view - var overlay = RectangleF.Intersect(rect, _targetView.Frame); - - _currentInset = _targetView.ContentInset; - _setInsetAction(new UIEdgeInsets(0, 0, overlay.Height, 0)); - - if (field is UITextView && _setContentOffset != null) - { - var keyboardTop = boundsSize.Height - overlay.Height; - var fieldPosition = field.ConvertPointToView(field.Frame.Location, _targetView.Superview); - var fieldBottom = fieldPosition.Y + field.Frame.Height; - var offset = fieldBottom - keyboardTop; - if (offset > 0) - _setContentOffset(new PointF(0, offset)); - } - } - - public void OnLayoutSubviews() => _shellScrollViewTracker?.OnLayoutSubviews(); - - void OnKeyboardHidden(object sender, UIKeyboardEventArgs args) - { - if (_shellScrollViewTracker == null || !_shellScrollViewTracker.Reset()) - _setInsetAction(new UIEdgeInsets(0, 0, 0, 0)); - - _lastKeyboardRect = RectangleF.Empty; - } - - void OnKeyboardShown(object sender, UIKeyboardEventArgs args) - { - _lastKeyboardRect = args.FrameEnd; - UpdateInsets(); - } - } -} diff --git a/src/Controls/src/Core/Compatibility/Handlers/iOS/ViewRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/iOS/ViewRenderer.cs index 1abeea986685..44ce4c6c3c26 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/iOS/ViewRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/iOS/ViewRenderer.cs @@ -51,12 +51,14 @@ public override void LayoutSubviews() } } +#pragma warning disable CS0618 // Type or member is obsolete public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) { return new SizeRequest(this.GetDesiredSizeFromHandler(widthConstraint, heightConstraint), MinimumSize()); } +#pragma warning restore CS0618 // Type or member is obsolete public override void SizeToFit() { diff --git a/src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs index a24934741384..eed44ee37327 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs @@ -59,7 +59,10 @@ partial void ElementPropertyChangedPartial(object sender, PropertyChangedEventAr e.PropertyName == VisualElement.IsEnabledProperty.PropertyName || e.PropertyName == VisualElement.InputTransparentProperty.PropertyName || e.PropertyName == VisualElement.OpacityProperty.PropertyName || - e.PropertyName == Controls.Compatibility.Layout.CascadeInputTransparentProperty.PropertyName) +#pragma warning disable CS0618 // Type or member is obsolete + e.PropertyName == Controls.Compatibility.Layout.CascadeInputTransparentProperty.PropertyName +#pragma warning restore CS0618 // Type or member is obsolete + ) { UpdateNativeWidget(); } diff --git a/src/Controls/src/Core/Compatibility/Tizen/PlatformSizeService.cs b/src/Controls/src/Core/Compatibility/Tizen/PlatformSizeService.cs deleted file mode 100644 index b50b2f06654b..000000000000 --- a/src/Controls/src/Core/Compatibility/Tizen/PlatformSizeService.cs +++ /dev/null @@ -1,21 +0,0 @@ -#nullable disable -using Microsoft.Maui.Controls.Internals; - -[assembly: Microsoft.Maui.Controls.Dependency(typeof(Microsoft.Maui.Controls.Compatibility.Platform.Tizen.PlatformSizeService))] - -namespace Microsoft.Maui.Controls.Compatibility.Platform.Tizen -{ - class PlatformSizeService : IPlatformSizeService - { - public SizeRequest GetPlatformSize(VisualElement view, double widthConstraint, double heightConstraint) - { - if (widthConstraint > 0 && heightConstraint > 0) - { - return view.Handler?.GetDesiredSize(widthConstraint, heightConstraint) ?? - new SizeRequest(); - } - - return new SizeRequest(); - } - } -} \ No newline at end of file diff --git a/src/Controls/src/Core/Compatibility/Windows/CaseConverter.cs b/src/Controls/src/Core/Compatibility/Windows/CaseConverter.cs index b382c1c99002..f1bbdc6facb2 100644 --- a/src/Controls/src/Core/Compatibility/Windows/CaseConverter.cs +++ b/src/Controls/src/Core/Compatibility/Windows/CaseConverter.cs @@ -4,7 +4,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public class CaseConverter : Microsoft.UI.Xaml.Data.IValueConverter + public partial class CaseConverter : Microsoft.UI.Xaml.Data.IValueConverter { public bool ConvertToUpper { get; set; } diff --git a/src/Controls/src/Core/Compatibility/Windows/CollapseWhenEmptyConverter.cs b/src/Controls/src/Core/Compatibility/Windows/CollapseWhenEmptyConverter.cs index 794f73004daf..93b7645377ad 100644 --- a/src/Controls/src/Core/Compatibility/Windows/CollapseWhenEmptyConverter.cs +++ b/src/Controls/src/Core/Compatibility/Windows/CollapseWhenEmptyConverter.cs @@ -4,7 +4,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public class CollapseWhenEmptyConverter : Microsoft.UI.Xaml.Data.IValueConverter + public partial class CollapseWhenEmptyConverter : Microsoft.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/src/Controls/src/Core/Compatibility/Windows/ColorConverter.cs b/src/Controls/src/Core/Compatibility/Windows/ColorConverter.cs index 91f3163093b5..529b8dadbcd3 100644 --- a/src/Controls/src/Core/Compatibility/Windows/ColorConverter.cs +++ b/src/Controls/src/Core/Compatibility/Windows/ColorConverter.cs @@ -8,7 +8,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public sealed class ColorConverter : Microsoft.UI.Xaml.Data.IValueConverter + public sealed partial class ColorConverter : Microsoft.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/src/Controls/src/Core/Compatibility/Windows/HeightConverter.cs b/src/Controls/src/Core/Compatibility/Windows/HeightConverter.cs index 9ec9a18b5c94..b0cfd1a1ed79 100644 --- a/src/Controls/src/Core/Compatibility/Windows/HeightConverter.cs +++ b/src/Controls/src/Core/Compatibility/Windows/HeightConverter.cs @@ -3,7 +3,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public sealed class HeightConverter : Microsoft.UI.Xaml.Data.IValueConverter + public sealed partial class HeightConverter : Microsoft.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/src/Controls/src/Core/Compatibility/Windows/HorizontalTextAlignmentConverter.cs b/src/Controls/src/Core/Compatibility/Windows/HorizontalTextAlignmentConverter.cs index afdb4c3058c9..fac102a692f6 100644 --- a/src/Controls/src/Core/Compatibility/Windows/HorizontalTextAlignmentConverter.cs +++ b/src/Controls/src/Core/Compatibility/Windows/HorizontalTextAlignmentConverter.cs @@ -3,7 +3,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public class HorizontalTextAlignmentConverter : Microsoft.UI.Xaml.Data.IValueConverter + public partial class HorizontalTextAlignmentConverter : Microsoft.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/src/Controls/src/Core/Compatibility/Windows/KeyboardConverter.cs b/src/Controls/src/Core/Compatibility/Windows/KeyboardConverter.cs index d750f3bd417d..e3fcc2cbd524 100644 --- a/src/Controls/src/Core/Compatibility/Windows/KeyboardConverter.cs +++ b/src/Controls/src/Core/Compatibility/Windows/KeyboardConverter.cs @@ -5,7 +5,7 @@ namespace Microsoft.Maui.Controls.Platform.Compatibility { - public class KeyboardConverter : Microsoft.UI.Xaml.Data.IValueConverter + public partial class KeyboardConverter : Microsoft.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/src/Controls/src/Core/Compatibility/Windows/PlatformSizeService.cs b/src/Controls/src/Core/Compatibility/Windows/PlatformSizeService.cs deleted file mode 100644 index a1374d080b8d..000000000000 --- a/src/Controls/src/Core/Compatibility/Windows/PlatformSizeService.cs +++ /dev/null @@ -1,21 +0,0 @@ -#nullable disable -using Microsoft.Maui.Controls.Internals; - -[assembly: Microsoft.Maui.Controls.Dependency(typeof(Microsoft.Maui.Controls.Compatibility.Platform.UWP.PlatformSizeService))] - -namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP -{ - class PlatformSizeService : IPlatformSizeService - { - public SizeRequest GetPlatformSize(VisualElement view, double widthConstraint, double heightConstraint) - { - if (widthConstraint > 0 && heightConstraint > 0) - { - return view.Handler?.GetDesiredSize(widthConstraint, heightConstraint) ?? - new SizeRequest(); - } - - return new SizeRequest(); - } - } -} \ No newline at end of file diff --git a/src/Controls/src/Core/Compatibility/iOS/Extensions/UIViewExtensions.cs b/src/Controls/src/Core/Compatibility/iOS/Extensions/UIViewExtensions.cs index 1cd6dce834ee..30e2417cf7e2 100644 --- a/src/Controls/src/Core/Compatibility/iOS/Extensions/UIViewExtensions.cs +++ b/src/Controls/src/Core/Compatibility/iOS/Extensions/UIViewExtensions.cs @@ -5,6 +5,8 @@ using static System.String; using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Graphics; +using System.Diagnostics.CodeAnalysis; + #if __MOBILE__ using ObjCRuntime; using UIKit; @@ -37,6 +39,7 @@ internal static IEnumerable DescendantsTree(this UIView self) } } + [Obsolete("Use IView.Measure or just call SizeThatFits directly on the UIView")] public static SizeRequest GetSizeRequest(this UIView self, double widthConstraint, double heightConstraint, double minimumWidth = -1, double minimumHeight = -1) { @@ -48,6 +51,7 @@ public static SizeRequest GetSizeRequest(this UIView self, double widthConstrain return new SizeRequest(request, minimum); } + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public static void SetBinding(this UIView view, string propertyName, BindingBase bindingBase, string updateSourceEventName = null) { diff --git a/src/Controls/src/Core/Compatibility/iOS/PlatformSizeService.cs b/src/Controls/src/Core/Compatibility/iOS/PlatformSizeService.cs deleted file mode 100644 index 843fabab8353..000000000000 --- a/src/Controls/src/Core/Compatibility/iOS/PlatformSizeService.cs +++ /dev/null @@ -1,21 +0,0 @@ -#nullable disable -using Microsoft.Maui.Controls.Internals; - -[assembly: Microsoft.Maui.Controls.Dependency(typeof(Microsoft.Maui.Controls.Compatibility.Platform.iOS.PlatformSizeService))] - -namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS -{ - class PlatformSizeService : IPlatformSizeService - { - public SizeRequest GetPlatformSize(VisualElement view, double widthConstraint, double heightConstraint) - { - if (widthConstraint > 0 && heightConstraint > 0) - { - return view.Handler?.GetDesiredSize(widthConstraint, heightConstraint) ?? - new SizeRequest(); - } - - return new SizeRequest(); - } - } -} \ No newline at end of file diff --git a/src/Controls/src/Core/ContentConverter.cs b/src/Controls/src/Core/ContentConverter.cs index b27fb7847cd6..992379bb30af 100644 --- a/src/Controls/src/Core/ContentConverter.cs +++ b/src/Controls/src/Core/ContentConverter.cs @@ -66,29 +66,45 @@ static Label ConvertToLabel(string textContent, ContentPresenter presenter) static void BindTextProperties(BindableObject content) { - BindProperty(content, TextElement.TextColorProperty, typeof(ITextElement)); - BindProperty(content, TextElement.CharacterSpacingProperty, typeof(ITextElement)); - BindProperty(content, TextElement.TextTransformProperty, typeof(ITextElement)); + var source = new RelativeBindingSource(RelativeBindingSourceMode.FindAncestor, typeof(ITextElement)); + if (ShouldSetBinding(content, TextElement.TextColorProperty)) + { + content.SetBinding(TextElement.TextColorProperty, static (ITextElement te) => te.TextColor, source: source); + } + + if (ShouldSetBinding(content, TextElement.CharacterSpacingProperty)) + { + content.SetBinding(TextElement.CharacterSpacingProperty, static (ITextElement te) => te.CharacterSpacing, source: source); + } + + if (ShouldSetBinding(content, TextElement.TextTransformProperty)) + { + content.SetBinding(TextElement.TextTransformProperty, static (ITextElement te) => te.TextTransform, source: source); + } } static void BindFontProperties(BindableObject content) { - BindProperty(content, FontElement.FontAttributesProperty, typeof(IFontElement)); - BindProperty(content, FontElement.FontSizeProperty, typeof(IFontElement)); - BindProperty(content, FontElement.FontFamilyProperty, typeof(IFontElement)); - } + var source = new RelativeBindingSource(RelativeBindingSourceMode.FindAncestor, typeof(IFontElement)); + if (ShouldSetBinding(content, FontElement.FontAttributesProperty)) + { + content.SetBinding(FontElement.FontAttributesProperty, static (IFontElement fe) => fe.FontAttributes, source: source); + } - static void BindProperty(BindableObject content, BindableProperty property, Type type) - { - if (content.IsSet(property) || content.GetIsBound(property)) + if (ShouldSetBinding(content, FontElement.FontSizeProperty)) { - // Don't override the property if user has already set it - return; + content.SetBinding(FontElement.FontSizeProperty, static (IFontElement fe) => fe.FontSize, source: source); } - content.SetBinding(property, - new Binding(property.PropertyName, - source: new RelativeBindingSource(RelativeBindingSourceMode.FindAncestor, type))); + if (ShouldSetBinding(content, FontElement.FontFamilyProperty)) + { + content.SetBinding(FontElement.FontFamilyProperty, static (IFontElement fe) => fe.FontFamily, source: source); + } + } + + static bool ShouldSetBinding(BindableObject content, BindableProperty property) + { + return !content.IsSet(property) && !content.GetIsBound(property); } static bool HasTemplateAncestor(ContentPresenter presenter, Type type) diff --git a/src/Controls/src/Core/ContentPage/ContentPage.cs b/src/Controls/src/Core/ContentPage/ContentPage.cs index 31a171452f8f..e8ff9244ca10 100644 --- a/src/Controls/src/Core/ContentPage/ContentPage.cs +++ b/src/Controls/src/Core/ContentPage/ContentPage.cs @@ -73,6 +73,15 @@ protected override Size MeasureOverride(double widthConstraint, double heightCon return this.ComputeDesiredSize(widthConstraint, heightConstraint); } + [Obsolete("Use ArrangeOverride instead")] + protected override void LayoutChildren(double x, double y, double width, double height) + { + // This call is redundant when a handler is attached because the handler just calls + // CrossPlatformArrange + if (Handler is null) + base.LayoutChildren(x, y, width, height); + } + protected override Size ArrangeOverride(Rect bounds) { Frame = this.ComputeFrame(bounds); diff --git a/src/Controls/src/Core/ContentPresenter.cs b/src/Controls/src/Core/ContentPresenter.cs index 6816bd1ddff5..8eb9de9b0ee3 100644 --- a/src/Controls/src/Core/ContentPresenter.cs +++ b/src/Controls/src/Core/ContentPresenter.cs @@ -3,11 +3,14 @@ using System.ComponentModel; using Microsoft.Maui.Graphics; using Microsoft.Maui.Layouts; +using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls { /// +#pragma warning disable CS0618 // Type or member is obsolete public class ContentPresenter : Compatibility.Layout, IContentView +#pragma warning restore CS0618 // Type or member is obsolete { /// public static BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), @@ -16,8 +19,12 @@ public class ContentPresenter : Compatibility.Layout, IContentView /// public ContentPresenter() { - SetBinding(ContentProperty, new Binding(ContentProperty.PropertyName, source: RelativeBindingSource.TemplatedParent, - converterParameter: this, converter: new ContentConverter())); + this.SetBinding( + ContentProperty, + static (IContentView view) => view.Content, + source: RelativeBindingSource.TemplatedParent, + converter: new ContentConverter(), + converterParameter: this); } /// @@ -30,17 +37,18 @@ public View Content object IContentView.Content => Content; IView IContentView.PresentedContent => Content; + [Obsolete("Use InvalidateArrange if you need to trigger a new arrange and then put your arrange logic inside ArrangeOverride instead")] protected override void LayoutChildren(double x, double y, double width, double height) { for (var i = 0; i < LogicalChildrenInternal.Count; i++) { Element element = LogicalChildrenInternal[i]; var child = element as View; - if (child != null) - LayoutChildIntoBoundingRegion(child, new Rect(x, y, width, height)); + child?.Arrange(new Rect(x, y, width, height)); } } + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { double widthRequest = WidthRequest; diff --git a/src/Controls/src/Core/ControlTemplate.cs b/src/Controls/src/Core/ControlTemplate.cs index 34fcc5ea1611..ace2459ac69a 100644 --- a/src/Controls/src/Core/ControlTemplate.cs +++ b/src/Controls/src/Core/ControlTemplate.cs @@ -14,7 +14,7 @@ public ControlTemplate() /// public ControlTemplate( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) : base(type) { } diff --git a/src/Controls/src/Core/Controls.Core.csproj b/src/Controls/src/Core/Controls.Core.csproj index 5ab191afca11..58deb310a4c7 100644 --- a/src/Controls/src/Core/Controls.Core.csproj +++ b/src/Controls/src/Core/Controls.Core.csproj @@ -1,7 +1,8 @@ - + netstandard2.1;netstandard2.0;$(_MauiDotNetTfm);$(MauiPlatforms) + $(TargetFrameworks);$(_MauiPreviousDotNetTfm);$(MauiPreviousPlatforms) Microsoft.Maui.Controls Microsoft.Maui.Controls enable @@ -21,6 +22,14 @@ .NET Multi-platform App UI (.NET MAUI) is a cross-platform framework for creating native mobile and desktop apps with C# and XAML. This package only contains the core C# and XAML objects used by .NET MAUI. Please install the Microsoft.Maui.Controls package to start using .NET MAUI. + + true + true + true + + $(NoWarn);IL2059 + + @@ -37,6 +46,18 @@ + + $(InterceptorsPreviewNamespaces);Microsoft.Maui.Controls.Generated + + $(CompilerResponseFile);WorkaroundXamlPreCompilePreviewFeatures.rsp + + + + + diff --git a/src/Controls/src/Core/DataTemplate.cs b/src/Controls/src/Core/DataTemplate.cs index 22e146c8bf40..4abc45c5c7d4 100644 --- a/src/Controls/src/Core/DataTemplate.cs +++ b/src/Controls/src/Core/DataTemplate.cs @@ -23,7 +23,7 @@ public DataTemplate() /// public DataTemplate( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) : base(type) { _id = Interlocked.Increment(ref idCounter); diff --git a/src/Controls/src/Core/DatePicker/DatePicker.Mapper.cs b/src/Controls/src/Core/DatePicker/DatePicker.Mapper.cs index 8a363702c097..0f34af68f51b 100644 --- a/src/Controls/src/Core/DatePicker/DatePicker.Mapper.cs +++ b/src/Controls/src/Core/DatePicker/DatePicker.Mapper.cs @@ -6,9 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class DatePicker { - [Obsolete("Use DatePickerHandler.Mapper instead.")] - public static IPropertyMapper ControlsDatePickerMapper = new ControlsMapper(DatePickerHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.DatePicker legacy behaviors diff --git a/src/Controls/src/Core/DoubleCollectionConverter.cs b/src/Controls/src/Core/DoubleCollectionConverter.cs index 42ac8a1ef800..9db3ae7cd184 100644 --- a/src/Controls/src/Core/DoubleCollectionConverter.cs +++ b/src/Controls/src/Core/DoubleCollectionConverter.cs @@ -10,13 +10,24 @@ namespace Microsoft.Maui.Controls public class DoubleCollectionConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - => sourceType == typeof(string); + => sourceType == typeof(string) + || sourceType == typeof(double[]) + || sourceType == typeof(float[]); public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => destinationType == typeof(string); public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { + if (value is double[] doublesArray) + { + return (DoubleCollection)doublesArray; + } + else if (value is float[] floatsArray) + { + return (DoubleCollection)floatsArray; + } + var strValue = value?.ToString(); string[] doubles = strValue.Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries); diff --git a/src/Controls/src/Core/Editor/Editor.Mapper.cs b/src/Controls/src/Core/Editor/Editor.Mapper.cs index 9ebe4dad1161..01ce7ee9e79e 100644 --- a/src/Controls/src/Core/Editor/Editor.Mapper.cs +++ b/src/Controls/src/Core/Editor/Editor.Mapper.cs @@ -6,10 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class Editor { - [Obsolete("Use EditorHandler.Mapper instead.")] - public static IPropertyMapper ControlsEditorMapper = - new ControlsMapper(EditorHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.Editor legacy behaviors diff --git a/src/Controls/src/Core/Effect.cs b/src/Controls/src/Core/Effect.cs index 12d7b67df3ab..405c17ee7b90 100644 --- a/src/Controls/src/Core/Effect.cs +++ b/src/Controls/src/Core/Effect.cs @@ -32,9 +32,9 @@ internal Effect() public static Effect Resolve(string name) { Effect result = null; - if (Internals.Registrar.Effects.TryGetValue(name, out Type effectType)) + if (Internals.Registrar.Effects.TryGetValue(name, out var effectType)) { - result = (Effect)DependencyResolver.ResolveOrCreate(effectType); + result = (Effect)DependencyResolver.ResolveOrCreate(effectType.Type); } if (result == null) diff --git a/src/Controls/src/Core/Element/Element.Mapper.cs b/src/Controls/src/Core/Element/Element.Mapper.cs index 350883d35f21..9b1d39ce456c 100644 --- a/src/Controls/src/Core/Element/Element.Mapper.cs +++ b/src/Controls/src/Core/Element/Element.Mapper.cs @@ -8,12 +8,6 @@ namespace Microsoft.Maui.Controls { public partial class Element { - /// - /// Maps UI information to platform-specific implementations for accessibility services - /// - [Obsolete("Use ViewHandler.ViewMapper instead.")] - public static IPropertyMapper ControlsElementMapper = new ControlsMapper(ViewHandler.ViewMapper); - internal static void RemapForControls() { ViewHandler.ViewMapper.ReplaceMapping(AutomationProperties.IsInAccessibleTreeProperty.PropertyName, MapAutomationPropertiesIsInAccessibleTree); diff --git a/src/Controls/src/Core/Element/Element.cs b/src/Controls/src/Core/Element/Element.cs index ad59ab4801db..734e475ecbc3 100644 --- a/src/Controls/src/Core/Element/Element.cs +++ b/src/Controls/src/Core/Element/Element.cs @@ -46,7 +46,7 @@ namespace Microsoft.Maui.Controls /// /// /// - public abstract partial class Element : BindableObject, IElementDefinition, INameScope, IElementController, IVisualTreeElement, Maui.IElement, IEffectControlProvider, IToolTipElement, IContextFlyoutElement, IControlsElement + public abstract partial class Element : BindableObject, IElementDefinition, INameScope, IElementController, IVisualTreeElement, Maui.IElement, IEffectControlProvider, IToolTipElement, IContextFlyoutElement, IControlsElement, IHandlerDisconnectPolicies { internal static readonly ReadOnlyCollection EmptyChildren = new ReadOnlyCollection(Array.Empty()); @@ -631,13 +631,38 @@ protected virtual void OnParentSet() (this as IPropertyPropagationController)?.PropagatePropertyChanged(null); } + HashSet _pendingHandlerUpdatesFromBPSet = new HashSet(); + private protected override void OnBindablePropertySet(BindableProperty property, object original, object value, bool changed, bool willFirePropertyChanged) + { + if(willFirePropertyChanged) + { + _pendingHandlerUpdatesFromBPSet.Add(property.PropertyName); + } + + base.OnBindablePropertySet(property, original, value, changed, willFirePropertyChanged); + _pendingHandlerUpdatesFromBPSet.Remove(property.PropertyName); + UpdateHandlerValue(property.PropertyName, changed); + + } + /// Method that is called when a bound property is changed. /// The name of the bound property that changed. protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) { - base.OnPropertyChanged(propertyName); + // If OnPropertyChanged is being called from a SetValue call on the BO we want the handler update to happen after + // the PropertyChanged Delegate on the BP and this OnPropertyChanged has fired. + // if you look at BO you'll see the order is this + // + // OnPropertyChanged(property.PropertyName); + // property.PropertyChanged?.Invoke(this, original, value); + // + // It can cause somewhat confusing behavior if the handler update happens between these two calls + // And the user has placed reacting code inside the BP.PropertyChanged callback + // + // If the OnPropertyChanged is being called from user code, we still want that to propagate to the mapper + bool waitForHandlerUpdateToFireFromBP = _pendingHandlerUpdatesFromBPSet.Contains(propertyName); - UpdateHandlerValue(propertyName); + base.OnPropertyChanged(propertyName); if (_effects?.Count > 0) { @@ -647,10 +672,20 @@ protected override void OnPropertyChanged([CallerMemberName] string propertyName effect?.SendOnElementPropertyChanged(args); } } + + if (!waitForHandlerUpdateToFireFromBP) + { + UpdateHandlerValue(propertyName, true); + } } - private protected virtual void UpdateHandlerValue(string property) => - Handler?.UpdateValue(property); + private protected virtual void UpdateHandlerValue(string property, bool valueChanged) + { + if (valueChanged) + { + Handler?.UpdateValue(property); + } + } internal IEnumerable Descendants() => Descendants(); @@ -753,7 +788,7 @@ internal void OnResourcesChanged(IEnumerable> value internal override void OnSetDynamicResource(BindableProperty property, string key, SetterSpecificity specificity) { base.OnSetDynamicResource(property, key, specificity); - if (!DynamicResources.TryGetValue(property, out var existing) || existing.Item2.CompareTo(specificity) <= 0) + if (!DynamicResources.TryGetValue(property, out var existing) || existing.Item2 <= specificity) DynamicResources[property] = (key, specificity); if (this.TryGetResource(key, out var value)) OnResourceChanged(property, value, specificity); @@ -1031,6 +1066,12 @@ void IEffectControlProvider.RegisterEffect(Effect effect) /// IFlyout IContextFlyoutElement.ContextFlyout => FlyoutBase.GetContextFlyout(this); + HandlerDisconnectPolicy IHandlerDisconnectPolicies.DisconnectPolicy + { + get => HandlerProperties.GetDisconnectPolicy(this); + set => HandlerProperties.SetDisconnectPolicy(this, value); + } + class TemporaryWrapper : IList { IReadOnlyList _inner; diff --git a/src/Controls/src/Core/ElementTemplate.cs b/src/Controls/src/Core/ElementTemplate.cs index 2b1bebe692d1..187f63bfc7a0 100644 --- a/src/Controls/src/Core/ElementTemplate.cs +++ b/src/Controls/src/Core/ElementTemplate.cs @@ -13,7 +13,7 @@ public class ElementTemplate : IElementDefinition Element _parent; bool _canRecycle; // aka IsDeclarative - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] readonly Type _type; internal ElementTemplate() @@ -21,7 +21,7 @@ internal ElementTemplate() } internal ElementTemplate( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) : this() { if (type == null) @@ -44,7 +44,8 @@ void IElementDefinition.AddResourcesChangedListener(Action _canRecycle; - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] internal Type Type => _type; Element IElementDefinition.Parent diff --git a/src/Controls/src/Core/Embedding/EmbeddingExtensions.cs b/src/Controls/src/Core/Embedding/EmbeddingExtensions.cs index 7831e9d6974f..e5f165cecca8 100644 --- a/src/Controls/src/Core/Embedding/EmbeddingExtensions.cs +++ b/src/Controls/src/Core/Embedding/EmbeddingExtensions.cs @@ -24,13 +24,16 @@ namespace Microsoft.Maui.Controls.Embedding; /// /// A set of extension methods that allow for embedding a MAUI view within a native application. /// -internal static class EmbeddingExtensions +public static class EmbeddingExtensions { /// /// Enables MAUI to be embedded in native platform application by injecting embedded handlers into the service collection. /// /// The instance. /// The instance. + /// + /// This is internal as it is exposed in Controls.Xaml since it needs to setup XAML defaults. + /// internal static MauiAppBuilder UseMauiEmbedding(this MauiAppBuilder builder) { #if ANDROID diff --git a/src/Controls/src/Core/Entry/Entry.Mapper.cs b/src/Controls/src/Core/Entry/Entry.Mapper.cs index a73cefd256a0..413f01b94078 100644 --- a/src/Controls/src/Core/Entry/Entry.Mapper.cs +++ b/src/Controls/src/Core/Entry/Entry.Mapper.cs @@ -6,10 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class Entry { - [Obsolete("Use EntryHandler.Mapper instead.")] - public static IPropertyMapper ControlsEntryMapper = - new ControlsMapper(EntryHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.Entry legacy behaviors diff --git a/src/Controls/src/Core/ExportEffectAttribute.cs b/src/Controls/src/Core/ExportEffectAttribute.cs index 4831b179d106..b8dfc10b60e0 100644 --- a/src/Controls/src/Core/ExportEffectAttribute.cs +++ b/src/Controls/src/Core/ExportEffectAttribute.cs @@ -1,5 +1,6 @@ #nullable disable using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls { @@ -10,7 +11,9 @@ namespace Microsoft.Maui.Controls public sealed class ExportEffectAttribute : Attribute { /// - public ExportEffectAttribute(Type effectType, string uniqueName) + public ExportEffectAttribute( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type effectType, + string uniqueName) { if (uniqueName.IndexOf(".", StringComparison.Ordinal) != -1) throw new ArgumentException("uniqueName must not contain a ."); @@ -20,6 +23,7 @@ public ExportEffectAttribute(Type effectType, string uniqueName) internal string Id { get; private set; } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] internal Type Type { get; private set; } } } \ No newline at end of file diff --git a/src/Controls/src/Core/FileImageSourceConverter.cs b/src/Controls/src/Core/FileImageSourceConverter.cs index fe75c3932551..ad1ae0242296 100644 --- a/src/Controls/src/Core/FileImageSourceConverter.cs +++ b/src/Controls/src/Core/FileImageSourceConverter.cs @@ -12,7 +12,7 @@ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceT => sourceType == typeof(string); public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - => true; + => destinationType == typeof(string); public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { diff --git a/src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs b/src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs index a19abe485580..8f74e8987301 100644 --- a/src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs +++ b/src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs @@ -6,9 +6,6 @@ namespace Microsoft.Maui.Controls /// public partial class FlyoutPage { - [Obsolete("Use FlyoutViewHandler.Mapper instead.")] - public static IPropertyMapper ControlsFlyoutPageMapper = new ControlsMapper(FlyoutViewHandler.Mapper); - internal new static void RemapForControls() { FlyoutViewHandler.Mapper.ReplaceMapping(nameof(FlyoutLayoutBehavior), MapFlyoutLayoutBehavior); diff --git a/src/Controls/src/Core/FlyoutPage/FlyoutPage.cs b/src/Controls/src/Core/FlyoutPage/FlyoutPage.cs index 333839a858b8..b5eb04f867f5 100644 --- a/src/Controls/src/Core/FlyoutPage/FlyoutPage.cs +++ b/src/Controls/src/Core/FlyoutPage/FlyoutPage.cs @@ -66,7 +66,7 @@ public Page Detail _detail?.SendAppearing(); } - previousDetail?.SendNavigatedFrom(new NavigatedFromEventArgs(_detail)); + previousDetail?.SendNavigatedFrom(new NavigatedFromEventArgs(_detail, NavigationType.PageSwap)); _detail?.SendNavigatedTo(new NavigatedToEventArgs(previousDetail)); } } @@ -121,7 +121,7 @@ public Page Flyout _flyout?.SendAppearing(); } - previousFlyout?.SendNavigatedFrom(new NavigatedFromEventArgs(_flyout)); + previousFlyout?.SendNavigatedFrom(new NavigatedFromEventArgs(_flyout, NavigationType.PageSwap)); _flyout?.SendNavigatedTo(new NavigatedToEventArgs(previousFlyout)); } } @@ -191,6 +191,7 @@ public virtual bool ShouldShowToolbarButton() return behavior != FlyoutLayoutBehavior.Split && !isSplitOnLandscape && !isSplitOnPortrait; } + [Obsolete("Use ArrangeOverride instead")] protected override void LayoutChildren(double x, double y, double width, double height) { if (Flyout == null || Detail == null) diff --git a/src/Controls/src/Core/FormattedString.cs b/src/Controls/src/Core/FormattedString.cs index da9198be4628..c4c83e6701a7 100644 --- a/src/Controls/src/Core/FormattedString.cs +++ b/src/Controls/src/Core/FormattedString.cs @@ -10,6 +10,7 @@ namespace Microsoft.Maui.Controls { /// [ContentProperty("Spans")] + [TypeConverter(typeof(FormattedStringConverter))] public class FormattedString : Element { readonly SpanCollection _spans = new SpanCollection(); @@ -87,5 +88,34 @@ protected override void ClearItems() base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed)); } } + + private sealed class FormattedStringConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + => sourceType == typeof(string); + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + => destinationType == typeof(string); + + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + if (value is string strValue) + { + return (FormattedString)strValue; + } + + throw new NotSupportedException(); + } + + public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + { + if (value is FormattedString formattedStr) + { + return (string)formattedStr; + } + + throw new NotSupportedException(); + } + } } } \ No newline at end of file diff --git a/src/Controls/src/Core/Frame/Frame.cs b/src/Controls/src/Core/Frame/Frame.cs index e040e154fe44..8c6a2a28ceff 100644 --- a/src/Controls/src/Core/Frame/Frame.cs +++ b/src/Controls/src/Core/Frame/Frame.cs @@ -7,6 +7,7 @@ namespace Microsoft.Maui.Controls { /// [ContentProperty(nameof(Content))] + [Obsolete("Frame is obsolete as of .NET 9. Please use Border instead.")] public partial class Frame : ContentView, IElementConfiguration, IPaddingElement, IBorderElement, IView, IContentView { /// Bindable property for . @@ -129,6 +130,7 @@ Size ICrossPlatformLayout.CrossPlatformMeasure(double widthConstraint, double he } } + [Obsolete("Frame is obsolete as of .NET 9. Please use Border instead.")] internal static class FrameExtensions { internal static bool IsClippedToBoundsSet(this Frame frame, bool defaultValue) => diff --git a/src/Controls/src/Core/HandlerAttribute.cs b/src/Controls/src/Core/HandlerAttribute.cs index 671ac6ddbb14..3c1794d95717 100644 --- a/src/Controls/src/Core/HandlerAttribute.cs +++ b/src/Controls/src/Core/HandlerAttribute.cs @@ -1,6 +1,7 @@ #nullable disable using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls { @@ -8,11 +9,11 @@ namespace Microsoft.Maui.Controls [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public abstract class HandlerAttribute : Attribute { - protected HandlerAttribute(Type handler, Type target) : this(handler, target, null) + protected HandlerAttribute(Type handler, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type target) : this(handler, target, null) { } - protected HandlerAttribute(Type handler, Type target, Type[] supportedVisuals) + protected HandlerAttribute(Type handler, [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type target, Type[] supportedVisuals) { SupportedVisuals = supportedVisuals ?? new[] { typeof(VisualMarker.DefaultVisual) }; TargetType = target; @@ -26,6 +27,7 @@ protected HandlerAttribute(Type handler, Type target, Type[] supportedVisuals) internal Type[] SupportedVisuals { get; private set; } internal Type HandlerType { get; private set; } + [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] internal Type TargetType { get; private set; } /// diff --git a/src/Controls/src/Core/Handlers/HandlerProperties.cs b/src/Controls/src/Core/Handlers/HandlerProperties.cs new file mode 100644 index 000000000000..c925264e99e9 --- /dev/null +++ b/src/Controls/src/Core/Handlers/HandlerProperties.cs @@ -0,0 +1,23 @@ +using Microsoft.Maui; + +namespace Microsoft.Maui.Controls +{ + public static class HandlerProperties + { + public static readonly BindableProperty DisconnectPolicyProperty = BindableProperty.CreateAttached( + "DisconnectPolicy", + typeof(HandlerDisconnectPolicy), + typeof(HandlerProperties), + HandlerDisconnectPolicy.Automatic); + + public static void SetDisconnectPolicy(BindableObject target, HandlerDisconnectPolicy value) + { + target.SetValue(DisconnectPolicyProperty, value); + } + + public static HandlerDisconnectPolicy GetDisconnectPolicy(BindableObject target) + { + return (HandlerDisconnectPolicy)target.GetValue(DisconnectPolicyProperty); + } + } +} diff --git a/src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs b/src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs index 9bcc1758eb3e..7926a57d7224 100644 --- a/src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs +++ b/src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs @@ -531,7 +531,9 @@ protected virtual void LayoutPropertyChanged(object sender, PropertyChangedEvent protected override void OnLayout(bool changed, int l, int t, int r, int b) { base.OnLayout(changed, l, t, r, b); +#pragma warning disable CS0618 // Obsolete AViewCompat.SetClipBounds(this, new ARect(0, 0, Width, Height)); +#pragma warning restore CS0618 // Obsolete // After a direct (non-animated) scroll operation, we may need to make adjustments // to align the target item; if an adjustment is pending, execute it here. diff --git a/src/Controls/src/Core/Handlers/Items/SelectableItemsViewHandler.Windows.cs b/src/Controls/src/Core/Handlers/Items/SelectableItemsViewHandler.Windows.cs index 821f83a0bcb5..35f765d72132 100644 --- a/src/Controls/src/Core/Handlers/Items/SelectableItemsViewHandler.Windows.cs +++ b/src/Controls/src/Core/Handlers/Items/SelectableItemsViewHandler.Windows.cs @@ -216,7 +216,7 @@ protected override void UpdateItemsSource() _ignorePlatformSelectionChange = false; } - class SelectionModeConvert : Microsoft.UI.Xaml.Data.IValueConverter + partial class SelectionModeConvert : Microsoft.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/src/Controls/src/Core/Handlers/Items/Tizen/ItemTemplateAdaptor.cs b/src/Controls/src/Core/Handlers/Items/Tizen/ItemTemplateAdaptor.cs index 5b116649ff4e..82e7a05f34ab 100644 --- a/src/Controls/src/Core/Handlers/Items/Tizen/ItemTemplateAdaptor.cs +++ b/src/Controls/src/Core/Handlers/Items/Tizen/ItemTemplateAdaptor.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Globalization; +using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Graphics; using Tizen.UIExtensions.NUI; using NView = Tizen.NUI.BaseComponents.View; @@ -435,7 +436,7 @@ static View CreateView() { TextColor = Colors.Black, }; - label.SetBinding(XLabel.TextProperty, new Binding(".", converter: new ToTextConverter())); + label.SetBinding(XLabel.TextProperty, static (object source) => source, converter: new ToTextConverter()); return new Controls.StackLayout { diff --git a/src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs b/src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs index 2bcb4ba77133..7edc7e9c6f9e 100644 --- a/src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs +++ b/src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs @@ -541,13 +541,13 @@ protected void RemeasureLayout(VisualElement formsElement) { if (IsHorizontal) { - var request = formsElement.Measure(double.PositiveInfinity, CollectionView.Frame.Height, MeasureFlags.IncludeMargins); - Controls.Compatibility.Layout.LayoutChildIntoBoundingRegion(formsElement, new Rect(0, 0, request.Request.Width, CollectionView.Frame.Height)); + var request = formsElement.Measure(double.PositiveInfinity, CollectionView.Frame.Height); + formsElement.Arrange(new Rect(0, 0, request.Width, CollectionView.Frame.Height)); } else { - var request = formsElement.Measure(CollectionView.Frame.Width, double.PositiveInfinity, MeasureFlags.IncludeMargins); - Controls.Compatibility.Layout.LayoutChildIntoBoundingRegion(formsElement, new Rect(0, 0, CollectionView.Frame.Width, request.Request.Height)); + var request = formsElement.Measure(CollectionView.Frame.Width, double.PositiveInfinity); + formsElement.Arrange(new Rect(0, 0, CollectionView.Frame.Width, request.Height)); } } diff --git a/src/Controls/src/Core/Handlers/Items/iOS/ObservableItemsSource.cs b/src/Controls/src/Core/Handlers/Items/iOS/ObservableItemsSource.cs index 6415779de709..0d9d0f604787 100644 --- a/src/Controls/src/Core/Handlers/Items/iOS/ObservableItemsSource.cs +++ b/src/Controls/src/Core/Handlers/Items/iOS/ObservableItemsSource.cs @@ -178,8 +178,29 @@ protected virtual NSIndexPath[] CreateIndexesFrom(int startIndex, int count) return IndexPathHelpers.GenerateIndexPathRange(_section, startIndex, count); } + private protected virtual bool ShouldReload(NotifyCollectionChangedEventArgs args) + { + if (args.Action == NotifyCollectionChangedAction.Remove) + { + // INCC implementation isn't giving us enough information to know where the removed items were in the + // collection. So the best we can do is a ReloadData() + var startIndex = args.OldStartingIndex; + if (startIndex < 0) + { + return true; + } + } + return false; + } + void Add(NotifyCollectionChangedEventArgs args) { + if (ShouldReload(args)) + { + Reload(); + return; + } + var count = args.NewItems.Count; Count += count; var startIndex = args.NewStartingIndex > -1 ? args.NewStartingIndex : IndexOf(args.NewItems[0]); @@ -192,10 +213,8 @@ void Remove(NotifyCollectionChangedEventArgs args) { var startIndex = args.OldStartingIndex; - if (startIndex < 0) + if (ShouldReload(args)) { - // INCC implementation isn't giving us enough information to know where the removed items were in the - // collection. So the best we can do is a ReloadData() Reload(); return; } diff --git a/src/Controls/src/Core/Handlers/Items2/CarouselViewHandler2.iOS.cs b/src/Controls/src/Core/Handlers/Items2/CarouselViewHandler2.iOS.cs new file mode 100644 index 000000000000..fd1ed3f474bb --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/CarouselViewHandler2.iOS.cs @@ -0,0 +1,211 @@ +#nullable disable +using System; +using Foundation; +using Microsoft.Maui.Controls.Handlers.Items; +using Microsoft.Maui.Graphics; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public partial class CarouselViewHandler2 + { + + public CarouselViewHandler2() : base(Mapper) + { + + + } + public CarouselViewHandler2(PropertyMapper mapper = null) : base(mapper ?? Mapper) + { + + } + + public static PropertyMapper Mapper = new(ItemsViewMapper) + { + + [Controls.CarouselView.IsSwipeEnabledProperty.PropertyName] = MapIsSwipeEnabled, + [Controls.CarouselView.PeekAreaInsetsProperty.PropertyName] = MapPeekAreaInsets, + [Controls.CarouselView.IsBounceEnabledProperty.PropertyName] = MapIsBounceEnabled, + [Controls.CarouselView.PositionProperty.PropertyName] = MapPosition, + [Controls.CarouselView.CurrentItemProperty.PropertyName] = MapCurrentItem + }; + } + + public partial class CarouselViewHandler2 : ItemsViewHandler2 + { + protected override CarouselViewController2 CreateController(CarouselView newElement, UICollectionViewLayout layout) + => new(newElement, layout); + + protected override UICollectionViewLayout SelectLayout() + { + bool IsHorizontal = VirtualView.ItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal; + UICollectionViewScrollDirection scrollDirection = IsHorizontal ? UICollectionViewScrollDirection.Horizontal : UICollectionViewScrollDirection.Vertical; + + NSCollectionLayoutDimension itemWidth = NSCollectionLayoutDimension.CreateFractionalWidth(1); + NSCollectionLayoutDimension itemHeight = NSCollectionLayoutDimension.CreateFractionalHeight(1); + NSCollectionLayoutDimension groupWidth = NSCollectionLayoutDimension.CreateFractionalWidth(1); + NSCollectionLayoutDimension groupHeight = NSCollectionLayoutDimension.CreateFractionalHeight(1); + nfloat itemSpacing = 0; + + var layout = new UICollectionViewCompositionalLayout((sectionIndex, environment) => + { + if (VirtualView is null) + { + return null; + } + double sectionMargin = 0.0; + if (!IsHorizontal) + { + sectionMargin = VirtualView.PeekAreaInsets.VerticalThickness / 2; + var newGroupHeight = environment.Container.ContentSize.Height - VirtualView.PeekAreaInsets.VerticalThickness; + groupHeight = NSCollectionLayoutDimension.CreateAbsolute((nfloat)newGroupHeight); + groupWidth = NSCollectionLayoutDimension.CreateFractionalWidth(1); + } + else + { + sectionMargin = VirtualView.PeekAreaInsets.HorizontalThickness / 2; + var newGroupWidth = environment.Container.ContentSize.Width - VirtualView.PeekAreaInsets.HorizontalThickness; + groupWidth = NSCollectionLayoutDimension.CreateAbsolute((nfloat)newGroupWidth); + groupHeight = NSCollectionLayoutDimension.CreateFractionalHeight(1); + } + + // Each item has a size + var itemSize = NSCollectionLayoutSize.Create(itemWidth, itemHeight); + // Create the item itself from the size + var item = NSCollectionLayoutItem.Create(layoutSize: itemSize); + + //item.ContentInsets = new NSDirectionalEdgeInsets(0, itemInset, 0, 0); + + var groupSize = NSCollectionLayoutSize.Create(groupWidth, groupHeight); + + var group = IsHorizontal ? NSCollectionLayoutGroup.GetHorizontalGroup(groupSize, item, 1) : + NSCollectionLayoutGroup.GetVerticalGroup(groupSize, item, 1); + + // Create our section layout + var section = NSCollectionLayoutSection.Create(group: group); + section.InterGroupSpacing = itemSpacing; + section.OrthogonalScrollingBehavior = UICollectionLayoutSectionOrthogonalScrollingBehavior.GroupPagingCentered; + section.VisibleItemsInvalidationHandler = (items, offset, env) => + { + //This will allow us to SetPosition when we are scrolling the items + //based on the current page + var page = (offset.X + sectionMargin) / env.Container.ContentSize.Width; + + // Check if we not are at the beginning or end of the page and if we have items + if (Math.Abs(page % 1) > (double.Epsilon * 100) || Controller.ItemsSource.ItemCount <= 0) + { + return; + } + + var pageIndex = (int)page; + var carouselPosition = pageIndex; + + var cv2Controller = (CarouselViewController2)Controller; + + //If we are looping, we need to get the correct position + if (ItemsView.Loop) + { + var maxIndex = (Controller.ItemsSource as ILoopItemsViewSource).LoopCount - 1; + + //To mimic looping, we needed to modify the ItemSource and inserted a new item at the beginning and at the end + if (pageIndex == maxIndex) + { + //When at last item, we need to change to 2nd item, so we can scroll right or left + pageIndex = 1; + } + else if (pageIndex == 0) + { + //When at first item, need to change to one before last, so we can scroll right or left + pageIndex = maxIndex - 1; + } + + //since we added one item at the beginning of our ItemSource, we need to subtract one + carouselPosition = pageIndex - 1; + + if (ItemsView.Position != carouselPosition) + { + //If we are updating the ItemsSource, we don't want to scroll the CollectionView + if (cv2Controller.IsUpdating()) + { + return; + } + + var goToIndexPath = cv2Controller.GetScrollToIndexPath(carouselPosition); + + //This will move the carousel to fake the loop + Controller.CollectionView.ScrollToItem(NSIndexPath.FromItemSection(pageIndex, 0), UICollectionViewScrollPosition.Left, false); + + } + } + + //Update the CarouselView position + cv2Controller?.SetPosition(carouselPosition); + + }; + return section; + }); + + return layout; + } + + protected override void ScrollToRequested(object sender, ScrollToRequestEventArgs args) + { + if (VirtualView?.Loop == true) + { + var goToIndexPath = (Controller as CarouselViewController2).GetScrollToIndexPath(args.Index); + + if (!IsIndexPathValid(goToIndexPath)) + { + return; + } + + bool IsHorizontal = VirtualView.ItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal; + UICollectionViewScrollDirection scrollDirection = IsHorizontal ? UICollectionViewScrollDirection.Horizontal : UICollectionViewScrollDirection.Vertical; + + Controller.CollectionView.ScrollToItem(goToIndexPath, + args.ScrollToPosition.ToCollectionViewScrollPosition(scrollDirection), // TODO: Fix _layout.ScrollDirection), + args.IsAnimated); + } + else + { + base.ScrollToRequested(sender, args); + } + } + + public static void MapIsSwipeEnabled(CarouselViewHandler2 handler, CarouselView carouselView) + { + handler.Controller.CollectionView.ScrollEnabled = carouselView.IsSwipeEnabled; + } + + public static void MapIsBounceEnabled(CarouselViewHandler2 handler, CarouselView carouselView) + { + handler.Controller.CollectionView.Bounces = carouselView.IsBounceEnabled; + } + + public static void MapPeekAreaInsets(CarouselViewHandler2 handler, CarouselView carouselView) + { + handler.UpdateLayout(); + } + + public static void MapCurrentItem(CarouselViewHandler2 handler, CarouselView carouselView) + { + (handler.Controller as CarouselViewController2)?.UpdateFromCurrentItem(); + } + + public static void MapPosition(CarouselViewHandler2 handler, CarouselView carouselView) + { + // If the initial position hasn't been set, we have a UpdateInitialPosition call on CarouselViewController2 + // that will handle this so we want to skip this mapper call. We need to wait for the CollectionView to be ready + if (handler.Controller is CarouselViewController2 CarouselViewController2 && CarouselViewController2.InitialPositionSet) + { + CarouselViewController2.UpdateFromPosition(); + } + } + + public static void MapLoop(CarouselViewHandler2 handler, CarouselView carouselView) + { + (handler.Controller as CarouselViewController2)?.UpdateLoop(); + } + + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/CollectionViewHandler2.iOS.cs b/src/Controls/src/Core/Handlers/Items2/CollectionViewHandler2.iOS.cs new file mode 100644 index 000000000000..f30f433e2426 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/CollectionViewHandler2.iOS.cs @@ -0,0 +1,210 @@ +#nullable disable +using System; +using System.Collections.Generic; +using System.Text; +using Foundation; +using Microsoft.Maui.Handlers; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal class LayoutHeaderFooterInfo + { + public IView FooterView { get; set; } + public IView HeaderView { get; set; } + public DataTemplate FooterTemplate { get; set; } + public DataTemplate HeaderTemplate { get; set; } + public bool HasHeader { get; set; } + public bool HasFooter { get; set; } + } + + internal class LayoutGroupingInfo + { + public bool IsGrouped { get; set; } + public bool HasHeader { get; set; } + public bool HasFooter { get; set; } + } + + internal class LayoutSnapInfo + { + public SnapPointsAlignment SnapAligment { get; set; } + public SnapPointsType SnapType { get; set; } + } + + public partial class CollectionViewHandler2 + { + + public CollectionViewHandler2() : base(Mapper) + { + + + } + public CollectionViewHandler2(PropertyMapper mapper = null) : base(mapper ?? Mapper) + { + + } + + public static PropertyMapper Mapper = new(ItemsViewMapper) + { + [ReorderableItemsView.CanReorderItemsProperty.PropertyName] = MapCanReorderItems, + [GroupableItemsView.IsGroupedProperty.PropertyName] = MapIsGrouped, + [SelectableItemsView.SelectedItemProperty.PropertyName] = MapSelectedItem, + [SelectableItemsView.SelectedItemsProperty.PropertyName] = MapSelectedItems, + [SelectableItemsView.SelectionModeProperty.PropertyName] = MapSelectionMode, + [StructuredItemsView.HeaderTemplateProperty.PropertyName] = MapHeaderTemplate, + [StructuredItemsView.FooterTemplateProperty.PropertyName] = MapFooterTemplate, + [StructuredItemsView.HeaderProperty.PropertyName] = MapHeaderTemplate, + [StructuredItemsView.FooterProperty.PropertyName] = MapFooterTemplate, + }; + } + + public partial class CollectionViewHandler2 : ItemsViewHandler2 + { + // Reorderable + protected override ItemsViewController2 CreateController(ReorderableItemsView itemsView, UICollectionViewLayout layout) + => new ReorderableItemsViewController2(itemsView, layout); + + public static void MapCanReorderItems(CollectionViewHandler2 handler, ReorderableItemsView itemsView) + { + (handler.Controller as ReorderableItemsViewController2)?.UpdateCanReorderItems(); + } + + // Groupable + protected override void ScrollToRequested(object sender, ScrollToRequestEventArgs args) + { + if (WillNeedScrollAdjustment(args)) + { + if (args.IsAnimated) + { + (Controller as GroupableItemsViewController2)?.SetScrollAnimationEndedCallback(() => base.ScrollToRequested(sender, args)); + } + else + { + base.ScrollToRequested(sender, args); + } + } + + base.ScrollToRequested(sender, args); + } + + public static void MapIsGrouped(CollectionViewHandler2 handler, GroupableItemsView itemsView) + { + handler.Controller?.UpdateItemsSource(); + } + + bool WillNeedScrollAdjustment(ScrollToRequestEventArgs args) + { + return ItemsView.ItemSizingStrategy == ItemSizingStrategy.MeasureAllItems + && ItemsView.IsGrouped + && (args.ScrollToPosition == ScrollToPosition.End || args.ScrollToPosition == ScrollToPosition.MakeVisible); + } + + + // Selectable + public static void MapItemsSource(CollectionViewHandler2 handler, SelectableItemsView itemsView) + { + ItemsViewHandler2.MapItemsSource(handler, itemsView); + MapSelectedItem(handler, itemsView); + } + + public static void MapSelectedItem(CollectionViewHandler2 handler, SelectableItemsView itemsView) + { + (handler.Controller as SelectableItemsViewController2)?.UpdatePlatformSelection(); + } + + public static void MapSelectedItems(CollectionViewHandler2 handler, SelectableItemsView itemsView) + { + (handler.Controller as SelectableItemsViewController2)?.UpdatePlatformSelection(); + } + + public static void MapSelectionMode(CollectionViewHandler2 handler, SelectableItemsView itemsView) + { + (handler.Controller as SelectableItemsViewController2)?.UpdateSelectionMode(); + } + + + // Structured + protected override UICollectionViewLayout SelectLayout() + { + var headerFooterInfo = new LayoutHeaderFooterInfo(); + var groupInfo = new LayoutGroupingInfo(); + + if (ItemsView is GroupableItemsView groupableItemsView && groupableItemsView.IsGrouped) + { + groupInfo.IsGrouped = groupableItemsView.IsGrouped; + groupInfo.HasHeader = groupableItemsView.GroupHeaderTemplate is not null; + groupInfo.HasFooter = groupableItemsView.GroupFooterTemplate is not null; + } + + if (ItemsView is StructuredItemsView structuredItemsView) + { + headerFooterInfo.HeaderTemplate = structuredItemsView.HeaderTemplate; + headerFooterInfo.FooterTemplate = structuredItemsView.FooterTemplate; + if (structuredItemsView.Header is View headerView) + { + headerFooterInfo.HeaderView = headerView; + } + if (structuredItemsView.Footer is View footerView) + { + headerFooterInfo.FooterView = footerView; + } + headerFooterInfo.HasHeader = structuredItemsView.Header is not null; + headerFooterInfo.HasFooter = structuredItemsView.Footer is not null; + } + + var itemSizingStrategy = ItemsView.ItemSizingStrategy; + var itemsLayout = ItemsView.ItemsLayout; + + //TODO: Find a better way to do this + itemsLayout.PropertyChanged += (sender, args) => + { + if (args.PropertyName == nameof(ItemsLayout.SnapPointsAlignment) || + args.PropertyName == nameof(ItemsLayout.SnapPointsType) || + args.PropertyName == nameof(GridItemsLayout.VerticalItemSpacing) || + args.PropertyName == nameof(GridItemsLayout.HorizontalItemSpacing) || + args.PropertyName == nameof(GridItemsLayout.Span) || + args.PropertyName == nameof(LinearItemsLayout.ItemSpacing)) + + { + UpdateLayout(); + } + }; + + if (itemsLayout is GridItemsLayout gridItemsLayout) + { + return LayoutFactory2.CreateGrid(gridItemsLayout, groupInfo, headerFooterInfo); + } + + if (itemsLayout is LinearItemsLayout listItemsLayout) + { + return LayoutFactory2.CreateList(listItemsLayout, groupInfo, headerFooterInfo); + } + + // Fall back to vertical list + return LayoutFactory2.CreateList(new LinearItemsLayout(ItemsLayoutOrientation.Vertical), groupInfo, headerFooterInfo); + } + + public static void MapHeaderTemplate(CollectionViewHandler2 handler, StructuredItemsView itemsView) + { + handler.UpdateLayout(); + // (handler.Controller as StructuredItemsViewController2)?.UpdateHeaderView(); + } + + public static void MapFooterTemplate(CollectionViewHandler2 handler, StructuredItemsView itemsView) + { + handler.UpdateLayout(); + //(handler.Controller as StructuredItemsViewController2)?.UpdateFooterView(); + } + + public static void MapItemsLayout(CollectionViewHandler2 handler, StructuredItemsView itemsView) + { + handler.UpdateLayout(); + } + + public static void MapItemSizingStrategy(CollectionViewHandler2 handler, StructuredItemsView itemsView) + { + handler.UpdateLayout(); + } + } +} diff --git a/src/Controls/src/Core/Handlers/Items2/ItemsViewHandler2.iOS.cs b/src/Controls/src/Core/Handlers/Items2/ItemsViewHandler2.iOS.cs new file mode 100644 index 000000000000..d4f994bb2397 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/ItemsViewHandler2.iOS.cs @@ -0,0 +1,212 @@ +#nullable disable +using System; +using System.Collections.Generic; +using System.Text; +using Foundation; +using Microsoft.Maui.Graphics; +using Microsoft.Maui.Handlers; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public abstract partial class ItemsViewHandler2 : ViewHandler where TItemsView : ItemsView + { + public ItemsViewHandler2() : base(ItemsViewMapper) + { + + } + + public ItemsViewHandler2(PropertyMapper mapper = null) : base(mapper ?? ItemsViewMapper) + { + + } + + public static PropertyMapper> ItemsViewMapper = new(ViewMapper) + { + [Controls.ItemsView.ItemsSourceProperty.PropertyName] = MapItemsSource, + [Controls.ItemsView.HorizontalScrollBarVisibilityProperty.PropertyName] = MapHorizontalScrollBarVisibility, + [Controls.ItemsView.VerticalScrollBarVisibilityProperty.PropertyName] = MapVerticalScrollBarVisibility, + [Controls.ItemsView.ItemTemplateProperty.PropertyName] = MapItemTemplate, + [Controls.ItemsView.EmptyViewProperty.PropertyName] = MapEmptyView, + [Controls.ItemsView.EmptyViewTemplateProperty.PropertyName] = MapEmptyViewTemplate, + [Controls.ItemsView.FlowDirectionProperty.PropertyName] = MapFlowDirection, + [Controls.ItemsView.IsVisibleProperty.PropertyName] = MapIsVisible, + [Controls.ItemsView.ItemsUpdatingScrollModeProperty.PropertyName] = MapItemsUpdatingScrollMode + }; + + UICollectionViewLayout _layout; + + protected override void DisconnectHandler(UIView platformView) + { + ItemsView.ScrollToRequested -= ScrollToRequested; + _layout = null; + MauiContext?.GetDispatcher()?.Dispatch(() => + { + Controller?.DisposeItemsSource(); + }); + base.DisconnectHandler(platformView); + } + + protected override void ConnectHandler(UIView platformView) + { + base.ConnectHandler(platformView); + Controller.CollectionView.BackgroundColor = UIColor.Clear; + ItemsView.ScrollToRequested += ScrollToRequested; + } + + private protected override UIView OnCreatePlatformView() + { + UpdateLayout(); + Controller = CreateController(ItemsView, _layout); + return base.OnCreatePlatformView(); + } + + protected TItemsView ItemsView => VirtualView; + + protected internal ItemsViewController2 Controller { get; private set; } + + protected abstract UICollectionViewLayout SelectLayout(); + + protected abstract ItemsViewController2 CreateController(TItemsView newElement, UICollectionViewLayout layout); + + protected override UIView CreatePlatformView() => Controller?.View; + + public static void MapItemsSource(ItemsViewHandler2 handler, ItemsView itemsView) + { + MapItemsUpdatingScrollMode(handler, itemsView); + handler.Controller?.UpdateItemsSource(); + } + + public static void MapHorizontalScrollBarVisibility(ItemsViewHandler2 handler, ItemsView itemsView) + { + handler.Controller?.CollectionView?.UpdateHorizontalScrollBarVisibility(itemsView.HorizontalScrollBarVisibility); + } + + public static void MapVerticalScrollBarVisibility(ItemsViewHandler2 handler, ItemsView itemsView) + { + handler.Controller?.CollectionView?.UpdateVerticalScrollBarVisibility(itemsView.VerticalScrollBarVisibility); + } + + public static void MapItemTemplate(ItemsViewHandler2 handler, ItemsView itemsView) + { + handler.UpdateLayout(); + } + + public static void MapEmptyView(ItemsViewHandler2 handler, ItemsView itemsView) + { + handler.Controller?.UpdateEmptyView(); + } + + public static void MapEmptyViewTemplate(ItemsViewHandler2 handler, ItemsView itemsView) + { + handler.Controller?.UpdateEmptyView(); + } + + public static void MapFlowDirection(ItemsViewHandler2 handler, ItemsView itemsView) + { + handler.Controller?.UpdateFlowDirection(); + } + + public static void MapIsVisible(ItemsViewHandler2 handler, ItemsView itemsView) + { + handler.Controller?.UpdateVisibility(); + } + + public static void MapItemsUpdatingScrollMode(ItemsViewHandler2 handler, ItemsView itemsView) + { + // TODO: Fix handler._layout.ItemsUpdatingScrollMode = itemsView.ItemsUpdatingScrollMode; + } + + //TODO: this is being called 2 times on startup, one from OnCreatePlatformView and otehr from the mapper for the layout + protected virtual void UpdateLayout() + { + _layout = SelectLayout(); + Controller?.UpdateLayout(_layout); + } + + protected virtual void ScrollToRequested(object sender, ScrollToRequestEventArgs args) + { + using (var indexPath = DetermineIndex(args)) + { + if (!IsIndexPathValid(indexPath)) + { + // Specified path wasn't valid, or item wasn't found + return; + } + + var position = Items.ScrollToPositionExtensions.ToCollectionViewScrollPosition(args.ScrollToPosition, UICollectionViewScrollDirection.Vertical); + + Controller.CollectionView.ScrollToItem(indexPath, + position, args.IsAnimated); + } + + NSIndexPath DetermineIndex(ScrollToRequestEventArgs args) + { + if (args.Mode == ScrollToMode.Position) + { + if (args.GroupIndex == -1) + { + return NSIndexPath.Create(0, args.Index); + } + + return NSIndexPath.Create(args.GroupIndex, args.Index); + } + + return Controller.GetIndexForItem(args.Item); + } + } + + protected bool IsIndexPathValid(NSIndexPath indexPath) + { + if (indexPath.Item < 0 || indexPath.Section < 0) + { + return false; + } + + var collectionView = Controller.CollectionView; + if (indexPath.Section >= collectionView.NumberOfSections()) + { + return false; + } + + if (indexPath.Item >= collectionView.NumberOfItemsInSection(indexPath.Section)) + { + return false; + } + + return true; + } + + // public override Size GetDesiredSize(double widthConstraint, double heightConstraint) + // { + // var size = base.GetDesiredSize(widthConstraint, heightConstraint); + + // var potentialContentSize = Controller.GetSize(); + + + // System.Diagnostics.Debug.WriteLine($"potentialContentSize: {potentialContentSize}"); + // // If contentSize comes back null, it means none of the content has been realized yet; + // // we need to return the expansive size the collection view wants by default to get + // // it to start measuring its content + // if (potentialContentSize == null) + // { + // return size; + // } + + // var contentSize = potentialContentSize.Value; + + // // If contentSize does have a value, our target size is the smaller of it and the constraints + + // size.Width = contentSize.Width <= widthConstraint ? contentSize.Width : widthConstraint; + // size.Height = contentSize.Height <= heightConstraint ? contentSize.Height : heightConstraint; + + // var virtualView = this.VirtualView as IView; + + // size.Width = ViewHandlerExtensions.ResolveConstraints(size.Width, virtualView.Width, virtualView.MinimumWidth, virtualView.MaximumWidth); + // size.Height = ViewHandlerExtensions.ResolveConstraints(size.Height, virtualView.Height, virtualView.MinimumHeight, virtualView.MaximumHeight); + + // return size; + // } + } +} diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/CarouselViewController2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/CarouselViewController2.cs new file mode 100644 index 000000000000..1f426d8f9ef1 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/CarouselViewController2.cs @@ -0,0 +1,677 @@ +#nullable disable +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using CoreGraphics; +using Foundation; +using Microsoft.Maui.ApplicationModel; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class CarouselViewController2 : ItemsViewController2 + { + bool _isUpdating = false; + int _section = 0; + CarouselViewLoopManager _carouselViewLoopManager; + + // We need to keep track of the old views to update the visual states + // if this is null we are not attached to the window + List _oldViews; + Items.ILoopItemsViewSource LoopItemsSource => ItemsSource as Items.ILoopItemsViewSource; + + public CarouselViewController2(CarouselView itemsView, UICollectionViewLayout layout) : base(itemsView, layout) + { + CollectionView.AllowsSelection = false; + CollectionView.AllowsMultipleSelection = false; + } + + private protected override NSIndexPath GetAdjustedIndexPathForItemSource(NSIndexPath indexPath) + { + return NSIndexPath.FromItemSection(GetIndexFromIndexPath(indexPath), _section); + } + + public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath) + { + UICollectionViewCell cell; + + cell = base.GetCell(collectionView, indexPath); + + var element = (cell as TemplatedCell2)?.PlatformHandler?.VirtualView as VisualElement; + + if (element is not null) + { + VisualStateManager.GoToState(element, CarouselView.DefaultItemVisualState); + } + + return cell; + } + + public override nint GetItemsCount(UICollectionView collectionView, nint section) => LoopItemsSource.LoopCount; + + void InitializeCarouselViewLoopManager() + { + if (_carouselViewLoopManager is null) + { + _carouselViewLoopManager = new CarouselViewLoopManager(); + _carouselViewLoopManager.SetItemsSource(LoopItemsSource); + } + } + + public override void ViewDidLoad() + { + InitializeCarouselViewLoopManager(); + base.ViewDidLoad(); + } + + public override void ViewWillLayoutSubviews() + { + base.ViewWillLayoutSubviews(); + UpdateVisualStates(); + } + + + public override async void ViewDidLayoutSubviews() + { + base.ViewDidLayoutSubviews(); + await UpdateInitialPosition(); + } + + public override void DraggingStarted(UIScrollView scrollView) + { + // _isDragging = true; + ItemsView?.SetIsDragging(true); + } + + public override void DraggingEnded(UIScrollView scrollView, bool willDecelerate) + { + ItemsView?.SetIsDragging(false); + //_isDragging = false; + } + + public override void UpdateItemsSource() + { + UnsubscribeCollectionItemsSourceChanged(ItemsSource); + _isUpdating = true; + base.UpdateItemsSource(); + //we don't need to Subscribe because base calls CreateItemsViewSource + _carouselViewLoopManager?.SetItemsSource(LoopItemsSource); + + if (InitialPositionSet && ItemsView is CarouselView carousel) + { + carousel.SetValueFromRenderer(CarouselView.CurrentItemProperty, null); + carousel.SetValueFromRenderer(CarouselView.PositionProperty, 0); + } + _isUpdating = false; + } + + protected override bool IsHorizontal => ItemsView?.ItemsLayout?.Orientation == ItemsLayoutOrientation.Horizontal; + + protected override UICollectionViewDelegateFlowLayout CreateDelegator() => new CarouselViewDelegator2(ItemsViewLayout, this); + + protected override string DetermineCellReuseId(NSIndexPath indexPath) + { + var itemIndex = GetAdjustedIndexPathForItemSource(indexPath); + return base.DetermineCellReuseId(itemIndex); + } + + protected override Items.IItemsViewSource CreateItemsViewSource() + { + var itemsSource = ItemsSourceFactory2.CreateForCarouselView(ItemsView.ItemsSource, this, ItemsView.Loop); + _carouselViewLoopManager?.SetItemsSource(itemsSource); + SubscribeCollectionItemsSourceChanged(itemsSource); + return itemsSource; + } + + private protected override async void AttachingToWindow() + { + base.AttachingToWindow(); + Setup(ItemsView); + // if we navigate back on NavigationController LayoutSubviews might not fire. + await UpdateInitialPosition(); + } + + private protected override void DetachingFromWindow() + { + base.DetachingFromWindow(); + TearDown(ItemsView); + } + + internal bool InitialPositionSet { get; private set; } + + void TearDown(CarouselView carouselView) + { + _oldViews = null; + InitialPositionSet = false; + + UnsubscribeCollectionItemsSourceChanged(ItemsSource); + + _carouselViewLoopManager?.Dispose(); + _carouselViewLoopManager = null; + _isUpdating = false; + } + + void Setup(CarouselView carouselView) + { + InitializeCarouselViewLoopManager(); + + _oldViews = new List(); + + SubscribeCollectionItemsSourceChanged(ItemsSource); + } + + internal void UpdateIsScrolling(bool isScrolling) + { + if (ItemsView is CarouselView carousel) + { + carousel.IsScrolling = isScrolling; + } + } + + internal NSIndexPath GetScrollToIndexPath(int position) + { + if (ItemsView?.Loop == true && _carouselViewLoopManager != null) + { + return _carouselViewLoopManager.GetCorrectedIndexPathFromIndex(position); + } + + return NSIndexPath.FromItemSection(position, _section); + } + + internal int GetIndexFromIndexPath(NSIndexPath indexPath) + { + if (ItemsView?.Loop == true && _carouselViewLoopManager != null) + { + return _carouselViewLoopManager.GetCorrectedIndexFromIndexPath(indexPath); + } + + return indexPath.Row; + } + + // [UnconditionalSuppressMessage("Memory", "MEM0003", Justification = "Proven safe in test: MemoryTests.HandlerDoesNotLeak")] + // void CarouselViewScrolled(object sender, ItemsViewScrolledEventArgs e) + // { + // System.Diagnostics.Debug.WriteLine($"CarouselViewScrolled: {e.CenterItemIndex}"); + // // If we are trying to center the item when Loop is enabled we don't want to update the position + // // if (_isCenteringItem) + // // { + // // return; + // // } + + // // // If we are dragging the carousel we don't want to update the position + // // // We will do it when the dragging ends + // // if (_isDragging) + // // { + // // return; + // // } + + // // SetPosition(e.CenterItemIndex); + + // UpdateVisualStates(); + // } + + int _positionAfterUpdate = -1; + + [UnconditionalSuppressMessage("Memory", "MEM0003", Justification = "Proven safe in test: MemoryTests.HandlerDoesNotLeak")] + void CollectionViewUpdating(object sender, NotifyCollectionChangedEventArgs e) + { + _isUpdating = true; + if (ItemsView is not CarouselView carousel) + { + return; + } + + var count = ItemsSource.ItemCount; + + if (count == 0) + { + _positionAfterUpdate = -1; + return; + } + + int carouselPosition = carousel.Position; + _positionAfterUpdate = carouselPosition; + var currentItemPosition = ItemsSource.GetIndexForItem(carousel.CurrentItem).Row; + + if (e.Action == NotifyCollectionChangedAction.Remove) + { + _positionAfterUpdate = GetPositionWhenRemovingItems(e.OldStartingIndex, carouselPosition, currentItemPosition, count); + } + + if (e.Action == NotifyCollectionChangedAction.Reset) + { + _positionAfterUpdate = GetPositionWhenResetItems(); + } + + if (e.Action == NotifyCollectionChangedAction.Add) + { + _positionAfterUpdate = GetPositionWhenAddingItems(carouselPosition, currentItemPosition); + } + } + + [UnconditionalSuppressMessage("Memory", "MEM0003", Justification = "Proven safe in test: MemoryTests.HandlerDoesNotLeak")] + void CollectionViewUpdated(object sender, NotifyCollectionChangedEventArgs e) + { + if (_positionAfterUpdate == -1) + { + return; + } + + //_gotoPosition = -1; + + var targetPosition = _positionAfterUpdate; + _positionAfterUpdate = -1; + + SetPosition(targetPosition); + SetCurrentItem(targetPosition); + + if (e.Action == NotifyCollectionChangedAction.Reset) + { + + } + else + { + //Since we can be removing the item that is already created next to the current item we need to update the visible cells + if (ItemsView.Loop) + { + CollectionView.ReloadItems(new NSIndexPath[] { GetScrollToIndexPath(targetPosition) }); + } + } + + + _isUpdating = false; + ScrollToPosition(targetPosition, targetPosition, false, true); + } + + int GetPositionWhenAddingItems(int carouselPosition, int currentItemPosition) + { + //If we are adding a new item make sure to maintain the CurrentItemPosition + return currentItemPosition != -1 ? currentItemPosition : carouselPosition; + } + + int GetPositionWhenResetItems() + { + //If we are reseting the collection Position should go to 0 + ItemsView?.SetValueFromRenderer(CarouselView.CurrentItemProperty, null); + return 0; + } + + int GetPositionWhenRemovingItems(int oldStartingIndex, int carouselPosition, int currentItemPosition, int count) + { + bool removingCurrentElement = currentItemPosition == -1; + + bool removingFirstElement = oldStartingIndex == 0; + bool removingLastElement = oldStartingIndex == count; + + int currentPosition = ItemsView?.Position ?? 0; + bool removingCurrentElementAndLast = removingCurrentElement && removingLastElement && currentPosition > 0; + if (removingCurrentElementAndLast) + { + //If we are removing the last element update the position + carouselPosition = currentPosition - 1; + } + else if (removingFirstElement && !removingCurrentElement) + { + //If we are not removing the current element set position to the CurrentItem + carouselPosition = currentItemPosition; + } + + return carouselPosition; + } + + void SubscribeCollectionItemsSourceChanged(Items.IItemsViewSource itemsSource) + { + UnsubscribeCollectionItemsSourceChanged(ItemsSource); + + if (itemsSource is Items.ObservableItemsSource newItemsSource) + { + newItemsSource.CollectionViewUpdating += CollectionViewUpdating; + newItemsSource.CollectionViewUpdated += CollectionViewUpdated; + } + } + + void UnsubscribeCollectionItemsSourceChanged(Items.IItemsViewSource oldItemsSource) + { + if (oldItemsSource is Items.ObservableItemsSource oldObservableItemsSource) + { + oldObservableItemsSource.CollectionViewUpdating -= CollectionViewUpdating; + oldObservableItemsSource.CollectionViewUpdated -= CollectionViewUpdated; + } + } + + internal bool IsUpdating() + { + return _isUpdating; + } + internal void UpdateLoop() + { + if (ItemsView is not CarouselView carousel) + { + return; + } + + var carouselPosition = carousel.Position; + + if (LoopItemsSource is not null) + { + LoopItemsSource.Loop = carousel.Loop; + } + + // CollectionView.ReloadData(); + + // ScrollToPosition(carouselPosition, carouselPosition, false, true); + } + + void ScrollToPosition(int goToPosition, int carouselPosition, bool animate, bool forceScroll = false) + { + if (ItemsView is not CarouselView carousel) + { + return; + } + + if (ItemsSource is null || ItemsSource.ItemCount == 0) + { + return; + } + + if (goToPosition != carouselPosition || forceScroll) + { + UICollectionViewScrollPosition uICollectionViewScrollPosition = IsHorizontal ? UICollectionViewScrollPosition.CenteredHorizontally : UICollectionViewScrollPosition.CenteredVertically; + var goToIndexPath = GetScrollToIndexPath(goToPosition); + + CollectionView.ScrollToItem(goToIndexPath, uICollectionViewScrollPosition, animate); + } + } + + internal void SetPosition(int position) + { + if (ItemsView is not CarouselView carousel) + { + return; + } + + if (ItemsSource is null || ItemsSource.ItemCount == 0) + { + return; + } + + if (!InitialPositionSet || position == -1) + { + return; + } + + ItemsView.SetValueFromRenderer(CarouselView.PositionProperty, position); + SetCurrentItem(position); + UpdateVisualStates(); + } + + void SetCurrentItem(int carouselPosition) + { + if (ItemsView is not CarouselView carousel) + { + return; + } + + if (ItemsSource is null || ItemsSource.ItemCount == 0) + { + return; + } + + var item = GetItemAtIndex(NSIndexPath.FromItemSection(carouselPosition, _section)); + ItemsView?.SetValueFromRenderer(CarouselView.CurrentItemProperty, item); + UpdateVisualStates(); + } + + internal void UpdateFromCurrentItem() + { + if (!InitialPositionSet) + return; + + if (ItemsView is not CarouselView carousel) + { + return; + } + + if (carousel.CurrentItem is null || ItemsSource is null || ItemsSource.ItemCount == 0) + { + return; + } + + var currentItemPosition = GetIndexForItem(carousel.CurrentItem).Row; + + ScrollToPosition(currentItemPosition, carousel.Position, carousel.AnimateCurrentItemChanges); + + UpdateVisualStates(); + } + + internal void UpdateFromPosition() + { + if (!InitialPositionSet) + { + return; + } + + if (ItemsView is not CarouselView carousel) + { + return; + } + + if (ItemsSource is null || ItemsSource.ItemCount == 0) + { + return; + } + + var currentItemPosition = GetIndexForItem(carousel.CurrentItem).Row; + var carouselPosition = carousel.Position; + + ScrollToPosition(carouselPosition, currentItemPosition, carousel.AnimatePositionChanges); + + // SetCurrentItem(carouselPosition); + } + + async Task UpdateInitialPosition() + { + if (ItemsView is not CarouselView carousel) + { + return; + } + + if (ItemsSource is null) + { + return; + } + + if (InitialPositionSet) + { + return; + } + + int position = carousel.Position; + var currentItem = carousel.CurrentItem; + + if (currentItem != null) + { + // Sometimes the item could be just being removed while we navigate back to the CarouselView + var positionCurrentItem = ItemsSource.GetIndexForItem(currentItem).Row; + if (positionCurrentItem != -1) + { + position = positionCurrentItem; + } + } + + var projectedPosition = NSIndexPath.FromItemSection(position, _section); + + if (LoopItemsSource.Loop) + { + //We need to set the position to the correct position since we added 1 item at the beginning + projectedPosition = GetScrollToIndexPath(position); + } + + var uICollectionViewScrollPosition = IsHorizontal ? UICollectionViewScrollPosition.CenteredHorizontally : UICollectionViewScrollPosition.CenteredVertically; + + await Task.Delay(100).ContinueWith((t) => + { + MainThread.BeginInvokeOnMainThread(() => + { + if (!IsViewLoaded) + { + return; + } + InitialPositionSet = true; + + if (ItemsSource is null || ItemsSource.ItemCount == 0) + { + return; + } + + CollectionView.ScrollToItem(projectedPosition, uICollectionViewScrollPosition, false); + + //Set the position on VirtualView to update the CurrentItem also + SetPosition(position); + + UpdateVisualStates(); + }); + + }); + + } + + void UpdateVisualStates() + { + if (ItemsView is not CarouselView carousel) + { + return; + } + + // We aren't ready to update the visual states yet + if (_oldViews is null) + { + return; + } + + var cells = CollectionView.VisibleCells; + + var newViews = new List(); + + var carouselPosition = carousel.Position; + var previousPosition = carouselPosition - 1; + var nextPosition = carouselPosition + 1; + + foreach (var cell in cells) + { + if (!((cell as TemplatedCell2)?.PlatformHandler?.VirtualView is View itemView)) + { + return; + } + + var item = itemView.BindingContext; + var pos = GetIndexForItem(item).Row; + + if (pos == carouselPosition) + { + VisualStateManager.GoToState(itemView, CarouselView.CurrentItemVisualState); + } + else if (pos == previousPosition) + { + VisualStateManager.GoToState(itemView, CarouselView.PreviousItemVisualState); + } + else if (pos == nextPosition) + { + VisualStateManager.GoToState(itemView, CarouselView.NextItemVisualState); + } + else + { + VisualStateManager.GoToState(itemView, CarouselView.DefaultItemVisualState); + } + + newViews.Add(itemView); + + if (!carousel.VisibleViews.Contains(itemView)) + { + carousel.VisibleViews.Add(itemView); + } + } + + foreach (var itemView in _oldViews) + { + if (!newViews.Contains(itemView)) + { + VisualStateManager.GoToState(itemView, CarouselView.DefaultItemVisualState); + if (carousel.VisibleViews.Contains(itemView)) + { + carousel.VisibleViews.Remove(itemView); + } + } + } + + _oldViews = newViews; + } + + internal protected override void UpdateVisibility() + { + if (ItemsView.IsVisible) + { + CollectionView.Hidden = false; + } + else + { + CollectionView.Hidden = true; + } + } + } + + class CarouselViewLoopManager : IDisposable + { + int _section = 0; + Items.ILoopItemsViewSource _itemsSource; + bool _disposed; + + public CarouselViewLoopManager() + { + + } + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + _itemsSource = null; + } + + _disposed = true; + } + } + + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + public NSIndexPath GetCorrectedIndexPathFromIndex(int index) + { + return NSIndexPath.FromItemSection(index + 1, _section); + } + + public int GetCorrectedIndexFromIndexPath(NSIndexPath indexPath) + { + if (indexPath.Row == 0) + { + return Math.Max(0, _itemsSource.ItemCount - 1); + } + else if (indexPath.Row == _itemsSource.ItemCount + 1) + { + return 0; + } + else + { + return Math.Max(0, indexPath.Row - 1); + } + } + + public void SetItemsSource(Items.ILoopItemsViewSource itemsSource) => _itemsSource = itemsSource; + } +} diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/CarouselViewDelegator2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/CarouselViewDelegator2.cs new file mode 100644 index 000000000000..db33e7e5e595 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/CarouselViewDelegator2.cs @@ -0,0 +1,61 @@ +#nullable disable +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class CarouselViewDelegator2 : ItemsViewDelegator2 + { + public CarouselViewDelegator2(UICollectionViewLayout itemsViewLayout, CarouselViewController2 ItemsViewController2) + : base(itemsViewLayout, ItemsViewController2) + { + } + + public override void Scrolled(UIScrollView scrollView) + { + base.Scrolled(scrollView); + + ViewController?.UpdateIsScrolling(true); + } + + public override void ScrollAnimationEnded(UIScrollView scrollView) + { + ViewController?.UpdateIsScrolling(false); + } + + public override void DecelerationEnded(UIScrollView scrollView) + { + ViewController?.UpdateIsScrolling(false); + } + + public override void DraggingStarted(UIScrollView scrollView) + { + ViewController?.DraggingStarted(scrollView); + + PreviousHorizontalOffset = (float)scrollView.ContentOffset.X; + PreviousVerticalOffset = (float)scrollView.ContentOffset.Y; + } + + public override void DraggingEnded(UIScrollView scrollView, bool willDecelerate) + { + PreviousHorizontalOffset = 0; + PreviousVerticalOffset = 0; + + ViewController?.DraggingEnded(scrollView, willDecelerate); + } + + protected override (bool VisibleItems, int First, int Center, int Last) GetVisibleItemsIndex() + { + var (VisibleItems, First, Center, Last) = GetVisibleItemsIndexPath(); + int firstVisibleItemIndex = -1, centerItemIndex = -1, lastVisibleItemIndex = -1; + if (VisibleItems && ViewController is CarouselViewController2 vc) + { + firstVisibleItemIndex = vc.GetIndexFromIndexPath(First); + centerItemIndex = vc.GetIndexFromIndexPath(Center); + lastVisibleItemIndex = vc.GetIndexFromIndexPath(Last); + } + return (VisibleItems, firstVisibleItemIndex, centerItemIndex, lastVisibleItemIndex); + } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/DefaultCell2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/DefaultCell2.cs new file mode 100644 index 000000000000..af9de67789a6 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/DefaultCell2.cs @@ -0,0 +1,40 @@ +#nullable disable +using System; +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class DefaultCell2 : ItemsViewCell2 + { + //public const string ReuseId = "Microsoft.Maui.Controls.DefaultCell2"; + + public UILabel Label { get; } + + protected NSLayoutConstraint Constraint { get; set; } + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public DefaultCell2(CGRect frame) : base(frame) + { + Label = new UILabel(frame) + { + TextColor = Maui.Platform.ColorExtensions.LabelColor, + Lines = 1, + Font = UIFont.PreferredBody, + TranslatesAutoresizingMaskIntoConstraints = false + }; + + ContentView.BackgroundColor = UIColor.Clear; + + InitializeContentConstraints(Label); + } + + // public override void ConstrainTo(nfloat constant) + // { + // Constraint.Constant = constant; + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/GroupableItemsViewController2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/GroupableItemsViewController2.cs new file mode 100644 index 000000000000..6f23351071d5 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/GroupableItemsViewController2.cs @@ -0,0 +1,322 @@ +#nullable disable +using System; +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class GroupableItemsViewController2 : SelectableItemsViewController2 + where TItemsView : GroupableItemsView + { + // Keep a cached value for the current state of grouping around so we can avoid hitting the + // BindableProperty all the time + bool _isGrouped; + + // Keep out header measurement cells for iOS handy so we don't have to + // create new ones all the time. For other versions, the reusable cells + // queueing mechanism does this for us. + // TemplatedCell2 _measurementCellTemplated; + // DefaultCell2 _measurementCellDefault; + + Action _scrollAnimationEndedCallback; + + public GroupableItemsViewController2(TItemsView groupableItemsView, UICollectionViewLayout layout) + : base(groupableItemsView, layout) + { + _isGrouped = ItemsView.IsGrouped; + } + + protected override UICollectionViewDelegateFlowLayout CreateDelegator() + { + return new GroupableItemsViewDelegator2>(ItemsViewLayout, this); + } + + protected override Items.IItemsViewSource CreateItemsViewSource() + { + // Use the BindableProperty here (instead of _isGroupingEnabled) because the cached value might not be set yet + if (ItemsView.IsGrouped) + { + return Items.ItemsSourceFactory.CreateGrouped(ItemsView.ItemsSource, this); + } + + return base.CreateItemsViewSource(); + } + + public override void UpdateItemsSource() + { + _isGrouped = ItemsView.IsGrouped; + base.UpdateItemsSource(); + } + + protected override void RegisterViewTypes() + { + base.RegisterViewTypes(); + + RegisterSupplementaryViews(UICollectionElementKindSection.Header); + RegisterSupplementaryViews(UICollectionElementKindSection.Footer); + } + + private protected override void RegisterSupplementaryViews(UICollectionElementKindSection kind) + { + base.RegisterSupplementaryViews(kind); + if (IsHorizontal) + { + CollectionView.RegisterClassForSupplementaryView(typeof(HorizontalSupplementaryView2), + kind, HorizontalSupplementalView2ReuseId); + CollectionView.RegisterClassForSupplementaryView(typeof(HorizontalDefaultSupplementalView2), + kind, HorizontalDefaultSupplementalView2ReuseId); + } + else + { + CollectionView.RegisterClassForSupplementaryView(typeof(VerticalSupplementaryView2), + kind, VerticalSupplementaryView2ReuseId); + CollectionView.RegisterClassForSupplementaryView(typeof(VerticalDefaultSupplementalView2), + kind, VerticalDefaultSupplementalView2ReuseId); + } + } + + string DetermineViewReuseId(NSString elementKind) + { + return DetermineViewReuseId(elementKind == UICollectionElementKindSectionKey.Header + ? ItemsView.GroupHeaderTemplate + : ItemsView.GroupFooterTemplate); + } + + public override UICollectionReusableView GetViewForSupplementaryElement(UICollectionView collectionView, + NSString elementKind, NSIndexPath indexPath) + { + var suplementaryViewFromStructuredView = base.GetViewForSupplementaryElement(collectionView, elementKind, indexPath); + if (suplementaryViewFromStructuredView is not null) + { + return suplementaryViewFromStructuredView; + } + + var reuseId = DetermineViewReuseId(elementKind); + + var view = collectionView.DequeueReusableSupplementaryView(elementKind, reuseId, indexPath) as UICollectionReusableView; + + switch (view) + { + case DefaultCell2 DefaultCell2: + UpdateDefaultSupplementaryView(DefaultCell2, elementKind, indexPath); + break; + case TemplatedCell2 TemplatedCell2: + UpdateTemplatedSupplementaryView(TemplatedCell2, elementKind, indexPath); + break; + } + + return view; + } + + void UpdateDefaultSupplementaryView(DefaultCell2 cell, NSString elementKind, NSIndexPath indexPath) + { + cell.Label.Text = ItemsSource?.Group(indexPath)?.ToString(); + + // if (cell is ItemsViewCell2) + // { + // cell.ConstrainTo(GetLayoutSpanCount() * ItemsViewLayout.ConstrainedDimension); + // } + } + + void UpdateTemplatedSupplementaryView(TemplatedCell2 cell, NSString elementKind, NSIndexPath indexPath) + { + DataTemplate template = elementKind == UICollectionElementKindSectionKey.Header + ? ItemsView.GroupHeaderTemplate + : ItemsView.GroupFooterTemplate; + + var bindingContext = ItemsSource.Group(indexPath); + + cell.Bind(template, bindingContext, ItemsView); + + // if (cell is ItemsViewCell2) + // { + // cell.ConstrainTo(GetLayoutSpanCount() * ItemsViewLayout.ConstrainedDimension); + // } + } + + + + string DetermineViewReuseId(DataTemplate template) + { + var orientation = ItemsLayoutOrientation.Vertical; + + if (this.ItemsView.ItemsLayout is LinearItemsLayout linearItemsLayout) + orientation = linearItemsLayout.Orientation; + else if (this.ItemsView.ItemsLayout is GridItemsLayout gridItemsLayout) + orientation = gridItemsLayout.Orientation; + + if (template == null) + { + // No template, fall back the the default supplemental views + return orientation == ItemsLayoutOrientation.Horizontal + ? HorizontalDefaultSupplementalView2ReuseId + : VerticalDefaultSupplementalView2ReuseId; + } + + return orientation == ItemsLayoutOrientation.Horizontal + ? HorizontalSupplementalView2ReuseId + : VerticalSupplementaryView2ReuseId; + } + + static NSString HorizontalDefaultSupplementalView2ReuseId = new NSString("Microsoft.Maui.Controls.HorizontalDefaultSupplementalGroupView2"); + static NSString VerticalDefaultSupplementalView2ReuseId = new NSString("Microsoft.Maui.Controls.VerticalDefaultSupplementaryGroupView2"); + static NSString HorizontalSupplementalView2ReuseId = new NSString("Microsoft.Maui.Controls.HorizontalSupplementalGroupView2"); + static NSString VerticalSupplementaryView2ReuseId = new NSString("Microsoft.Maui.Controls.VerticalSupplementaryGroupView2"); + + + // internal CGSize GetReferenceSizeForHeader(UICollectionView collectionView, UICollectionViewLayout layout, nint section) + // { + // if (!_isGrouped) + // { + // return CGSize.Empty; + // } + // + // // Currently we explicitly measure all of the headers/footers + // // Long-term, we might want to look at performance hints (similar to ItemSizingStrategy) for + // // headers/footers (if the dev knows for sure they'll all the be the same size) + // return GetReferenceSizeForheaderOrFooter(collectionView, ItemsView.GroupHeaderTemplate, UICollectionElementKindSectionKey.Header, section); + // } + + // internal CGSize GetReferenceSizeForFooter(UICollectionView collectionView, UICollectionViewLayout layout, nint section) + // { + // if (!_isGrouped) + // { + // return CGSize.Empty; + // } + // + // return GetReferenceSizeForheaderOrFooter(collectionView, ItemsView.GroupFooterTemplate, UICollectionElementKindSectionKey.Footer, section); + // } + + // internal CGSize GetReferenceSizeForheaderOrFooter(UICollectionView collectionView, DataTemplate template, NSString elementKind, nint section) + // { + // if (!_isGrouped || template == null) + // { + // return CGSize.Empty; + // } + // + // if (ItemsSource.GroupCount < 1 || section > ItemsSource.GroupCount - 1) + // { + // return CGSize.Empty; + // } + // + // // if (!(OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsTvOSVersionAtLeast(11))) + // // { + // // // iOS 10 crashes if we try to dequeue a cell for measurement + // // // so we'll use an alternate method + // // return MeasureSupplementaryView(elementKind, section); + // // } + // + // var cell = GetViewForSupplementaryElement(collectionView, elementKind, + // NSIndexPath.FromItemSection(0, section)) as ItemsViewCell2; + // + // return cell.Measure(); + // } + + internal void SetScrollAnimationEndedCallback(Action callback) + { + _scrollAnimationEndedCallback = callback; + } + + internal void HandleScrollAnimationEnded() + { + _scrollAnimationEndedCallback?.Invoke(); + _scrollAnimationEndedCallback = null; + } + + + // internal UIEdgeInsets GetInsetForSection(UICollectionViewLayout itemsViewLayout, + // UICollectionView collectionView, nint section) + // { + // var uIEdgeInsets = itemsViewLayout.GetInsetForSection(collectionView, itemsViewLayout, section); + // + // if (!ItemsView.IsGrouped) + // { + // return uIEdgeInsets; + // } + // + // // If we're grouping, we'll need to inset the sections to maintain the spacing between the + // // groups and their group headers/footers + // + // nfloat spacing = itemsViewLayout.GetMinimumLineSpacingForSection(collectionView, itemsViewLayout, section); + // + // var top = uIEdgeInsets.Top; + // var left = uIEdgeInsets.Left; + // + // if (itemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Horizontal) + // { + // left += spacing; + // } + // else + // { + // top += spacing; + // } + // + // return new UIEdgeInsets(top, left, + // uIEdgeInsets.Bottom, uIEdgeInsets.Right); + // } + + // These measurement methods are only necessary for iOS 10 and lower + // CGSize MeasureTemplatedSupplementaryCell(NSString elementKind, nint section, NSString reuseId) + // { + // if (_measurementCellTemplated == null) + // { + // if (reuseId == HorizontalSupplementaryView2.ReuseId) + // { + // _measurementCellTemplated = new HorizontalSupplementaryView2(CGRect.Empty); + // } + // else if (reuseId == VerticalSupplementaryView2.ReuseId) + // { + // _measurementCellTemplated = new VerticalSupplementaryView2(CGRect.Empty); + // } + // } + // + // if (_measurementCellTemplated == null) + // { + // return CGSize.Empty; + // } + // + // UpdateTemplatedSupplementaryView(_measurementCellTemplated, elementKind, NSIndexPath.FromItemSection(0, section)); + // return _measurementCellTemplated.Measure(); + // } + + // CGSize MeasureDefaultSupplementaryCell(NSString elementKind, nint section, NSString reuseId) + // { + // if (_measurementCellDefault == null) + // { + // if (reuseId == HorizontalDefaultSupplementalView2.ReuseId) + // { + // _measurementCellDefault = new HorizontalDefaultSupplementalView2(CGRect.Empty); + // } + // else if (reuseId == VerticalDefaultSupplementalView2.ReuseId) + // { + // _measurementCellDefault = new VerticalDefaultSupplementalView2(CGRect.Empty); + // } + // } + // + // if (_measurementCellDefault == null) + // { + // return CGSize.Empty; + // } + // + // UpdateDefaultSupplementaryView(_measurementCellDefault, elementKind, NSIndexPath.FromItemSection(0, section)); + // return _measurementCellDefault.Measure(); + // } + // + // CGSize MeasureSupplementaryView(NSString elementKind, nint section) + // { + // var reuseId = (NSString)DetermineViewReuseId(elementKind); + // + // if (reuseId == HorizontalDefaultSupplementalView2.ReuseId + // || reuseId == VerticalDefaultSupplementalView2.ReuseId) + // { + // return MeasureDefaultSupplementaryCell(elementKind, section, reuseId); + // } + // + // return MeasureTemplatedSupplementaryCell(elementKind, section, reuseId); + // } + + // end of iOS 10 workaround stuff + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/GroupableItemsViewDelegator2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/GroupableItemsViewDelegator2.cs new file mode 100644 index 000000000000..2e51e6990d2c --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/GroupableItemsViewDelegator2.cs @@ -0,0 +1,43 @@ +#nullable disable +using System; +using CoreGraphics; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class GroupableItemsViewDelegator2 : SelectableItemsViewDelegator2 + where TItemsView : GroupableItemsView + where TViewController : GroupableItemsViewController2 + { + public GroupableItemsViewDelegator2(UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) + : base(itemsViewLayout, ItemsViewController2) + { + } + + // public override CGSize GetReferenceSizeForHeader(UICollectionView collectionView, UICollectionViewLayout layout, nint section) + // { + // return ViewController?.GetReferenceSizeForHeader(collectionView, layout, section) ?? CGSize.Empty; + // } + // + // public override CGSize GetReferenceSizeForFooter(UICollectionView collectionView, UICollectionViewLayout layout, nint section) + // { + // return ViewController?.GetReferenceSizeForFooter(collectionView, layout, section) ?? CGSize.Empty; + // } + + public override void ScrollAnimationEnded(UIScrollView scrollView) + { + ViewController?.HandleScrollAnimationEnded(); + } + + // public override UIEdgeInsets GetInsetForSection(UICollectionView collectionView, UICollectionViewLayout layout, nint section) + // { + // if (ItemsViewLayout == null) + // { + // return default; + // } + // + // return ViewController?.GetInsetForSection(ItemsViewLayout, collectionView, section) ?? UIEdgeInsets.Zero; + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/HeightConstrainedTemplatedCell2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/HeightConstrainedTemplatedCell2.cs new file mode 100644 index 000000000000..d8ef8f0ba903 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/HeightConstrainedTemplatedCell2.cs @@ -0,0 +1,50 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using Microsoft.Maui.Graphics; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal abstract partial class HeightConstrainedTemplatedCell2 : TemplatedCell2 + { + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public HeightConstrainedTemplatedCell2(CGRect frame) : base(frame) + { + } + + // public override void ConstrainTo(CGSize constraint) + // { + // ClearConstraints(); + // ConstrainedDimension = constraint.Height; + // } + + // protected override (bool, Size) NeedsContentSizeUpdate(Size currentSize) + // { + // if (PlatformHandler?.VirtualView == null) + // { + // return (false, currentSize); + // } + // + // var bounds = PlatformHandler.VirtualView.Frame; + // + // if (bounds.Width <= 0 || bounds.Height <= 0) + // { + // return (false, currentSize); + // } + // + // var desiredBounds = PlatformHandler.VirtualView.Measure(double.PositiveInfinity, bounds.Height); + // + // if (desiredBounds.Width == currentSize.Width) + // { + // // Nothing in the cell needs more room, so leave it as it is + // return (false, currentSize); + // } + // + // // Keep the current height in the updated content size + // desiredBounds.Height = bounds.Height; + // + // return (true, desiredBounds); + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalCell2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalCell2.cs new file mode 100644 index 000000000000..fc7b6aad3477 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalCell2.cs @@ -0,0 +1,31 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal sealed class HorizontalCell2 : HeightConstrainedTemplatedCell2 + { + public new static NSString ReuseId = new NSString("Microsoft.Maui.Controls.HorizontalCell2"); + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public HorizontalCell2(CGRect frame) : base(frame) + { + } + + // public override CGSize Measure() + // { + // var measure = PlatformHandler.VirtualView.Measure(double.PositiveInfinity, ConstrainedDimension); + // + // return new CGSize(measure.Width, ConstrainedDimension); + // } + // + // protected override bool AttributesConsistentWithConstrainedDimension(UICollectionViewLayoutAttributes attributes) + // { + // return attributes.Frame.Width == ConstrainedDimension; + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalDefaultCell2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalDefaultCell2.cs new file mode 100644 index 000000000000..3cf262aee0e5 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalDefaultCell2.cs @@ -0,0 +1,32 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal sealed class HorizontalDefaultCell2 : DefaultCell2 + { + public static NSString ReuseId = new NSString("Microsoft.Maui.Controls.HorizontalDefaultCell2"); + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public HorizontalDefaultCell2(CGRect frame) : base(frame) + { + Constraint = Label.HeightAnchor.ConstraintEqualTo(Frame.Height); + Constraint.Priority = (float)UILayoutPriority.DefaultHigh; + Constraint.Active = true; + } + + // public override void ConstrainTo(CGSize constraint) + // { + // Constraint.Constant = constraint.Height; + // } + // + // public override CGSize Measure() + // { + // return new CGSize(Label.IntrinsicContentSize.Width, Constraint.Constant); + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalDefaultSupplementalView2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalDefaultSupplementalView2.cs new file mode 100644 index 000000000000..70a0cd1a5327 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalDefaultSupplementalView2.cs @@ -0,0 +1,34 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal sealed class HorizontalDefaultSupplementalView2 : DefaultCell2 + { + public static NSString ReuseId = new NSString("Microsoft.Maui.Controls.HorizontalDefaultSupplementalView2"); + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public HorizontalDefaultSupplementalView2(CGRect frame) : base(frame) + { + Label.Font = UIFont.PreferredHeadline; + + Constraint = Label.HeightAnchor.ConstraintEqualTo(Frame.Height); + Constraint.Priority = (float)UILayoutPriority.DefaultHigh; + Constraint.Active = true; + } + + // public override void ConstrainTo(CGSize constraint) + // { + // Constraint.Constant = constraint.Height; + // } + // + // public override CGSize Measure() + // { + // return new CGSize(Label.IntrinsicContentSize.Width, Constraint.Constant); + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalTemplatedHeaderView2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalTemplatedHeaderView2.cs new file mode 100644 index 000000000000..b45f6c40f68b --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/HorizontalTemplatedHeaderView2.cs @@ -0,0 +1,40 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal sealed class HorizontalSupplementaryView2 : HeightConstrainedTemplatedCell2 + { + public new static NSString ReuseId = new NSString("Microsoft.Maui.Controls.HorizontalSupplementaryView2"); + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public HorizontalSupplementaryView2(CGRect frame) : base(frame) + { + } + + // public override CGSize Measure() + // { + // if (PlatformHandler?.VirtualView == null) + // { + // return CGSize.Empty; + // } + // + // var measure = PlatformHandler.VirtualView.Measure(double.PositiveInfinity, ConstrainedDimension); + // + // + // var width = PlatformHandler.VirtualView.Width > 0 + // ? PlatformHandler.VirtualView.Width : measure.Width; + // + // return new CGSize(width, ConstrainedDimension); + // } + // + // protected override bool AttributesConsistentWithConstrainedDimension(UICollectionViewLayoutAttributes attributes) + // { + // return attributes.Frame.Height == ConstrainedDimension; + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/ItemsSourceFactory2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsSourceFactory2.cs new file mode 100644 index 000000000000..c4071d41cefa --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsSourceFactory2.cs @@ -0,0 +1,29 @@ +#nullable disable +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using Microsoft.Maui.Controls.Handlers.Items; +using UIKit; + + +namespace Microsoft.Maui.Controls.Handlers.Items2; + +internal static class ItemsSourceFactory2 +{ + public static ILoopItemsViewSource CreateForCarouselView(IEnumerable itemsSource, UICollectionViewController collectionViewController, bool loop) + { + if (itemsSource == null) + { + return new EmptySource(); + } + + return itemsSource switch + { + IList _ when itemsSource is INotifyCollectionChanged => new LoopObservableItemsSource2(itemsSource as IList, collectionViewController, loop), + IEnumerable _ when itemsSource is INotifyCollectionChanged => new LoopObservableItemsSource2(itemsSource as IEnumerable, collectionViewController, loop), + IEnumerable generic => new LoopListSource2(generic, loop), + _ => new LoopListSource(itemsSource, loop), + }; + } + +} diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewCell2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewCell2.cs new file mode 100644 index 000000000000..428fa4812fec --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewCell2.cs @@ -0,0 +1,50 @@ +#nullable disable +using System; +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public abstract class ItemsViewCell2 : UICollectionViewCell + { + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + protected ItemsViewCell2(CGRect frame) : base(frame) + { + ContentView.BackgroundColor = UIColor.Clear; + + var selectedBackgroundView = new UIView + { + BackgroundColor = Maui.Platform.ColorExtensions.Gray + }; + + SelectedBackgroundView = selectedBackgroundView; + } + + protected void InitializeContentConstraints(UIView platformView) + { + ContentView.TranslatesAutoresizingMaskIntoConstraints = false; + platformView.TranslatesAutoresizingMaskIntoConstraints = false; + + ContentView.AddSubview(platformView); + + // We want the cell to be the same size as the ContentView + ContentView.TopAnchor.ConstraintEqualTo(TopAnchor).Active = true; + ContentView.BottomAnchor.ConstraintEqualTo(BottomAnchor).Active = true; + ContentView.LeadingAnchor.ConstraintEqualTo(LeadingAnchor).Active = true; + ContentView.TrailingAnchor.ConstraintEqualTo(TrailingAnchor).Active = true; + + // And we want the ContentView to be the same size as the root renderer for the Forms element + ContentView.TopAnchor.ConstraintEqualTo(platformView.TopAnchor).Active = true; + ContentView.BottomAnchor.ConstraintEqualTo(platformView.BottomAnchor).Active = true; + ContentView.LeadingAnchor.ConstraintEqualTo(platformView.LeadingAnchor).Active = true; + ContentView.TrailingAnchor.ConstraintEqualTo(platformView.TrailingAnchor).Active = true; + } + + // public abstract void ConstrainTo(nfloat constant); + // public abstract void ConstrainTo(CGSize constraint); + // public abstract CGSize Measure(); + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs new file mode 100644 index 000000000000..77a5f631876e --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs @@ -0,0 +1,609 @@ +#nullable disable +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using CoreGraphics; +using Foundation; +using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Graphics; +using PassKit; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public abstract class ItemsViewController2 : UICollectionViewController, Items.MauiCollectionView.ICustomMauiCollectionViewDelegate + where TItemsView : ItemsView + { + public const int EmptyTag = 333; + readonly WeakReference _itemsView; + + public Items.IItemsViewSource ItemsSource { get; protected set; } + public TItemsView ItemsView => _itemsView.GetTargetOrDefault(); + + // ItemsViewLayout provides an accessor to the typed UICollectionViewLayout. It's also important to note that the + // initial UICollectionViewLayout which is passed in to the ItemsViewController2 (and accessed via the Layout property) + // _does not_ get updated when the layout is updated for the CollectionView. That property only refers to the + // original layout. So it's unlikely that you would ever want to use .Layout; use .ItemsViewLayout instead. + // See https://developer.apple.com/documentation/uikit/uicollectionviewcontroller/1623980-collectionviewlayout + [UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "Proven safe in test: MemoryTests.HandlerDoesNotLeak")] + protected UICollectionViewLayout ItemsViewLayout { get; set; } + + bool _initialized; + bool _isEmpty = true; + bool _emptyViewDisplayed; + bool _disposed; + + [UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "Proven safe in test: MemoryTests.HandlerDoesNotLeak")] + UIView _emptyUIView; + VisualElement _emptyViewFormsElement; + List _cellReuseIds = new List(); + + [UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "Proven safe in test: MemoryTests.HandlerDoesNotLeak")] + protected UICollectionViewDelegateFlowLayout Delegator { get; set; } + + protected UICollectionViewScrollDirection ScrollDirection { get; private set; } = + UICollectionViewScrollDirection.Vertical; + + protected ItemsViewController2(TItemsView itemsView, UICollectionViewLayout layout) : base(layout) + { + _itemsView = new(itemsView); + ItemsViewLayout = layout; + } + + public void UpdateLayout(UICollectionViewLayout newLayout) + { + // Ignore calls to this method if the new layout is the same as the old one + if (CollectionView.CollectionViewLayout == newLayout) + return; + + if (newLayout is UICollectionViewCompositionalLayout compositionalLayout) + { + ScrollDirection = compositionalLayout.Configuration.ScrollDirection; + } + + ItemsViewLayout = newLayout; + _initialized = false; + + EnsureLayoutInitialized(); + + if (_initialized) + { + // Reload the data so the currently visible cells get laid out according to the new layout + CollectionView.ReloadData(); + } + } + + protected override void Dispose(bool disposing) + { + if (_disposed) + return; + + _disposed = true; + + if (disposing) + { + ItemsSource?.Dispose(); + + CollectionView.Delegate = null; + Delegator?.Dispose(); + + _emptyUIView?.Dispose(); + _emptyUIView = null; + + _emptyViewFormsElement = null; + + ItemsViewLayout?.Dispose(); + CollectionView?.Dispose(); + } + + base.Dispose(disposing); + } + + public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath) + { + var cell = collectionView.DequeueReusableCell(DetermineCellReuseId(indexPath), indexPath) as UICollectionViewCell; + + // We need to get the index path that is adjusted for the item source + // Some ItemsView like CarouselView have a loop feature that will make the index path different from the item source + var indexpathAdjusted = GetAdjustedIndexPathForItemSource(indexPath); + + if (cell is TemplatedCell2 TemplatedCell2) + { + TemplatedCell2.ScrollDirection = ScrollDirection; + + TemplatedCell2.Bind(ItemsView.ItemTemplate, ItemsSource[indexpathAdjusted], ItemsView); + } + else if (cell is DefaultCell2 DefaultCell2) + { + DefaultCell2.Label.Text = ItemsSource[indexpathAdjusted].ToString(); + } + + return cell; + } + + public override nint GetItemsCount(UICollectionView collectionView, nint section) + { + CheckForEmptySource(); + + return ItemsSource.ItemCountInGroup(section); + } + + void CheckForEmptySource() + { + var wasEmpty = _isEmpty; + + _isEmpty = ItemsSource.ItemCount == 0; + + if (wasEmpty != _isEmpty) + { + UpdateEmptyViewVisibility(_isEmpty); + } + + if (wasEmpty && !_isEmpty) + { + // If we're going from empty to having stuff, it's possible that we've never actually measured + // a prototype cell and our itemSize or estimatedItemSize are wrong/unset + // So trigger a constraint update; if we need a measurement, that will make it happen + // TODO: Fix ItemsViewLayout.ConstrainTo(CollectionView.Bounds.Size); + } + } + + public override void ViewDidLoad() + { + base.ViewDidLoad(); + + ItemsSource = CreateItemsViewSource(); + + if (!(OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsMacCatalystVersionAtLeast(11) +#if TVOS + || OperatingSystem.IsTvOSVersionAtLeast(11) +#endif + )) + { + AutomaticallyAdjustsScrollViewInsets = false; + } + else + { + // We set this property to keep iOS from trying to be helpful about insetting all the + // CollectionView content when we're in landscape mode (to avoid the notch) + // The SetUseSafeArea Platform Specific is already taking care of this for us + // That said, at some point it's possible folks will want a PS for controlling this behavior + CollectionView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never; + } + + RegisterViewTypes(); + + EnsureLayoutInitialized(); + } + + public override void LoadView() + { + base.LoadView(); + var collectionView = new Items.MauiCollectionView(CGRect.Empty, ItemsViewLayout); + collectionView.SetCustomDelegate(this); + CollectionView = collectionView; + } + + public override void ViewWillLayoutSubviews() + { + base.ViewWillLayoutSubviews(); + LayoutEmptyView(); + } + + void Items.MauiCollectionView.ICustomMauiCollectionViewDelegate.MovedToWindow(UIView view) + { + if (CollectionView?.Window != null) + { + AttachingToWindow(); + } + else + { + DetachingFromWindow(); + } + } + + internal void DisposeItemsSource() + { + ItemsSource?.Dispose(); + ItemsSource = new Items.EmptySource(); + CollectionView.ReloadData(); + } + + // void InvalidateMeasureIfContentSizeChanged() + // { + // var contentSize = CollectionView?.CollectionViewLayout?.CollectionViewContentSize; + // + // if (!contentSize.HasValue) + // { + // return; + // } + // + // bool widthChanged = _previousContentSize.Width != contentSize.Value.Width; + // bool heightChanged = _previousContentSize.Height != contentSize.Value.Height; + // + // if (_initialized && (widthChanged || heightChanged)) + // { + // var screenFrame = CollectionView?.Window?.Frame; + // + // if (!screenFrame.HasValue) + // { + // return; + // } + // + // var screenWidth = screenFrame.Value.Width; + // var screenHeight = screenFrame.Value.Height; + // bool invalidate = false; + // + // // If both the previous content size and the current content size are larger + // // than the screen size, then we know that we're already maxed out and the + // // CollectionView items are scrollable. There's no reason to force an invalidation + // // of the CollectionView to expand/contract it. + // + // // If either size is smaller than that, we need to invalidate to ensure that the + // // CollectionView is re-measured and set to the correct size. + // + // if (widthChanged && (contentSize.Value.Width < screenWidth || _previousContentSize.Width < screenWidth)) + // { + // invalidate = true; + // } + // + // if (heightChanged && (contentSize.Value.Height < screenHeight || _previousContentSize.Height < screenHeight)) + // { + // invalidate = true; + // } + // + // if (invalidate) + // { + // (ItemsView as IView)?.InvalidateMeasure(); + // } + // } + // _previousContentSize = contentSize.Value; + // } + + const int HeaderTag = 111; + + // internal Size? GetSize() + // { + // if (_emptyViewDisplayed) + // { + // return _emptyUIView.Frame.Size.ToSize(); + // } + + // nfloat headerHeight = 0; + // var headerView = CollectionView.ViewWithTag(HeaderTag); + + // if (headerView != null) + // headerHeight = headerView.Frame.Height; + + // var sizeColl = CollectionView.CollectionViewLayout.CollectionViewContentSize; + // return sizeColl.ToSize(); + // } + + // void ConstrainItemsToBounds() + // { + // var contentBounds = CollectionView.AdjustedContentInset.InsetRect(CollectionView.Bounds); + // var constrainedSize = contentBounds.Size; + // ItemsViewLayout.UpdateConstraints(constrainedSize); + // } + + void EnsureLayoutInitialized() + { + if (_initialized) + { + return; + } + + _initialized = true; + + Delegator = CreateDelegator(); + CollectionView.Delegate = Delegator; + + CollectionView.SetCollectionViewLayout(ItemsViewLayout, false); + + UpdateEmptyView(); + } + + protected virtual UICollectionViewDelegateFlowLayout CreateDelegator() + { + return new ItemsViewDelegator2>(ItemsViewLayout, this); + } + + protected virtual Items.IItemsViewSource CreateItemsViewSource() + { + return Items.ItemsSourceFactory.Create(ItemsView.ItemsSource, this); + } + + public virtual void UpdateItemsSource() + { + ItemsSource?.Dispose(); + ItemsSource = CreateItemsViewSource(); + + CollectionView.ReloadData(); + CollectionView.CollectionViewLayout.InvalidateLayout(); + + (ItemsView as IView)?.InvalidateMeasure(); + } + + public virtual void UpdateFlowDirection() + { + CollectionView.UpdateFlowDirection(ItemsView); + + if (_emptyViewDisplayed) + { + AlignEmptyView(); + } + + Layout.InvalidateLayout(); + } + + public override nint NumberOfSections(UICollectionView collectionView) + { + CheckForEmptySource(); + return ItemsSource.GroupCount; + } + + + public virtual NSIndexPath GetIndexForItem(object item) + { + return ItemsSource.GetIndexForItem(item); + } + + protected object GetItemAtIndex(NSIndexPath index) + { + return ItemsSource[index]; + } + + protected virtual string DetermineCellReuseId(NSIndexPath indexPath) + { + if (ItemsView.ItemTemplate != null) + { + var item = ItemsSource[indexPath]; + + var dataTemplate = ItemsView.ItemTemplate.SelectDataTemplate(item, ItemsView); + + var cellType = typeof(TemplatedCell2); + + var orientation = ScrollDirection == UICollectionViewScrollDirection.Horizontal ? "Horizontal" : "Vertical"; + var reuseId = $"{TemplatedCell2.ReuseId}.{orientation}.{dataTemplate.Id}"; + + if (!_cellReuseIds.Contains(reuseId)) + { + Console.WriteLine($"REGISTER CELL ID: {reuseId}"); + CollectionView.RegisterClassForCell(cellType, new NSString(reuseId)); + _cellReuseIds.Add(reuseId); + } + + return reuseId; + } + + return ScrollDirection == UICollectionViewScrollDirection.Horizontal ? HorizontalDefaultCell2.ReuseId : VerticalDefaultCell2.ReuseId; + } + + protected virtual void RegisterViewTypes() + { + CollectionView.RegisterClassForCell(typeof(HorizontalDefaultCell2), HorizontalDefaultCell2.ReuseId); + CollectionView.RegisterClassForCell(typeof(VerticalDefaultCell2), VerticalDefaultCell2.ReuseId); + CollectionView.RegisterClassForCell(typeof(HorizontalCell2), HorizontalCell2.ReuseId); + CollectionView.RegisterClassForCell(typeof(VerticalCell2), VerticalCell2.ReuseId); + } + + protected abstract bool IsHorizontal { get; } + + protected virtual CGRect DetermineEmptyViewFrame() + { + return new CGRect(CollectionView.Frame.X, CollectionView.Frame.Y, + CollectionView.Frame.Width, CollectionView.Frame.Height); + } + + + internal void UpdateView(object view, DataTemplate viewTemplate, ref UIView uiView, ref VisualElement formsElement) + { + // Is view set on the ItemsView? + if (view == null) + { + if (formsElement != null) + { + //Platform.GetRenderer(formsElement)?.DisposeRendererAndChildren(); + } + + + uiView?.Dispose(); + uiView = null; + + formsElement = null; + } + else + { + // Create the native renderer for the view, and keep the actual Forms element (if any) + // around for updating the layout later + (uiView, formsElement) = Items.TemplateHelpers.RealizeView(view, viewTemplate, ItemsView); + } + } + + internal void UpdateEmptyView() + { + if (!_initialized) + { + return; + } + + // Get rid of the old view + TearDownEmptyView(); + + // Set up the new empty view + UpdateView(ItemsView?.EmptyView, ItemsView?.EmptyViewTemplate, ref _emptyUIView, ref _emptyViewFormsElement); + + // We may need to show the updated empty view + UpdateEmptyViewVisibility(ItemsSource?.ItemCount == 0); + } + + void UpdateEmptyViewVisibility(bool isEmpty) + { + if (!_initialized) + { + return; + } + + if (isEmpty) + { + ShowEmptyView(); + } + else + { + HideEmptyView(); + } + } + + void AlignEmptyView() + { + if (_emptyUIView == null) + { + return; + } + + bool isRtl; + + if (OperatingSystem.IsIOSVersionAtLeast(10) || OperatingSystem.IsTvOSVersionAtLeast(10)) + isRtl = CollectionView.EffectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirection.RightToLeft; + else + isRtl = CollectionView.SemanticContentAttribute == UISemanticContentAttribute.ForceRightToLeft; + + if (isRtl) + { + if (_emptyUIView.Transform.A == -1) + { + return; + } + + FlipEmptyView(); + } + else + { + if (_emptyUIView.Transform.A == -1) + { + FlipEmptyView(); + } + } + } + + void FlipEmptyView() + { + // Flip the empty view 180 degrees around the X axis + _emptyUIView.Transform = CGAffineTransform.Scale(_emptyUIView.Transform, -1, 1); + } + + void ShowEmptyView() + { + if (_emptyViewDisplayed || _emptyUIView == null) + { + return; + } + + _emptyUIView.Tag = EmptyTag; + CollectionView.AddSubview(_emptyUIView); + + if (((IElementController)ItemsView).LogicalChildren.IndexOf(_emptyViewFormsElement) == -1) + { + ItemsView.AddLogicalChild(_emptyViewFormsElement); + } + + LayoutEmptyView(); + + AlignEmptyView(); + _emptyViewDisplayed = true; + } + + void HideEmptyView() + { + if (!_emptyViewDisplayed || _emptyUIView == null) + { + return; + } + + _emptyUIView.RemoveFromSuperview(); + + _emptyViewDisplayed = false; + } + + void TearDownEmptyView() + { + HideEmptyView(); + + // RemoveLogicalChild will trigger a disposal of the native view and its content + ItemsView.RemoveLogicalChild(_emptyViewFormsElement); + + _emptyUIView = null; + _emptyViewFormsElement = null; + } + + void LayoutEmptyView() + { + if (!_initialized || _emptyUIView == null || _emptyUIView.Superview == null) + { + return; + } + + var frame = DetermineEmptyViewFrame(); + + _emptyUIView.Frame = frame; + + if (_emptyViewFormsElement != null && ((IElementController)ItemsView).LogicalChildren.IndexOf(_emptyViewFormsElement) != -1) + _emptyViewFormsElement.Layout(frame.ToRectangle()); + } + + internal protected virtual void UpdateVisibility() + { + if (ItemsView.IsVisible) + { + if (CollectionView.Hidden) + { + CollectionView.ReloadData(); + CollectionView.Hidden = false; + Layout.InvalidateLayout(); + CollectionView.LayoutIfNeeded(); + } + } + else + { + CollectionView.Hidden = true; + } + } + + private protected virtual void AttachingToWindow() + { + + } + + private protected virtual void DetachingFromWindow() + { + } + + private protected virtual NSIndexPath GetAdjustedIndexPathForItemSource(NSIndexPath indexPath) + { + return indexPath; + } + + internal virtual void CellDisplayingEndedFromDelegate(UICollectionViewCell cell, NSIndexPath indexPath) + { + if (cell is TemplatedCell2 TemplatedCell2 && + (TemplatedCell2.PlatformHandler?.VirtualView as View)?.BindingContext is object bindingContext) + { + // We want to unbind a cell that is no longer present in the items source. Unfortunately + // it's too expensive to check directly, so let's check that the current binding context + // matches the item at a given position. + + indexPath = GetAdjustedIndexPathForItemSource(indexPath); + + var itemsSource = ItemsSource; + if (itemsSource is null || + !Items.IndexPathHelpers.IsIndexPathValid(itemsSource, indexPath) || + !Equals(itemsSource[indexPath], bindingContext)) + { + TemplatedCell2.Unbind(); + } + } + } + } +} diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewDelegator2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewDelegator2.cs new file mode 100644 index 000000000000..f0317391c8b8 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewDelegator2.cs @@ -0,0 +1,170 @@ +#nullable disable +using System; +using System.Linq; +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class ItemsViewDelegator2 : UICollectionViewDelegateFlowLayout + where TItemsView : ItemsView + where TViewController : ItemsViewController2 + { + readonly WeakReference _viewController; + + public UICollectionViewLayout ItemsViewLayout { get; } + public TViewController ViewController => _viewController.TryGetTarget(out var vc) ? vc : null; + + protected float PreviousHorizontalOffset, PreviousVerticalOffset; + + public ItemsViewDelegator2(UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) + { + ItemsViewLayout = itemsViewLayout; + _viewController = new(ItemsViewController2); + } + + public override void Scrolled(UIScrollView scrollView) + { + var (visibleItems, firstVisibleItemIndex, centerItemIndex, lastVisibleItemIndex) = GetVisibleItemsIndex(); + + if (!visibleItems) + return; + + var contentInset = scrollView.ContentInset; + var contentOffsetX = scrollView.ContentOffset.X + contentInset.Left; + var contentOffsetY = scrollView.ContentOffset.Y + contentInset.Top; + + var itemsViewScrolledEventArgs = new ItemsViewScrolledEventArgs + { + HorizontalDelta = contentOffsetX - PreviousHorizontalOffset, + VerticalDelta = contentOffsetY - PreviousVerticalOffset, + HorizontalOffset = contentOffsetX, + VerticalOffset = contentOffsetY, + FirstVisibleItemIndex = firstVisibleItemIndex, + CenterItemIndex = centerItemIndex, + LastVisibleItemIndex = lastVisibleItemIndex + }; + + var viewController = ViewController; + if (viewController is null) + return; + + var itemsView = viewController.ItemsView; + var source = viewController.ItemsSource; + itemsView.SendScrolled(itemsViewScrolledEventArgs); + + PreviousHorizontalOffset = (float)contentOffsetX; + PreviousVerticalOffset = (float)contentOffsetY; + + switch (itemsView.RemainingItemsThreshold) + { + case -1: + return; + case 0: + if (lastVisibleItemIndex == source.ItemCount - 1) + itemsView.SendRemainingItemsThresholdReached(); + break; + default: + if (source.ItemCount - 1 - lastVisibleItemIndex <= itemsView.RemainingItemsThreshold) + itemsView.SendRemainingItemsThresholdReached(); + break; + } + } + + public override UIEdgeInsets GetInsetForSection(UICollectionView collectionView, UICollectionViewLayout layout, + nint section) + { + if (ItemsViewLayout == null) + { + return default; + } + + return default; // TODO: FIx ItemsViewLayout.GetInsetForSection(collectionView, layout, section); + } + + public override nfloat GetMinimumInteritemSpacingForSection(UICollectionView collectionView, + UICollectionViewLayout layout, nint section) + { + if (ItemsViewLayout == null) + { + return default; + } + + return default; // TODO: Fix ItemsViewLayout.GetMinimumInteritemSpacingForSection(collectionView, layout, section); + } + + public override nfloat GetMinimumLineSpacingForSection(UICollectionView collectionView, + UICollectionViewLayout layout, nint section) + { + if (ItemsViewLayout == null) + { + return default; + } + + return default; // TODO: Fix ItemsViewLayout.GetMinimumLineSpacingForSection(collectionView, layout, section); + } + + public override void CellDisplayingEnded(UICollectionView collectionView, UICollectionViewCell cell, NSIndexPath indexPath) + { + ViewController?.CellDisplayingEndedFromDelegate(cell, indexPath); + } + + protected virtual (bool VisibleItems, NSIndexPath First, NSIndexPath Center, NSIndexPath Last) GetVisibleItemsIndexPath() + { + var collectionView = ViewController?.CollectionView; + if (collectionView is null) + return default; + + var indexPathsForVisibleItems = collectionView.IndexPathsForVisibleItems.OrderBy(x => x.Row).ToList(); + + var visibleItems = indexPathsForVisibleItems.Count > 0; + NSIndexPath firstVisibleItemIndex = null, centerItemIndex = null, lastVisibleItemIndex = null; + + if (visibleItems) + { + firstVisibleItemIndex = indexPathsForVisibleItems.First(); + centerItemIndex = GetCenteredIndexPath(collectionView); + lastVisibleItemIndex = indexPathsForVisibleItems.Last(); + } + + return (visibleItems, firstVisibleItemIndex, centerItemIndex, lastVisibleItemIndex); + } + + protected virtual (bool VisibleItems, int First, int Center, int Last) GetVisibleItemsIndex() + { + var (VisibleItems, First, Center, Last) = GetVisibleItemsIndexPath(); + int firstVisibleItemIndex = -1, centerItemIndex = -1, lastVisibleItemIndex = -1; + if (VisibleItems) + { + firstVisibleItemIndex = (int)First.Item; + centerItemIndex = (int)Center.Item; + lastVisibleItemIndex = (int)Last.Item; + } + return (VisibleItems, firstVisibleItemIndex, centerItemIndex, lastVisibleItemIndex); + } + + static NSIndexPath GetCenteredIndexPath(UICollectionView collectionView) + { + NSIndexPath centerItemIndex = null; + + var indexPathsForVisibleItems = collectionView.IndexPathsForVisibleItems.OrderBy(x => x.Row).ToList(); + + if (indexPathsForVisibleItems.Count == 0) + return centerItemIndex; + + var firstVisibleItemIndex = indexPathsForVisibleItems.First(); + + var centerPoint = new CGPoint(collectionView.Center.X + collectionView.ContentOffset.X, collectionView.Center.Y + collectionView.ContentOffset.Y); + var centerIndexPath = collectionView.IndexPathForItemAtPoint(centerPoint); + centerItemIndex = centerIndexPath ?? firstVisibleItemIndex; + return centerItemIndex; + } + + // public override CGSize GetSizeForItem(UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath) + // { + // return ViewController?.GetSizeForItem(indexPath) ?? CGSize.Empty; + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutAttributesChangedEventArgs2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutAttributesChangedEventArgs2.cs new file mode 100644 index 000000000000..df2cbac5da9e --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutAttributesChangedEventArgs2.cs @@ -0,0 +1,14 @@ +#nullable disable +using System; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class LayoutAttributesChangedEventArgs2 : EventArgs + { + public UICollectionViewLayoutAttributes NewAttributes { get; } + + public LayoutAttributesChangedEventArgs2(UICollectionViewLayoutAttributes newAttributes) => NewAttributes = newAttributes; + } +} diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs new file mode 100644 index 000000000000..5723cbebfe6d --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs @@ -0,0 +1,368 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using CoreGraphics; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2; + +internal static class LayoutFactory2 +{ + public static UICollectionViewLayout CreateList(LinearItemsLayout linearItemsLayout, + LayoutGroupingInfo groupingInfo, LayoutHeaderFooterInfo headerFooterInfo) + => linearItemsLayout.Orientation == ItemsLayoutOrientation.Vertical + ? CreateVerticalList(linearItemsLayout, groupingInfo, headerFooterInfo) + : CreateHorizontalList(linearItemsLayout, groupingInfo, headerFooterInfo); + + public static UICollectionViewLayout CreateGrid(GridItemsLayout gridItemsLayout, + LayoutGroupingInfo groupingInfo, LayoutHeaderFooterInfo headerFooterInfo) + => gridItemsLayout.Orientation == ItemsLayoutOrientation.Vertical + ? CreateVerticalGrid(gridItemsLayout, groupingInfo, headerFooterInfo) + : CreateHorizontalGrid(gridItemsLayout, groupingInfo, headerFooterInfo); + + static NSCollectionLayoutBoundarySupplementaryItem[] CreateSupplementaryItems(LayoutGroupingInfo? groupingInfo, LayoutHeaderFooterInfo? layoutHeaderFooterInfo, + UICollectionViewScrollDirection scrollDirection, NSCollectionLayoutDimension width, NSCollectionLayoutDimension height) + { + if (groupingInfo is not null && groupingInfo.IsGrouped) + { + var items = new List(); + + if (groupingInfo.HasHeader) + { + items.Add(NSCollectionLayoutBoundarySupplementaryItem.Create( + NSCollectionLayoutSize.Create(width, height), + UICollectionElementKindSectionKey.Header.ToString(), + scrollDirection == UICollectionViewScrollDirection.Vertical + ? NSRectAlignment.Top + : NSRectAlignment.Leading)); + } + + if (groupingInfo.HasFooter) + { + items.Add(NSCollectionLayoutBoundarySupplementaryItem.Create( + NSCollectionLayoutSize.Create(width, height), + UICollectionElementKindSectionKey.Footer.ToString(), + scrollDirection == UICollectionViewScrollDirection.Vertical + ? NSRectAlignment.Bottom + : NSRectAlignment.Trailing)); + } + + return items.ToArray(); + } + + if (layoutHeaderFooterInfo is not null) + { + var items = new List(); + + if (layoutHeaderFooterInfo.HasHeader) + { + items.Add(NSCollectionLayoutBoundarySupplementaryItem.Create( + NSCollectionLayoutSize.Create(width, height), + UICollectionElementKindSectionKey.Header.ToString(), + scrollDirection == UICollectionViewScrollDirection.Vertical + ? NSRectAlignment.Top + : NSRectAlignment.Leading)); + }; + + if (layoutHeaderFooterInfo.HasFooter) + { + items.Add(NSCollectionLayoutBoundarySupplementaryItem.Create( + NSCollectionLayoutSize.Create(width, height), + UICollectionElementKindSectionKey.Footer.ToString(), + scrollDirection == UICollectionViewScrollDirection.Vertical + ? NSRectAlignment.Bottom + : NSRectAlignment.Trailing)); + } + + return items.ToArray(); + } + + return []; + } + + static UICollectionViewLayout CreateListLayout(UICollectionViewScrollDirection scrollDirection, LayoutGroupingInfo groupingInfo, LayoutHeaderFooterInfo layoutHeaderFooterInfo, LayoutSnapInfo snapInfo, NSCollectionLayoutDimension itemWidth, NSCollectionLayoutDimension itemHeight, NSCollectionLayoutDimension groupWidth, NSCollectionLayoutDimension groupHeight, double itemSpacing, Func? peekAreaInsetsFunc) + { + var layoutConfiguration = new UICollectionViewCompositionalLayoutConfiguration(); + layoutConfiguration.ScrollDirection = scrollDirection; + + //create global header and footer + layoutConfiguration.BoundarySupplementaryItems = CreateSupplementaryItems(null, layoutHeaderFooterInfo, scrollDirection, groupWidth, groupHeight); + + var layout = new CustomUICollectionViewCompositionalLayout(snapInfo, (sectionIndex, environment) => + { + // Each item has a size + var itemSize = NSCollectionLayoutSize.Create(itemWidth, itemHeight); + // Create the item itself from the size + var item = NSCollectionLayoutItem.Create(layoutSize: itemSize); + + if (peekAreaInsetsFunc?.Invoke() is Thickness peekAreaInsets) + { + if (scrollDirection == UICollectionViewScrollDirection.Vertical) + { + var newGroupHeight = environment.Container.ContentSize.Height - peekAreaInsets.Top - peekAreaInsets.Bottom; + groupHeight = NSCollectionLayoutDimension.CreateAbsolute((nfloat)newGroupHeight); + } + else + { + var newGroupWidth = environment.Container.ContentSize.Width - peekAreaInsets.Left - peekAreaInsets.Right; + groupWidth = NSCollectionLayoutDimension.CreateAbsolute((nfloat)newGroupWidth); + } + } + // Each group of items (for grouped collections) has a size + var groupSize = NSCollectionLayoutSize.Create(groupWidth, groupHeight); + + // Create the group + // If vertical list, we want the group to layout horizontally (eg: grid columns go left to right) + // for horizontal list, we want to lay grid rows out vertically + // For simple lists it doesn't matter so much since the items span the entire width or height + var group = scrollDirection == UICollectionViewScrollDirection.Vertical + ? NSCollectionLayoutGroup.CreateHorizontal(groupSize, item, 1) + : NSCollectionLayoutGroup.CreateVertical(groupSize, item, 1); + + //group.InterItemSpacing = NSCollectionLayoutSpacing.CreateFixed(new NFloat(itemSpacing)); + + // Create our section layout + var section = NSCollectionLayoutSection.Create(group: group); + section.InterGroupSpacing = new NFloat(itemSpacing); + + // Create header and footer for group + section.BoundarySupplementaryItems = CreateSupplementaryItems( + groupingInfo, + null, + scrollDirection, + groupWidth, + groupHeight); + + return section; + }, layoutConfiguration); + + return layout; + } + + + + static UICollectionViewLayout CreateGridLayout(UICollectionViewScrollDirection scrollDirection, LayoutGroupingInfo groupingInfo, LayoutHeaderFooterInfo headerFooterInfo, LayoutSnapInfo snapInfo, NSCollectionLayoutDimension itemWidth, NSCollectionLayoutDimension itemHeight, NSCollectionLayoutDimension groupWidth, NSCollectionLayoutDimension groupHeight, double verticalItemSpacing, double horizontalItemSpacing, int columns) + { + var layoutConfiguration = new UICollectionViewCompositionalLayoutConfiguration(); + layoutConfiguration.ScrollDirection = scrollDirection; + + var layout = new CustomUICollectionViewCompositionalLayout(snapInfo, (sectionIndex, environment) => + { + // Each item has a size + var itemSize = NSCollectionLayoutSize.Create(itemWidth, itemHeight); + // Create the item itself from the size + var item = NSCollectionLayoutItem.Create(layoutSize: itemSize); + + // Each group of items (for grouped collections) has a size + var groupSize = NSCollectionLayoutSize.Create(groupWidth, groupHeight); + + // Create the group + // If vertical list, we want the group to layout horizontally (eg: grid columns go left to right) + // for horizontal list, we want to lay grid rows out vertically + // For simple lists it doesn't matter so much since the items span the entire width or height + var group = scrollDirection == UICollectionViewScrollDirection.Vertical + ? NSCollectionLayoutGroup.CreateHorizontal(groupSize, item, columns) + : NSCollectionLayoutGroup.CreateVertical(groupSize, item, columns); + + if (scrollDirection == UICollectionViewScrollDirection.Vertical) + group.InterItemSpacing = NSCollectionLayoutSpacing.CreateFixed(new NFloat(horizontalItemSpacing)); + else + group.InterItemSpacing = NSCollectionLayoutSpacing.CreateFixed(new NFloat(verticalItemSpacing)); + + // Create our section layout + var section = NSCollectionLayoutSection.Create(group: group); + + if (scrollDirection == UICollectionViewScrollDirection.Vertical) + section.InterGroupSpacing = new NFloat(verticalItemSpacing); + else + section.InterGroupSpacing = new NFloat(horizontalItemSpacing); + + + section.BoundarySupplementaryItems = CreateSupplementaryItems( + groupingInfo, + headerFooterInfo, + scrollDirection, + groupWidth, + groupHeight); + + return section; + }, layoutConfiguration); + + return layout; + } + + public static UICollectionViewLayout CreateVerticalList(LinearItemsLayout linearItemsLayout, + LayoutGroupingInfo groupingInfo, LayoutHeaderFooterInfo headerFooterInfo) + => CreateListLayout(UICollectionViewScrollDirection.Vertical, + groupingInfo, + headerFooterInfo, + new LayoutSnapInfo { SnapType = linearItemsLayout.SnapPointsType, SnapAligment = linearItemsLayout.SnapPointsAlignment }, + // Fill the width + NSCollectionLayoutDimension.CreateFractionalWidth(1f), + // Dynamic (estimate required) + NSCollectionLayoutDimension.CreateEstimated(30f), + NSCollectionLayoutDimension.CreateFractionalWidth(1f), + NSCollectionLayoutDimension.CreateEstimated(30f), + linearItemsLayout.ItemSpacing, + null); + + + public static UICollectionViewLayout CreateHorizontalList(LinearItemsLayout linearItemsLayout, + LayoutGroupingInfo groupingInfo, LayoutHeaderFooterInfo headerFooterInfo) + => CreateListLayout(UICollectionViewScrollDirection.Horizontal, + groupingInfo, + headerFooterInfo, + new LayoutSnapInfo { SnapType = linearItemsLayout.SnapPointsType, SnapAligment = linearItemsLayout.SnapPointsAlignment }, + // Dynamic, estimated width + NSCollectionLayoutDimension.CreateEstimated(30f), + // Fill the height for horizontal + NSCollectionLayoutDimension.CreateFractionalHeight(1f), + NSCollectionLayoutDimension.CreateEstimated(30f), + NSCollectionLayoutDimension.CreateFractionalHeight(1f), + linearItemsLayout.ItemSpacing, + null); + + public static UICollectionViewLayout CreateVerticalGrid(GridItemsLayout gridItemsLayout, + LayoutGroupingInfo groupingInfo, LayoutHeaderFooterInfo headerFooterInfo) + => CreateGridLayout(UICollectionViewScrollDirection.Vertical, + groupingInfo, + headerFooterInfo, + new LayoutSnapInfo { SnapType = gridItemsLayout.SnapPointsType, SnapAligment = gridItemsLayout.SnapPointsAlignment }, + // Width is the number of columns + NSCollectionLayoutDimension.CreateFractionalWidth(1f / gridItemsLayout.Span), + // Height is dynamic, estimated + NSCollectionLayoutDimension.CreateEstimated(30f), + // Group spans all columns, full width for vertical + NSCollectionLayoutDimension.CreateFractionalWidth(1f), + // Group is dynamic height for vertical + NSCollectionLayoutDimension.CreateEstimated(30f), + gridItemsLayout.VerticalItemSpacing, + gridItemsLayout.HorizontalItemSpacing, + gridItemsLayout.Span); + + + public static UICollectionViewLayout CreateHorizontalGrid(GridItemsLayout gridItemsLayout, + LayoutGroupingInfo groupingInfo, LayoutHeaderFooterInfo headerFooterInfo) + => CreateGridLayout(UICollectionViewScrollDirection.Horizontal, + groupingInfo, + headerFooterInfo, + new LayoutSnapInfo { SnapType = gridItemsLayout.SnapPointsType, SnapAligment = gridItemsLayout.SnapPointsAlignment }, + // Item width is estimated + NSCollectionLayoutDimension.CreateEstimated(30f), + // Item height is number of rows + NSCollectionLayoutDimension.CreateFractionalHeight(1f / gridItemsLayout.Span), + // Group width is dynamic for horizontal + NSCollectionLayoutDimension.CreateEstimated(30f), + // Group spans all rows, full height for horizontal + NSCollectionLayoutDimension.CreateFractionalHeight(1f), + gridItemsLayout.VerticalItemSpacing, + gridItemsLayout.HorizontalItemSpacing, + gridItemsLayout.Span); + + + class CustomUICollectionViewCompositionalLayout : UICollectionViewCompositionalLayout + { + LayoutSnapInfo _snapInfo; + public CustomUICollectionViewCompositionalLayout(LayoutSnapInfo snapInfo, UICollectionViewCompositionalLayoutSectionProvider sectionProvider, UICollectionViewCompositionalLayoutConfiguration configuration) : base(sectionProvider, configuration) + { + _snapInfo = snapInfo; + } + + public override CGPoint TargetContentOffset(CGPoint proposedContentOffset, CGPoint scrollingVelocity) + { + var snapPointsType = _snapInfo.SnapType; + var alignment = _snapInfo.SnapAligment; + + if (snapPointsType == SnapPointsType.None) + { + // Nothing to do here; fall back to the default + return base.TargetContentOffset(proposedContentOffset, scrollingVelocity); + } + + if (snapPointsType == SnapPointsType.MandatorySingle) + { + // Mandatory snapping, single element + return ScrollSingle(alignment, proposedContentOffset, scrollingVelocity); + } + + // Get the viewport of the UICollectionView at the proposed content offset + var viewport = new CGRect(proposedContentOffset, CollectionView.Bounds.Size); + + // And find all the elements currently visible in the viewport + var visibleElements = LayoutAttributesForElementsInRect(viewport); + + if (visibleElements.Length == 0) + { + // Nothing to see here; fall back to the default + return base.TargetContentOffset(proposedContentOffset, scrollingVelocity); + } + + if (visibleElements.Length == 1) + { + // If there is only one item in the viewport, then we need to align the viewport with it + return Items.SnapHelpers.AdjustContentOffset(proposedContentOffset, visibleElements[0].Frame, viewport, + alignment, Configuration.ScrollDirection); + } + + // If there are multiple items in the viewport, we need to choose the one which is + // closest to the relevant part of the viewport while being sufficiently visible + + // Find the spot in the viewport we're trying to align with + var alignmentTarget = Items.SnapHelpers.FindAlignmentTarget(alignment, proposedContentOffset, + CollectionView, Configuration.ScrollDirection); + + // Find the closest sufficiently visible candidate + var bestCandidate = Items.SnapHelpers.FindBestSnapCandidate(visibleElements, viewport, alignmentTarget); + + if (bestCandidate != null) + { + return Items.SnapHelpers.AdjustContentOffset(proposedContentOffset, bestCandidate.Frame, viewport, alignment, + Configuration.ScrollDirection); + } + + // If we got this far an nothing matched, it means that we have multiple items but somehow + // none of them fit at least half in the viewport. So just fall back to the first item + return Items.SnapHelpers.AdjustContentOffset(proposedContentOffset, visibleElements[0].Frame, viewport, alignment, + Configuration.ScrollDirection); + } + + CGPoint ScrollSingle(SnapPointsAlignment alignment, CGPoint proposedContentOffset, CGPoint scrollingVelocity) + { + // Get the viewport of the UICollectionView at the current content offset + var contentOffset = CollectionView.ContentOffset; + var viewport = new CGRect(contentOffset, CollectionView.Bounds.Size); + + // Find the spot in the viewport we're trying to align with + var alignmentTarget = Items.SnapHelpers.FindAlignmentTarget(alignment, contentOffset, CollectionView, Configuration.ScrollDirection); + + var visibleElements = LayoutAttributesForElementsInRect(viewport); + + // Find the current aligned item + var currentItem = Items.SnapHelpers.FindBestSnapCandidate(visibleElements, viewport, alignmentTarget); + + if (currentItem == null) + { + // Somehow we don't currently have an item in the viewport near the target; fall back to the + // default behavior + return base.TargetContentOffset(proposedContentOffset, scrollingVelocity); + } + + // Determine the index of the current item + var currentIndex = visibleElements.IndexOf(currentItem); + + // Figure out the step size when jumping to the "next" element + var span = 1; + // if (_itemsLayout is GridItemsLayout gridItemsLayout) + // { + // span = gridItemsLayout.Span; + // } + + // Find the next item in the + currentItem = Items.SnapHelpers.FindNextItem(visibleElements, Configuration.ScrollDirection, span, scrollingVelocity, currentIndex); + + return Items.SnapHelpers.AdjustContentOffset(CollectionView.ContentOffset, currentItem.Frame, viewport, alignment, + Configuration.ScrollDirection); + } + } + +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/LoopListSource2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/LoopListSource2.cs new file mode 100644 index 000000000000..225df794085c --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/LoopListSource2.cs @@ -0,0 +1,29 @@ +#nullable disable +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal class LoopListSource2 : Items.ListSource, Items.ILoopItemsViewSource + { + public LoopListSource2(IEnumerable enumerable, bool loop) : base(enumerable) + { + Loop = loop; + } + + public LoopListSource2(IEnumerable enumerable, bool loop) + { + Loop = loop; + + foreach (object item in enumerable) + { + Add(item); + } + } + + public bool Loop { get; set; } + + public int LoopCount => Loop && Count > 0 ? Count + 2 : Count; + } +} diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/LoopObservableItemsSource2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/LoopObservableItemsSource2.cs new file mode 100644 index 000000000000..f77766b07e7f --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/LoopObservableItemsSource2.cs @@ -0,0 +1,71 @@ +#nullable disable +using System; +using System.Collections; +using Foundation; +using ObjCRuntime; +using UIKit; +using Microsoft.Maui.Controls.Handlers.Items; +using System.Collections.Specialized; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal class LoopObservableItemsSource2 : Items.ObservableItemsSource, Items.ILoopItemsViewSource + { + int _section = 0; + + public LoopObservableItemsSource2(IEnumerable itemSource, UICollectionViewController collectionViewController, bool loop, int group = -1) : base(itemSource, collectionViewController, group) + { + Loop = loop; + } + + public bool Loop { get; set; } + + protected override NSIndexPath[] CreateIndexesFrom(int startIndex, int count) + { + if (ItemCount == 0) + { + count += 2; + startIndex = 0; + } + return IndexPathHelpers.GenerateIndexPathRange(_section, startIndex, count); + } + + private protected override bool ShouldReload(NotifyCollectionChangedEventArgs args) + { + if (args.Action == NotifyCollectionChangedAction.Reset) + { + return true; + } + if (args.Action == NotifyCollectionChangedAction.Add) + { + if (ItemCount == 0) + { + return true; + } + } + if (args.Action == NotifyCollectionChangedAction.Remove) + { + if (ItemCount < 1) + { + return true; + } + } + return base.ShouldReload(args); + } + + //We are going to add 2 items since we are inserting 1 item at the beginning and 1 item at the end + public int LoopCount + { + get + { + var newCount = ItemCount; + if (newCount > 0) + { + newCount = ItemCount + 2; + } + return newCount; + } + } + + } +} diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/ReorderableItemsViewController2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/ReorderableItemsViewController2.cs new file mode 100644 index 000000000000..12e33e65ef62 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/ReorderableItemsViewController2.cs @@ -0,0 +1,174 @@ +#nullable disable +using System; +using System.Collections; +using System.Collections.Specialized; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class ReorderableItemsViewController2 : GroupableItemsViewController2 + where TItemsView : ReorderableItemsView + { + bool _disposed; + UILongPressGestureRecognizer _longPressGestureRecognizer; + + public ReorderableItemsViewController2(TItemsView reorderableItemsView, UICollectionViewLayout layout) + : base(reorderableItemsView, layout) + { + // The UICollectionViewController has built-in recognizer for reorder that can be installed by setting "InstallsStandardGestureForInteractiveMovement". + // For some reason it only seemed to work when the CollectionView was inside the Flyout section of a FlyoutPage. + // The UILongPressGestureRecognizer is simple enough to set up so let's just add our own. + InstallsStandardGestureForInteractiveMovement = false; + } + + public override bool CanMoveItem(UICollectionView collectionView, NSIndexPath indexPath) + { + return ItemsView?.CanReorderItems == true; + } + + protected override UICollectionViewDelegateFlowLayout CreateDelegator() + { + return new ReorderableItemsViewDelegator2>(ItemsViewLayout, this); + } + + protected override Items.IItemsViewSource CreateItemsViewSource() + { + if (ItemsSource != null) + { + // There's a bug in the current Maui Controls library. + // It will call "CreateItemsViewSource" 2x in a row when opening a page. + // It's invoked from both ViewDidLoad & UpdateItemsSource + // For the time being, until the issue is fixed, we need to dispose of the current source if one already exist. + ItemsSource.Dispose(); + } + return base.CreateItemsViewSource(); + } + + protected override void Dispose(bool disposing) + { + if (disposing && !_disposed) + { + if (_longPressGestureRecognizer != null) + { + CollectionView.RemoveGestureRecognizer(_longPressGestureRecognizer); + _longPressGestureRecognizer.Dispose(); + _longPressGestureRecognizer = null; + } + + _disposed = true; + } + + base.Dispose(disposing); + } + + void HandleLongPress(UILongPressGestureRecognizer gestureRecognizer) + { + var collectionView = CollectionView; + if (collectionView == null) + return; + + var location = gestureRecognizer.LocationInView(collectionView); + + // We are updating "CancelsTouchesInView" so views can still receive touch events when this gesture runs. + // Those events shouldn't be aborted until they've actually moved the position of the CollectionView item. + switch (gestureRecognizer.State) + { + case UIGestureRecognizerState.Began: + var indexPath = collectionView?.IndexPathForItemAtPoint(location); + if (indexPath == null) + { + return; + } + gestureRecognizer.CancelsTouchesInView = false; + collectionView.BeginInteractiveMovementForItem(indexPath); + break; + case UIGestureRecognizerState.Changed: + gestureRecognizer.CancelsTouchesInView = true; + collectionView.UpdateInteractiveMovement(location); + break; + case UIGestureRecognizerState.Ended: + collectionView.EndInteractiveMovement(); + break; + default: + collectionView.CancelInteractiveMovement(); + break; + } + } + + public override void MoveItem(UICollectionView collectionView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath) + { + var itemsSource = ItemsSource; + var itemsView = ItemsView; + + if (itemsSource == null || itemsView == null) + { + return; + } + + if (itemsView.IsGrouped) + { + var fromList = itemsSource.Group(sourceIndexPath) as IList; + var fromItemsSource = fromList is INotifyCollectionChanged ? itemsSource.GroupItemsViewSource(sourceIndexPath) : null; + var fromItemIndex = sourceIndexPath.Row; + + var toList = itemsSource.Group(destinationIndexPath) as IList; + var toItemsSource = toList is INotifyCollectionChanged ? itemsSource.GroupItemsViewSource(destinationIndexPath) : null; + var toItemIndex = destinationIndexPath.Row; + + if (fromList != null && toList != null) + { + var fromItem = fromList[fromItemIndex]; + SetObserveChanges(fromItemsSource, false); + SetObserveChanges(toItemsSource, false); + fromList.RemoveAt(fromItemIndex); + toList.Insert(toItemIndex, fromItem); + SetObserveChanges(fromItemsSource, true); + SetObserveChanges(toItemsSource, true); + itemsView.SendReorderCompleted(); + } + } + else if (itemsView.ItemsSource is IList list) + { + var fromPosition = sourceIndexPath.Row; + var toPosition = destinationIndexPath.Row; + var fromItem = list[fromPosition]; + SetObserveChanges(itemsSource, false); + list.RemoveAt(fromPosition); + list.Insert(toPosition, fromItem); + SetObserveChanges(itemsSource, true); + itemsView.SendReorderCompleted(); + } + } + + void SetObserveChanges(Items.IItemsViewSource itemsSource, bool enable) + { + if (itemsSource is Items.IObservableItemsViewSource observableSource) + { + observableSource.ObserveChanges = enable; + } + } + + public void UpdateCanReorderItems() + { + if (ItemsView.CanReorderItems) + { + if (_longPressGestureRecognizer == null) + { + _longPressGestureRecognizer = new UILongPressGestureRecognizer(HandleLongPress); + CollectionView.AddGestureRecognizer(_longPressGestureRecognizer); + } + } + else + { + if (_longPressGestureRecognizer != null) + { + CollectionView.RemoveGestureRecognizer(_longPressGestureRecognizer); + _longPressGestureRecognizer.Dispose(); + _longPressGestureRecognizer = null; + } + } + } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/ReorderableItemsViewDelegator2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/ReorderableItemsViewDelegator2.cs new file mode 100644 index 000000000000..9a3fc42e3e23 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/ReorderableItemsViewDelegator2.cs @@ -0,0 +1,42 @@ +#nullable disable +using System; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class ReorderableItemsViewDelegator2 : GroupableItemsViewDelegator2 + where TItemsView : ReorderableItemsView + where TViewController : ReorderableItemsViewController2 + { + public ReorderableItemsViewDelegator2(UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) + : base(itemsViewLayout, ItemsViewController2) + { + } + + public override NSIndexPath GetTargetIndexPathForMove(UICollectionView collectionView, NSIndexPath originalIndexPath, NSIndexPath proposedIndexPath) + { + NSIndexPath targetIndexPath; + + var itemsView = ViewController?.ItemsView; + if (itemsView?.IsGrouped == true) + { + if (originalIndexPath.Section == proposedIndexPath.Section || itemsView.CanMixGroups) + { + targetIndexPath = proposedIndexPath; + } + else + { + targetIndexPath = originalIndexPath; + } + } + else + { + targetIndexPath = proposedIndexPath; + } + + return targetIndexPath; + } + } +} diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/SelectableItemsViewController2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/SelectableItemsViewController2.cs new file mode 100644 index 000000000000..07ab2a4d6b93 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/SelectableItemsViewController2.cs @@ -0,0 +1,171 @@ +#nullable disable +using System; +using System.Collections.Generic; +using System.Linq; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class SelectableItemsViewController2 : StructuredItemsViewController2 + where TItemsView : SelectableItemsView + { + public SelectableItemsViewController2(TItemsView selectableItemsView, UICollectionViewLayout layout) + : base(selectableItemsView, layout) + { + } + + protected override UICollectionViewDelegateFlowLayout CreateDelegator() + { + return new SelectableItemsViewDelegator2>(ItemsViewLayout, this); + } + + // _Only_ called if the user initiates the selection change; will not be called for programmatic selection + public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath) + { + FormsSelectItem(indexPath); + } + + // _Only_ called if the user initiates the selection change; will not be called for programmatic selection + public override void ItemDeselected(UICollectionView collectionView, NSIndexPath indexPath) + { + FormsDeselectItem(indexPath); + } + + // Called by Forms to mark an item selected + internal void SelectItem(object selectedItem) + { + var index = GetIndexForItem(selectedItem); + + if (index.Section > -1 && index.Item > -1) + { + CollectionView.SelectItem(index, true, UICollectionViewScrollPosition.None); + } + } + + // Called by Forms to clear the native selection + internal void ClearSelection() + { + var selectedItemIndexes = CollectionView.GetIndexPathsForSelectedItems(); + + foreach (var index in selectedItemIndexes) + { + CollectionView.DeselectItem(index, true); + } + } + + void FormsSelectItem(NSIndexPath indexPath) + { + var mode = ItemsView.SelectionMode; + + switch (mode) + { + case SelectionMode.None: + break; + case SelectionMode.Single: + ItemsView.SelectedItem = GetItemAtIndex(indexPath); + break; + case SelectionMode.Multiple: + ItemsView.SelectedItems.Add(GetItemAtIndex(indexPath)); + break; + } + } + + void FormsDeselectItem(NSIndexPath indexPath) + { + var mode = ItemsView.SelectionMode; + + switch (mode) + { + case SelectionMode.None: + break; + case SelectionMode.Single: + break; + case SelectionMode.Multiple: + ItemsView.SelectedItems.Remove(GetItemAtIndex(indexPath)); + break; + } + } + + internal void UpdatePlatformSelection() + { + if (ItemsView == null) + { + return; + } + + var mode = ItemsView.SelectionMode; + + switch (mode) + { + case SelectionMode.None: + return; + case SelectionMode.Single: + var selectedItem = ItemsView.SelectedItem; + + if (selectedItem != null) + { + SelectItem(selectedItem); + } + else + { + // SelectedItem has been set to null; if an item is selected, we need to de-select it + ClearSelection(); + } + + return; + case SelectionMode.Multiple: + SynchronizePlatformSelectionWithSelectedItems(); + break; + } + } + + internal void UpdateSelectionMode() + { + var mode = ItemsView.SelectionMode; + + switch (mode) + { + case SelectionMode.None: + CollectionView.AllowsSelection = false; + CollectionView.AllowsMultipleSelection = false; + break; + case SelectionMode.Single: + CollectionView.AllowsSelection = true; + CollectionView.AllowsMultipleSelection = false; + break; + case SelectionMode.Multiple: + CollectionView.AllowsSelection = true; + CollectionView.AllowsMultipleSelection = true; + break; + } + + UpdatePlatformSelection(); + } + + void SynchronizePlatformSelectionWithSelectedItems() + { + var selectedItems = ItemsView.SelectedItems.ToHashSet(); + var selectedIndexPaths = CollectionView.GetIndexPathsForSelectedItems(); + + foreach (var path in selectedIndexPaths) + { + var itemAtPath = GetItemAtIndex(path); + if (!selectedItems.Contains(itemAtPath)) + { + CollectionView.DeselectItem(path, true); + } + else + { + selectedItems.Remove(itemAtPath); + } + } + + foreach (var item in selectedItems) + { + SelectItem(item); + } + } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/SelectableItemsViewDelegator2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/SelectableItemsViewDelegator2.cs new file mode 100644 index 000000000000..2ddaa8d1dd75 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/SelectableItemsViewDelegator2.cs @@ -0,0 +1,27 @@ +#nullable disable +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class SelectableItemsViewDelegator2 : ItemsViewDelegator2 + where TItemsView : SelectableItemsView + where TViewController : SelectableItemsViewController2 + { + public SelectableItemsViewDelegator2(UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) + : base(itemsViewLayout, ItemsViewController2) + { + } + + public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath) + { + ViewController?.ItemSelected(collectionView, indexPath); + } + + public override void ItemDeselected(UICollectionView collectionView, NSIndexPath indexPath) + { + ViewController?.ItemDeselected(collectionView, indexPath); + } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/StructuredItemsViewController2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/StructuredItemsViewController2.cs new file mode 100644 index 000000000000..0b3a63d88a52 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/StructuredItemsViewController2.cs @@ -0,0 +1,187 @@ +#nullable disable +using System; +using CoreGraphics; +using Foundation; +using Microsoft.Maui.Controls.Handlers.Items; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class StructuredItemsViewController2 : ItemsViewController2 + where TItemsView : StructuredItemsView + { + public const int HeaderTag = 111; + public const int FooterTag = 222; + + bool _disposed; + + public StructuredItemsViewController2(TItemsView structuredItemsView, UICollectionViewLayout layout) + : base(structuredItemsView, layout) + { + } + + protected override void RegisterViewTypes() + { + base.RegisterViewTypes(); + + RegisterSupplementaryViews(UICollectionElementKindSection.Header); + RegisterSupplementaryViews(UICollectionElementKindSection.Footer); + } + + protected override void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + _disposed = true; + + if (disposing) + { + + } + + base.Dispose(disposing); + } + + protected override bool IsHorizontal => (ItemsView?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal; + + public override UICollectionReusableView GetViewForSupplementaryElement(UICollectionView collectionView, NSString elementKind, NSIndexPath indexPath) + { + // We don't have a header or footer, so we don't need to do anything + if(ItemsView.Header is null && ItemsView.Footer is null && ItemsView.HeaderTemplate is null && ItemsView.FooterTemplate is null) + { + return null; + } + + var reuseId = DetermineViewReuseId(elementKind); + + var view = collectionView.DequeueReusableSupplementaryView(elementKind, reuseId, indexPath) as UICollectionReusableView; + + switch (view) + { + case DefaultCell2 defaultCell: + UpdateDefaultSupplementaryView(defaultCell, elementKind); + break; + case TemplatedCell2 templatedCell: + UpdateTemplatedSupplementaryView(templatedCell, elementKind); + break; + } + + return view; + } + + private protected virtual void RegisterSupplementaryViews(UICollectionElementKindSection kind) + { + if (IsHorizontal) + { + CollectionView.RegisterClassForSupplementaryView(typeof(HorizontalSupplementaryView2), + kind, HorizontalSupplementaryView2.ReuseId); + CollectionView.RegisterClassForSupplementaryView(typeof(HorizontalDefaultSupplementalView2), + kind, HorizontalDefaultSupplementalView2.ReuseId); + } + else + { + CollectionView.RegisterClassForSupplementaryView(typeof(VerticalSupplementaryView2), + kind, VerticalSupplementaryView2.ReuseId); + CollectionView.RegisterClassForSupplementaryView(typeof(VerticalDefaultSupplementalView2), + kind, VerticalDefaultSupplementalView2.ReuseId); + } + } + + string DetermineViewReuseId(NSString elementKind) + { + return DetermineViewReuseId(elementKind == UICollectionElementKindSectionKey.Header + ? ItemsView.HeaderTemplate + : ItemsView.FooterTemplate, elementKind == UICollectionElementKindSectionKey.Header + ? ItemsView.Header + : ItemsView.Footer); + } + + void UpdateDefaultSupplementaryView(DefaultCell2 cell, NSString elementKind) + { + var obj = elementKind == UICollectionElementKindSectionKey.Header + ? ItemsView.Header + : ItemsView.Footer; + + cell.Label.Text = obj?.ToString(); + } + + void UpdateTemplatedSupplementaryView(TemplatedCell2 cell, NSString elementKind) + { + bool isHeader = elementKind == UICollectionElementKindSectionKey.Header; + + if(isHeader) + { + if(ItemsView.Header is View headerView) + { + cell.Bind(headerView, ItemsView); + } + else if(ItemsView.HeaderTemplate is not null) + { + cell.Bind(ItemsView.HeaderTemplate, ItemsView.Header, ItemsView); + } + cell.Tag = HeaderTag; + } + else + { + if(ItemsView.Footer is View footerView) + { + cell.Bind(footerView, ItemsView); + } + else if(ItemsView.FooterTemplate is not null) + { + cell.Bind(ItemsView.FooterTemplate, ItemsView.Footer, ItemsView); + } + cell.Tag = FooterTag; + } + } + + string DetermineViewReuseId(DataTemplate template, object item) + { + if (template == null) + { + if (item is View) + { + // No template, but we can fall back to the view + return IsHorizontal + ? HorizontalSupplementaryView2.ReuseId + : VerticalSupplementaryView2.ReuseId; + } + // No template, no item, fall back to the default supplemental views + return IsHorizontal + ? HorizontalDefaultSupplementalView2.ReuseId + : VerticalDefaultSupplementalView2.ReuseId; + } + + return IsHorizontal + ? HorizontalSupplementaryView2.ReuseId + : VerticalSupplementaryView2.ReuseId; + } + + protected override CGRect DetermineEmptyViewFrame() + { + nfloat headerHeight = 0; + var headerView = CollectionView.ViewWithTag(HeaderTag); + + if (headerView != null) + headerHeight = headerView.Frame.Height; + + nfloat footerHeight = 0; + var footerView = CollectionView.ViewWithTag(FooterTag); + + if (footerView != null) + footerHeight = footerView.Frame.Height; + + return new CGRect(CollectionView.Frame.X, CollectionView.Frame.Y, CollectionView.Frame.Width, + Math.Abs(CollectionView.Frame.Height - (headerHeight + footerHeight))); + } + + public override void ViewWillLayoutSubviews() + { + base.ViewWillLayoutSubviews(); + } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/TemplatedCell2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/TemplatedCell2.cs new file mode 100644 index 000000000000..6f35bcf7cedd --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/TemplatedCell2.cs @@ -0,0 +1,306 @@ +#nullable disable +using System; +using System.ComponentModel; +using CoreGraphics; +using Foundation; +using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Graphics; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + public class TemplatedCell2 : ItemsViewCell2 + { + internal const string ReuseId = "Microsoft.Maui.Controls.TemplatedCell2"; + + readonly WeakEventManager _weakEventManager = new(); + + public event EventHandler ContentSizeChanged + { + add => _weakEventManager.AddEventHandler(value); + remove => _weakEventManager.RemoveEventHandler(value); + } + + public event EventHandler LayoutAttributesChanged + { + add => _weakEventManager.AddEventHandler(value); + remove => _weakEventManager.RemoveEventHandler(value); + } + + protected CGSize ConstrainedSize; + + protected nfloat ConstrainedDimension; + + WeakReference _currentTemplate; + + public DataTemplate CurrentTemplate + { + get => _currentTemplate is not null && _currentTemplate.TryGetTarget(out var target) ? target : null; + private set => _currentTemplate = value is null ? null : new(value); + } + + // Keep track of the cell size so we can verify whether a measure invalidation + // actually changed the size of the cell + //Size _size; + + //internal CGSize CurrentSize => _size.ToCGSize(); + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public TemplatedCell2(CGRect frame) : base(frame) + { + + } + + public UICollectionViewScrollDirection ScrollDirection { get; set; } + + internal IPlatformViewHandler PlatformHandler { get; set; } + + internal UIView PlatformView { get; set; } + + internal void Unbind() + { + if (PlatformHandler?.VirtualView is View view) + { + //view.MeasureInvalidated -= MeasureInvalidated; + view.BindingContext = null; + } + } + + public override UICollectionViewLayoutAttributes PreferredLayoutAttributesFittingAttributes( + UICollectionViewLayoutAttributes layoutAttributes) + { + var preferredAttributes = base.PreferredLayoutAttributesFittingAttributes(layoutAttributes); + + if (PlatformHandler?.VirtualView is not null) + { + if (ScrollDirection == UICollectionViewScrollDirection.Vertical) + { + var measure = + PlatformHandler.VirtualView.Measure(preferredAttributes.Size.Width, double.PositiveInfinity); + + preferredAttributes.Frame = + new CGRect(preferredAttributes.Frame.X, preferredAttributes.Frame.Y, + preferredAttributes.Frame.Width, measure.Height); + } + else + { + var measure = + PlatformHandler.VirtualView.Measure(double.PositiveInfinity, preferredAttributes.Size.Height); + + preferredAttributes.Frame = + new CGRect(preferredAttributes.Frame.X, preferredAttributes.Frame.Y, + measure.Width, preferredAttributes.Frame.Height); + } + + preferredAttributes.ZIndex = 2; + } + + return preferredAttributes; + } + + public override void PrepareForReuse() + { + //Unbind(); + base.PrepareForReuse(); + } + + public void Bind(DataTemplate template, object bindingContext, ItemsView itemsView) + { + if (PlatformHandler is null) + { + var virtualView = template.CreateContent(bindingContext, itemsView) as View; + + var mauiContext = itemsView.FindMauiContext()!; + var nativeView = virtualView!.ToPlatform(mauiContext); + + PlatformView = nativeView; + + PlatformHandler = virtualView.Handler as IPlatformViewHandler; + + InitializeContentConstraints(nativeView); + + virtualView.BindingContext = bindingContext; + } + + if (PlatformHandler?.VirtualView is View view) + { + view.SetValueFromRenderer(BindableObject.BindingContextProperty, bindingContext); + } + } + + public void Bind(View virtualView, ItemsView itemsView) + { + if (PlatformHandler is null && virtualView is not null) + { + var mauiContext = itemsView.FindMauiContext()!; + var nativeView = virtualView!.ToPlatform(mauiContext); + + var mauiWrapperView = new UIContainerView2(virtualView, mauiContext); + + PlatformView = mauiWrapperView; + + PlatformHandler = virtualView.Handler as IPlatformViewHandler; + + InitializeContentConstraints(mauiWrapperView); + + virtualView.BindingContext = itemsView.BindingContext; + } + + if (PlatformHandler?.VirtualView is View view) + { + view.SetValueFromRenderer(BindableObject.BindingContextProperty, itemsView.BindingContext); + } + } + + bool IsUsingVSMForSelectionColor(View view) + { + var groups = VisualStateManager.GetVisualStateGroups(view); + for (var groupIndex = 0; groupIndex < groups.Count; groupIndex++) + { + var group = groups[groupIndex]; + for (var stateIndex = 0; stateIndex < group.States.Count; stateIndex++) + { + var state = group.States[stateIndex]; + if (state.Name != VisualStateManager.CommonStates.Selected) + { + continue; + } + + for (var setterIndex = 0; setterIndex < state.Setters.Count; setterIndex++) + { + var setter = state.Setters[setterIndex]; + if (setter.Property.PropertyName == VisualElement.BackgroundColorProperty.PropertyName) + { + return true; + } + } + } + } + + return false; + } + + public override bool Selected + { + get => base.Selected; + set + { + base.Selected = value; + + UpdateVisualStates(); + + if (base.Selected) + { + // This must be called here otherwise the first item will have a gray background + UpdateSelectionColor(); + } + } + } + + //protected abstract (bool, Size) NeedsContentSizeUpdate(Size currentSize); + + // void MeasureInvalidated(object sender, EventArgs args) + // { + // var (needsUpdate, toSize) = NeedsContentSizeUpdate(_size); + // + // if (!needsUpdate) + // { + // return; + // } + // + // // Cache the size for next time + // _size = toSize; + // + // // Let the controller know that things need to be laid out again + // OnContentSizeChanged(); + // } + + protected void OnContentSizeChanged() + { + _weakEventManager.HandleEvent(this, EventArgs.Empty, nameof(ContentSizeChanged)); + } + + protected void OnLayoutAttributesChanged(UICollectionViewLayoutAttributes newAttributes) + { + _weakEventManager.HandleEvent(this, new LayoutAttributesChangedEventArgs2(newAttributes), nameof(LayoutAttributesChanged)); + } + + //protected abstract bool AttributesConsistentWithConstrainedDimension(UICollectionViewLayoutAttributes attributes); + + void UpdateVisualStates() + { + if (PlatformHandler?.VirtualView is VisualElement element) + { + VisualStateManager.GoToState(element, Selected + ? VisualStateManager.CommonStates.Selected + : VisualStateManager.CommonStates.Normal); + } + } + + void UpdateSelectionColor() + { + if (PlatformHandler?.VirtualView is not View view) + { + return; + } + + UpdateSelectionColor(view); + } + + void UpdateSelectionColor(View view) + { + if (SelectedBackgroundView is null) + { + return; + } + + // Prevents the use of default color when there are VisualStateManager with Selected state setting the background color + // First we check whether the cell has the default selected background color; if it does, then we should check + // to see if the cell content is the VSM to set a selected color + + if (ColorExtensions.AreEqual(SelectedBackgroundView.BackgroundColor, ColorExtensions.Gray) && IsUsingVSMForSelectionColor(view)) + { + SelectedBackgroundView.BackgroundColor = UIColor.Clear; + } + } + } + + class UIContainerView2 : UIView + { + readonly IView _view; + readonly IMauiContext _mauiContext; + + public UIContainerView2(IView view, IMauiContext mauiContext) + { + _view = view; + _mauiContext = mauiContext; + UpdatePlatformView(); + ClipsToBounds = true; + } + + internal void UpdatePlatformView() + { + var handler = _view.ToHandler(_mauiContext); + var nativeView = _view.ToPlatform(); + + if (nativeView.Superview == this) + { + nativeView.RemoveFromSuperview(); + } + + AddSubview(nativeView); + } + + public override void LayoutSubviews() + { + _view?.Arrange(new Rect(0, 0, Frame.Width, Frame.Height)); + base.LayoutSubviews(); + } + + public override CGSize SizeThatFits(CGSize size) + { + return _view.Measure(size.Width, size.Height).ToCGSize(); + } + } +} diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/VerticalCell2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/VerticalCell2.cs new file mode 100644 index 000000000000..20fdab260ee0 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/VerticalCell2.cs @@ -0,0 +1,31 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal sealed class VerticalCell2 : WidthConstrainedTemplatedCell2 + { + public new static NSString ReuseId = new NSString("Microsoft.Maui.Controls.VerticalCell2"); + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public VerticalCell2(CGRect frame) : base(frame) + { + } + + // public override CGSize Measure() + // { + // var measure = PlatformHandler.VirtualView.Measure(ConstrainedDimension, double.PositiveInfinity); + // + // return new CGSize(ConstrainedDimension, measure.Height); + // } + // + // protected override bool AttributesConsistentWithConstrainedDimension(UICollectionViewLayoutAttributes attributes) + // { + // return attributes.Frame.Width == ConstrainedDimension; + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/VerticalDefaultCell2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/VerticalDefaultCell2.cs new file mode 100644 index 000000000000..1eea8ca35823 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/VerticalDefaultCell2.cs @@ -0,0 +1,32 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal sealed class VerticalDefaultCell2 : DefaultCell2 + { + public static NSString ReuseId = new NSString("Microsoft.Maui.Controls.VerticalDefaultCell2"); + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public VerticalDefaultCell2(CGRect frame) : base(frame) + { + Constraint = Label.WidthAnchor.ConstraintEqualTo(Frame.Width); + Constraint.Priority = (float)UILayoutPriority.DefaultHigh; + Constraint.Active = true; + } + + // public override void ConstrainTo(CGSize constraint) + // { + // Constraint.Constant = constraint.Width; + // } + // + // public override CGSize Measure() + // { + // return new CGSize(Constraint.Constant, Label.IntrinsicContentSize.Height); + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/VerticalDefaultSupplementalView2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/VerticalDefaultSupplementalView2.cs new file mode 100644 index 000000000000..f6110d1fa863 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/VerticalDefaultSupplementalView2.cs @@ -0,0 +1,24 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal sealed class VerticalDefaultSupplementalView2 : DefaultCell2 + { + public static NSString ReuseId = new NSString("Microsoft.Maui.Controls.VerticalDefaultSupplementalView2"); + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public VerticalDefaultSupplementalView2(CGRect frame) : base(frame) + { + Label.Font = UIFont.PreferredHeadline; + + Constraint = Label.WidthAnchor.ConstraintEqualTo(Frame.Width); + Constraint.Priority = (float)UILayoutPriority.DefaultHigh; + Constraint.Active = true; + } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/VerticalSupplementaryView2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/VerticalSupplementaryView2.cs new file mode 100644 index 000000000000..c5b7bc23bcf9 --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/VerticalSupplementaryView2.cs @@ -0,0 +1,39 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using ObjCRuntime; +using UIKit; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal sealed class VerticalSupplementaryView2 : WidthConstrainedTemplatedCell2 + { + public new static NSString ReuseId = new NSString("Microsoft.Maui.Controls.VerticalSupplementaryView2"); + + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public VerticalSupplementaryView2(CGRect frame) : base(frame) + { + } + + // public override CGSize Measure() + // { + // if (PlatformHandler?.VirtualView == null) + // { + // return CGSize.Empty; + // } + // + // var measure = PlatformHandler.VirtualView.Measure(ConstrainedDimension, double.PositiveInfinity); + // + // var height = PlatformHandler.VirtualView.Height > 0 + // ? PlatformHandler.VirtualView.Height : measure.Height; + // + // return new CGSize(ConstrainedDimension, height); + // } + // + // protected override bool AttributesConsistentWithConstrainedDimension(UICollectionViewLayoutAttributes attributes) + // { + // return attributes.Frame.Width == ConstrainedDimension; + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/WidthConstrainedTemplatedCell2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/WidthConstrainedTemplatedCell2.cs new file mode 100644 index 000000000000..dfe1de99dd7c --- /dev/null +++ b/src/Controls/src/Core/Handlers/Items2/iOS/WidthConstrainedTemplatedCell2.cs @@ -0,0 +1,50 @@ +#nullable disable +using CoreGraphics; +using Foundation; +using Microsoft.Maui.Graphics; + +namespace Microsoft.Maui.Controls.Handlers.Items2 +{ + internal abstract class WidthConstrainedTemplatedCell2 : TemplatedCell2 + { + [Export("initWithFrame:")] + [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] + public WidthConstrainedTemplatedCell2(CGRect frame) : base(frame) + { + } + + // public override void ConstrainTo(CGSize constraint) + // { + // ClearConstraints(); + // ConstrainedDimension = constraint.Width; + // } + // + // protected override (bool, Size) NeedsContentSizeUpdate(Size currentSize) + // { + // if (PlatformHandler?.VirtualView == null) + // { + // return (false, currentSize); + // } + // + // var bounds = PlatformHandler.VirtualView.Frame; + // + // if (bounds.Width <= 0 || bounds.Height <= 0) + // { + // return (false, currentSize); + // } + // + // var desiredBounds = PlatformHandler.VirtualView.Measure(bounds.Width, double.PositiveInfinity); + // + // if (desiredBounds.Height == currentSize.Height) + // { + // // Nothing in the cell needs more room, so leave it as it is + // return (false, currentSize); + // } + // + // // Keep the current width in the updated content size + // desiredBounds.Width = bounds.Width; + // + // return (true, desiredBounds); + // } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellContentItemAdaptor.cs b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellContentItemAdaptor.cs index 541cedb7822a..00ada2dfd7a6 100644 --- a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellContentItemAdaptor.cs +++ b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellContentItemAdaptor.cs @@ -1,5 +1,6 @@ using System.Collections; using Microsoft.Maui.Controls.Handlers.Items; +using Microsoft.Maui.Controls.Internals; using GColor = Microsoft.Maui.Graphics.Color; using NView = Tizen.NUI.BaseComponents.View; @@ -28,9 +29,9 @@ public override NView CreateNativeView(int index) var nativeView = base.CreateNativeView(index); var view = GetTemplatedView(nativeView); - view?.SetBinding(ShellContentItemView.SelectedTextColorProperty, new Binding("TitleColor", source: _itemAppearance)); - view?.SetBinding(ShellContentItemView.SelectedBarColorProperty, new Binding("ForegroundColor", source: _itemAppearance)); - view?.SetBinding(ShellContentItemView.UnselectedColorProperty, new Binding("UnselectedColor", source: _itemAppearance)); + view?.SetBinding(ShellContentItemView.SelectedTextColorProperty, static (ItemAppearance appearance) => appearance.TitleColor, source: _itemAppearance); + view?.SetBinding(ShellContentItemView.SelectedBarColorProperty, static (ItemAppearance appearance) => appearance.ForegroundColor, source: _itemAppearance); + view?.SetBinding(ShellContentItemView.UnselectedColorProperty, static (ItemAppearance appearance) => appearance.UnselectedColor, source: _itemAppearance); return nativeView; } diff --git a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellContentItemView.cs b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellContentItemView.cs index 201eafdd5f98..9141ef4ca5fe 100644 --- a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellContentItemView.cs +++ b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellContentItemView.cs @@ -1,9 +1,12 @@ +using Microsoft.Maui.Controls.Internals; using GColor = Microsoft.Maui.Graphics.Color; using GColors = Microsoft.Maui.Graphics.Colors; namespace Microsoft.Maui.Controls.Platform { +#pragma warning disable CS0618 // Type or member is obsolete class ShellContentItemView : Frame +#pragma warning restore CS0618 // Type or member is obsolete { static readonly BindableProperty SelectedStateProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(ShellContentItemView), false, propertyChanged: (b, o, n) => ((ShellContentItemView)b).UpdateViewColors()); internal static readonly BindableProperty SelectedTextColorProperty = BindableProperty.Create(nameof(SelectedTextColor), typeof(GColor), typeof(ShellContentItemView), null, propertyChanged: (b, o, n) => ((ShellContentItemView)b).UpdateViewColors()); @@ -60,7 +63,7 @@ void InitializeComponent() HorizontalTextAlignment = TextAlignment.Center, VerticalTextAlignment = TextAlignment.Center, }; - _label.SetBinding(Label.TextProperty, new Binding("Title")); + _label.SetBinding(Label.TextProperty, static (BaseShellItem item) => item.Title); _bar = new BoxView { diff --git a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellFlyoutItemView.cs b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellFlyoutItemView.cs index a076b57faefa..cb068265dfd4 100644 --- a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellFlyoutItemView.cs +++ b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellFlyoutItemView.cs @@ -1,8 +1,11 @@ +using Microsoft.Maui.Controls.Internals; using GColors = Microsoft.Maui.Graphics.Colors; namespace Microsoft.Maui.Controls.Platform { +#pragma warning disable CS0618 // Type or member is obsolete class ShellFlyoutItemView : Frame +#pragma warning restore CS0618 // Type or member is obsolete { static readonly BindableProperty SelectedStateProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(ShellFlyoutItemView), false, propertyChanged: (b, o, n) => ((ShellFlyoutItemView)b).UpdateSelectedState()); @@ -33,7 +36,7 @@ void InitializeComponent() HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, }; - icon.SetBinding(Image.SourceProperty, new Binding("Icon")); + icon.SetBinding(Image.SourceProperty, static (BaseShellItem item) => item.Icon); var label = new Label { @@ -41,7 +44,7 @@ void InitializeComponent() FontSize = 16, VerticalTextAlignment = TextAlignment.Center, }; - label.SetBinding(Label.TextProperty, new Binding("Title")); + label.SetBinding(Label.TextProperty, static (BaseShellItem item) => item.Title); _grid = new Grid { diff --git a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellItemView.cs b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellItemView.cs index 20b2eda92d21..d558cb2d440d 100644 --- a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellItemView.cs +++ b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellItemView.cs @@ -254,7 +254,7 @@ void HideTabBar() Remove(_bottomTabBar); } - class MoreItem + internal class MoreItem { const string PathMoreVert = "M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"; diff --git a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSearchItemAdaptor.cs b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSearchItemAdaptor.cs index 9edc8504d1b0..e6caeef1e5a5 100644 --- a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSearchItemAdaptor.cs +++ b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSearchItemAdaptor.cs @@ -1,5 +1,6 @@ using System.Collections; using Microsoft.Maui.Controls.Handlers.Items; +using Microsoft.Maui.Controls.Internals; using GColor = Microsoft.Maui.Graphics.Color; using GColors = Microsoft.Maui.Graphics.Colors; @@ -24,7 +25,7 @@ static View CreateView() { TextColor = GColors.Black, }; - label.SetBinding(Label.TextProperty, new Binding(".")); + label.SetBinding(Label.TextProperty, static (object source) => source); return new Controls.StackLayout { diff --git a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSectionItemAdaptor.cs b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSectionItemAdaptor.cs index d3d068bd4367..6225f2349744 100644 --- a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSectionItemAdaptor.cs +++ b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSectionItemAdaptor.cs @@ -1,5 +1,6 @@ using System.Collections; using Microsoft.Maui.Controls.Handlers.Items; +using Microsoft.Maui.Controls.Internals; using GColor = Microsoft.Maui.Graphics.Color; using NView = Tizen.NUI.BaseComponents.View; @@ -27,8 +28,8 @@ public override NView CreateNativeView(int index) var nativeView = base.CreateNativeView(index); var view = GetTemplatedView(nativeView); - view?.SetBinding(ShellSectionItemView.SelectedColorProperty, new Binding("TitleColor", source: _itemAppearance)); - view?.SetBinding(ShellSectionItemView.UnselectedColorProperty, new Binding("UnselectedColor", source: _itemAppearance)); + view?.SetBinding(ShellSectionItemView.SelectedColorProperty, static (ItemAppearance appearance) => appearance.TitleColor, source: _itemAppearance); + view?.SetBinding(ShellSectionItemView.UnselectedColorProperty, static (ItemAppearance appearance) => appearance.UnselectedColor, source: _itemAppearance); return nativeView; } diff --git a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSectionItemView.cs b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSectionItemView.cs index 7f3210807946..ec33c2b5d160 100644 --- a/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSectionItemView.cs +++ b/src/Controls/src/Core/Handlers/Shell/Tizen/ShellSectionItemView.cs @@ -1,10 +1,13 @@ +using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Shapes; using GColor = Microsoft.Maui.Graphics.Color; using GColors = Microsoft.Maui.Graphics.Colors; namespace Microsoft.Maui.Controls.Platform { +#pragma warning disable CS0618 // Type or member is obsolete class ShellSectionItemView : Frame +#pragma warning restore CS0618 // Type or member is obsolete { static readonly BindableProperty SelectedStateProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(ShellSectionItemView), false, propertyChanged: (b, o, n) => ((ShellSectionItemView)b).UpdateViewColors()); internal static readonly BindableProperty SelectedColorProperty = BindableProperty.Create(nameof(SelectedColor), typeof(GColor), typeof(ShellSectionItemView), null, propertyChanged: (b, o, n) => ((ShellSectionItemView)b).UpdateViewColors()); @@ -119,7 +122,7 @@ View CreateIconView() VerticalOptions = LayoutOptions.Center, }; - _icon.SetBinding(Path.DataProperty, new Binding("IconPath", converter: new IconConverter())); + _icon.SetBinding(Path.DataProperty, static (ShellItemView.MoreItem item) => item.IconPath, converter: new IconConverter()); return _icon; } else @@ -130,7 +133,7 @@ View CreateIconView() VerticalOptions = LayoutOptions.Center, }; - _icon.SetBinding(Image.SourceProperty, new Binding("Icon")); + _icon.SetBinding(Image.SourceProperty, static (BaseShellItem item) => item.Icon); return _icon; } } @@ -144,7 +147,16 @@ View CreateTextView() HorizontalTextAlignment = TextAlignment.Center, VerticalTextAlignment = TextAlignment.Center, }; - _label.SetBinding(Label.TextProperty, new Binding("Title")); + + if (_isMoreItem) + { + _label.SetBinding(Label.TextProperty, static (ShellItemView.MoreItem item) => item.Title); + } + else + { + _label.SetBinding(Label.TextProperty, static (BaseShellItem item) => item.Title); + } + return _label; } diff --git a/src/Controls/src/Core/Handlers/Shell/Windows/ShellFlyoutItemView.cs b/src/Controls/src/Core/Handlers/Shell/Windows/ShellFlyoutItemView.cs index 42bd8927c54d..5718cef5b539 100644 --- a/src/Controls/src/Core/Handlers/Shell/Windows/ShellFlyoutItemView.cs +++ b/src/Controls/src/Core/Handlers/Shell/Windows/ShellFlyoutItemView.cs @@ -9,7 +9,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class ShellFlyoutItemView : ContentControl + public partial class ShellFlyoutItemView : ContentControl { public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( nameof(IsSelected), typeof(bool), typeof(ShellFlyoutItemView), diff --git a/src/Controls/src/Core/Handlers/Shell/Windows/ShellFlyoutTemplateSelector.cs b/src/Controls/src/Core/Handlers/Shell/Windows/ShellFlyoutTemplateSelector.cs index 594e40aa923a..3da609289145 100644 --- a/src/Controls/src/Core/Handlers/Shell/Windows/ShellFlyoutTemplateSelector.cs +++ b/src/Controls/src/Core/Handlers/Shell/Windows/ShellFlyoutTemplateSelector.cs @@ -4,7 +4,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class ShellFlyoutTemplateSelector : Microsoft.UI.Xaml.Controls.DataTemplateSelector + public partial class ShellFlyoutTemplateSelector : Microsoft.UI.Xaml.Controls.DataTemplateSelector { Microsoft.UI.Xaml.DataTemplate BaseShellItemTemplate { get; } Microsoft.UI.Xaml.DataTemplate MenuItemTemplate { get; } diff --git a/src/Controls/src/Core/Handlers/Shell/Windows/ShellFooterView.cs b/src/Controls/src/Core/Handlers/Shell/Windows/ShellFooterView.cs index 2eb35c310ea8..9be9483f1203 100644 --- a/src/Controls/src/Core/Handlers/Shell/Windows/ShellFooterView.cs +++ b/src/Controls/src/Core/Handlers/Shell/Windows/ShellFooterView.cs @@ -7,7 +7,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class ShellFooterView : Microsoft.UI.Xaml.Controls.ContentControl + public partial class ShellFooterView : Microsoft.UI.Xaml.Controls.ContentControl { Shell _shell; @@ -22,8 +22,7 @@ public ShellFooterView(Shell element) void OnShellFooterViewSizeChanged(object sender, SizeChangedEventArgs e) { - if (Element is Controls.Compatibility.Layout layout) - layout.ForceLayout(); + Element?.InvalidateMeasure(); } internal VisualElement Element { get; set; } diff --git a/src/Controls/src/Core/Handlers/Shell/Windows/ShellHeaderView.cs b/src/Controls/src/Core/Handlers/Shell/Windows/ShellHeaderView.cs index 3feff597ed55..fd64d61ae7d9 100644 --- a/src/Controls/src/Core/Handlers/Shell/Windows/ShellHeaderView.cs +++ b/src/Controls/src/Core/Handlers/Shell/Windows/ShellHeaderView.cs @@ -4,7 +4,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class ShellHeaderView : UI.Xaml.Controls.ContentControl + public partial class ShellHeaderView : UI.Xaml.Controls.ContentControl { Shell _shell; @@ -19,8 +19,7 @@ public ShellHeaderView(Shell element) void OnShellHeaderViewSizeChanged(object sender, SizeChangedEventArgs e) { - if (Element is Controls.Compatibility.Layout layout) - layout.ForceLayout(); + Element?.InvalidateMeasure(); } internal VisualElement Element { get; set; } diff --git a/src/Controls/src/Core/Handlers/Shell/Windows/ShellNavigationViewItem.cs b/src/Controls/src/Core/Handlers/Shell/Windows/ShellNavigationViewItem.cs index 51bd36d12547..54673a05f6be 100644 --- a/src/Controls/src/Core/Handlers/Shell/Windows/ShellNavigationViewItem.cs +++ b/src/Controls/src/Core/Handlers/Shell/Windows/ShellNavigationViewItem.cs @@ -8,7 +8,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class ShellNavigationViewItem : NavigationViewItem + public partial class ShellNavigationViewItem : NavigationViewItem { protected override AutomationPeer OnCreateAutomationPeer() { @@ -16,7 +16,7 @@ protected override AutomationPeer OnCreateAutomationPeer() } } - public class ShellNavigationViewItemAutomationPeer : NavigationViewItemAutomationPeer + public partial class ShellNavigationViewItemAutomationPeer : NavigationViewItemAutomationPeer { readonly ShellNavigationViewItem _owner; diff --git a/src/Controls/src/Core/Handlers/Shell/Windows/ShellToolbarItemView.cs b/src/Controls/src/Core/Handlers/Shell/Windows/ShellToolbarItemView.cs index 2c44043e470a..fcd59342e178 100644 --- a/src/Controls/src/Core/Handlers/Shell/Windows/ShellToolbarItemView.cs +++ b/src/Controls/src/Core/Handlers/Shell/Windows/ShellToolbarItemView.cs @@ -11,7 +11,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class ShellToolbarItemView : Microsoft.UI.Xaml.Controls.Button + public partial class ShellToolbarItemView : Microsoft.UI.Xaml.Controls.Button { public static readonly DependencyProperty ToolbarItemProperty = diff --git a/src/Controls/src/Core/Handlers/Shell/Windows/ShellView.cs b/src/Controls/src/Core/Handlers/Shell/Windows/ShellView.cs index 11daffc3d896..eb6f4284e626 100644 --- a/src/Controls/src/Core/Handlers/Shell/Windows/ShellView.cs +++ b/src/Controls/src/Core/Handlers/Shell/Windows/ShellView.cs @@ -11,7 +11,7 @@ namespace Microsoft.Maui.Controls.Platform { [Microsoft.UI.Xaml.Data.Bindable] - public class ShellView : RootNavigationView, IAppearanceObserver, IFlyoutBehaviorObserver + public partial class ShellView : RootNavigationView, IAppearanceObserver, IFlyoutBehaviorObserver { internal static readonly global::Windows.UI.Color DefaultBackgroundColor = global::Windows.UI.Color.FromArgb(255, 3, 169, 244); internal static readonly global::Windows.UI.Color DefaultForegroundColor = Microsoft.UI.Colors.White; @@ -178,7 +178,7 @@ IEnumerable IterateItems(List> groups) } } - class FlyoutItemMenuSeparator : Microsoft.UI.Xaml.Controls.MenuFlyoutSeparator + partial class FlyoutItemMenuSeparator : Microsoft.UI.Xaml.Controls.MenuFlyoutSeparator { public FlyoutItemMenuSeparator(int separatorNumber) { @@ -274,6 +274,6 @@ ShellItemHandler CreateShellItemView() } void TabSelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) => - Element.Handler.UpdateValue(nameof(Shell.CurrentItem)); + Element?.Handler?.UpdateValue(nameof(Shell.CurrentItem)); } } diff --git a/src/Controls/src/Core/Handlers/Shell/Windows/ViewToHandlerConverter.cs b/src/Controls/src/Core/Handlers/Shell/Windows/ViewToHandlerConverter.cs index bd14b8118f62..91d35e8dc509 100644 --- a/src/Controls/src/Core/Handlers/Shell/Windows/ViewToHandlerConverter.cs +++ b/src/Controls/src/Core/Handlers/Shell/Windows/ViewToHandlerConverter.cs @@ -7,7 +7,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class ViewToHandlerConverter : Microsoft.UI.Xaml.Data.IValueConverter + public partial class ViewToHandlerConverter : Microsoft.UI.Xaml.Data.IValueConverter { public object? Convert(object value, Type targetType, object parameter, string language) { @@ -32,7 +32,7 @@ public object ConvertBack(object value, Type targetType, object parameter, strin throw new NotSupportedException(); } - internal class WrapperControl : Panel + internal partial class WrapperControl : Panel { readonly View _view; IView View => _view; diff --git a/src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs b/src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs index 551651264f6e..088d701ac541 100644 --- a/src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs +++ b/src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs @@ -85,6 +85,7 @@ internal static IMauiHandlersCollection AddControlsHandlers(this IMauiHandlersCo handlersCollection.AddHandler(); handlersCollection.AddHandler(); handlersCollection.AddHandler(); + handlersCollection.AddHandler(); handlersCollection.AddHandler(); handlersCollection.AddHandler(); handlersCollection.AddHandler(); @@ -121,7 +122,9 @@ internal static IMauiHandlersCollection AddControlsHandlers(this IMauiHandlersCo handlersCollection.AddHandler(typeof(SwitchCell), typeof(Handlers.Compatibility.SwitchCellRenderer)); #endif handlersCollection.AddHandler(typeof(TableView), typeof(Handlers.Compatibility.TableViewRenderer)); +#pragma warning disable CS0618 // Type or member is obsolete handlersCollection.AddHandler(typeof(Frame), typeof(Handlers.Compatibility.FrameRenderer)); +#pragma warning restore CS0618 // Type or member is obsolete #endif #if WINDOWS || MACCATALYST @@ -166,7 +169,6 @@ static MauiAppBuilder SetupDefaults(this MauiAppBuilder builder) #if WINDOWS || ANDROID || IOS || MACCATALYST || TIZEN // initialize compatibility DependencyService DependencyService.SetToInitialized(); - DependencyService.Register(); #pragma warning disable CS0612, CA1416 // Type or member is obsolete, 'ResourcesProvider' is unsupported on: 'iOS' 14.0 and later DependencyService.Register(); @@ -252,6 +254,7 @@ internal static MauiAppBuilder RemapForControls(this MauiAppBuilder builder) Shape.RemapForControls(); WebView.RemapForControls(); ContentPage.RemapForControls(); + return builder; } } diff --git a/src/Controls/src/Core/HybridWebView/HybridWebView.cs b/src/Controls/src/Core/HybridWebView/HybridWebView.cs new file mode 100644 index 000000000000..8b667474251f --- /dev/null +++ b/src/Controls/src/Core/HybridWebView/HybridWebView.cs @@ -0,0 +1,109 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization.Metadata; +using System.Threading.Tasks; + +namespace Microsoft.Maui.Controls +{ + /// + /// A that presents local HTML content in a web view and allows JavaScript and C# code to + /// communicate by using messages and by invoking methods. + /// + public class HybridWebView : View, IHybridWebView + { + /// Bindable property for . + public static readonly BindableProperty DefaultFileProperty = + BindableProperty.Create(nameof(DefaultFile), typeof(string), typeof(HybridWebView), defaultValue: "index.html"); + /// Bindable property for . + public static readonly BindableProperty HybridRootProperty = + BindableProperty.Create(nameof(HybridRoot), typeof(string), typeof(HybridWebView), defaultValue: "wwwroot"); + + + /// + public string? DefaultFile + { + get { return (string)GetValue(DefaultFileProperty); } + set { SetValue(DefaultFileProperty, value); } + } + + /// + public string? HybridRoot + { + get { return (string)GetValue(HybridRootProperty); } + set { SetValue(HybridRootProperty, value); } + } + + void IHybridWebView.RawMessageReceived(string rawMessage) + { + RawMessageReceived?.Invoke(this, new HybridWebViewRawMessageReceivedEventArgs(rawMessage)); + } + + /// + /// Raised when a raw message is received from the web view. Raw messages are strings that have no additional processing. + /// + public event EventHandler? RawMessageReceived; + + /// + /// Sends a raw message to the code running in the web view. Raw messages have no additional processing. + /// + /// + public void SendRawMessage(string rawMessage) + { + Handler?.Invoke( + nameof(IHybridWebView.SendRawMessage), + new HybridWebViewRawMessage + { + Message = rawMessage, + }); + } + + /// + public async Task InvokeJavaScriptAsync( + string methodName, + JsonTypeInfo returnTypeJsonTypeInfo, + object?[]? paramValues = null, + JsonTypeInfo?[]? paramJsonTypeInfos = null) + { + if (string.IsNullOrEmpty(methodName)) + { + throw new ArgumentException($"The method name cannot be null or empty.", nameof(methodName)); + } + if (paramValues != null && paramJsonTypeInfos == null) + { + throw new ArgumentException($"The parameter values were provided, but the parameter JSON type infos were not.", nameof(paramJsonTypeInfos)); + } + if (paramValues == null && paramJsonTypeInfos != null) + { + throw new ArgumentException($"The parameter JSON type infos were provided, but the parameter values were not.", nameof(paramValues)); + } + if (paramValues != null && paramValues.Length != paramJsonTypeInfos!.Length) + { + throw new ArgumentException($"The number of parameter values does not match the number of parameter JSON type infos.", nameof(paramValues)); + } + + var invokeResult = await Handler?.InvokeAsync( + nameof(IHybridWebView.InvokeJavaScriptAsync), + new HybridWebViewInvokeJavaScriptRequest(methodName, returnTypeJsonTypeInfo, paramValues, paramJsonTypeInfos))!; + + if (invokeResult is null) + { + return default; + } + return (TReturnType)invokeResult; + } + + /// + public async Task EvaluateJavaScriptAsync(string script) + { + if (script == null) + { + return null; + } + + var result = await Handler!.InvokeAsync(nameof(IHybridWebView.EvaluateJavaScriptAsync), + new EvaluateJavaScriptAsyncRequest(script)); + + return result; + } + } +} diff --git a/src/Controls/src/Core/HybridWebView/HybridWebViewRawMessageReceivedEventArgs.cs b/src/Controls/src/Core/HybridWebView/HybridWebViewRawMessageReceivedEventArgs.cs new file mode 100644 index 000000000000..d431303de8de --- /dev/null +++ b/src/Controls/src/Core/HybridWebView/HybridWebViewRawMessageReceivedEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace Microsoft.Maui.Controls +{ + public class HybridWebViewRawMessageReceivedEventArgs : EventArgs + { + public HybridWebViewRawMessageReceivedEventArgs(string? message) + { + Message = message; + } + + public string? Message { get; } + } +} diff --git a/src/Controls/src/Core/IMarkupExtension.cs b/src/Controls/src/Core/IMarkupExtension.cs index 6e9d12300398..1a2e9cab2742 100644 --- a/src/Controls/src/Core/IMarkupExtension.cs +++ b/src/Controls/src/Core/IMarkupExtension.cs @@ -18,4 +18,14 @@ public interface IMarkupExtension public sealed class AcceptEmptyServiceProviderAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + public sealed class RequireServiceAttribute : Attribute + { + public RequireServiceAttribute(Type[] serviceTypes) + { + ServiceTypes = serviceTypes; + } + public Type[] ServiceTypes { get; } + } } \ No newline at end of file diff --git a/src/Controls/src/Core/INativeBindingService.cs b/src/Controls/src/Core/INativeBindingService.cs index 721c3149fc29..26f7acc3eaba 100644 --- a/src/Controls/src/Core/INativeBindingService.cs +++ b/src/Controls/src/Core/INativeBindingService.cs @@ -1,9 +1,12 @@ #nullable disable +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.Maui.Controls.Xaml.Internals { public interface INativeBindingService { + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] bool TrySetBinding(object target, string propertyName, BindingBase binding); bool TrySetBinding(object target, BindableProperty property, BindingBase binding); bool TrySetValue(object target, BindableProperty property, object value); diff --git a/src/Controls/src/Core/IPlatformSizeService.cs b/src/Controls/src/Core/IPlatformSizeService.cs index d59f630e30ea..5fc8ae50f139 100644 --- a/src/Controls/src/Core/IPlatformSizeService.cs +++ b/src/Controls/src/Core/IPlatformSizeService.cs @@ -1,8 +1,10 @@ #nullable disable +using System; namespace Microsoft.Maui.Controls.Internals { + [Obsolete("No .NET MAUI code makes use of IPlatformSizeService and this interface will be removed in a future .NET MAUI release.")] public interface IPlatformSizeService { SizeRequest GetPlatformSize(VisualElement view, double widthConstraint, double heightConstraint); } -} \ No newline at end of file +} diff --git a/src/Controls/src/Core/IWrappedValue.cs b/src/Controls/src/Core/IWrappedValue.cs new file mode 100644 index 000000000000..19554c6bb106 --- /dev/null +++ b/src/Controls/src/Core/IWrappedValue.cs @@ -0,0 +1,11 @@ +#nullable enable +using System; + +namespace Microsoft.Maui.Controls +{ + internal interface IWrappedValue + { + object? Value { get; } + Type ValueType { get; } + } +} diff --git a/src/Controls/src/Core/Image/Image.cs b/src/Controls/src/Core/Image/Image.cs index 2b91eabfdbc4..b3cfd031f38a 100644 --- a/src/Controls/src/Core/Image/Image.cs +++ b/src/Controls/src/Core/Image/Image.cs @@ -74,6 +74,7 @@ protected override void OnBindingContextChanged() base.OnBindingContextChanged(); } + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { SizeRequest desiredSize = base.OnMeasure(double.PositiveInfinity, double.PositiveInfinity); diff --git a/src/Controls/src/Core/ImageButton/ImageButton.cs b/src/Controls/src/Core/ImageButton/ImageButton.cs index 6271ccaece03..738fdaf40c65 100644 --- a/src/Controls/src/Core/ImageButton/ImageButton.cs +++ b/src/Controls/src/Core/ImageButton/ImageButton.cs @@ -145,11 +145,17 @@ protected internal override void ChangeVisualState() } } +#pragma warning disable CS0672 // Member overrides obsolete member +#pragma warning disable CS0618 // Type or member is obsolete protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) +#pragma warning restore CS0618 // Type or member is obsolete { +#pragma warning disable CS0618 // Type or member is obsolete SizeRequest desiredSize = base.OnMeasure(double.PositiveInfinity, double.PositiveInfinity); +#pragma warning restore CS0618 // Type or member is obsolete return ImageElement.Measure(this, desiredSize, widthConstraint, heightConstraint); } +#pragma warning restore CS0672 // Member overrides obsolete member /// public IPlatformElementConfiguration On() where T : IConfigPlatform => _platformConfigurationRegistry.Value.On(); diff --git a/src/Controls/src/Core/ImageElement.cs b/src/Controls/src/Core/ImageElement.cs index 90de1f299989..8c704262bd8f 100644 --- a/src/Controls/src/Core/ImageElement.cs +++ b/src/Controls/src/Core/ImageElement.cs @@ -42,6 +42,7 @@ static void OnImageSourceChanging(BindableObject bindable, object oldValue, obje ImageSourceChanging(oldSource); } +#pragma warning disable CS0618 // Type or member is obsolete public static SizeRequest Measure(IImageElement ImageElementManager, SizeRequest desiredSize, double widthConstraint, double heightConstraint) { double desiredAspect = desiredSize.Request.Width / desiredSize.Request.Height; @@ -96,6 +97,7 @@ public static SizeRequest Measure(IImageElement ImageElementManager, SizeRequest return new SizeRequest(new Size(width, height)); } +#pragma warning restore CS0618 // Type or member is obsolete public static void OnBindingContextChanged(IImageElement image, VisualElement visualElement) { diff --git a/src/Controls/src/Core/ImageSource.cs b/src/Controls/src/Core/ImageSource.cs index 63bf8dd978d9..13d54d7a8800 100644 --- a/src/Controls/src/Core/ImageSource.cs +++ b/src/Controls/src/Core/ImageSource.cs @@ -18,8 +18,11 @@ public abstract partial class ImageSource : Element readonly WeakEventManager _weakEventManager = new WeakEventManager(); + internal readonly MergedStyle _mergedStyle; + protected ImageSource() { + _mergedStyle = new MergedStyle(GetType(), this); } /// diff --git a/src/Controls/src/Core/ImageSourceConverter.cs b/src/Controls/src/Core/ImageSourceConverter.cs index 4fac2085f0d9..bb808769ba16 100644 --- a/src/Controls/src/Core/ImageSourceConverter.cs +++ b/src/Controls/src/Core/ImageSourceConverter.cs @@ -11,13 +11,18 @@ namespace Microsoft.Maui.Controls public sealed class ImageSourceConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - => sourceType == typeof(string); + => sourceType == typeof(string) || sourceType == typeof(Uri); public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => destinationType == typeof(string); public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { + if (value is Uri uriValue) + { + return (ImageSource)uriValue; + } + // IMPORTANT! Update ImageSourceDesignTypeConverter.IsValid if making changes here var strValue = value?.ToString(); if (strValue != null) diff --git a/src/Controls/src/Core/IndicatorView/IndicatorView.cs b/src/Controls/src/Core/IndicatorView/IndicatorView.cs index 5071ca48a1a7..fe5cbf2aae0c 100644 --- a/src/Controls/src/Core/IndicatorView/IndicatorView.cs +++ b/src/Controls/src/Core/IndicatorView/IndicatorView.cs @@ -130,20 +130,15 @@ public IEnumerable ItemsSource set => SetValue(ItemsSourceProperty, value); } - IPlatformSizeService _platformSizeService; - + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { if (IndicatorTemplate == null) { - if (Handler != null) - return new SizeRequest(Handler.GetDesiredSize(widthConstraint, heightConstraint)); - - _platformSizeService ??= DependencyService.Get(); - return _platformSizeService.GetPlatformSize(this, widthConstraint, heightConstraint); + return Handler?.GetDesiredSize(widthConstraint, heightConstraint) ?? new(); } - else - return base.OnMeasure(widthConstraint, heightConstraint); + + return base.OnMeasure(widthConstraint, heightConstraint); } static void UpdateIndicatorLayout(IndicatorView indicatorView, object newValue) diff --git a/src/Controls/src/Core/Interactivity/BindingCondition.cs b/src/Controls/src/Core/Interactivity/BindingCondition.cs index db6a372a15e8..505bb3953383 100644 --- a/src/Controls/src/Core/Interactivity/BindingCondition.cs +++ b/src/Controls/src/Core/Interactivity/BindingCondition.cs @@ -69,7 +69,7 @@ internal override void SetUp(BindableObject bindable) internal override void TearDown(BindableObject bindable) { bindable.RemoveBinding(_boundProperty); - bindable.ClearValue(_boundProperty); + bindable.ClearValue(_boundProperty, SetterSpecificity.FromBinding); } static IValueConverterProvider s_valueConverter = DependencyService.Get(); diff --git a/src/Controls/src/Core/Interactivity/EventTrigger.cs b/src/Controls/src/Core/Interactivity/EventTrigger.cs index 032582cf5a6c..40de79c6f232 100644 --- a/src/Controls/src/Core/Interactivity/EventTrigger.cs +++ b/src/Controls/src/Core/Interactivity/EventTrigger.cs @@ -78,7 +78,7 @@ void AttachHandlerTo(BindableObject bindable) try { _eventinfo = bindable.GetType().GetRuntimeEvent(Event); - _handlerdelegate = s_handlerinfo.CreateDelegate(_eventinfo.EventHandlerType, this); + _handlerdelegate = ((EventHandler)OnEventTriggered).Method.CreateDelegate(_eventinfo.EventHandlerType, this); } catch (Exception) { @@ -94,7 +94,6 @@ void DetachHandlerFrom(BindableObject bindable) _eventinfo.RemoveEventHandler(bindable, _handlerdelegate); } - [Preserve] void OnEventTriggered(object sender, EventArgs e) { var bindable = (BindableObject)sender; diff --git a/src/Controls/src/Core/Interactivity/TriggerBase.cs b/src/Controls/src/Core/Interactivity/TriggerBase.cs index ce57e898e258..60332e2b7206 100644 --- a/src/Controls/src/Core/Interactivity/TriggerBase.cs +++ b/src/Controls/src/Core/Interactivity/TriggerBase.cs @@ -2,7 +2,6 @@ using System; using System.Collections; using System.Collections.Generic; -using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls { @@ -11,16 +10,12 @@ public abstract class TriggerBase : BindableObject, IAttachedObject { bool _isSealed; - //each trigger is different - static int count = 1; - internal TriggerBase(Type targetType) { TargetType = targetType ?? throw new ArgumentNullException(nameof(targetType)); EnterActions = new SealedList(); ExitActions = new SealedList(); - Specificity = new SetterSpecificity(0, 100 + (count++), 0, 0, 0, 0, 0, 0); } internal TriggerBase(Condition condition, Type targetType) : this(targetType) @@ -59,9 +54,6 @@ private set //Setters and Condition are used by Trigger, DataTrigger and MultiTrigger internal IList Setters { get; } - //FIXME: add specificity as ctor argument - internal SetterSpecificity Specificity { get; } - void IAttachedObject.AttachTo(BindableObject bindable) { IsSealed = true; @@ -83,13 +75,23 @@ void IAttachedObject.DetachFrom(BindableObject bindable) internal virtual void OnAttachedTo(BindableObject bindable) { if (Condition != null) + { + var triggerIndex = ++bindable._triggerCount; + var manualSpecificity = (ushort)(SetterSpecificity.ManualTriggerBaseline + triggerIndex); + var specificity = new SetterSpecificity(0, manualSpecificity, 0, 0, 0, 0, 0, 0); + + bindable._triggerSpecificity[this] = specificity; Condition.SetUp(bindable); + } } internal virtual void OnDetachingFrom(BindableObject bindable) { if (Condition != null) + { Condition.TearDown(bindable); + bindable._triggerSpecificity.Remove(this); + } } internal virtual void OnSeal() @@ -104,17 +106,23 @@ internal virtual void OnSeal() void OnConditionChanged(BindableObject bindable, bool oldValue, bool newValue) { + if (!bindable._triggerSpecificity.TryGetValue(this, out var specificity)) + { + // this should never happen + return; + } + if (newValue) { foreach (TriggerAction action in EnterActions) action.DoInvoke(bindable); foreach (Setter setter in Setters) - setter.Apply(bindable, Specificity); + setter.Apply(bindable, specificity); } else { foreach (Setter setter in Setters) - setter.UnApply(bindable, Specificity); + setter.UnApply(bindable, specificity); foreach (TriggerAction action in ExitActions) action.DoInvoke(bindable); } diff --git a/src/Controls/src/Core/Items/CarouselView.cs b/src/Controls/src/Core/Items/CarouselView.cs index 50594f8908a6..8b45cb00b885 100644 --- a/src/Controls/src/Core/Items/CarouselView.cs +++ b/src/Controls/src/Core/Items/CarouselView.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Windows.Input; +using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls { @@ -208,17 +209,8 @@ static void LinkToIndicatorView(CarouselView carouselView, IndicatorView indicat if (indicatorView == null) return; - indicatorView.SetBinding(IndicatorView.PositionProperty, new Binding - { - Path = nameof(CarouselView.Position), - Source = carouselView - }); - - indicatorView.SetBinding(IndicatorView.ItemsSourceProperty, new Binding - { - Path = nameof(ItemsView.ItemsSource), - Source = carouselView - }); + indicatorView.SetBinding(IndicatorView.PositionProperty, static (CarouselView carousel) => carousel.Position, source: carouselView); + indicatorView.SetBinding(IndicatorView.ItemsSourceProperty, static (CarouselView carousel) => carousel.ItemsSource, source: carouselView); } /// diff --git a/src/Controls/src/Core/Items/ItemsView.cs b/src/Controls/src/Core/Items/ItemsView.cs index fc2a3ce343bb..a86d8e658d4a 100644 --- a/src/Controls/src/Core/Items/ItemsView.cs +++ b/src/Controls/src/Core/Items/ItemsView.cs @@ -189,6 +189,7 @@ public void SendScrolled(ItemsViewScrolledEventArgs e) public event EventHandler RemainingItemsThresholdReached; + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { // TODO hartez 2018-05-22 05:04 PM This 40,40 is what LV1 does; can we come up with something less arbitrary? diff --git a/src/Controls/src/Core/Label/Label.Android.cs b/src/Controls/src/Core/Label/Label.Android.cs index 8392c9820379..f9b74b9712fa 100644 --- a/src/Controls/src/Core/Label/Label.Android.cs +++ b/src/Controls/src/Core/Label/Label.Android.cs @@ -70,7 +70,7 @@ void OnLayoutChanged(object sender, LayoutChangedEventArgs args) var spannableString = virtualView.ToSpannableString(); - platformView.RecalculateSpanPositions(virtualView, spannableString, new SizeRequest(new Size(args.Right - args.Left, args.Bottom - args.Top))); + platformView.RecalculateSpanPositions(virtualView, spannableString, new Size(args.Right - args.Left, args.Bottom - args.Top)); } } } diff --git a/src/Controls/src/Core/Label/Label.Mapper.cs b/src/Controls/src/Core/Label/Label.Mapper.cs index 0528fd98744a..9759653dcea4 100644 --- a/src/Controls/src/Core/Label/Label.Mapper.cs +++ b/src/Controls/src/Core/Label/Label.Mapper.cs @@ -9,10 +9,6 @@ namespace Microsoft.Maui.Controls /// public partial class Label { - [Obsolete("Use LabelHandler.Mapper instead.")] - public static IPropertyMapper ControlsLabelMapper = - new ControlsMapper(LabelHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.Label legacy behaviors diff --git a/src/Controls/src/Core/Layout/Layout.Mapper.cs b/src/Controls/src/Core/Layout/Layout.Mapper.cs index ee4b56f75295..f4ad8baf70ee 100644 --- a/src/Controls/src/Core/Layout/Layout.Mapper.cs +++ b/src/Controls/src/Core/Layout/Layout.Mapper.cs @@ -12,11 +12,5 @@ public abstract partial class Layout internal static new void RemapForControls() { } - - /// - /// The associated property mapper for this layout. - /// - [Obsolete("Use LayoutHandler.Mapper instead.")] - public static IPropertyMapper ControlsLayoutMapper = new PropertyMapper(ControlsVisualElementMapper); } } diff --git a/src/Controls/src/Core/Layout/Layout.cs b/src/Controls/src/Core/Layout/Layout.cs index 15ca40847091..48e984dcccfd 100644 --- a/src/Controls/src/Core/Layout/Layout.cs +++ b/src/Controls/src/Core/Layout/Layout.cs @@ -5,6 +5,7 @@ using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Maui.Controls.Xaml.Diagnostics; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Layouts; namespace Microsoft.Maui.Controls @@ -32,7 +33,7 @@ static ILayoutManager GetLayoutManagerFromFactory(Layout layout) } // The actual backing store for the IViews in the ILayout - readonly List _children = new(); + readonly private protected List _children = new(); /// /// Gets the child objects contained in this layout. @@ -136,12 +137,6 @@ public Thickness Padding IEnumerator IEnumerable.GetEnumerator() => _children.GetEnumerator(); - public override SizeRequest Measure(double widthConstraint, double heightConstraint, MeasureFlags flags = MeasureFlags.None) - { - var size = (this as IView).Measure(widthConstraint, heightConstraint); - return new SizeRequest(size); - } - protected override void InvalidateMeasureOverride() { base.InvalidateMeasureOverride(); diff --git a/src/Controls/src/Core/LegacyLayouts/AbsoluteLayout.cs b/src/Controls/src/Core/LegacyLayouts/AbsoluteLayout.cs index e3d42993ef4c..131b2ba9f723 100644 --- a/src/Controls/src/Core/LegacyLayouts/AbsoluteLayout.cs +++ b/src/Controls/src/Core/LegacyLayouts/AbsoluteLayout.cs @@ -11,6 +11,7 @@ namespace Microsoft.Maui.Controls.Compatibility { [ContentProperty(nameof(Children))] + [Obsolete("Use Microsoft.Maui.Controls.AbsoluteLayout instead. For more information, see https://learn.microsoft.com/dotnet/maui/migration/layouts")] public class AbsoluteLayout : Layout, IElementConfiguration { /// Bindable property for attached property LayoutFlags. @@ -64,7 +65,9 @@ public static void SetLayoutFlags(BindableObject bindable, AbsoluteLayoutFlags f bindable.SetValue(LayoutFlagsProperty, flags); } +#pragma warning disable CS0672 // Member overrides obsolete member protected override void LayoutChildren(double x, double y, double width, double height) +#pragma warning restore CS0672 // Member overrides obsolete member { foreach (View child in LogicalChildrenInternal) { @@ -88,6 +91,7 @@ protected override void OnChildRemoved(Element child, int oldLogicalIndex) base.OnChildRemoved(child, oldLogicalIndex); } + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { var bestFitSize = new Size(); diff --git a/src/Controls/src/Core/LegacyLayouts/ConstraintExpression.cs b/src/Controls/src/Core/LegacyLayouts/ConstraintExpression.cs index a05780e21e70..a47c4307c2a9 100644 --- a/src/Controls/src/Core/LegacyLayouts/ConstraintExpression.cs +++ b/src/Controls/src/Core/LegacyLayouts/ConstraintExpression.cs @@ -8,6 +8,7 @@ namespace Microsoft.Maui.Controls.Compatibility { + [RequireService([typeof(IReferenceProvider), typeof(IProvideValueTarget)])] public class ConstraintExpression : IMarkupExtension { public ConstraintExpression() diff --git a/src/Controls/src/Core/LegacyLayouts/FlexLayout.cs b/src/Controls/src/Core/LegacyLayouts/FlexLayout.cs index 7e3f0ca86751..492669acea70 100644 --- a/src/Controls/src/Core/LegacyLayouts/FlexLayout.cs +++ b/src/Controls/src/Core/LegacyLayouts/FlexLayout.cs @@ -10,6 +10,7 @@ namespace Microsoft.Maui.Controls.Compatibility { [ContentProperty(nameof(Children))] + [Obsolete("Use Microsoft.Maui.Controls.FlexLayout instead. For more information, see https://learn.microsoft.com/dotnet/maui/migration/layouts")] public class FlexLayout : Layout { /// Bindable property for . @@ -310,7 +311,7 @@ void AddChild(View view) var sizeConstrains = item.GetConstraints(); sizeConstrains.Width = (_measuring && sizeConstrains.Width == 0) ? double.PositiveInfinity : sizeConstrains.Width; sizeConstrains.Height = (_measuring && sizeConstrains.Height == 0) ? double.PositiveInfinity : sizeConstrains.Height; - var request = view.Measure(sizeConstrains.Width, sizeConstrains.Height).Request; + var request = view.Measure(sizeConstrains.Width, sizeConstrains.Height, MeasureFlags.None).Request; w = (float)request.Width; h = (float)request.Height; }; @@ -409,7 +410,9 @@ void OnChildPropertyChanged(object sender, PropertyChangedEventArgs e) } } +#pragma warning disable CS0672 // Member overrides obsolete member protected override void LayoutChildren(double x, double y, double width, double height) +#pragma warning restore CS0672 // Member overrides obsolete member { if (_root == null) return; @@ -429,8 +432,10 @@ protected override void LayoutChildren(double x, double y, double width, double } bool _measuring; +#pragma warning disable CS0672 // Member overrides obsolete member protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { +#pragma warning restore CS0672 // Member overrides obsolete member if (_root == null) return new SizeRequest(new Size(widthConstraint, heightConstraint)); diff --git a/src/Controls/src/Core/LegacyLayouts/Grid.cs b/src/Controls/src/Core/LegacyLayouts/Grid.cs index 7d2caf663181..aa1245427900 100644 --- a/src/Controls/src/Core/LegacyLayouts/Grid.cs +++ b/src/Controls/src/Core/LegacyLayouts/Grid.cs @@ -10,6 +10,7 @@ namespace Microsoft.Maui.Controls.Compatibility { [ContentProperty(nameof(Children))] + [Obsolete("Use Microsoft.Maui.Controls.Grid instead. For more information, see https://learn.microsoft.com/dotnet/maui/migration/layouts")] public partial class Grid : Layout, IGridController, IElementConfiguration, IGridLayout { /// Bindable property for attached property Row. diff --git a/src/Controls/src/Core/LegacyLayouts/GridCalc.cs b/src/Controls/src/Core/LegacyLayouts/GridCalc.cs index 74763209170f..48f3e1cd6b18 100644 --- a/src/Controls/src/Core/LegacyLayouts/GridCalc.cs +++ b/src/Controls/src/Core/LegacyLayouts/GridCalc.cs @@ -9,7 +9,10 @@ namespace Microsoft.Maui.Controls.Compatibility { public partial class Grid { + +#pragma warning disable CS0672 // Member overrides obsolete member protected override void LayoutChildren(double x, double y, double width, double height) +#pragma warning restore CS0672 // Member overrides obsolete member { if (!InternalChildren.Any()) return; @@ -46,7 +49,9 @@ protected override void LayoutChildren(double x, double y, double width, double } } +#pragma warning disable CS0672 // Member overrides obsolete member protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) +#pragma warning restore CS0672 // Member overrides obsolete member { if (!InternalChildren.Any()) return new SizeRequest(new Size(0, 0)); diff --git a/src/Controls/src/Core/LegacyLayouts/Layout.cs b/src/Controls/src/Core/LegacyLayouts/Layout.cs index 0f3b6d0b0d7f..130c2d8d09fe 100644 --- a/src/Controls/src/Core/LegacyLayouts/Layout.cs +++ b/src/Controls/src/Core/LegacyLayouts/Layout.cs @@ -17,6 +17,7 @@ namespace Microsoft.Maui.Controls.Compatibility /// /// The type of that can be added to the layout. [ContentProperty(nameof(Children))] + [Obsolete("Use Microsoft.Maui.Controls.Layout instead. For more information, see https://learn.microsoft.com/dotnet/maui/user-interface/layouts/custom")] public abstract partial class Layout : Layout, Microsoft.Maui.ILayout, ILayoutManager, IBindableLayout, IViewContainer where T : View { readonly ElementCollection _children; @@ -88,6 +89,7 @@ Size ILayoutManager.ArrangeChildren(Rect bounds) /// /// Base class for layouts that allow you to arrange and group UI controls in your application. /// + [Obsolete("Use Microsoft.Maui.Controls.Layout instead. For more information, see https://learn.microsoft.com/dotnet/maui/user-interface/layouts/custom")] public abstract class Layout : View, ILayout, ILayoutController, IPaddingElement, IView, IVisualTreeElement, IInputTransparentContainerElement { /// Bindable property for . @@ -174,6 +176,7 @@ private protected override IList LogicalChildrenInternalBackingStore /// /// Occurs at the end of a layout cycle if any of the child element's have changed. /// + [Obsolete("Use SizeChanged.")] public event EventHandler LayoutChanged; /// The children contained in this layout. @@ -185,16 +188,25 @@ private protected override IList LogicalChildrenInternalBackingStore /// Forces a layout cycle on the element and all of its descendants. /// /// Calling this method frequently can have negative impacts on performance. + [Obsolete("Call InvalidateMeasure instead depending on your scenario.")] public void ForceLayout() => SizeAllocated(Width, Height); IReadOnlyList IVisualTreeElement.GetVisualChildren() => Children.ToList().AsReadOnly(); +#pragma warning disable CS0672 // Member overrides obsolete member +#pragma warning disable CS0618 // Type or member is obsolete public override SizeRequest Measure(double widthConstraint, double heightConstraint, MeasureFlags flags = MeasureFlags.None) +#pragma warning restore CS0618 // Type or member is obsolete { +#pragma warning disable CS0618 // Type or member is obsolete SizeRequest size = base.Measure(widthConstraint - Padding.HorizontalThickness, heightConstraint - Padding.VerticalThickness, flags); +#pragma warning restore CS0618 // Type or member is obsolete +#pragma warning disable CS0618 // Type or member is obsolete return new SizeRequest(new Size(size.Request.Width + Padding.HorizontalThickness, size.Request.Height + Padding.VerticalThickness), new Size(size.Minimum.Width + Padding.HorizontalThickness, size.Minimum.Height + Padding.VerticalThickness)); +#pragma warning restore CS0618 // Type or member is obsolete } +#pragma warning restore CS0672 // Member overrides obsolete member /// /// Positions a child element into a bounding region while respecting the child elements and . @@ -203,6 +215,7 @@ public override SizeRequest Measure(double widthConstraint, double heightConstra /// The bounding region in which the child should be positioned. /// This method is called in the layout cycle after the general regions for each child have been calculated. /// This method will handle positioning the element relative to the bounding region given if the bounding region given is larger than the child's desired size. + [Obsolete("Use the Arrange method on child instead.")] public static void LayoutChildIntoBoundingRegion(VisualElement child, Rect region) { bool isRightToLeft = false; @@ -230,7 +243,9 @@ public static void LayoutChildIntoBoundingRegion(VisualElement child, Rect regio LayoutOptions horizontalOptions = view.HorizontalOptions; if (horizontalOptions.Alignment != LayoutAlignment.Fill) { +#pragma warning disable CS0618 // Type or member is obsolete SizeRequest request = child.Measure(region.Width, region.Height, MeasureFlags.IncludeMargins); +#pragma warning restore CS0618 // Type or member is obsolete double diff = Math.Max(0, region.Width - request.Request.Width); double horizontalAlign = horizontalOptions.Alignment.ToDouble(); if (isRightToLeft) @@ -245,7 +260,9 @@ public static void LayoutChildIntoBoundingRegion(VisualElement child, Rect regio LayoutOptions verticalOptions = view.VerticalOptions; if (verticalOptions.Alignment != LayoutAlignment.Fill) { +#pragma warning disable CS0618 // Type or member is obsolete SizeRequest request = child.Measure(region.Width, region.Height, MeasureFlags.IncludeMargins); +#pragma warning restore CS0618 // Type or member is obsolete double diff = Math.Max(0, region.Height - request.Request.Height); region.Y += (int)(diff * verticalOptions.Alignment.ToDouble()); region.Height -= diff; @@ -266,6 +283,7 @@ public static void LayoutChildIntoBoundingRegion(VisualElement child, Rect regio /// The view to lower in the visual stack. /// Children are internally stored in visual stack order. /// This means that raising or lowering a child also changes the order in which the children are enumerated. + [Obsolete("Use the ZIndex Property instead")] public void LowerChild(View view) { if (!InternalChildren.Contains(view) || InternalChildren.First() == view) @@ -283,6 +301,7 @@ public void LowerChild(View view) /// The view to raise in the visual stack. /// Children are internally stored in visual stack order. /// This means that raising or lowering a child also changes the order in which the children are enumerated. + [Obsolete("Use the ZIndex Property instead")] public void RaiseChild(View view) { if (!InternalChildren.Contains(view) || InternalChildren.Last() == view) @@ -298,6 +317,7 @@ public void RaiseChild(View view) /// Invalidates the current layout. /// /// Calling this method will invalidate the measure and triggers a new layout cycle. + [Obsolete("Use InvalidateMeasure depending on your scenario")] protected virtual void InvalidateLayout() { _hasDoneLayout = false; @@ -317,6 +337,8 @@ protected virtual void InvalidateLayout() /// A value representing the height of the child region bounding box. /// Implementors wishing to change the default behavior of a Layout should override this method. /// It is suggested to still call the base method and modify its calculated results. + + [Obsolete("Use ArrangeOverride")] protected abstract void LayoutChildren(double x, double y, double width, double height); internal override void OnChildMeasureInvalidatedInternal(VisualElement child, InvalidationTrigger trigger) @@ -343,6 +365,7 @@ protected void OnChildMeasureInvalidated(object sender, EventArgs e) /// Invoked whenever a child of the layout has emitted . /// Implement this method to add class handling for this event. /// + [Obsolete("Subscribe to the MeasureInvalidated Event on the Children.")] protected virtual void OnChildMeasureInvalidated() { } @@ -355,7 +378,9 @@ Size IView.Measure(double widthConstraint, double heightConstraint) protected override Size MeasureOverride(double widthConstraint, double heightConstraint) { +#pragma warning disable CS0618 // Type or member is obsolete var sansMargins = OnMeasure(widthConstraint, heightConstraint).Request; +#pragma warning restore CS0618 // Type or member is obsolete return new Size(sansMargins.Width + Margin.HorizontalThickness, sansMargins.Height + Margin.VerticalThickness); } @@ -371,6 +396,7 @@ protected override void OnSizeAllocated(double width, double height) /// /// The child for which to specify whether or not to track invalidation. /// if should call , otherwise . + [Obsolete("If you want to influence invalidation override InvalidateMeasureOverride")] protected virtual bool ShouldInvalidateOnChildAdded(View child) => true; /// @@ -379,12 +405,14 @@ protected override void OnSizeAllocated(double width, double height) /// /// The child for which to specify whether or not to track invalidation. /// if should call , otherwise . + [Obsolete("If you want to influence invalidation override InvalidateMeasureOverride")] protected virtual bool ShouldInvalidateOnChildRemoved(View child) => true; /// /// Instructs the layout to relayout all of its children. /// /// This method starts a new layout cycle for the layout. Invoking this method frequently can negatively impact performance. + [Obsolete("Use InvalidateMeasure depending on your scenario")] protected void UpdateChildrenLayout() { _hasDoneLayout = true; @@ -444,7 +472,9 @@ protected void UpdateChildrenLayout() } } +#pragma warning disable CS0618 // Type or member is obsolete internal static void LayoutChildIntoBoundingRegion(View child, Rect region, SizeRequest childSizeRequest) +#pragma warning restore CS0618 // Type or member is obsolete { bool isRightToLeft = false; if (child.Parent is IFlowDirectionController parent && (isRightToLeft = parent.ApplyEffectiveFlowDirectionToChildContainer && parent.EffectiveFlowDirection.IsRightToLeft())) @@ -466,7 +496,9 @@ internal static void LayoutChildIntoBoundingRegion(View child, Rect region, Size LayoutOptions horizontalOptions = child.HorizontalOptions; if (horizontalOptions.Alignment != LayoutAlignment.Fill) { +#pragma warning disable CS0618 // Type or member is obsolete SizeRequest request = canUseAlreadyDoneRequest ? childSizeRequest : child.Measure(region.Width, region.Height, MeasureFlags.IncludeMargins); +#pragma warning restore CS0618 // Type or member is obsolete double diff = Math.Max(0, region.Width - request.Request.Width); double horizontalAlign = horizontalOptions.Alignment.ToDouble(); if (isRightToLeft) @@ -481,7 +513,9 @@ internal static void LayoutChildIntoBoundingRegion(View child, Rect region, Size LayoutOptions verticalOptions = child.VerticalOptions; if (verticalOptions.Alignment != LayoutAlignment.Fill) { +#pragma warning disable CS0618 // Type or member is obsolete SizeRequest request = canUseAlreadyDoneRequest ? childSizeRequest : child.Measure(region.Width, region.Height, MeasureFlags.IncludeMargins); +#pragma warning restore CS0618 // Type or member is obsolete double diff = Math.Max(0, region.Height - request.Request.Height); region.Y += (int)(diff * verticalOptions.Alignment.ToDouble()); region.Height -= diff; @@ -675,7 +709,9 @@ protected override Size ArrangeOverride(Rect bounds) /// public Size CrossPlatformMeasure(double widthConstraint, double heightConstraint) { +#pragma warning disable CS0618 // Type or member is obsolete return OnMeasure(widthConstraint, heightConstraint).Request; +#pragma warning restore CS0618 // Type or member is obsolete } /// diff --git a/src/Controls/src/Core/LegacyLayouts/RelativeLayout.cs b/src/Controls/src/Core/LegacyLayouts/RelativeLayout.cs index 0b67cd1b58a5..e47cf6a68e00 100644 --- a/src/Controls/src/Core/LegacyLayouts/RelativeLayout.cs +++ b/src/Controls/src/Core/LegacyLayouts/RelativeLayout.cs @@ -11,7 +11,9 @@ namespace Microsoft.Maui.Controls.Compatibility { [ContentProperty(nameof(Children))] +#pragma warning disable CS0618 // Type or member is obsolete public class RelativeLayout : Layout, IElementConfiguration +#pragma warning restore CS0618 // Type or member is obsolete { /// Bindable property for attached property XConstraint. public static readonly BindableProperty XConstraintProperty = BindableProperty.CreateAttached("XConstraint", typeof(Constraint), typeof(RelativeLayout), null, propertyChanged: ConstraintChanged); @@ -111,7 +113,9 @@ void UpdateBoundsConstraint(View view) _childrenInSolveOrder = null; // New constraints may have impact on solve order +#pragma warning disable CS0618 // Type or member is obsolete InvalidateLayout(); +#pragma warning restore CS0618 // Type or member is obsolete } public static BoundsConstraint GetBoundsConstraint(BindableObject bindable) @@ -164,13 +168,17 @@ public static void SetYConstraint(BindableObject bindable, Constraint value) bindable.SetValue(YConstraintProperty, value); } +#pragma warning disable CS0672 // Member overrides obsolete member protected override void LayoutChildren(double x, double y, double width, double height) { foreach (View child in ChildrenInSolveOrder) { +#pragma warning disable CS0618 // Type or member is obsolete LayoutChildIntoBoundingRegion(child, SolveView(child)); +#pragma warning restore CS0618 // Type or member is obsolete } } +#pragma warning restore CS0672 // Member overrides obsolete member protected override void OnAdded(View view) { @@ -191,7 +199,11 @@ protected override void OnRemoved(View view) base.OnRemoved(view); } +#pragma warning disable CS0672 // Member overrides obsolete member +#pragma warning disable CS0618 // Type or member is obsolete protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) +#pragma warning restore CS0618 // Type or member is obsolete +#pragma warning restore CS0672 // Member overrides obsolete member { double mockWidth = double.IsPositiveInfinity(widthConstraint) ? (Parent as VisualElement).Width : widthConstraint; double mockHeight = double.IsPositiveInfinity(heightConstraint) ? (Parent as VisualElement).Height : heightConstraint; @@ -222,7 +234,9 @@ protected override SizeRequest OnMeasure(double widthConstraint, double heightCo UnmockBounds(); +#pragma warning disable CS0618 // Type or member is obsolete return new SizeRequest(new Size(boundsRectangle.Right, boundsRectangle.Bottom)); +#pragma warning restore CS0618 // Type or member is obsolete } bool CanSolveView(View view, Dictionary solveTable) @@ -292,7 +306,9 @@ void CreateBoundsFromConstraints(View view, Constraint xConstraint, Constraint y parents.AddRange(widthConstraint.RelativeTo); } else +#pragma warning disable CS0618 // Type or member is obsolete width = () => view.Measure(Width, heightConstraint != null ? height() : Height, MeasureFlags.IncludeMargins).Request.Width; +#pragma warning restore CS0618 // Type or member is obsolete if (heightConstraint != null) { @@ -301,12 +317,13 @@ void CreateBoundsFromConstraints(View view, Constraint xConstraint, Constraint y parents.AddRange(heightConstraint.RelativeTo); } else +#pragma warning disable CS0618 // Type or member is obsolete height = () => view.Measure(widthConstraint != null ? width() : Width, Height, MeasureFlags.IncludeMargins).Request.Height; +#pragma warning restore CS0618 // Type or member is obsolete BoundsConstraint bounds = BoundsConstraint.FromExpression(() => new Rect(x(), y(), width(), height()), parents.Distinct().ToArray()); SetBoundsConstraint(view, bounds); } - static Rect SolveView(View view) { BoundsConstraint boundsConstraint = GetBoundsConstraint(view); @@ -352,8 +369,10 @@ public void Add(View view, Expression> x = null, Expression xCompiled = x != null ? x.Compile() : () => 0; Func yCompiled = y != null ? y.Compile() : () => 0; +#pragma warning disable CS0618 // Type or member is obsolete Func widthCompiled = width != null ? width.Compile() : () => view.Measure(Parent.Width, Parent.Height, MeasureFlags.IncludeMargins).Request.Width; Func heightCompiled = height != null ? height.Compile() : () => view.Measure(Parent.Width, Parent.Height, MeasureFlags.IncludeMargins).Request.Height; +#pragma warning restore CS0618 // Type or member is obsolete var parents = new List(); parents.AddRange(ExpressionSearch.Default.FindObjects(x)); diff --git a/src/Controls/src/Core/LegacyLayouts/StackLayout.cs b/src/Controls/src/Core/LegacyLayouts/StackLayout.cs index db341b2df4d4..8dd88840580c 100644 --- a/src/Controls/src/Core/LegacyLayouts/StackLayout.cs +++ b/src/Controls/src/Core/LegacyLayouts/StackLayout.cs @@ -7,6 +7,7 @@ namespace Microsoft.Maui.Controls.Compatibility { [ContentProperty(nameof(Children))] + [Obsolete("Use Microsoft.Maui.Controls.StackLayout instead. For more information, see https://learn.microsoft.com/dotnet/maui/migration/layouts")] public class StackLayout : Layout, IElementConfiguration, IView { /// Bindable property for . @@ -45,6 +46,7 @@ public double Spacing set { SetValue(SpacingProperty, value); } } +#pragma warning disable CS0672 // Member overrides obsolete member protected override void LayoutChildren(double x, double y, double width, double height) { if (!HasVisibleChildren()) @@ -72,8 +74,11 @@ protected override void LayoutChildren(double x, double y, double width, double LayoutChildIntoBoundingRegion(child, layoutInformationCopy.Plots[i], layoutInformationCopy.Requests[i]); } } +#pragma warning restore CS0672 // Member overrides obsolete member +#pragma warning disable CS0672 // Member overrides obsolete member protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) +#pragma warning restore CS0672 // Member overrides obsolete member { if (!HasVisibleChildren()) { diff --git a/src/Controls/src/Core/ListView/ListView.cs b/src/Controls/src/Core/ListView/ListView.cs index 881317625e7f..73e14502dd54 100644 --- a/src/Controls/src/Core/ListView/ListView.cs +++ b/src/Controls/src/Core/ListView/ListView.cs @@ -8,6 +8,7 @@ using System.Windows.Input; using Microsoft.Extensions.Logging; using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Controls.Xaml; using Microsoft.Maui.Controls.Xaml.Diagnostics; using Microsoft.Maui.Devices; using Microsoft.Maui.Graphics; @@ -151,6 +152,7 @@ protected override void OnBindingContextChanged() } /// + [DoesNotInheritDataType] public BindingBase GroupDisplayBinding { get { return _groupDisplayBinding; } @@ -176,6 +178,7 @@ public DataTemplate GroupHeaderTemplate } /// + [DoesNotInheritDataType] public BindingBase GroupShortNameBinding { get { return _groupShortNameBinding; } @@ -411,10 +414,11 @@ public void ScrollTo(object item, object group, ScrollToPosition position, bool protected override Cell CreateDefault(object item) { TextCell textCell = new TextCell(); - textCell.SetBinding(TextCell.TextProperty, ".", converter: _toStringValueConverter); + textCell.SetBinding(TextCell.TextProperty, static (object cell) => cell, BindingMode.OneWay, _toStringValueConverter); return textCell; } + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { var minimumSize = new Size(40, 40); diff --git a/src/Controls/src/Core/Menu/BaseMenuItem.cs b/src/Controls/src/Core/Menu/BaseMenuItem.cs index a0ec89817eab..e88501f5bd4b 100644 --- a/src/Controls/src/Core/Menu/BaseMenuItem.cs +++ b/src/Controls/src/Core/Menu/BaseMenuItem.cs @@ -1,7 +1,7 @@ namespace Microsoft.Maui.Controls { /// - public abstract class BaseMenuItem : Element + public abstract class BaseMenuItem : StyleableElement { } } \ No newline at end of file diff --git a/src/Controls/src/Core/Menu/MenuItem.cs b/src/Controls/src/Core/Menu/MenuItem.cs index 5b762e8054ff..58d81b3d4b71 100644 --- a/src/Controls/src/Core/Menu/MenuItem.cs +++ b/src/Controls/src/Core/Menu/MenuItem.cs @@ -1,7 +1,6 @@ #nullable disable using System; using System.Collections.Generic; -using System.ComponentModel; using System.Windows.Input; using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.StyleSheets; @@ -10,7 +9,7 @@ namespace Microsoft.Maui.Controls { /// - public partial class MenuItem : BaseMenuItem, IMenuItemController, IStyleSelectable, ICommandElement, IMenuElement, IPropertyPropagationController + public partial class MenuItem : BaseMenuItem, IMenuItemController, ICommandElement, IMenuElement, IPropertyPropagationController { /// Bindable property for . [Obsolete("Use MenuFlyoutItem.KeyboardAcceleratorsProperty instead.")] @@ -52,14 +51,11 @@ public partial class MenuItem : BaseMenuItem, IMenuItemController, IStyleSelecta /// [Obsolete("Use MenuFlyoutItem.KeyboardAcceleratorsProperty instead.")] public static void SetAccelerator(BindableObject bindable, Accelerator value) => bindable.SetValue(AcceleratorProperty, value); - - internal readonly MergedStyle _mergedStyle; bool _isEnabledExplicit = (bool)IsEnabledProperty.DefaultValue; /// public MenuItem() { - _mergedStyle = new MergedStyle(GetType(), this); } /// @@ -104,27 +100,6 @@ public bool IsEnabled set => SetValue(IsEnabledProperty, value); } - /// - [System.ComponentModel.TypeConverter(typeof(ListStringTypeConverter))] - public IList StyleClass - { - get { return @class; } - set { @class = value; } - } - - /// - [System.ComponentModel.TypeConverter(typeof(ListStringTypeConverter))] - public IList @class - { - get { return _mergedStyle.StyleClass; } - set - { - _mergedStyle.StyleClass = value; - } - } - - IList IStyleSelectable.Classes => StyleClass; - public event EventHandler Clicked; protected virtual void OnClicked() => Clicked?.Invoke(this, EventArgs.Empty); diff --git a/src/Controls/src/Core/MergedStyle.cs b/src/Controls/src/Core/MergedStyle.cs index b96ae59d00db..a4c9180a42cb 100644 --- a/src/Controls/src/Core/MergedStyle.cs +++ b/src/Controls/src/Core/MergedStyle.cs @@ -12,7 +12,11 @@ sealed class MergedStyle : IStyle { ////If the base type is one of these, stop registering dynamic resources further ////The last one (typeof(Element)) is a safety guard as we might be creating VisualElement directly in internal code - static readonly IList s_stopAtTypes = new List { typeof(View), typeof(Compatibility.Layout<>), typeof(VisualElement), typeof(NavigableElement), typeof(Element) }; + static readonly IList s_stopAtTypes = new List { typeof(View), +#pragma warning disable CS0618 // Type or member is obsolete + typeof(Compatibility.Layout<>), +#pragma warning restore CS0618 // Type or member is obsolete + typeof(VisualElement), typeof(NavigableElement), typeof(Element) }; IList _classStyleProperties; diff --git a/src/Controls/src/Core/MultiBinding.cs b/src/Controls/src/Core/MultiBinding.cs index 3b29a3efd5bd..b61ffabcdc9c 100644 --- a/src/Controls/src/Core/MultiBinding.cs +++ b/src/Controls/src/Core/MultiBinding.cs @@ -76,6 +76,8 @@ internal override BindingBase Clone() return clone; } + internal static readonly object DoNothing = new object(); // this object instance must be the same as Binding.DoNothing + internal override void Apply(bool fromTarget) { if (_applying) @@ -95,10 +97,10 @@ internal override void Apply(bool fromTarget) if (!fromTarget) { var value = GetSourceValue(GetValueArray(), _targetProperty.ReturnType); - if (value != Binding.DoNothing) + if (value != DoNothing) { _applying = true; - if (!BindingExpression.TryConvert(ref value, _targetProperty, _targetProperty.ReturnType, true)) + if (!BindingExpressionHelper.TryConvert(ref value, _targetProperty, _targetProperty.ReturnType, true)) { BindingDiagnostics.SendBindingFailure(this, null, _targetObject, _targetProperty, "MultiBinding", BindingExpression.CannotConvertTypeErrorMessage, value, _targetProperty.ReturnType); return; @@ -118,7 +120,7 @@ internal override void Apply(bool fromTarget) return; for (var i = 0; i < Math.Min(_bpProxies.Length, values.Length); i++) { - if (ReferenceEquals(values[i], Binding.DoNothing) || ReferenceEquals(values[i], BindableProperty.UnsetValue)) + if (ReferenceEquals(values[i], DoNothing) || ReferenceEquals(values[i], BindableProperty.UnsetValue)) continue; _proxyObject.SetValue(_bpProxies[i], values[i]); } @@ -168,10 +170,10 @@ internal override void Apply(object context, BindableObject targetObject, Bindab return; var value = GetSourceValue(GetValueArray(), _targetProperty.ReturnType); - if (value != Binding.DoNothing) + if (value != DoNothing) { _applying = true; - if (!BindingExpression.TryConvert(ref value, _targetProperty, _targetProperty.ReturnType, true)) + if (!BindingExpressionHelper.TryConvert(ref value, _targetProperty, _targetProperty.ReturnType, true)) { BindingDiagnostics.SendBindingFailure(this, context, _targetObject, _targetProperty, "MultiBinding", BindingExpression.CannotConvertTypeErrorMessage, value, _targetProperty.ReturnType); return; diff --git a/src/Controls/src/Core/MultiPage.cs b/src/Controls/src/Core/MultiPage.cs index 8ebf34234626..57e9fec8c72f 100644 --- a/src/Controls/src/Core/MultiPage.cs +++ b/src/Controls/src/Core/MultiPage.cs @@ -13,7 +13,7 @@ namespace Microsoft.Maui.Controls { [ContentProperty("Children")] - public abstract class MultiPage<[DynamicallyAccessedMembers(BindableProperty.DeclaringTypeMembers)] T> : Page, IViewContainer, IPageContainer, IItemsView, IMultiPageController where T : Page + public abstract class MultiPage<[DynamicallyAccessedMembers(BindableProperty.DeclaringTypeMembers | BindableProperty.ReturnTypeMembers)] T> : Page, IViewContainer, IPageContainer, IItemsView, IMultiPageController where T : Page { /// Bindable property for . public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(MultiPage<>), null); @@ -97,7 +97,7 @@ public T CurrentPage if (HasAppeared) _current?.SendAppearing(); - previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(_current)); + previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(_current, NavigationType.PageSwap)); _current?.SendNavigatedTo(new NavigatedToEventArgs(previousPage)); } } diff --git a/src/Controls/src/Core/Shell/NavigableElement.cs b/src/Controls/src/Core/NavigableElement/NavigableElement.cs similarity index 52% rename from src/Controls/src/Core/Shell/NavigableElement.cs rename to src/Controls/src/Core/NavigableElement/NavigableElement.cs index f09bd8080cca..4d2553a8e540 100644 --- a/src/Controls/src/Core/Shell/NavigableElement.cs +++ b/src/Controls/src/Core/NavigableElement/NavigableElement.cs @@ -8,25 +8,20 @@ namespace Microsoft.Maui.Controls { /// Represents an with base functionality for navigation. Does not necessarily render on screen. /// Not meant to be used directly. Instead, opt to use derived types, such as . - public class NavigableElement : Element, INavigationProxy, IStyleSelectable + public class NavigableElement : StyleableElement, INavigationProxy { static readonly BindablePropertyKey NavigationPropertyKey = - BindableProperty.CreateReadOnly(nameof(Navigation), typeof(INavigation), typeof(VisualElement), default(INavigation)); + BindableProperty.CreateReadOnly(nameof(Navigation), typeof(INavigation), typeof(NavigableElement), default(INavigation)); /// Bindable property for . public static readonly BindableProperty NavigationProperty = NavigationPropertyKey.BindableProperty; - /// Bindable property for . - public static readonly BindableProperty StyleProperty = - BindableProperty.Create(nameof(Style), typeof(Style), typeof(VisualElement), default(Style), - propertyChanged: (bindable, oldvalue, newvalue) => ((NavigableElement)bindable)._mergedStyle.Style = (Style)newvalue); - - internal readonly MergedStyle _mergedStyle; + /// + public static readonly new BindableProperty StyleProperty = StyleableElement.StyleProperty; internal NavigableElement() { Navigation = new NavigationProxy(); - _mergedStyle = new MergedStyle(GetType(), this); } /// Gets the object responsible for handling stack-based navigation. @@ -37,44 +32,6 @@ public INavigation Navigation internal set { SetValue(NavigationPropertyKey, value); } } - /// Gets or sets the unique for this element. - public Style Style - { - get { return (Style)GetValue(StyleProperty); } - set { SetValue(StyleProperty, value); } - } - - /// Gets or sets the style classes for the element. - /// - /// Equiavalent to . - /// Style classes enable multiple styles to be applied to a control, without resorting to style inheritance. - /// - /// Conceptual documentation on style classes - [System.ComponentModel.TypeConverter(typeof(ListStringTypeConverter))] - public IList StyleClass - { - get { return @class; } - set { @class = value; } - } - - /// Gets or sets the style classes for the element. - /// - /// Equiavalent to . - /// Style classes enable multiple styles to be applied to a control, without resorting to style inheritance. - /// - /// Conceptual documentation on style classes - [System.ComponentModel.TypeConverter(typeof(ListStringTypeConverter))] - public IList @class - { - get { return _mergedStyle.StyleClass; } - set - { - _mergedStyle.StyleClass = value; - } - } - - IList IStyleSelectable.Classes => StyleClass; - /// Gets the cast of to a . /// /// Determines whether the element will proxy navigation calls. diff --git a/src/Controls/src/Core/NavigationPage/NavigationPage.Legacy.cs b/src/Controls/src/Core/NavigationPage/NavigationPage.Legacy.cs index 1e9629e0068c..2262c4ed7eab 100644 --- a/src/Controls/src/Core/NavigationPage/NavigationPage.Legacy.cs +++ b/src/Controls/src/Core/NavigationPage/NavigationPage.Legacy.cs @@ -27,7 +27,7 @@ async Task PopAsyncInner( var previousPage = CurrentPage; SendNavigating(); var removedPage = await RemoveAsyncInner(page, animated, fast); - SendNavigated(previousPage); + SendNavigated(previousPage, NavigationType.Pop); return removedPage; } @@ -174,7 +174,7 @@ async Task PopToRootAsyncInner(bool animated) } PoppedToRoot?.Invoke(this, new PoppedToRootEventArgs(RootPage, childrenToRemove.OfType().ToList())); - SendNavigated(previousPage); + SendNavigated(previousPage, NavigationType.PopToRoot); } async Task PushAsyncInner(Page page, bool animated) @@ -200,7 +200,7 @@ async Task PushAsyncInner(Page page, bool animated) await args.Task; } - SendNavigated(previousPage); + SendNavigated(previousPage, NavigationType.Push); Pushed?.Invoke(this, args); } @@ -209,12 +209,12 @@ async Task PushAsyncInner(Page page, bool animated) // there are scenarios where the legacy handler needs to alert the xplat // code of when a navigation has occurred. // For example, initial load and when the user taps the back button - internal void SendNavigatedFromHandler(Page previousPage) + internal void SendNavigatedFromHandler(Page previousPage, NavigationType navigationType) { if (CurrentPage.HasNavigatedTo) return; - SendNavigated(previousPage); + SendNavigated(previousPage, navigationType); } #endif diff --git a/src/Controls/src/Core/NavigationPage/NavigationPage.Mapper.cs b/src/Controls/src/Core/NavigationPage/NavigationPage.Mapper.cs index a9dbb8c8209a..44ca4050d7c5 100644 --- a/src/Controls/src/Core/NavigationPage/NavigationPage.Mapper.cs +++ b/src/Controls/src/Core/NavigationPage/NavigationPage.Mapper.cs @@ -6,10 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class NavigationPage { - [Obsolete("Use NavigationViewHandler.Mapper instead.")] - public static IPropertyMapper ControlsNavigationPageMapper = - new ControlsMapper(NavigationViewHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.NavigationPage legacy behaviors diff --git a/src/Controls/src/Core/NavigationPage/NavigationPage.cs b/src/Controls/src/Core/NavigationPage/NavigationPage.cs index 24153fcbd3d2..414ff519e821 100644 --- a/src/Controls/src/Core/NavigationPage/NavigationPage.cs +++ b/src/Controls/src/Core/NavigationPage/NavigationPage.cs @@ -374,9 +374,9 @@ protected override bool OnBackButtonPressed() return base.OnBackButtonPressed(); } - void SendNavigated(Page previousPage) + void SendNavigated(Page previousPage, NavigationType navigationType) { - previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage)); + previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage, navigationType)); CurrentPage.SendNavigatedTo(new NavigatedToEventArgs(previousPage)); } @@ -442,6 +442,7 @@ partial void Init() Thickness IView.Margin => Thickness.Zero; + [Obsolete("Use ArrangeOverride instead")] protected override void LayoutChildren(double x, double y, double width, double height) { // We don't want forcelayout to call the legacy @@ -701,7 +702,8 @@ private protected override void OnHandlerChangedCore() }, () => { - SendNavigated(null); + // TODO this is the wrong navigation type + SendNavigated(null, NavigationType.Initialize); }) .FireAndForget(Handler); } @@ -799,7 +801,7 @@ await Owner.SendHandlerUpdateAsync(animated, }, () => { - Owner.SendNavigated(currentPage); + Owner.SendNavigated(currentPage, NavigationType.Pop); Owner?.Popped?.Invoke(Owner, new NavigationEventArgs(currentPage)); }); @@ -836,7 +838,7 @@ protected override Task OnPopToRootAsync(bool animated) }, () => { - Owner.SendNavigated(previousPage); + Owner.SendNavigated(previousPage, NavigationType.PopToRoot); Owner?.PoppedToRoot?.Invoke(Owner, new PoppedToRootEventArgs(newPage, pagesToRemove)); }); } @@ -861,7 +863,7 @@ protected override Task OnPushAsync(Page root, bool animated) }, () => { - Owner.SendNavigated(previousPage); + Owner.SendNavigated(previousPage, NavigationType.Push); Owner?.Pushed?.Invoke(Owner, new NavigationEventArgs(root)); }); } diff --git a/src/Controls/src/Core/OnIdiom.cs b/src/Controls/src/Core/OnIdiom.cs index 346165739ad9..65b624eacbca 100644 --- a/src/Controls/src/Core/OnIdiom.cs +++ b/src/Controls/src/Core/OnIdiom.cs @@ -3,7 +3,7 @@ namespace Microsoft.Maui.Controls { - public class OnIdiom + public class OnIdiom : IWrappedValue { T _phone; T _tablet; @@ -87,5 +87,8 @@ public static implicit operator T(OnIdiom onIdiom) else return onIdiom._isPhoneSet ? onIdiom.Phone : (onIdiom._isDefaultSet ? onIdiom.Default : default(T)); } + + object IWrappedValue.Value => (T)this; + System.Type IWrappedValue.ValueType => typeof(T); } } diff --git a/src/Controls/src/Core/OnPlatform.cs b/src/Controls/src/Core/OnPlatform.cs index 1d8e114d4c18..4dc8c1036cda 100644 --- a/src/Controls/src/Core/OnPlatform.cs +++ b/src/Controls/src/Core/OnPlatform.cs @@ -6,7 +6,7 @@ namespace Microsoft.Maui.Controls { [ContentProperty("Platforms")] - public class OnPlatform + public class OnPlatform : IWrappedValue { public OnPlatform() { @@ -54,6 +54,9 @@ public static implicit operator T(OnPlatform onPlatform) return onPlatform.hasDefault ? onPlatform.@default : default(T); } + + object IWrappedValue.Value => (T)this; + System.Type IWrappedValue.ValueType => typeof(T); } /// diff --git a/src/Controls/src/Core/Page/NavigatedFromEventArgs.cs b/src/Controls/src/Core/Page/NavigatedFromEventArgs.cs index 832175c16d84..887047b1c986 100644 --- a/src/Controls/src/Core/Page/NavigatedFromEventArgs.cs +++ b/src/Controls/src/Core/Page/NavigatedFromEventArgs.cs @@ -1,15 +1,30 @@ #nullable disable using System; +using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls { + internal enum NavigationType + { + Push, + Pop, + PopToRoot, + Insert, + Remove, + PageSwap, + Initialize + } + public sealed class NavigatedFromEventArgs : EventArgs { - internal NavigatedFromEventArgs(Page destinationPage) + internal NavigationType NavigationType { get; } + + internal Page DestinationPage { get; } + + internal NavigatedFromEventArgs(Page destinationPage, NavigationType navigationType) { DestinationPage = destinationPage; + NavigationType = navigationType; } - - internal Page DestinationPage { get; } } } diff --git a/src/Controls/src/Core/Page/Page.cs b/src/Controls/src/Core/Page/Page.cs index 53b083d64504..da4bad7c31fd 100644 --- a/src/Controls/src/Core/Page/Page.cs +++ b/src/Controls/src/Core/Page/Page.cs @@ -147,7 +147,7 @@ Thickness IPaddingElement.PaddingDefaultValueCreator() void IPaddingElement.OnPaddingPropertyChanged(Thickness oldValue, Thickness newValue) { - UpdateChildrenLayout(); + (this as IView).InvalidateMeasure(); } /// @@ -411,6 +411,7 @@ public bool SendBackButtonPressed() /// Y-coordinate of the top left corner of the bounding rectangle. /// Width of the bounding rectangle. /// Height of the bounding rectangle. + [Obsolete("Use ArrangeOverride instead")] protected virtual void LayoutChildren(double x, double y, double width, double height) { var area = new Rect(x, y, width, height); @@ -434,10 +435,12 @@ protected virtual void LayoutChildren(double x, double y, double width, double h continue; var page = child as Page; +#pragma warning disable CS0618 // Type or member is obsolete if (page != null && page.IgnoresContainerArea) Maui.Controls.Compatibility.Layout.LayoutChildIntoBoundingRegion(child, originalArea); else Maui.Controls.Compatibility.Layout.LayoutChildIntoBoundingRegion(child, area); +#pragma warning restore CS0618 // Type or member is obsolete } } @@ -543,12 +546,19 @@ protected override void OnParentSet() protected override void OnSizeAllocated(double width, double height) { base.OnSizeAllocated(width, height); - UpdateChildrenLayout(); + + if (Handler is null) + { +#pragma warning disable CS0618 // Type or member is obsolete + UpdateChildrenLayout(); +#pragma warning restore CS0618 // Type or member is obsolete + } } /// /// Requests that the child s of the page update their layouts. /// + [Obsolete("Use ArrangeOverride instead")] protected void UpdateChildrenLayout() { if (!ShouldLayoutChildren()) @@ -844,12 +854,30 @@ internal void SendNavigatingFrom(NavigatingFromEventArgs args) (this as IPageContainer)?.CurrentPage?.SendNavigatingFrom(args); } - internal void SendNavigatedFrom(NavigatedFromEventArgs args) + internal void SendNavigatedFrom(NavigatedFromEventArgs args, bool disconnectHandlers = true) { HasNavigatedTo = false; NavigatedFrom?.Invoke(this, args); OnNavigatedFrom(args); - (this as IPageContainer)?.CurrentPage?.SendNavigatedFrom(args); + (this as IPageContainer)?.CurrentPage?.SendNavigatedFrom(args, false); + + if (!disconnectHandlers) + { + return; + } + + if (args.NavigationType == NavigationType.Pop || + args.NavigationType == NavigationType.PopToRoot) + { + if (!this.IsLoaded) + { + this.DisconnectHandlers(); + } + else + { + this.OnUnloaded(() => this.DisconnectHandlers()); + } + } } /// diff --git a/src/Controls/src/Core/Picker/Picker.Mapper.cs b/src/Controls/src/Core/Picker/Picker.Mapper.cs index cb656f7f0583..e4c66149c5bf 100644 --- a/src/Controls/src/Core/Picker/Picker.Mapper.cs +++ b/src/Controls/src/Core/Picker/Picker.Mapper.cs @@ -6,9 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class Picker { - [Obsolete("Use PickerHandler.Mapper instead.")] - public static IPropertyMapper ControlsPickerMapper = new ControlsMapper(PickerHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.Picker legacy behaviors diff --git a/src/Controls/src/Core/Picker/Picker.cs b/src/Controls/src/Core/Picker/Picker.cs index 85f282d717c5..cfc071ad248e 100644 --- a/src/Controls/src/Core/Picker/Picker.cs +++ b/src/Controls/src/Core/Picker/Picker.cs @@ -7,6 +7,7 @@ using System.ComponentModel; using System.Runtime.CompilerServices; using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Controls.Xaml; using Microsoft.Maui.Graphics; namespace Microsoft.Maui.Controls @@ -199,6 +200,7 @@ public TextAlignment VerticalTextAlignment BindingBase _itemDisplayBinding; /// + [DoesNotInheritDataType] public BindingBase ItemDisplayBinding { get { return _itemDisplayBinding; } diff --git a/src/Controls/src/Core/Platform/AlertManager/ActionSheetDialog.Windows.cs b/src/Controls/src/Core/Platform/AlertManager/ActionSheetDialog.Windows.cs index c5175edc265a..b6c6f20465d8 100644 --- a/src/Controls/src/Core/Platform/AlertManager/ActionSheetDialog.Windows.cs +++ b/src/Controls/src/Core/Platform/AlertManager/ActionSheetDialog.Windows.cs @@ -7,7 +7,7 @@ namespace Microsoft.Maui.Controls.Platform { - public sealed class ActionSheetContent : UserControl + public sealed partial class ActionSheetContent : UserControl { readonly ActionSheetArguments _options; diff --git a/src/Controls/src/Core/Platform/AlertManager/AlertDialog.Windows.cs b/src/Controls/src/Core/Platform/AlertManager/AlertDialog.Windows.cs index 6c866545880c..98ef57fc9c1b 100644 --- a/src/Controls/src/Core/Platform/AlertManager/AlertDialog.Windows.cs +++ b/src/Controls/src/Core/Platform/AlertManager/AlertDialog.Windows.cs @@ -3,7 +3,7 @@ namespace Microsoft.Maui.Controls.Platform { - public sealed class AlertDialog : ContentDialog + public sealed partial class AlertDialog : ContentDialog { public UI.Xaml.Controls.ScrollBarVisibility VerticalScrollBarVisibility { get; set; } diff --git a/src/Controls/src/Core/Platform/AlertManager/PromptDialog.Windows.cs b/src/Controls/src/Core/Platform/AlertManager/PromptDialog.Windows.cs index 4c4d49198cd3..b2c2a466368c 100644 --- a/src/Controls/src/Core/Platform/AlertManager/PromptDialog.Windows.cs +++ b/src/Controls/src/Core/Platform/AlertManager/PromptDialog.Windows.cs @@ -2,63 +2,63 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; -namespace Microsoft.Maui.Controls.Platform +namespace Microsoft.Maui.Controls.Platform; + +public sealed partial class PromptDialog : ContentDialog { - public sealed class PromptDialog : ContentDialog + public PromptDialog() { - public PromptDialog() - { - Title = "TITLE"; - PrimaryButtonText = "Ok"; - SecondaryButtonText = "Cancel"; + Title = "TITLE"; + PrimaryButtonText = "Ok"; + SecondaryButtonText = "Cancel"; - Initialize(); - } + Initialize(); + } - internal TextBlock TextBlockMessage { get; private set; } - internal TextBox TextBoxInput { get; private set; } - public string Message - { - get => TextBlockMessage.Text; - set => TextBlockMessage.Text = value; - } + internal TextBlock TextBlockMessage { get; private set; } + internal MauiPasswordTextBox TextBoxInput { get; private set; } - public string Input - { - get => TextBoxInput.Text; - set => TextBoxInput.Text = value; - } + public string Message + { + get => TextBlockMessage.Text; + set => TextBlockMessage.Text = value; + } + + public string Input + { + get => TextBoxInput.Password; + set => TextBoxInput.Password = value; + } - public string Placeholder - { - get => TextBoxInput.PlaceholderText; - set => TextBoxInput.PlaceholderText = value; - } + public string Placeholder + { + get => TextBoxInput.PlaceholderText; + set => TextBoxInput.PlaceholderText = value; + } - public int MaxLength - { - get => TextBoxInput.MaxLength; - set => TextBoxInput.MaxLength = value; - } + public int MaxLength + { + get => TextBoxInput.MaxLength; + set => TextBoxInput.MaxLength = value; + } - public InputScope InputScope - { - get => TextBoxInput.InputScope; - set => TextBoxInput.InputScope = value; - } + public InputScope InputScope + { + get => TextBoxInput.InputScope; + set => TextBoxInput.InputScope = value; + } - void Initialize() - { - var layout = new StackPanel(); + void Initialize() + { + var layout = new StackPanel(); - TextBlockMessage = new TextBlock { Text = "Message", TextWrapping = UI.Xaml.TextWrapping.Wrap }; - TextBoxInput = new TextBox(); + TextBlockMessage = new TextBlock { Text = "Message", TextWrapping = UI.Xaml.TextWrapping.Wrap }; + TextBoxInput = new MauiPasswordTextBox(); - layout.Children.Add(TextBlockMessage); - layout.Children.Add(TextBoxInput); + layout.Children.Add(TextBlockMessage); + layout.Children.Add(TextBoxInput); - Content = layout; - } + Content = layout; } } \ No newline at end of file diff --git a/src/Controls/src/Core/Platform/Android/BottomNavigationViewUtils.cs b/src/Controls/src/Core/Platform/Android/BottomNavigationViewUtils.cs index 60de64e5f181..99188c12c6dc 100644 --- a/src/Controls/src/Core/Platform/Android/BottomNavigationViewUtils.cs +++ b/src/Controls/src/Core/Platform/Android/BottomNavigationViewUtils.cs @@ -255,12 +255,14 @@ public static void SetShiftMode(this BottomNavigationView bottomNavigationView, { try { +#pragma warning disable XAOBS001 // Obsolete var menuView = bottomNavigationView.GetChildAt(0) as BottomNavigationMenuView; if (menuView is null) { System.Diagnostics.Debug.WriteLine("Unable to find BottomNavigationMenuView"); return; } +#pragma warning restore XAOBS001 // Obsolete #if __ANDROID_28__ if (enableShiftMode) @@ -277,7 +279,9 @@ public static void SetShiftMode(this BottomNavigationView bottomNavigationView, for (int i = 0; i < menuView.ChildCount; i++) { var child = menuView.GetChildAt(i); +#pragma warning disable XAOBS001 // Obsolete var item = child as BottomNavigationItemView; +#pragma warning restore XAOBS001 // Obsolete if (item != null) { #if __ANDROID_28__ diff --git a/src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs b/src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs index b698c492eb55..3270907eeb22 100644 --- a/src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs +++ b/src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs @@ -131,7 +131,9 @@ internal static SpannableString ToSpannableStringNewWay( return spannable; } +#pragma warning disable CS0618 // Type or member is obsolete public static void RecalculateSpanPositions(this TextView textView, Label element, SpannableString spannableString, SizeRequest finalSize) +#pragma warning restore CS0618 // Type or member is obsolete { if (element?.FormattedText?.Spans is null || element.FormattedText.Spans.Count == 0) return; diff --git a/src/Controls/src/Core/Platform/Android/MultiPageFragmentStateAdapter.cs b/src/Controls/src/Core/Platform/Android/MultiPageFragmentStateAdapter.cs index 346251c95020..536119e7007f 100644 --- a/src/Controls/src/Core/Platform/Android/MultiPageFragmentStateAdapter.cs +++ b/src/Controls/src/Core/Platform/Android/MultiPageFragmentStateAdapter.cs @@ -7,7 +7,11 @@ namespace Microsoft.Maui.Controls.Platform { - internal class MultiPageFragmentStateAdapter<[DynamicallyAccessedMembers(BindableProperty.DeclaringTypeMembers)] T> : FragmentStateAdapter where T : Page + internal class MultiPageFragmentStateAdapter<[DynamicallyAccessedMembers(BindableProperty.DeclaringTypeMembers + #if NET8_0 // IL2091 + | BindableProperty.ReturnTypeMembers + #endif + )] T> : FragmentStateAdapter where T : Page { MultiPage _page; readonly IMauiContext _context; diff --git a/src/Controls/src/Core/Platform/Android/TabbedPageManager.cs b/src/Controls/src/Core/Platform/Android/TabbedPageManager.cs index 4fd95c9a6e81..3a64fd23918f 100644 --- a/src/Controls/src/Core/Platform/Android/TabbedPageManager.cs +++ b/src/Controls/src/Core/Platform/Android/TabbedPageManager.cs @@ -659,8 +659,10 @@ protected virtual ColorStateList GetItemIconTintColorState() } else { +#pragma warning disable XAOBS001 // Obsolete var styledAttributes = TintTypedArray.ObtainStyledAttributes(_context.Context, null, Resource.Styleable.NavigationBarView, Resource.Attribute.bottomNavigationStyle, 0); +#pragma warning restore XAOBS001 // Obsolete try { diff --git a/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Android.cs b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Android.cs index 687a16e2080e..9f2c74c74396 100644 --- a/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Android.cs +++ b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Android.cs @@ -1,18 +1,22 @@ using System; -using System.ComponentModel; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Android.Content; +using Android.Graphics.Drawables; using Android.OS; +using Android.Runtime; using Android.Views; +using System.Runtime.CompilerServices; using Android.Views.Animations; -using AndroidX.Activity; -using AndroidX.AppCompat.App; -using AndroidX.AppCompat.Widget; -using AndroidX.Core.View; using AndroidX.Fragment.App; -using Microsoft.Maui.Graphics; -using Microsoft.Maui.Platform; +using AAnimation = Android.Views.Animations.Animation; +using AColor = Android.Graphics.Color; using AView = Android.Views.View; +using AndroidX.AppCompat.App; +using Microsoft.Maui.LifecycleEvents; +using AndroidX.Activity; +using System.ComponentModel; namespace Microsoft.Maui.Controls.Platform { @@ -21,11 +25,57 @@ internal partial class ModalNavigationManager ViewGroup? _modalParentView; bool _navAnimationInProgress; internal const string CloseContextActionsSignalName = "Xamarin.CloseContextActions"; + AAnimation? _dismissAnimation; + bool _platformActivated; + + readonly Stack _modals = []; partial void InitializePlatform() { _window.Activated += (_, _) => SyncModalStackWhenPlatformIsReady(); - _window.Resumed += (_, _) => SyncModalStackWhenPlatformIsReady(); + _window.HandlerChanging += OnPlatformWindowHandlerChanging; + _window.PropertyChanging += OnWindowPropertyChanging; + } + + void OnWindowPropertyChanging(object sender, PropertyChangingEventArgs e) + { + if (e.PropertyName != Window.PageProperty.PropertyName) + { + return; + } + + var handler = _currentPage?.Handler; + var windowP = _window.Page; + if (CurrentPage is not null && + _window.Page != CurrentPage) + { + ClearModalPages(xplat: true, platform: true); + + var fragmentManager = WindowMauiContext.GetFragmentManager(); + + foreach (var dialogFragmentId in _modals) + { + var dialogFragment = (ModalFragment?)fragmentManager.FindFragmentByTag(dialogFragmentId); + dialogFragment?.Dismiss(); + } + _modals.Clear(); + } + } + + void OnPlatformWindowHandlerChanging(object? sender, HandlerChangingEventArgs e) + { + _platformActivated = _window.IsActivated; + } + + void OnWindowsActivated(object? sender, EventArgs e) + { + if (_platformActivated) + { + return; + } + + _platformActivated = true; + SyncModalStackWhenPlatformIsReady(); } // This is only here for the device tests to use. @@ -68,45 +118,47 @@ Task PopModalPlatformAsync(bool animated) Page modal = CurrentPlatformModalPage; _platformModalPages.Remove(modal); + var fragmentManager = WindowMauiContext.GetFragmentManager(); + + var dialogFragmentId = _modals.Pop(); + var dialogFragment = (ModalFragment?)fragmentManager.FindFragmentByTag(dialogFragmentId); + + // If for the dialog is null what we want to do? + if (dialogFragment is null) + { + return Task.FromResult(modal); + } + var source = new TaskCompletionSource(); - if (modal.Handler is IPlatformViewHandler modalHandler) + if (animated && dialogFragment.View is not null) { - ModalContainer? modalContainer = null; - for (int i = 0; i <= GetModalParentView().ChildCount; i++) - { - if (GetModalParentView().GetChildAt(i) is ModalContainer mc && - mc.Modal == modal) - { - modalContainer = mc; - } - } + _dismissAnimation ??= AnimationUtils.LoadAnimation(WindowMauiContext.Context, Resource.Animation.nav_modal_default_exit_anim)!; - _ = modalContainer ?? throw new InvalidOperationException("Parent is not Modal Container"); + _dismissAnimation.AnimationEnd += OnAnimationEnded; - if (animated) - { - modalContainer - .Animate()?.TranslationY(GetModalParentView().Height)? - .SetInterpolator(new AccelerateInterpolator(1))?.SetDuration(300)?.SetListener(new GenericAnimatorListener - { - OnEnd = a => - { - modalContainer.Destroy(); - source.TrySetResult(modal); - modalContainer = null; - } - }); - } - else - { - modalContainer.Destroy(); - source.TrySetResult(modal); - } + dialogFragment.View.StartAnimation(_dismissAnimation); + } + else + { + dialogFragment.Dismiss(); + source.TrySetResult(modal); } - RestoreFocusability(GetCurrentRootView()); return source.Task; + + void OnAnimationEnded(object? sender, AAnimation.AnimationEndEventArgs e) + { + if (sender is not AAnimation animation) + { + return; + } + + animation.AnimationEnd -= OnAnimationEnded; + dialogFragment.Dismiss(); + source.TrySetResult(modal); + _dismissAnimation = null; + } } // The CurrentPage doesn't represent the root of the platform hierarchy. @@ -124,13 +176,9 @@ async Task PushModalPlatformAsync(Page modal, bool animated) { var viewToHide = GetCurrentRootView(); - RemoveFocusability(viewToHide); - _platformModalPages.Add(modal); - Task presentModal = PresentModal(modal, animated); - - await presentModal; + await PresentModal(modal, animated); // The state of things might have changed after the modal view was pushed if (IsModalReady) @@ -140,326 +188,277 @@ async Task PushModalPlatformAsync(Page modal, bool animated) } } - Task PresentModal(Page modal, bool animated) + async Task PresentModal(Page modal, bool animated) { + TaskCompletionSource animationCompletionSource = new(); + var parentView = GetModalParentView(); - var modalContainer = new ModalContainer(WindowMauiContext, modal, parentView); - var source = new TaskCompletionSource(); - NavAnimationInProgress = true; + var dialogFragment = new ModalFragment(WindowMauiContext, modal) + { + Cancelable = false, + IsAnimated = animated + }; + + var fragmentManager = WindowMauiContext.GetFragmentManager(); + var dialogFragmentId = AView.GenerateViewId().ToString(); + _modals.Push(dialogFragmentId); + dialogFragment.Show(fragmentManager, dialogFragmentId); + if (animated) { - modalContainer.TranslationY = GetModalParentView().Height; - modalContainer?.Animate()?.TranslationY(0)?.SetInterpolator(new DecelerateInterpolator(1))?.SetDuration(300)?.SetListener(new GenericAnimatorListener - { - OnEnd = a => - { - source.TrySetResult(false); - modalContainer = null; - }, - OnCancel = a => - { - source.TrySetResult(true); - modalContainer = null; - } - }); + NavAnimationInProgress = true; + dialogFragment!.AnimationEnded += OnAnimationEnded; + + await animationCompletionSource.Task; } else { - source.TrySetResult(true); + NavAnimationInProgress = false; + animationCompletionSource.TrySetResult(true); } - return source.Task.ContinueWith(task => NavAnimationInProgress = false); + void OnAnimationEnded(object? sender, EventArgs e) + { + dialogFragment!.AnimationEnded -= OnAnimationEnded; + NavAnimationInProgress = false; + animationCompletionSource.SetResult(true); + } } - void RestoreFocusability(AView platformView) + internal class ModalFragment : DialogFragment { - platformView.ImportantForAccessibility = ImportantForAccessibility.Auto; - - if (OperatingSystem.IsAndroidVersionAtLeast(26)) - platformView.SetFocusable(ViewFocusability.FocusableAuto); + Page _modal; + IMauiContext _mauiWindowContext; + NavigationRootManager? _navigationRootManager; + static readonly ColorDrawable TransparentColorDrawable = new(AColor.Transparent); + bool _pendingAnimation = true; - if (platformView is ViewGroup vg) - vg.DescendantFocusability = DescendantFocusability.BeforeDescendants; - } + public event EventHandler? AnimationEnded; - void RemoveFocusability(AView platformView) - { - platformView.ImportantForAccessibility = ImportantForAccessibility.NoHideDescendants; - if (OperatingSystem.IsAndroidVersionAtLeast(26)) - platformView.SetFocusable(ViewFocusability.NotFocusable); + public bool IsAnimated { get; internal set; } - // Without setting this the keyboard will still navigate to components behind the modal page - if (platformView is ViewGroup vg) - vg.DescendantFocusability = DescendantFocusability.BlockDescendants; - } - - sealed class ModalContainer : ViewGroup - { - AView _backgroundView; - IMauiContext? _windowMauiContext; - public Page? Modal { get; private set; } - ModalFragment _modalFragment; - FragmentManager? _fragmentManager; - NavigationRootManager? NavigationRootManager => _modalFragment.NavigationRootManager; - int _currentRootViewHeight = 0; - int _currentRootViewWidth = 0; - GenericGlobalLayoutListener? _rootViewLayoutListener; - AView? _rootView; - - AView GetWindowRootView() => - _windowMauiContext - ?.GetNavigationRootManager() - ?.RootView ?? - throw new InvalidOperationException("Current Root View cannot be null"); - - public ModalContainer( - IMauiContext windowMauiContext, - Page modal, - ViewGroup parentView) - : base(windowMauiContext?.Context ?? throw new ArgumentNullException($"{nameof(windowMauiContext.Context)}")) + public ModalFragment(IMauiContext mauiContext, Page modal) { - _windowMauiContext = windowMauiContext; - Modal = modal; - _backgroundView = new AView(_windowMauiContext.Context); - UpdateBackgroundColor(); - AddView(_backgroundView); - - Id = AView.GenerateViewId(); - - _modalFragment = new ModalFragment(_windowMauiContext, modal); - _fragmentManager = _windowMauiContext.GetFragmentManager(); - - parentView.AddView(this); - - _fragmentManager - .BeginTransaction() - .Add(this.Id, _modalFragment) - .Commit(); + _modal = modal; + _modal.PropertyChanged += OnModalPagePropertyChanged; + _modal.HandlerChanged += OnPageHandlerChanged; + _mauiWindowContext = mauiContext; } - protected override void OnAttachedToWindow() + public override global::Android.App.Dialog OnCreateDialog(Bundle? savedInstanceState) { - base.OnAttachedToWindow(); - UpdateMargin(); - UpdateRootView(GetWindowRootView()); - } + var dialog = new CustomComponentDialog(RequireContext(), Theme); - protected override void OnDetachedFromWindow() - { - base.OnDetachedFromWindow(); - UpdateRootView(null); + if (dialog is null || dialog.Window is null) + throw new InvalidOperationException($"{dialog} or {dialog?.Window} is null, and it's invalid"); + + dialog.Window.SetBackgroundDrawable(TransparentColorDrawable); + + return dialog; } - void UpdateRootView(AView? rootView) + void OnPageHandlerChanged(object? sender, EventArgs e) { - if (_rootView.IsAlive()) + if (sender is Page page) { - _rootView.LayoutChange -= OnRootViewLayoutChanged; - _rootView = null; + page.HandlerChanged -= OnPageHandlerChanged; } - if (rootView.IsAlive()) - { - rootView.LayoutChange += OnRootViewLayoutChanged; - _rootView = rootView; - _currentRootViewHeight = _rootView.MeasuredHeight; - _currentRootViewWidth = _rootView.MeasuredWidth; - } + UpdateBackgroundColor(); } - // If the RootView changes sizes that means we also need to change sizes - // This will typically happen when the user is opening the soft keyboard - // which sometimes causes the available window size to change - void OnRootViewLayoutChanged(object? sender, LayoutChangeEventArgs e) + void OnModalPagePropertyChanged(object? sender, PropertyChangedEventArgs e) { - if (Modal is null || sender is not AView view) - return; - - var modalStack = Modal?.Navigation?.ModalStack; - if (modalStack is null || - modalStack.Count == 0 || - modalStack[modalStack.Count - 1] != Modal) + if (_modal is null) { - return; - } - - if ((_currentRootViewHeight != view.MeasuredHeight || _currentRootViewWidth != view.MeasuredWidth) - && this.ViewTreeObserver is not null) - { - // When the keyboard closes Android calls layout but doesn't call remeasure. - // MY guess is that this is due to the modal not being part of the FitSystemWindowView - // The modal is added to the decor view so its dimensions don't get updated. - // So, here we are waiting for the layout pass to finish and then we remeasure the modal - // - // For .NET 8 we'll convert this all over to using a DialogFragment - // which means we can delete most of the awkward code here - _currentRootViewHeight = view.MeasuredHeight; - _currentRootViewWidth = view.MeasuredWidth; - if (!this.IsInLayout) + if (sender is Page page) { - this.InvalidateMeasure(Modal); - return; + page.PropertyChanged -= OnModalPagePropertyChanged; + page.HandlerChanged -= OnPageHandlerChanged; } - _rootViewLayoutListener ??= new GenericGlobalLayoutListener((listener, view) => - { - if (view is not null && !this.IsInLayout) - { - listener.Invalidate(); - _rootViewLayoutListener = null; - this.InvalidateMeasure(Modal); - } - }, this); + return; } - } - void UpdateMargin() - { - // This sets up the modal container to be offset from the top of window the same - // amount as the view it's covering. This will make it so the - // ModalContainer takes into account the StatusBar or lack thereof - var decorView = Context?.GetActivity()?.Window?.DecorView; - if (decorView is not null && this.LayoutParameters is ViewGroup.MarginLayoutParams mlp) + if (e.IsOneOf(Page.BackgroundColorProperty, Page.BackgroundProperty)) { - var windowInsets = ViewCompat.GetRootWindowInsets(decorView); - if (windowInsets is not null) - { - var barInsets = windowInsets.GetInsets(WindowInsetsCompat.Type.SystemBars()); - - if (mlp.TopMargin != barInsets.Top) - mlp.TopMargin = barInsets.Top; - - if (mlp.LeftMargin != barInsets.Left) - mlp.LeftMargin = barInsets.Left; - - if (mlp.RightMargin != barInsets.Right) - mlp.RightMargin = barInsets.Right; - - if (mlp.BottomMargin != barInsets.Bottom) - mlp.BottomMargin = barInsets.Bottom; - } + UpdateBackgroundColor(); } } - public override bool OnTouchEvent(MotionEvent? e) - { - // Don't let touch events pass through to the view being covered up - return true; - } - - protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) + void UpdateBackgroundColor() { - if (Context is null || NavigationRootManager?.RootView is null) + if (_modal is not IView view || view.Handler is not IPlatformViewHandler platformViewHandler) { - SetMeasuredDimension(0, 0); return; } - UpdateMargin(); - var rootView = GetWindowRootView(); + var pageView = platformViewHandler.PlatformView; - widthMeasureSpec = MeasureSpecMode.Exactly.MakeMeasureSpec(rootView.MeasuredWidth); - heightMeasureSpec = MeasureSpecMode.Exactly.MakeMeasureSpec(rootView.MeasuredHeight); - NavigationRootManager - .RootView - .Measure(widthMeasureSpec, heightMeasureSpec); + if (pageView is null) + return; - SetMeasuredDimension(rootView.MeasuredWidth, rootView.MeasuredHeight); + var modalBkgndColor = view.Background; + if (modalBkgndColor is null) + pageView.SetWindowBackground(); } - protected override void OnLayout(bool changed, int l, int t, int r, int b) + public override AView OnCreateView(LayoutInflater inflater, ViewGroup? container, Bundle? savedInstanceState) { - if (Context is null || NavigationRootManager?.RootView is null) - return; + var modalContext = _mauiWindowContext + .MakeScoped(layoutInflater: inflater, fragmentManager: ChildFragmentManager, registerNewNavigationRoot: true); - NavigationRootManager - .RootView - .Layout(0, 0, r - l, b - t); + _navigationRootManager = modalContext.GetNavigationRootManager(); + _navigationRootManager.Connect(_modal, modalContext); + + UpdateBackgroundColor(); - _backgroundView.Layout(0, 0, r - l, b - t); + return _navigationRootManager?.RootView ?? + throw new InvalidOperationException("Root view not initialized"); } - void OnModalPagePropertyChanged(object? sender, PropertyChangedEventArgs e) + public override void OnCreate(Bundle? savedInstanceState) { - if (e.PropertyName == Page.BackgroundColorProperty.PropertyName) - UpdateBackgroundColor(); + base.OnCreate(savedInstanceState); + SetStyle(DialogFragment.StyleNormal, Resource.Style.Maui_MainTheme_NoActionBar); } - void UpdateBackgroundColor() + public override void OnStart() { - if (Modal is null) - return; + base.OnStart(); - Color modalBkgndColor = Modal.BackgroundColor; - if (modalBkgndColor is null) - _backgroundView.SetWindowBackground(); - else - _backgroundView.SetBackgroundColor(modalBkgndColor.ToPlatform()); - } + var dialog = Dialog; - public void Destroy() - { - if (Modal is null || _windowMauiContext is null || _fragmentManager is null || !_fragmentManager.IsAlive() || _fragmentManager.IsDestroyed) + if (dialog is null || dialog.Window is null || View is null) return; - if (Modal.Toolbar?.Handler is not null) - Modal.Toolbar.Handler = null; + int width = ViewGroup.LayoutParams.MatchParent; + int height = ViewGroup.LayoutParams.MatchParent; + dialog.Window.SetLayout(width, height); - Modal.Handler = null; + if (IsAnimated) + { + var animation = AnimationUtils.LoadAnimation(_mauiWindowContext.Context, Resource.Animation.nav_modal_default_enter_anim)!; + View.StartAnimation(animation); - UpdateRootView(null); - _rootViewLayoutListener?.Invalidate(); - _rootViewLayoutListener = null; + animation.AnimationEnd += OnAnimationEnded; + } - if (_windowMauiContext.Context is not null) + void OnAnimationEnded(object? sender, AAnimation.AnimationEndEventArgs e) { - _fragmentManager.RunOrWaitForResume(_windowMauiContext.Context, fm => + if (sender is not AAnimation animation) { - fm - .BeginTransaction() - .Remove(_modalFragment) - .SetReorderingAllowed(true) - .Commit(); - }); + return; + } + + animation.AnimationEnd -= OnAnimationEnded; + FireAnimationEnded(); } + } - Modal = null; - _windowMauiContext = null; - _fragmentManager = null; - this.RemoveFromParent(); + public override void OnDismiss(IDialogInterface dialog) + { + _modal.PropertyChanged -= OnModalPagePropertyChanged; + _modal.HandlerChanged -= OnPageHandlerChanged; + + if (_modal.Toolbar?.Handler is not null) + { + _modal.Toolbar.Handler = null; + } + + _modal.Handler = null; + _modal = null!; + _mauiWindowContext = null!; + _navigationRootManager?.Disconnect(); + _navigationRootManager = null; + base.OnDismiss(dialog); } - class ModalFragment : Fragment + public override void OnDestroy() { - readonly Page _modal; - readonly IMauiContext _mauiWindowContext; - NavigationRootManager? _navigationRootManager; + base.OnDestroy(); + FireAnimationEnded(); + } - public NavigationRootManager? NavigationRootManager + void FireAnimationEnded() + { + if (!_pendingAnimation) { - get => _navigationRootManager; - private set => _navigationRootManager = value; + return; } - public ModalFragment(IMauiContext mauiContext, Page modal) + _pendingAnimation = false; + AnimationEnded?.Invoke(this, EventArgs.Empty); + } + + + sealed class CustomComponentDialog : ComponentDialog + { + public CustomComponentDialog(Context context, int themeResId) : base(context, themeResId) { - _modal = modal; - _mauiWindowContext = mauiContext; + this.OnBackPressedDispatcher.AddCallback(new CallBack(true, this)); } - public override AView OnCreateView(LayoutInflater inflater, ViewGroup? container, Bundle? savedInstanceState) + sealed class CallBack : OnBackPressedCallback { - var modalContext = _mauiWindowContext - .MakeScoped(layoutInflater: inflater, fragmentManager: ChildFragmentManager, registerNewNavigationRoot: true); + WeakReference _customComponentDialog; + + public CallBack(bool enabled, CustomComponentDialog customComponentDialog) : base(enabled) + { + _customComponentDialog = new(customComponentDialog); + } - _navigationRootManager = modalContext.GetNavigationRootManager(); - _navigationRootManager.Connect(_modal, modalContext); + public override void HandleOnBackPressed() + { + if (!_customComponentDialog.TryGetTarget(out var customComponentDialog) || + customComponentDialog.Context.GetActivity() is not global::Android.App.Activity activity) + { + return; + } - return _navigationRootManager?.RootView ?? - throw new InvalidOperationException("Root view not initialized"); + Window? window = activity.GetWindow() as Window; + EventHandler? eventHandler = null; + eventHandler = OnPopCanceled; + if (window is not null) + { + window.PopCanceled += eventHandler; + } + + var preventBackPropagation = false; + + try + { + IPlatformApplication.Current?.Services?.InvokeLifecycleEvents(del => + { + preventBackPropagation = del(activity) || preventBackPropagation; + }); + } + finally + { + if (window is not null && eventHandler is not null) + { + window.PopCanceled -= eventHandler; + } + } + + if (!preventBackPropagation) + { + customComponentDialog.OnBackPressedDispatcher.OnBackPressed(); + } + + eventHandler = null; + void OnPopCanceled(object? sender, EventArgs e) + { + preventBackPropagation = true; + if (window is not null && eventHandler is not null) + { + window.PopCanceled -= eventHandler; + } + } + } } } } diff --git a/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Windows.cs b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Windows.cs index a86d13e651bf..5d9405e54e2f 100644 --- a/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Windows.cs +++ b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Windows.cs @@ -71,6 +71,7 @@ void RemovePage(Page page, bool popping) page.Handler?.DisconnectHandler(); } + IDisposable? _waitingForIncomingPage; void SetCurrent( Page newPage, Page previousPage, @@ -79,6 +80,8 @@ void SetCurrent( { try { + _waitingForIncomingPage?.Dispose(); + if (popping) { RemovePage(previousPage, popping); @@ -108,7 +111,9 @@ void SetCurrent( wrv.SetTitleBarBackgroundToTransparent(false); } - windowManager.Connect(newPage.ToPlatform(modalContext)); + var platform = newPage.ToPlatform(modalContext); + _waitingForIncomingPage = platform.OnLoaded(() => completedCallback?.Invoke()); + windowManager.Connect(platform); Container.AddPage(windowManager.RootView); } // popping modal @@ -117,10 +122,10 @@ void SetCurrent( var windowManager = newPage.FindMauiContext()?.GetNavigationRootManager() ?? throw new InvalidOperationException("Previous Page Has Lost its MauiContext"); + var platform = newPage.ToPlatform(); + _waitingForIncomingPage = platform.OnLoaded(() => completedCallback?.Invoke()); Container.AddPage(windowManager.RootView); } - - completedCallback?.Invoke(); } catch (Exception error) when (error.HResult == -2147417842) { diff --git a/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.cs b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.cs index 04067f4eace0..16a4489cec0b 100644 --- a/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.cs +++ b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.cs @@ -193,11 +193,15 @@ async Task SyncPlatformModalStackAsync() } } + Task _waitForModalToFinishTask = Task.CompletedTask; + public async Task PopModalAsync(bool animated) { if (_modalPages.Count <= 0) throw new InvalidOperationException("PopModalAsync failed because modal stack is currently empty."); + await _waitForModalToFinishTask; + Page modal = _modalPages[_modalPages.Count - 1].Page; if (_window.OnModalPopping(modal)) @@ -239,7 +243,7 @@ async Task SyncPlatformModalStackAsync() if (FireLifeCycleEvents) { - modal.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage)); + modal.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage, NavigationType.Pop)); CurrentPage?.SendNavigatedTo(new NavigatedToEventArgs(modal)); } @@ -251,6 +255,8 @@ async Task SyncPlatformModalStackAsync() public async Task PushModalAsync(Page modal, bool animated) { + await _waitForModalToFinishTask; + _window.OnModalPushing(modal); var previousPage = CurrentPage; @@ -295,7 +301,7 @@ public async Task PushModalAsync(Page modal, bool animated) if (FireLifeCycleEvents) { - previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage)); + previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage, NavigationType.Push)); CurrentPage?.SendNavigatedTo(new NavigatedToEventArgs(previousPage)); } @@ -375,8 +381,7 @@ async Task SyncModalStackWhenPlatformIsReadyAsync() { await SyncPlatformModalStackAsync().ConfigureAwait(false); } - else if (_window.IsActivated && - _window?.Page?.Handler is not null) + else if (IsWindowReadyForModals) { if (CurrentPlatformPage.Handler is null) { @@ -390,14 +395,15 @@ async Task SyncModalStackWhenPlatformIsReadyAsync() // This accounts for cases where we swap the root page out // We want to wait for that to finish loading before processing any modal changes #if ANDROID - else if (!_window.Page.IsLoadedOnPlatform()) + else if (_window?.Page is not null && !_window.Page.IsLoadedOnPlatform()) { var windowPage = _window.Page; _platformPageWatchingForLoaded = windowPage.OnLoaded(() => OnCurrentPlatformPageLoaded(windowPage, EventArgs.Empty)); } #endif - else if (!CurrentPlatformPage.IsLoadedOnPlatform() && + + if (!CurrentPlatformPage.IsLoadedOnPlatform() && CurrentPlatformPage.Handler is not null) { var currentPlatformPage = CurrentPlatformPage; @@ -424,15 +430,22 @@ void OnCurrentPlatformPageLoaded(object? sender, EventArgs e) SyncPlatformModalStack(); } + bool IsWindowReadyForModals => + _window?.Page?.Handler is not null && +#if WINDOWS + _firstActivated; +#else + _window.IsActivated; +#endif + bool IsModalPlatformReady { get { bool result = - _window?.Page?.Handler is not null && - _window.IsActivated + IsWindowReadyForModals #if ANDROID - && _window.Page.IsLoadedOnPlatform() + && _window?.Page?.IsLoadedOnPlatform() == true #endif && CurrentPlatformPage?.Handler is not null && CurrentPlatformPage.IsLoadedOnPlatform(); diff --git a/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.iOS.cs b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.iOS.cs index 4ed90742c000..614083446df6 100644 --- a/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.iOS.cs +++ b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.iOS.cs @@ -95,7 +95,7 @@ async Task PopModalPlatformAsync(bool animated) return modal; } - // if the presnting VC is null that means the modal window was already dismissed + // if the presenting VC is null that means the modal window was already dismissed // this will usually happen as a result of swapping out the content on the window // which is what was acting as the PresentingViewController return modal; @@ -116,8 +116,10 @@ Task PushModalPlatformAsync(Page modal, bool animated) async Task PresentModal(Page modal, bool animated) { bool failed = false; + TaskCompletionSource presentFinished = new TaskCompletionSource(); try { + _waitForModalToFinishTask = presentFinished.Task; _waitForModalToFinish = true; var wrapper = new ControlsModalWrapper(modal.ToHandler(WindowMauiContext)); @@ -152,6 +154,7 @@ async Task PresentModal(Page modal, bool animated) finally { _waitForModalToFinish = false; + presentFinished.SetResult(); if (!failed) SyncModalStackWhenPlatformIsReady(); diff --git a/src/Controls/src/Core/Platform/Tizen/Extensions/ImageExtensions.cs b/src/Controls/src/Core/Platform/Tizen/Extensions/ImageExtensions.cs index b90c7ed5b90f..366409dab67a 100644 --- a/src/Controls/src/Core/Platform/Tizen/Extensions/ImageExtensions.cs +++ b/src/Controls/src/Core/Platform/Tizen/Extensions/ImageExtensions.cs @@ -64,7 +64,7 @@ static string GetPath(string res) return res; } - foreach (AppFW.ResourceManager.Category category in Enum.GetValues(typeof(AppFW.ResourceManager.Category))) + foreach (AppFW.ResourceManager.Category category in Enum.GetValues()) { foreach (var file in new[] { res, res + ".jpg", res + ".png", res + ".gif" }) { diff --git a/src/Controls/src/Core/Platform/Windows/CollectionView/FormsGridView.cs b/src/Controls/src/Core/Platform/Windows/CollectionView/FormsGridView.cs index 9e633e8e5a3f..b68b26dbdd4a 100644 --- a/src/Controls/src/Core/Platform/Windows/CollectionView/FormsGridView.cs +++ b/src/Controls/src/Core/Platform/Windows/CollectionView/FormsGridView.cs @@ -10,7 +10,7 @@ namespace Microsoft.Maui.Controls.Platform { - internal class FormsGridView : GridView, IEmptyView + internal partial class FormsGridView : GridView, IEmptyView { int _span; ItemsWrapGrid _wrapGrid; diff --git a/src/Controls/src/Core/Platform/Windows/CollectionView/GroupHeaderStyleSelector.cs b/src/Controls/src/Core/Platform/Windows/CollectionView/GroupHeaderStyleSelector.cs index b84271acea3d..7cbe9cb71527 100644 --- a/src/Controls/src/Core/Platform/Windows/CollectionView/GroupHeaderStyleSelector.cs +++ b/src/Controls/src/Core/Platform/Windows/CollectionView/GroupHeaderStyleSelector.cs @@ -5,7 +5,7 @@ namespace Microsoft.Maui.Controls.Platform { - internal class GroupHeaderStyleSelector : GroupStyleSelector + internal partial class GroupHeaderStyleSelector : GroupStyleSelector { protected override GroupStyle SelectGroupStyleCore(object group, uint level) { diff --git a/src/Controls/src/Core/Platform/Windows/CollectionView/ItemContentControl.cs b/src/Controls/src/Core/Platform/Windows/CollectionView/ItemContentControl.cs index 3d74c838a162..e099f3f545e7 100644 --- a/src/Controls/src/Core/Platform/Windows/CollectionView/ItemContentControl.cs +++ b/src/Controls/src/Core/Platform/Windows/CollectionView/ItemContentControl.cs @@ -10,7 +10,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class ItemContentControl : ContentControl + public partial class ItemContentControl : ContentControl { VisualElement _visualElement; IViewHandler _handler; @@ -320,7 +320,7 @@ double ClampInfinity(double value) internal VisualElement GetVisualElement() => _visualElement; - class ContentLayoutPanel : Panel + partial class ContentLayoutPanel : Panel { IView _view; public ContentLayoutPanel(IView view) diff --git a/src/Controls/src/Core/Platform/Windows/CollectionView/LoopableCollectionView.cs b/src/Controls/src/Core/Platform/Windows/CollectionView/LoopableCollectionView.cs index a43326a84188..5c4f6105438a 100644 --- a/src/Controls/src/Core/Platform/Windows/CollectionView/LoopableCollectionView.cs +++ b/src/Controls/src/Core/Platform/Windows/CollectionView/LoopableCollectionView.cs @@ -13,7 +13,7 @@ namespace Microsoft.Maui.Controls.Platform // items over and over again for a very long time; it's the best version of "looping" // we can manage until we replace the ListViewBase with something more flexible. - internal class LoopableCollectionView : ICollectionView + internal partial class LoopableCollectionView : ICollectionView { const int FakeCount = 655360; // 640k ought to be enough for anybody readonly ICollectionView _internal; diff --git a/src/Controls/src/Core/Platform/Windows/Extensions/FrameworkElementExtensions.cs b/src/Controls/src/Core/Platform/Windows/Extensions/FrameworkElementExtensions.cs deleted file mode 100644 index 4598d227ba9d..000000000000 --- a/src/Controls/src/Core/Platform/Windows/Extensions/FrameworkElementExtensions.cs +++ /dev/null @@ -1,98 +0,0 @@ -#nullable disable -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Microsoft.Maui.Controls.Internals; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; -using WBinding = Microsoft.UI.Xaml.Data.Binding; -using WBindingExpression = Microsoft.UI.Xaml.Data.BindingExpression; -using WBrush = Microsoft.UI.Xaml.Media.Brush; - -namespace Microsoft.Maui.Controls.Platform -{ - internal static class FrameworkElementExtensions - { - static readonly Lazy> ForegroundProperties = - new Lazy>(() => new ConcurrentDictionary()); - - public static WBrush GetForeground(this FrameworkElement element) - { - if (element == null) - throw new ArgumentNullException(nameof(element)); - - return (WBrush)element.GetValue(GetForegroundProperty(element)); - } - - public static WBinding GetForegroundBinding(this FrameworkElement element) - { - WBindingExpression expr = element.GetBindingExpression(GetForegroundProperty(element)); - if (expr == null) - return null; - - return expr.ParentBinding; - } - - public static object GetForegroundCache(this FrameworkElement element) - { - WBinding binding = GetForegroundBinding(element); - if (binding != null) - return binding; - - return GetForeground(element); - } - - public static void RestoreForegroundCache(this FrameworkElement element, object cache) - { - var binding = cache as WBinding; - if (binding != null) - SetForeground(element, binding); - else - SetForeground(element, (WBrush)cache); - } - - public static void SetForeground(this FrameworkElement element, WBrush foregroundBrush) - { - if (element == null) - throw new ArgumentNullException(nameof(element)); - - element.SetValue(GetForegroundProperty(element), foregroundBrush); - } - - public static void SetForeground(this FrameworkElement element, WBinding binding) - { - if (element == null) - throw new ArgumentNullException(nameof(element)); - - element.SetBinding(GetForegroundProperty(element), binding); - } - - static DependencyProperty GetForegroundProperty(FrameworkElement element) - { - if (element is Control) - return Control.ForegroundProperty; - if (element is TextBlock) - return TextBlock.ForegroundProperty; - - Type type = element.GetType(); - - DependencyProperty foregroundProperty; - if (!ForegroundProperties.Value.TryGetValue(type, out foregroundProperty)) - { - FieldInfo field = ReflectionExtensions.GetFields(type).FirstOrDefault(f => f.Name == "ForegroundProperty"); - if (field == null) - throw new ArgumentException("type is not a Foregroundable type"); - - var property = (DependencyProperty)field.GetValue(null); - ForegroundProperties.Value.TryAdd(type, property); - - return property; - } - - return foregroundProperty; - } - } -} \ No newline at end of file diff --git a/src/Controls/src/Core/Platform/Windows/FormsListView.cs b/src/Controls/src/Core/Platform/Windows/FormsListView.cs index efffcadcb78f..bc8ae30f5222 100644 --- a/src/Controls/src/Core/Platform/Windows/FormsListView.cs +++ b/src/Controls/src/Core/Platform/Windows/FormsListView.cs @@ -10,7 +10,7 @@ namespace Microsoft.Maui.Controls.Platform { - internal class FormsListView : Microsoft.UI.Xaml.Controls.ListView, IEmptyView + internal partial class FormsListView : Microsoft.UI.Xaml.Controls.ListView, IEmptyView { ContentControl _emptyViewContentControl; FrameworkElement _emptyView; diff --git a/src/Controls/src/Core/Platform/Windows/IconConverter.cs b/src/Controls/src/Core/Platform/Windows/IconConverter.cs index 1901ea20ec73..f8d892d62abf 100644 --- a/src/Controls/src/Core/Platform/Windows/IconConverter.cs +++ b/src/Controls/src/Core/Platform/Windows/IconConverter.cs @@ -5,7 +5,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class IconConverter : Microsoft.UI.Xaml.Data.IValueConverter + public partial class IconConverter : Microsoft.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/src/Controls/src/Core/Platform/Windows/ImageConverter.cs b/src/Controls/src/Core/Platform/Windows/ImageConverter.cs index f44b9b64b417..1dd5d245a4fa 100644 --- a/src/Controls/src/Core/Platform/Windows/ImageConverter.cs +++ b/src/Controls/src/Core/Platform/Windows/ImageConverter.cs @@ -6,7 +6,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class ImageConverter : Microsoft.UI.Xaml.Data.IValueConverter + public partial class ImageConverter : Microsoft.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/src/Controls/src/Core/Platform/Windows/ImageSourceIconElementConverter.cs b/src/Controls/src/Core/Platform/Windows/ImageSourceIconElementConverter.cs index 36f39792482d..f641e4bce171 100644 --- a/src/Controls/src/Core/Platform/Windows/ImageSourceIconElementConverter.cs +++ b/src/Controls/src/Core/Platform/Windows/ImageSourceIconElementConverter.cs @@ -3,7 +3,7 @@ namespace Microsoft.Maui.Controls.Platform { - internal class ImageSourceIconElementConverter : Microsoft.UI.Xaml.Data.IValueConverter + internal partial class ImageSourceIconElementConverter : Microsoft.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/src/Controls/src/Core/Platform/Windows/MauiCommandBar.cs b/src/Controls/src/Core/Platform/Windows/MauiCommandBar.cs index ee97e8c3f200..6ec427adebcb 100644 --- a/src/Controls/src/Core/Platform/Windows/MauiCommandBar.cs +++ b/src/Controls/src/Core/Platform/Windows/MauiCommandBar.cs @@ -9,7 +9,7 @@ namespace Microsoft.Maui.Controls.Platform { - public class MauiCommandBar : CommandBar + public partial class MauiCommandBar : CommandBar { Microsoft.UI.Xaml.Controls.Button _moreButton; Microsoft.UI.Xaml.Controls.ItemsControl _primaryItemsControl; diff --git a/src/Controls/src/Core/Platform/Windows/MauiPresenter.cs b/src/Controls/src/Core/Platform/Windows/MauiPresenter.cs index 3dd9a7e9880f..76582e399d6b 100644 --- a/src/Controls/src/Core/Platform/Windows/MauiPresenter.cs +++ b/src/Controls/src/Core/Platform/Windows/MauiPresenter.cs @@ -6,7 +6,7 @@ namespace Microsoft.Maui.Controls.Platform { - internal class MauiPresenter : Microsoft.UI.Xaml.Controls.ContentPresenter + internal partial class MauiPresenter : Microsoft.UI.Xaml.Controls.ContentPresenter { public MauiPresenter() { diff --git a/src/Controls/src/Core/Platform/Windows/PageControl.cs b/src/Controls/src/Core/Platform/Windows/PageControl.cs index 03de31038836..0e8e399bb6fc 100644 --- a/src/Controls/src/Core/Platform/Windows/PageControl.cs +++ b/src/Controls/src/Core/Platform/Windows/PageControl.cs @@ -9,7 +9,7 @@ namespace Microsoft.Maui.Controls.Platform { - public sealed class PageControl : ContentControl, IToolbarProvider, ITitleViewRendererController + public sealed partial class PageControl : ContentControl, IToolbarProvider, ITitleViewRendererController { public static readonly DependencyProperty TitleVisibilityProperty = DependencyProperty.Register(nameof(TitleVisibility), typeof(WVisibility), typeof(PageControl), new PropertyMetadata(WVisibility.Visible)); diff --git a/src/Controls/src/Core/PlatformBindingHelpers.cs b/src/Controls/src/Core/PlatformBindingHelpers.cs index a9f04355e5e6..d3444129ff15 100644 --- a/src/Controls/src/Core/PlatformBindingHelpers.cs +++ b/src/Controls/src/Core/PlatformBindingHelpers.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; @@ -14,6 +15,7 @@ namespace Microsoft.Maui.Controls.Internals /// internal static class PlatformBindingHelpers { + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public static void SetBinding(TPlatformView target, string targetProperty, BindingBase bindingBase, string updateSourceEventName = null) where TPlatformView : class { var binding = bindingBase as Binding; @@ -22,11 +24,12 @@ public static void SetBinding(TPlatformView target, string target updateSourceEventName = binding.UpdateSourceEventName; INotifyPropertyChanged eventWrapper = null; if (!IsNullOrEmpty(updateSourceEventName)) - eventWrapper = new EventWrapper(target, targetProperty, updateSourceEventName); + eventWrapper = new EventWrapper(target, targetProperty, updateSourceEventName); SetBinding(target, targetProperty, bindingBase, eventWrapper); } + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public static void SetBinding(TPlatformView target, string targetProperty, BindingBase bindingBase, INotifyPropertyChanged propertyChanged) where TPlatformView : class { if (target == null) @@ -41,13 +44,13 @@ public static void SetBinding(TPlatformView target, string target var targetPropertyInfo = target.GetType().GetProperty(targetProperty); var propertyType = targetPropertyInfo?.PropertyType; var defaultValue = targetPropertyInfo?.GetMethod.Invoke(target, Array.Empty()); - bindableProperty = CreateBindableProperty(targetProperty, propertyType, defaultValue); + bindableProperty = CreateBindableProperty(targetProperty, propertyType, defaultValue); if (binding != null && binding.Mode != BindingMode.OneWay && propertyChanged != null) propertyChanged.PropertyChanged += (sender, e) => { if (e.PropertyName != targetProperty) return; - SetValueFromNative(sender as TPlatformView, targetProperty, bindableProperty); + SetValueFromNative(sender as TPlatformView, targetProperty, bindableProperty); //we need to keep the listener around he same time we have the proxy proxy.NativeINPCListener = propertyChanged; }; @@ -56,46 +59,46 @@ public static void SetBinding(TPlatformView target, string target SetValueFromNative(target, targetProperty, bindableProperty); proxy.SetBinding(bindableProperty, bindingBase); - } - static BindableProperty CreateBindableProperty(string targetProperty, Type propertyType = null, object defaultValue = null) where TPlatformView : class - { - propertyType = propertyType ?? typeof(object); - defaultValue = defaultValue ?? (propertyType.IsValueType ? Activator.CreateInstance(propertyType) : null); - return BindableProperty.Create( - targetProperty, - propertyType, - typeof(BindableObjectProxy), - defaultValue: defaultValue, - defaultBindingMode: BindingMode.Default, - propertyChanged: (bindable, oldValue, newValue) => - { - TPlatformView platformView; - if ((bindable as BindableObjectProxy).TargetReference.TryGetTarget(out platformView)) - SetPlatformValue(platformView, targetProperty, newValue); - } - ); - } + static BindableProperty CreateBindableProperty(string targetProperty, Type propertyType = null, object defaultValue = null) + { + propertyType = propertyType ?? typeof(object); + defaultValue = defaultValue ?? (propertyType.IsValueType ? Activator.CreateInstance(propertyType) : null); + return BindableProperty.Create( + targetProperty, + propertyType, + typeof(BindableObjectProxy), + defaultValue: defaultValue, + defaultBindingMode: BindingMode.Default, + propertyChanged: (bindable, oldValue, newValue) => + { + TPlatformView platformView; + if ((bindable as BindableObjectProxy).TargetReference.TryGetTarget(out platformView)) + SetPlatformValue(platformView, targetProperty, newValue); + } + ); + } - static void SetPlatformValue(TPlatformView target, string targetProperty, object newValue) where TPlatformView : class - { - var mi = target.GetType().GetProperty(targetProperty)?.SetMethod; - if (mi == null) - throw new InvalidOperationException(Format("Native Binding on {0}.{1} failed due to missing or inaccessible property", target.GetType(), targetProperty)); - mi.Invoke(target, new[] { newValue }); - } + static void SetPlatformValue(TPlatformView target, string targetProperty, object newValue) + { + var mi = target.GetType().GetProperty(targetProperty)?.SetMethod; + if (mi == null) + throw new InvalidOperationException(Format("Native Binding on {0}.{1} failed due to missing or inaccessible property", target.GetType(), targetProperty)); + mi.Invoke(target, new[] { newValue }); + } - static void SetValueFromNative(TPlatformView target, string targetProperty, BindableProperty bindableProperty) where TPlatformView : class - { - BindableObjectProxy proxy; - if (!BindableObjectProxy.BindableObjectProxies.TryGetValue(target, out proxy)) - return; - SetValueFromRenderer(proxy, bindableProperty, target.GetType().GetProperty(targetProperty)?.GetMethod.Invoke(target, Array.Empty())); - } + static void SetValueFromNative(TPlatformView target, string targetProperty, BindableProperty bindableProperty) + { + BindableObjectProxy proxy; + if (!BindableObjectProxy.BindableObjectProxies.TryGetValue(target, out proxy)) + return; + SetValueFromRenderer(proxy, bindableProperty, target.GetType().GetProperty(targetProperty)?.GetMethod.Invoke(target, Array.Empty())); + } - static void SetValueFromRenderer(BindableObject bindable, BindableProperty property, object value) - { - bindable.SetValue(property, value); + static void SetValueFromRenderer(BindableObject bindable, BindableProperty property, object value) + { + bindable.SetValue(property, value); + } } public static void SetBinding(TPlatformView target, BindableProperty targetProperty, BindingBase binding) where TPlatformView : class @@ -149,20 +152,19 @@ public static void TransferBindablePropertiesToWrapper : INotifyPropertyChanged { string TargetProperty { get; set; } - static readonly MethodInfo s_handlerinfo = typeof(EventWrapper).GetRuntimeMethods().Single(mi => mi.Name == "OnPropertyChanged" && mi.IsPublic == false); - public EventWrapper(object target, string targetProperty, string updateSourceEventName) + public EventWrapper(TTarget target, string targetProperty, string updateSourceEventName) { TargetProperty = targetProperty; Delegate handlerDelegate = null; EventInfo updateSourceEvent = null; try { - updateSourceEvent = target.GetType().GetRuntimeEvent(updateSourceEventName); - handlerDelegate = s_handlerinfo.CreateDelegate(updateSourceEvent.EventHandlerType, this); + updateSourceEvent = typeof(TTarget).GetRuntimeEvent(updateSourceEventName); + handlerDelegate = ((EventHandler)OnPropertyChanged).Method.CreateDelegate(updateSourceEvent.EventHandlerType, this); } catch (Exception) { diff --git a/src/Controls/src/Core/Properties/AssemblyInfo.cs b/src/Controls/src/Core/Properties/AssemblyInfo.cs index e255921fe828..6b85c51555f6 100644 --- a/src/Controls/src/Core/Properties/AssemblyInfo.cs +++ b/src/Controls/src/Core/Properties/AssemblyInfo.cs @@ -16,6 +16,7 @@ [assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Android.UnitTests")] [assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Compatibility.Android.UnitTests")] [assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Compatibility.UAP.UnitTests")] +[assembly: InternalsVisibleTo("Microsoft.Maui.Compatibility.Core.UnitTests")] [assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Xaml")] [assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Compatibility.Maps")] [assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Compatibility.Maps.iOS")] @@ -86,7 +87,9 @@ [assembly: StyleProperty("border-color", typeof(IBorderElement), nameof(BorderElement.BorderColorProperty))] [assembly: StyleProperty("border-radius", typeof(ICornerElement), nameof(CornerElement.CornerRadiusProperty))] [assembly: StyleProperty("border-radius", typeof(Button), nameof(Button.CornerRadiusProperty))] +#pragma warning disable CS0618 // Type or member is obsolete [assembly: StyleProperty("border-radius", typeof(Frame), nameof(Frame.CornerRadiusProperty))] +#pragma warning restore CS0618 // Type or member is obsolete [assembly: StyleProperty("border-radius", typeof(ImageButton), nameof(BorderElement.CornerRadiusProperty))] [assembly: StyleProperty("border-width", typeof(IBorderElement), nameof(BorderElement.BorderWidthProperty))] [assembly: StyleProperty("color", typeof(IColorElement), nameof(ColorElement.ColorProperty), Inherited = true)] diff --git a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt index 7dc5c58110bf..a8ee9da554ec 100644 --- a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt @@ -1 +1,148 @@ #nullable enable +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.get -> Microsoft.Maui.Controls.Style +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.set -> void +~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource(System.Uri value) -> void +*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +~Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.PlatformArgs.get -> Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[] +~override Microsoft.Maui.Controls.ShellContent.OnPropertyChanged(string propertyName = null) -> void +*REMOVED*~static Microsoft.Maui.Controls.Application.ControlsApplicationMapper -> Microsoft.Maui.IPropertyMapper +~static Microsoft.Maui.Controls.Brush.DarkGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DarkSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DimGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.Grey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.SlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +*REMOVED*~static Microsoft.Maui.Controls.Button.ControlsButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.DatePicker.ControlsDatePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Editor.ControlsEditorMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Element.ControlsElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Entry.ControlsEntryMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Label.ControlsLabelMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Layout.ControlsLayoutMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.NavigationPage.ControlsNavigationPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Picker.ControlsPickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RadioButton.ControlsRadioButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RefreshView.ControlsRefreshViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.ScrollView.ControlsScrollViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.SearchBar.ControlsSearchBarMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Shapes.Shape.ControlsShapeViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TabbedPage.ControlsTabbedPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TimePicker.ControlsTimePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.VisualElement.ControlsVisualElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.WebView.ControlsWebViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Window.ControlsWindowMapper -> Microsoft.Maui.IPropertyMapper +~static readonly Microsoft.Maui.Controls.BaseShellItem.FlyoutItemIsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty +const Microsoft.Maui.Controls.TitleBar.ContentHiddenState = "ContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.ContentVisibleState = "ContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.IconHiddenState = "IconCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.IconVisibleState = "IconVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingHiddenState = "LeadingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingVisibleState = "LeadingContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleHiddenState = "SubTitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleVisibleState = "SubtitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TemplateRootName = "PART_Root" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarActiveState = "TitleBarTitleActive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarContent = "PART_Content" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarIcon = "PART_Icon" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarInactiveState = "TitleBarTitleInactive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarLeading = "PART_LeadingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarSubtitle = "PART_Subtitle" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTitle = "PART_Title" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTrailing = "PART_TrailingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleHiddenState = "TitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleVisibleState = "TitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingHiddenState = "TrailingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingVisibleState = "TrailingContentVisible" -> string! +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.HandlerProperties +Microsoft.Maui.Controls.HybridWebView +Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string? +Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void +Microsoft.Maui.Controls.HybridWebView.EvaluateJavaScriptAsync(string! script) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string? +Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void +Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void +Microsoft.Maui.Controls.HybridWebView.InvokeJavaScriptAsync(string! methodName, System.Text.Json.Serialization.Metadata.JsonTypeInfo! returnTypeJsonTypeInfo, object?[]? paramValues = null, System.Text.Json.Serialization.Metadata.JsonTypeInfo?[]? paramJsonTypeInfos = null) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler? +Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string? +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs.RenderProcessGoneDetail.get -> Android.Webkit.RenderProcessGoneDetail? +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs.Sender.get -> Android.Views.View? +Microsoft.Maui.Controls.StyleableElement +Microsoft.Maui.Controls.StyleableElement.class.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.class.set -> void +Microsoft.Maui.Controls.StyleableElement.Style.get -> Microsoft.Maui.Controls.Style! +Microsoft.Maui.Controls.StyleableElement.Style.set -> void +Microsoft.Maui.Controls.StyleableElement.StyleableElement() -> void +Microsoft.Maui.Controls.StyleableElement.StyleClass.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.StyleClass.set -> void +Microsoft.Maui.Controls.TimeChangedEventArgs +Microsoft.Maui.Controls.TimeChangedEventArgs.NewTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void +Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler +Microsoft.Maui.Controls.TitleBar +Microsoft.Maui.Controls.TitleBar.Content.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.Content.set -> void +Microsoft.Maui.Controls.TitleBar.ForegroundColor.get -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Controls.TitleBar.ForegroundColor.set -> void +Microsoft.Maui.Controls.TitleBar.Icon.get -> Microsoft.Maui.Controls.ImageSource! +Microsoft.Maui.Controls.TitleBar.Icon.set -> void +Microsoft.Maui.Controls.TitleBar.LeadingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.LeadingContent.set -> void +Microsoft.Maui.Controls.TitleBar.PassthroughElements.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.TitleBar.Subtitle.get -> string! +Microsoft.Maui.Controls.TitleBar.Subtitle.set -> void +Microsoft.Maui.Controls.TitleBar.Title.get -> string! +Microsoft.Maui.Controls.TitleBar.Title.set -> void +Microsoft.Maui.Controls.TitleBar.TitleBar() -> void +Microsoft.Maui.Controls.TitleBar.TrailingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.TrailingContent.set -> void +Microsoft.Maui.Controls.VisualElement.Measure(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size +Microsoft.Maui.Controls.WebView.ProcessTerminated -> System.EventHandler +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.WebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.Window.TitleBar.get -> Microsoft.Maui.ITitleBar? +Microsoft.Maui.Controls.Window.TitleBar.set -> void +Microsoft.Maui.Controls.Xaml.RequireServiceAttribute +override Microsoft.Maui.Controls.ContentPage.LayoutChildren(double x, double y, double width, double height) -> void +*REMOVED*override Microsoft.Maui.Controls.Layout.Measure(double widthConstraint, double heightConstraint, Microsoft.Maui.Controls.MeasureFlags flags = Microsoft.Maui.Controls.MeasureFlags.None) -> Microsoft.Maui.SizeRequest +override Microsoft.Maui.Controls.TitleBar.OnApplyTemplate() -> void +static Microsoft.Maui.Controls.BindableObjectExtensions.SetBinding(this Microsoft.Maui.Controls.BindableObject! self, Microsoft.Maui.Controls.BindableProperty! targetProperty, System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> void +static Microsoft.Maui.Controls.BindingBase.Create(System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> Microsoft.Maui.Controls.BindingBase! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.CreateEmbeddedWindowContext(this Microsoft.Maui.Hosting.MauiApp! mauiApp, Android.App.Activity! platformWindow) -> Microsoft.Maui.IMauiContext! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.ToPlatformEmbedded(this Microsoft.Maui.IElement! element, Microsoft.Maui.Hosting.MauiApp! mauiApp, Android.App.Activity! platformWindow) -> Android.Views.View! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.ToPlatformEmbedded(this Microsoft.Maui.IElement! element, Microsoft.Maui.IMauiContext! context) -> Android.Views.View! +*REMOVED*static Microsoft.Maui.Controls.FlyoutPage.ControlsFlyoutPageMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.HandlerProperties.GetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target) -> Microsoft.Maui.HandlerDisconnectPolicy +static Microsoft.Maui.Controls.HandlerProperties.SetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target, Microsoft.Maui.HandlerDisconnectPolicy value) -> void +static Microsoft.Maui.Controls.TitleBar.DefaultTemplate.get -> Microsoft.Maui.Controls.ControlTemplate! +*REMOVED*static Microsoft.Maui.Controls.Toolbar.ControlsToolbarMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.ViewExtensions.InvalidateMeasure(this Microsoft.Maui.Controls.VisualElement! view) -> void +static readonly Microsoft.Maui.Controls.HandlerProperties.DisconnectPolicyProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.StyleableElement.StyleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ForegroundColorProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.IconProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.LeadingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.SubtitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TrailingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.Window.TitleBarProperty -> Microsoft.Maui.Controls.BindableProperty! +virtual Microsoft.Maui.Controls.Application.ActivateWindow(Microsoft.Maui.Controls.Window! window) -> void diff --git a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt index f8ec2fad5146..4608b2ad1ff2 100644 --- a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt @@ -1,2 +1,341 @@ #nullable enable +~abstract Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.CreateController(TItemsView newElement, UIKit.UICollectionViewLayout layout) -> Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2 +~abstract Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.SelectLayout() -> UIKit.UICollectionViewLayout +*REMOVED*~Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.ShellScrollViewTracker(Microsoft.Maui.IPlatformViewHandler renderer) -> void +~Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.CarouselViewController2(Microsoft.Maui.Controls.CarouselView itemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.CarouselViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2 ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.CarouselViewHandler2(Microsoft.Maui.PropertyMapper mapper = null) -> void +~Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.CollectionViewHandler2(Microsoft.Maui.PropertyMapper mapper = null) -> void +~Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2.Constraint.get -> UIKit.NSLayoutConstraint +~Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2.Constraint.set -> void +~Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2.Label.get -> UIKit.UILabel +~Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.GroupableItemsViewController2(TItemsView groupableItemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewDelegator2 +~Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewDelegator2.GroupableItemsViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewCell2.InitializeContentConstraints(UIKit.UIView platformView) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.Delegator.get -> UIKit.UICollectionViewDelegateFlowLayout +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.Delegator.set -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.GetItemAtIndex(Foundation.NSIndexPath index) -> object +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsSource.get -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsSource.set -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsView.get -> TItemsView +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsViewController2(TItemsView itemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsViewLayout.get -> UIKit.UICollectionViewLayout +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsViewLayout.set -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.UpdateLayout(UIKit.UICollectionViewLayout newLayout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2 +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.ItemsViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.ItemsViewLayout.get -> UIKit.UICollectionViewLayout +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.ViewController.get -> TViewController +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.Controller.get -> Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.IsIndexPathValid(Foundation.NSIndexPath indexPath) -> bool +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ItemsView.get -> TItemsView +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ItemsViewHandler2(Microsoft.Maui.PropertyMapper mapper = null) -> void +~Microsoft.Maui.Controls.Handlers.Items2.LayoutAttributesChangedEventArgs2.LayoutAttributesChangedEventArgs2(UIKit.UICollectionViewLayoutAttributes newAttributes) -> void +~Microsoft.Maui.Controls.Handlers.Items2.LayoutAttributesChangedEventArgs2.NewAttributes.get -> UIKit.UICollectionViewLayoutAttributes +~Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.ReorderableItemsViewController2(TItemsView reorderableItemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewDelegator2 +~Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewDelegator2.ReorderableItemsViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2.SelectableItemsViewController2(TItemsView selectableItemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewDelegator2 +~Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewDelegator2.SelectableItemsViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.StructuredItemsViewController2(TItemsView structuredItemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.Bind(Microsoft.Maui.Controls.DataTemplate template, object bindingContext, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.Bind(Microsoft.Maui.Controls.View virtualView, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.CurrentTemplate.get -> Microsoft.Maui.Controls.DataTemplate +~Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.OnLayoutAttributesChanged(UIKit.UICollectionViewLayoutAttributes newAttributes) -> void +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.get -> Microsoft.Maui.Controls.Style +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.set -> void +~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource(System.Uri value) -> void +*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +~Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.PlatformArgs.get -> Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[] +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.CreateItemsViewSource() -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.DetermineCellReuseId(Foundation.NSIndexPath indexPath) -> string +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.DraggingEnded(UIKit.UIScrollView scrollView, bool willDecelerate) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.DraggingStarted(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.GetCell(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> UIKit.UICollectionViewCell +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.GetItemsCount(UIKit.UICollectionView collectionView, nint section) -> nint +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.DecelerationEnded(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.DraggingEnded(UIKit.UIScrollView scrollView, bool willDecelerate) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.DraggingStarted(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.ScrollAnimationEnded(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.Scrolled(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.CreateController(Microsoft.Maui.Controls.CarouselView newElement, UIKit.UICollectionViewLayout layout) -> Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2 +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.ScrollToRequested(object sender, Microsoft.Maui.Controls.ScrollToRequestEventArgs args) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.SelectLayout() -> UIKit.UICollectionViewLayout +~override Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.CreateController(Microsoft.Maui.Controls.ReorderableItemsView itemsView, UIKit.UICollectionViewLayout layout) -> Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2 +~override Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.ScrollToRequested(object sender, Microsoft.Maui.Controls.ScrollToRequestEventArgs args) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.SelectLayout() -> UIKit.UICollectionViewLayout +~override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.CreateItemsViewSource() -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.GetViewForSupplementaryElement(UIKit.UICollectionView collectionView, Foundation.NSString elementKind, Foundation.NSIndexPath indexPath) -> UIKit.UICollectionReusableView +~override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewDelegator2.ScrollAnimationEnded(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.GetCell(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> UIKit.UICollectionViewCell +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.GetItemsCount(UIKit.UICollectionView collectionView, nint section) -> nint +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.NumberOfSections(UIKit.UICollectionView collectionView) -> nint +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.CellDisplayingEnded(UIKit.UICollectionView collectionView, UIKit.UICollectionViewCell cell, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetInsetForSection(UIKit.UICollectionView collectionView, UIKit.UICollectionViewLayout layout, nint section) -> UIKit.UIEdgeInsets +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetMinimumInteritemSpacingForSection(UIKit.UICollectionView collectionView, UIKit.UICollectionViewLayout layout, nint section) -> System.Runtime.InteropServices.NFloat +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetMinimumLineSpacingForSection(UIKit.UICollectionView collectionView, UIKit.UICollectionViewLayout layout, nint section) -> System.Runtime.InteropServices.NFloat +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.Scrolled(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ConnectHandler(UIKit.UIView platformView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.CreatePlatformView() -> UIKit.UIView +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.DisconnectHandler(UIKit.UIView platformView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.CanMoveItem(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> bool +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.CreateItemsViewSource() -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.MoveItem(UIKit.UICollectionView collectionView, Foundation.NSIndexPath sourceIndexPath, Foundation.NSIndexPath destinationIndexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewDelegator2.GetTargetIndexPathForMove(UIKit.UICollectionView collectionView, Foundation.NSIndexPath originalIndexPath, Foundation.NSIndexPath proposedIndexPath) -> Foundation.NSIndexPath +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2.ItemDeselected(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2.ItemSelected(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewDelegator2.ItemDeselected(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewDelegator2.ItemSelected(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.GetViewForSupplementaryElement(UIKit.UICollectionView collectionView, Foundation.NSString elementKind, Foundation.NSIndexPath indexPath) -> UIKit.UICollectionReusableView +~override Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.PreferredLayoutAttributesFittingAttributes(UIKit.UICollectionViewLayoutAttributes layoutAttributes) -> UIKit.UICollectionViewLayoutAttributes +~override Microsoft.Maui.Controls.ShellContent.OnPropertyChanged(string propertyName = null) -> void +*REMOVED*~static Microsoft.Maui.Controls.Application.ControlsApplicationMapper -> Microsoft.Maui.IPropertyMapper +~static Microsoft.Maui.Controls.Brush.DarkGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DarkSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DimGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.Grey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.SlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +*REMOVED*~static Microsoft.Maui.Controls.Button.ControlsButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.DatePicker.ControlsDatePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Editor.ControlsEditorMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Element.ControlsElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Entry.ControlsEntryMapper -> Microsoft.Maui.IPropertyMapper +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapCurrentItem(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapIsBounceEnabled(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapIsSwipeEnabled(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapLoop(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapPeekAreaInsets(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.Mapper -> Microsoft.Maui.PropertyMapper +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapPosition(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapCanReorderItems(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.ReorderableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapFooterTemplate(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.StructuredItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapHeaderTemplate(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.StructuredItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapIsGrouped(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.GroupableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapItemSizingStrategy(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.StructuredItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapItemsLayout(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.StructuredItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapItemsSource(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.SelectableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.Mapper -> Microsoft.Maui.PropertyMapper +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapSelectedItem(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.SelectableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapSelectedItems(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.SelectableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapSelectionMode(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.SelectableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ItemsViewMapper -> Microsoft.Maui.PropertyMapper> +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapEmptyView(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapEmptyViewTemplate(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapFlowDirection(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapHorizontalScrollBarVisibility(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapIsVisible(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapItemsSource(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapItemsUpdatingScrollMode(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapItemTemplate(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapVerticalScrollBarVisibility(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +*REMOVED*~static Microsoft.Maui.Controls.Label.ControlsLabelMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Layout.ControlsLayoutMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.NavigationPage.ControlsNavigationPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Picker.ControlsPickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RadioButton.ControlsRadioButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RefreshView.ControlsRefreshViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.ScrollView.ControlsScrollViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.SearchBar.ControlsSearchBarMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Shapes.Shape.ControlsShapeViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TabbedPage.ControlsTabbedPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TimePicker.ControlsTimePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.VisualElement.ControlsVisualElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.WebView.ControlsWebViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Window.ControlsWindowMapper -> Microsoft.Maui.IPropertyMapper +~static readonly Microsoft.Maui.Controls.BaseShellItem.FlyoutItemIsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.CreateItemsViewSource() -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.DetermineCellReuseId(Foundation.NSIndexPath indexPath) -> string +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.GetIndexForItem(object item) -> Foundation.NSIndexPath +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetVisibleItemsIndexPath() -> (bool VisibleItems, Foundation.NSIndexPath First, Foundation.NSIndexPath Center, Foundation.NSIndexPath Last) +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ScrollToRequested(object sender, Microsoft.Maui.Controls.ScrollToRequestEventArgs args) -> void +abstract Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.IsHorizontal.get -> bool +const Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.EmptyTag = 333 -> int +const Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.FooterTag = 222 -> int +const Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.HeaderTag = 111 -> int +const Microsoft.Maui.Controls.TitleBar.ContentHiddenState = "ContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.ContentVisibleState = "ContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.IconHiddenState = "IconCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.IconVisibleState = "IconVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingHiddenState = "LeadingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingVisibleState = "LeadingContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleHiddenState = "SubTitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleVisibleState = "SubtitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TemplateRootName = "PART_Root" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarActiveState = "TitleBarTitleActive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarContent = "PART_Content" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarIcon = "PART_Icon" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarInactiveState = "TitleBarTitleInactive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarLeading = "PART_LeadingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarSubtitle = "PART_Subtitle" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTitle = "PART_Title" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTrailing = "PART_TrailingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleHiddenState = "TitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleVisibleState = "TitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingHiddenState = "TrailingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingVisibleState = "TrailingContentVisible" -> string! +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.HandlerProperties +*REMOVED*Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker +*REMOVED*Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.Dispose() -> void +*REMOVED*Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.OnLayoutSubviews() -> void +*REMOVED*Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.Reset() -> bool +Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2 +Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2 +Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 +Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.CarouselViewHandler2() -> void +Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 +Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.CollectionViewHandler2() -> void +Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2 +Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2.DefaultCell2(CoreGraphics.CGRect frame) -> void +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewCell2 +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewCell2.ItemsViewCell2(CoreGraphics.CGRect frame) -> void +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ScrollDirection.get -> UIKit.UICollectionViewScrollDirection +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.PreviousHorizontalOffset -> float +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.PreviousVerticalOffset -> float +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ItemsViewHandler2() -> void +Microsoft.Maui.Controls.Handlers.Items2.LayoutAttributesChangedEventArgs2 +Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.UpdateCanReorderItems() -> void +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2 +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ConstrainedDimension -> System.Runtime.InteropServices.NFloat +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ConstrainedSize -> CoreGraphics.CGSize +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ContentSizeChanged -> System.EventHandler +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.LayoutAttributesChanged -> System.EventHandler +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.OnContentSizeChanged() -> void +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ScrollDirection.get -> UIKit.UICollectionViewScrollDirection +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ScrollDirection.set -> void +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.TemplatedCell2(CoreGraphics.CGRect frame) -> void +Microsoft.Maui.Controls.HybridWebView +Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string? +Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void +Microsoft.Maui.Controls.HybridWebView.EvaluateJavaScriptAsync(string! script) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string? +Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void +Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void +Microsoft.Maui.Controls.HybridWebView.InvokeJavaScriptAsync(string! methodName, System.Text.Json.Serialization.Metadata.JsonTypeInfo! returnTypeJsonTypeInfo, object?[]? paramValues = null, System.Text.Json.Serialization.Metadata.JsonTypeInfo?[]? paramJsonTypeInfos = null) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler? +Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string? +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs.Sender.get -> WebKit.WKWebView! +Microsoft.Maui.Controls.StyleableElement +Microsoft.Maui.Controls.StyleableElement.class.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.class.set -> void +Microsoft.Maui.Controls.StyleableElement.Style.get -> Microsoft.Maui.Controls.Style! +Microsoft.Maui.Controls.StyleableElement.Style.set -> void +Microsoft.Maui.Controls.StyleableElement.StyleableElement() -> void +Microsoft.Maui.Controls.StyleableElement.StyleClass.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.StyleClass.set -> void +Microsoft.Maui.Controls.TimeChangedEventArgs +Microsoft.Maui.Controls.TimeChangedEventArgs.NewTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void +Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler +Microsoft.Maui.Controls.TitleBar +Microsoft.Maui.Controls.TitleBar.Content.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.Content.set -> void +Microsoft.Maui.Controls.TitleBar.ForegroundColor.get -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Controls.TitleBar.ForegroundColor.set -> void +Microsoft.Maui.Controls.TitleBar.Icon.get -> Microsoft.Maui.Controls.ImageSource! +Microsoft.Maui.Controls.TitleBar.Icon.set -> void +Microsoft.Maui.Controls.TitleBar.LeadingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.LeadingContent.set -> void +Microsoft.Maui.Controls.TitleBar.PassthroughElements.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.TitleBar.Subtitle.get -> string! +Microsoft.Maui.Controls.TitleBar.Subtitle.set -> void +Microsoft.Maui.Controls.TitleBar.Title.get -> string! +Microsoft.Maui.Controls.TitleBar.Title.set -> void +Microsoft.Maui.Controls.TitleBar.TitleBar() -> void +Microsoft.Maui.Controls.TitleBar.TrailingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.TrailingContent.set -> void +Microsoft.Maui.Controls.VisualElement.Measure(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size +Microsoft.Maui.Controls.WebView.ProcessTerminated -> System.EventHandler +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.WebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.Window.TitleBar.get -> Microsoft.Maui.ITitleBar? +Microsoft.Maui.Controls.Window.TitleBar.set -> void +Microsoft.Maui.Controls.Xaml.RequireServiceAttribute +override Microsoft.Maui.Controls.ContentPage.LayoutChildren(double x, double y, double width, double height) -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.IsHorizontal.get -> bool +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.UpdateItemsSource() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.UpdateVisibility() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.ViewDidLayoutSubviews() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.ViewDidLoad() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.ViewWillLayoutSubviews() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.GetVisibleItemsIndex() -> (bool VisibleItems, int First, int Center, int Last) +override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.RegisterViewTypes() -> void +override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.UpdateItemsSource() -> void +override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.Dispose(bool disposing) -> void +override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.LoadView() -> void +override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ViewDidLoad() -> void +override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ViewWillLayoutSubviews() -> void +override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.Dispose(bool disposing) -> void +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.DetermineEmptyViewFrame() -> CoreGraphics.CGRect +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.Dispose(bool disposing) -> void +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.IsHorizontal.get -> bool +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.RegisterViewTypes() -> void +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.ViewWillLayoutSubviews() -> void +override Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.PrepareForReuse() -> void +override Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.Selected.get -> bool +override Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.Selected.set -> void +*REMOVED*override Microsoft.Maui.Controls.Layout.Measure(double widthConstraint, double heightConstraint, Microsoft.Maui.Controls.MeasureFlags flags = Microsoft.Maui.Controls.MeasureFlags.None) -> Microsoft.Maui.SizeRequest +override Microsoft.Maui.Controls.TitleBar.OnApplyTemplate() -> void +static Microsoft.Maui.Controls.BindableObjectExtensions.SetBinding(this Microsoft.Maui.Controls.BindableObject! self, Microsoft.Maui.Controls.BindableProperty! targetProperty, System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> void +static Microsoft.Maui.Controls.BindingBase.Create(System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> Microsoft.Maui.Controls.BindingBase! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.CreateEmbeddedWindowContext(this Microsoft.Maui.Hosting.MauiApp! mauiApp, UIKit.UIWindow! platformWindow) -> Microsoft.Maui.IMauiContext! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.ToPlatformEmbedded(this Microsoft.Maui.IElement! element, Microsoft.Maui.Hosting.MauiApp! mauiApp, UIKit.UIWindow! platformWindow) -> UIKit.UIView! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.ToPlatformEmbedded(this Microsoft.Maui.IElement! element, Microsoft.Maui.IMauiContext! context) -> UIKit.UIView! +*REMOVED*static Microsoft.Maui.Controls.FlyoutPage.ControlsFlyoutPageMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.HandlerProperties.GetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target) -> Microsoft.Maui.HandlerDisconnectPolicy +static Microsoft.Maui.Controls.HandlerProperties.SetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target, Microsoft.Maui.HandlerDisconnectPolicy value) -> void +static Microsoft.Maui.Controls.TitleBar.DefaultTemplate.get -> Microsoft.Maui.Controls.ControlTemplate! +*REMOVED*static Microsoft.Maui.Controls.Toolbar.ControlsToolbarMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.ViewExtensions.InvalidateMeasure(this Microsoft.Maui.Controls.VisualElement! view) -> void +static readonly Microsoft.Maui.Controls.HandlerProperties.DisconnectPolicyProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.StyleableElement.StyleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ForegroundColorProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.IconProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.LeadingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.SubtitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TrailingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.Window.TitleBarProperty -> Microsoft.Maui.Controls.BindableProperty! +virtual Microsoft.Maui.Controls.Application.ActivateWindow(Microsoft.Maui.Controls.Window! window) -> void +*REMOVED*virtual Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.Dispose(bool disposing) -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.DetermineEmptyViewFrame() -> CoreGraphics.CGRect +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.RegisterViewTypes() -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.UpdateFlowDirection() -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.UpdateItemsSource() -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.UpdateVisibility() -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetVisibleItemsIndex() -> (bool VisibleItems, int First, int Center, int Last) +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.UpdateLayout() -> void override Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer.MovedToWindow() -> void diff --git a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt index f8ec2fad5146..4608b2ad1ff2 100644 --- a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt @@ -1,2 +1,341 @@ #nullable enable +~abstract Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.CreateController(TItemsView newElement, UIKit.UICollectionViewLayout layout) -> Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2 +~abstract Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.SelectLayout() -> UIKit.UICollectionViewLayout +*REMOVED*~Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.ShellScrollViewTracker(Microsoft.Maui.IPlatformViewHandler renderer) -> void +~Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.CarouselViewController2(Microsoft.Maui.Controls.CarouselView itemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.CarouselViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2 ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.CarouselViewHandler2(Microsoft.Maui.PropertyMapper mapper = null) -> void +~Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.CollectionViewHandler2(Microsoft.Maui.PropertyMapper mapper = null) -> void +~Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2.Constraint.get -> UIKit.NSLayoutConstraint +~Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2.Constraint.set -> void +~Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2.Label.get -> UIKit.UILabel +~Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.GroupableItemsViewController2(TItemsView groupableItemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewDelegator2 +~Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewDelegator2.GroupableItemsViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewCell2.InitializeContentConstraints(UIKit.UIView platformView) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.Delegator.get -> UIKit.UICollectionViewDelegateFlowLayout +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.Delegator.set -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.GetItemAtIndex(Foundation.NSIndexPath index) -> object +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsSource.get -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsSource.set -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsView.get -> TItemsView +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsViewController2(TItemsView itemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsViewLayout.get -> UIKit.UICollectionViewLayout +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ItemsViewLayout.set -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.UpdateLayout(UIKit.UICollectionViewLayout newLayout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2 +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.ItemsViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.ItemsViewLayout.get -> UIKit.UICollectionViewLayout +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.ViewController.get -> TViewController +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.Controller.get -> Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.IsIndexPathValid(Foundation.NSIndexPath indexPath) -> bool +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ItemsView.get -> TItemsView +~Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ItemsViewHandler2(Microsoft.Maui.PropertyMapper mapper = null) -> void +~Microsoft.Maui.Controls.Handlers.Items2.LayoutAttributesChangedEventArgs2.LayoutAttributesChangedEventArgs2(UIKit.UICollectionViewLayoutAttributes newAttributes) -> void +~Microsoft.Maui.Controls.Handlers.Items2.LayoutAttributesChangedEventArgs2.NewAttributes.get -> UIKit.UICollectionViewLayoutAttributes +~Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.ReorderableItemsViewController2(TItemsView reorderableItemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewDelegator2 +~Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewDelegator2.ReorderableItemsViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2.SelectableItemsViewController2(TItemsView selectableItemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewDelegator2 +~Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewDelegator2.SelectableItemsViewDelegator2(UIKit.UICollectionViewLayout itemsViewLayout, TViewController ItemsViewController2) -> void +~Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2 +~Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.StructuredItemsViewController2(TItemsView structuredItemsView, UIKit.UICollectionViewLayout layout) -> void +~Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.Bind(Microsoft.Maui.Controls.DataTemplate template, object bindingContext, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.Bind(Microsoft.Maui.Controls.View virtualView, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.CurrentTemplate.get -> Microsoft.Maui.Controls.DataTemplate +~Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.OnLayoutAttributesChanged(UIKit.UICollectionViewLayoutAttributes newAttributes) -> void +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.get -> Microsoft.Maui.Controls.Style +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.set -> void +~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource(System.Uri value) -> void +*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +~Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.PlatformArgs.get -> Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[] +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.CreateItemsViewSource() -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.DetermineCellReuseId(Foundation.NSIndexPath indexPath) -> string +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.DraggingEnded(UIKit.UIScrollView scrollView, bool willDecelerate) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.DraggingStarted(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.GetCell(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> UIKit.UICollectionViewCell +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.GetItemsCount(UIKit.UICollectionView collectionView, nint section) -> nint +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.DecelerationEnded(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.DraggingEnded(UIKit.UIScrollView scrollView, bool willDecelerate) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.DraggingStarted(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.ScrollAnimationEnded(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.Scrolled(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.CreateController(Microsoft.Maui.Controls.CarouselView newElement, UIKit.UICollectionViewLayout layout) -> Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2 +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.ScrollToRequested(object sender, Microsoft.Maui.Controls.ScrollToRequestEventArgs args) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.SelectLayout() -> UIKit.UICollectionViewLayout +~override Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.CreateController(Microsoft.Maui.Controls.ReorderableItemsView itemsView, UIKit.UICollectionViewLayout layout) -> Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2 +~override Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.ScrollToRequested(object sender, Microsoft.Maui.Controls.ScrollToRequestEventArgs args) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.SelectLayout() -> UIKit.UICollectionViewLayout +~override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.CreateItemsViewSource() -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.GetViewForSupplementaryElement(UIKit.UICollectionView collectionView, Foundation.NSString elementKind, Foundation.NSIndexPath indexPath) -> UIKit.UICollectionReusableView +~override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewDelegator2.ScrollAnimationEnded(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.GetCell(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> UIKit.UICollectionViewCell +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.GetItemsCount(UIKit.UICollectionView collectionView, nint section) -> nint +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.NumberOfSections(UIKit.UICollectionView collectionView) -> nint +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.CellDisplayingEnded(UIKit.UICollectionView collectionView, UIKit.UICollectionViewCell cell, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetInsetForSection(UIKit.UICollectionView collectionView, UIKit.UICollectionViewLayout layout, nint section) -> UIKit.UIEdgeInsets +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetMinimumInteritemSpacingForSection(UIKit.UICollectionView collectionView, UIKit.UICollectionViewLayout layout, nint section) -> System.Runtime.InteropServices.NFloat +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetMinimumLineSpacingForSection(UIKit.UICollectionView collectionView, UIKit.UICollectionViewLayout layout, nint section) -> System.Runtime.InteropServices.NFloat +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.Scrolled(UIKit.UIScrollView scrollView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ConnectHandler(UIKit.UIView platformView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.CreatePlatformView() -> UIKit.UIView +~override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.DisconnectHandler(UIKit.UIView platformView) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.CanMoveItem(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> bool +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.CreateItemsViewSource() -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.MoveItem(UIKit.UICollectionView collectionView, Foundation.NSIndexPath sourceIndexPath, Foundation.NSIndexPath destinationIndexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewDelegator2.GetTargetIndexPathForMove(UIKit.UICollectionView collectionView, Foundation.NSIndexPath originalIndexPath, Foundation.NSIndexPath proposedIndexPath) -> Foundation.NSIndexPath +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2.ItemDeselected(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewController2.ItemSelected(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewDelegator2.ItemDeselected(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.SelectableItemsViewDelegator2.ItemSelected(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) -> void +~override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.GetViewForSupplementaryElement(UIKit.UICollectionView collectionView, Foundation.NSString elementKind, Foundation.NSIndexPath indexPath) -> UIKit.UICollectionReusableView +~override Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.PreferredLayoutAttributesFittingAttributes(UIKit.UICollectionViewLayoutAttributes layoutAttributes) -> UIKit.UICollectionViewLayoutAttributes +~override Microsoft.Maui.Controls.ShellContent.OnPropertyChanged(string propertyName = null) -> void +*REMOVED*~static Microsoft.Maui.Controls.Application.ControlsApplicationMapper -> Microsoft.Maui.IPropertyMapper +~static Microsoft.Maui.Controls.Brush.DarkGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DarkSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DimGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.Grey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.SlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +*REMOVED*~static Microsoft.Maui.Controls.Button.ControlsButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.DatePicker.ControlsDatePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Editor.ControlsEditorMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Element.ControlsElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Entry.ControlsEntryMapper -> Microsoft.Maui.IPropertyMapper +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapCurrentItem(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapIsBounceEnabled(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapIsSwipeEnabled(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapLoop(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapPeekAreaInsets(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.Mapper -> Microsoft.Maui.PropertyMapper +~static Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.MapPosition(Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 handler, Microsoft.Maui.Controls.CarouselView carouselView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapCanReorderItems(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.ReorderableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapFooterTemplate(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.StructuredItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapHeaderTemplate(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.StructuredItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapIsGrouped(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.GroupableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapItemSizingStrategy(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.StructuredItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapItemsLayout(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.StructuredItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapItemsSource(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.SelectableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.Mapper -> Microsoft.Maui.PropertyMapper +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapSelectedItem(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.SelectableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapSelectedItems(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.SelectableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.MapSelectionMode(Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 handler, Microsoft.Maui.Controls.SelectableItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ItemsViewMapper -> Microsoft.Maui.PropertyMapper> +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapEmptyView(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapEmptyViewTemplate(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapFlowDirection(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapHorizontalScrollBarVisibility(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapIsVisible(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapItemsSource(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapItemsUpdatingScrollMode(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapItemTemplate(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +~static Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.MapVerticalScrollBarVisibility(Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2 handler, Microsoft.Maui.Controls.ItemsView itemsView) -> void +*REMOVED*~static Microsoft.Maui.Controls.Label.ControlsLabelMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Layout.ControlsLayoutMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.NavigationPage.ControlsNavigationPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Picker.ControlsPickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RadioButton.ControlsRadioButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RefreshView.ControlsRefreshViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.ScrollView.ControlsScrollViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.SearchBar.ControlsSearchBarMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Shapes.Shape.ControlsShapeViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TabbedPage.ControlsTabbedPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TimePicker.ControlsTimePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.VisualElement.ControlsVisualElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.WebView.ControlsWebViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Window.ControlsWindowMapper -> Microsoft.Maui.IPropertyMapper +~static readonly Microsoft.Maui.Controls.BaseShellItem.FlyoutItemIsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.CreateDelegator() -> UIKit.UICollectionViewDelegateFlowLayout +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.CreateItemsViewSource() -> Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.DetermineCellReuseId(Foundation.NSIndexPath indexPath) -> string +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.GetIndexForItem(object item) -> Foundation.NSIndexPath +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetVisibleItemsIndexPath() -> (bool VisibleItems, Foundation.NSIndexPath First, Foundation.NSIndexPath Center, Foundation.NSIndexPath Last) +~virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ScrollToRequested(object sender, Microsoft.Maui.Controls.ScrollToRequestEventArgs args) -> void +abstract Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.IsHorizontal.get -> bool +const Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.EmptyTag = 333 -> int +const Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.FooterTag = 222 -> int +const Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.HeaderTag = 111 -> int +const Microsoft.Maui.Controls.TitleBar.ContentHiddenState = "ContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.ContentVisibleState = "ContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.IconHiddenState = "IconCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.IconVisibleState = "IconVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingHiddenState = "LeadingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingVisibleState = "LeadingContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleHiddenState = "SubTitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleVisibleState = "SubtitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TemplateRootName = "PART_Root" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarActiveState = "TitleBarTitleActive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarContent = "PART_Content" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarIcon = "PART_Icon" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarInactiveState = "TitleBarTitleInactive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarLeading = "PART_LeadingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarSubtitle = "PART_Subtitle" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTitle = "PART_Title" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTrailing = "PART_TrailingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleHiddenState = "TitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleVisibleState = "TitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingHiddenState = "TrailingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingVisibleState = "TrailingContentVisible" -> string! +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.HandlerProperties +*REMOVED*Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker +*REMOVED*Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.Dispose() -> void +*REMOVED*Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.OnLayoutSubviews() -> void +*REMOVED*Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.Reset() -> bool +Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2 +Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2 +Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2 +Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2.CarouselViewHandler2() -> void +Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2 +Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.CollectionViewHandler2() -> void +Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2 +Microsoft.Maui.Controls.Handlers.Items2.DefaultCell2.DefaultCell2(CoreGraphics.CGRect frame) -> void +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewCell2 +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewCell2.ItemsViewCell2(CoreGraphics.CGRect frame) -> void +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ScrollDirection.get -> UIKit.UICollectionViewScrollDirection +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.PreviousHorizontalOffset -> float +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.PreviousVerticalOffset -> float +Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.ItemsViewHandler2() -> void +Microsoft.Maui.Controls.Handlers.Items2.LayoutAttributesChangedEventArgs2 +Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.UpdateCanReorderItems() -> void +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2 +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ConstrainedDimension -> System.Runtime.InteropServices.NFloat +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ConstrainedSize -> CoreGraphics.CGSize +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ContentSizeChanged -> System.EventHandler +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.LayoutAttributesChanged -> System.EventHandler +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.OnContentSizeChanged() -> void +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ScrollDirection.get -> UIKit.UICollectionViewScrollDirection +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.ScrollDirection.set -> void +Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.TemplatedCell2(CoreGraphics.CGRect frame) -> void +Microsoft.Maui.Controls.HybridWebView +Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string? +Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void +Microsoft.Maui.Controls.HybridWebView.EvaluateJavaScriptAsync(string! script) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string? +Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void +Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void +Microsoft.Maui.Controls.HybridWebView.InvokeJavaScriptAsync(string! methodName, System.Text.Json.Serialization.Metadata.JsonTypeInfo! returnTypeJsonTypeInfo, object?[]? paramValues = null, System.Text.Json.Serialization.Metadata.JsonTypeInfo?[]? paramJsonTypeInfos = null) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler? +Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string? +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs.Sender.get -> WebKit.WKWebView! +Microsoft.Maui.Controls.StyleableElement +Microsoft.Maui.Controls.StyleableElement.class.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.class.set -> void +Microsoft.Maui.Controls.StyleableElement.Style.get -> Microsoft.Maui.Controls.Style! +Microsoft.Maui.Controls.StyleableElement.Style.set -> void +Microsoft.Maui.Controls.StyleableElement.StyleableElement() -> void +Microsoft.Maui.Controls.StyleableElement.StyleClass.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.StyleClass.set -> void +Microsoft.Maui.Controls.TimeChangedEventArgs +Microsoft.Maui.Controls.TimeChangedEventArgs.NewTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void +Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler +Microsoft.Maui.Controls.TitleBar +Microsoft.Maui.Controls.TitleBar.Content.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.Content.set -> void +Microsoft.Maui.Controls.TitleBar.ForegroundColor.get -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Controls.TitleBar.ForegroundColor.set -> void +Microsoft.Maui.Controls.TitleBar.Icon.get -> Microsoft.Maui.Controls.ImageSource! +Microsoft.Maui.Controls.TitleBar.Icon.set -> void +Microsoft.Maui.Controls.TitleBar.LeadingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.LeadingContent.set -> void +Microsoft.Maui.Controls.TitleBar.PassthroughElements.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.TitleBar.Subtitle.get -> string! +Microsoft.Maui.Controls.TitleBar.Subtitle.set -> void +Microsoft.Maui.Controls.TitleBar.Title.get -> string! +Microsoft.Maui.Controls.TitleBar.Title.set -> void +Microsoft.Maui.Controls.TitleBar.TitleBar() -> void +Microsoft.Maui.Controls.TitleBar.TrailingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.TrailingContent.set -> void +Microsoft.Maui.Controls.VisualElement.Measure(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size +Microsoft.Maui.Controls.WebView.ProcessTerminated -> System.EventHandler +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.WebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.Window.TitleBar.get -> Microsoft.Maui.ITitleBar? +Microsoft.Maui.Controls.Window.TitleBar.set -> void +Microsoft.Maui.Controls.Xaml.RequireServiceAttribute +override Microsoft.Maui.Controls.ContentPage.LayoutChildren(double x, double y, double width, double height) -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.IsHorizontal.get -> bool +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.UpdateItemsSource() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.UpdateVisibility() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.ViewDidLayoutSubviews() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.ViewDidLoad() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewController2.ViewWillLayoutSubviews() -> void +override Microsoft.Maui.Controls.Handlers.Items2.CarouselViewDelegator2.GetVisibleItemsIndex() -> (bool VisibleItems, int First, int Center, int Last) +override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.RegisterViewTypes() -> void +override Microsoft.Maui.Controls.Handlers.Items2.GroupableItemsViewController2.UpdateItemsSource() -> void +override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.Dispose(bool disposing) -> void +override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.LoadView() -> void +override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ViewDidLoad() -> void +override Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.ViewWillLayoutSubviews() -> void +override Microsoft.Maui.Controls.Handlers.Items2.ReorderableItemsViewController2.Dispose(bool disposing) -> void +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.DetermineEmptyViewFrame() -> CoreGraphics.CGRect +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.Dispose(bool disposing) -> void +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.IsHorizontal.get -> bool +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.RegisterViewTypes() -> void +override Microsoft.Maui.Controls.Handlers.Items2.StructuredItemsViewController2.ViewWillLayoutSubviews() -> void +override Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.PrepareForReuse() -> void +override Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.Selected.get -> bool +override Microsoft.Maui.Controls.Handlers.Items2.TemplatedCell2.Selected.set -> void +*REMOVED*override Microsoft.Maui.Controls.Layout.Measure(double widthConstraint, double heightConstraint, Microsoft.Maui.Controls.MeasureFlags flags = Microsoft.Maui.Controls.MeasureFlags.None) -> Microsoft.Maui.SizeRequest +override Microsoft.Maui.Controls.TitleBar.OnApplyTemplate() -> void +static Microsoft.Maui.Controls.BindableObjectExtensions.SetBinding(this Microsoft.Maui.Controls.BindableObject! self, Microsoft.Maui.Controls.BindableProperty! targetProperty, System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> void +static Microsoft.Maui.Controls.BindingBase.Create(System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> Microsoft.Maui.Controls.BindingBase! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.CreateEmbeddedWindowContext(this Microsoft.Maui.Hosting.MauiApp! mauiApp, UIKit.UIWindow! platformWindow) -> Microsoft.Maui.IMauiContext! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.ToPlatformEmbedded(this Microsoft.Maui.IElement! element, Microsoft.Maui.Hosting.MauiApp! mauiApp, UIKit.UIWindow! platformWindow) -> UIKit.UIView! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.ToPlatformEmbedded(this Microsoft.Maui.IElement! element, Microsoft.Maui.IMauiContext! context) -> UIKit.UIView! +*REMOVED*static Microsoft.Maui.Controls.FlyoutPage.ControlsFlyoutPageMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.HandlerProperties.GetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target) -> Microsoft.Maui.HandlerDisconnectPolicy +static Microsoft.Maui.Controls.HandlerProperties.SetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target, Microsoft.Maui.HandlerDisconnectPolicy value) -> void +static Microsoft.Maui.Controls.TitleBar.DefaultTemplate.get -> Microsoft.Maui.Controls.ControlTemplate! +*REMOVED*static Microsoft.Maui.Controls.Toolbar.ControlsToolbarMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.ViewExtensions.InvalidateMeasure(this Microsoft.Maui.Controls.VisualElement! view) -> void +static readonly Microsoft.Maui.Controls.HandlerProperties.DisconnectPolicyProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.StyleableElement.StyleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ForegroundColorProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.IconProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.LeadingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.SubtitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TrailingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.Window.TitleBarProperty -> Microsoft.Maui.Controls.BindableProperty! +virtual Microsoft.Maui.Controls.Application.ActivateWindow(Microsoft.Maui.Controls.Window! window) -> void +*REMOVED*virtual Microsoft.Maui.Controls.Handlers.Compatibility.ShellScrollViewTracker.Dispose(bool disposing) -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.DetermineEmptyViewFrame() -> CoreGraphics.CGRect +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.RegisterViewTypes() -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.UpdateFlowDirection() -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.UpdateItemsSource() -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewController2.UpdateVisibility() -> void +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewDelegator2.GetVisibleItemsIndex() -> (bool VisibleItems, int First, int Center, int Last) +virtual Microsoft.Maui.Controls.Handlers.Items2.ItemsViewHandler2.UpdateLayout() -> void override Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer.MovedToWindow() -> void diff --git a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt index 7dc5c58110bf..0a53e93e7fbc 100644 --- a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt @@ -1 +1,143 @@ #nullable enable +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.get -> Microsoft.Maui.Controls.Style +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.set -> void +~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource(System.Uri value) -> void +*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +~Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.PlatformArgs.get -> Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[] +~override Microsoft.Maui.Controls.ShellContent.OnPropertyChanged(string propertyName = null) -> void +*REMOVED*~static Microsoft.Maui.Controls.Application.ControlsApplicationMapper -> Microsoft.Maui.IPropertyMapper +~static Microsoft.Maui.Controls.Brush.DarkGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DarkSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DimGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.Grey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.SlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +*REMOVED*~static Microsoft.Maui.Controls.Button.ControlsButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.DatePicker.ControlsDatePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Editor.ControlsEditorMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Element.ControlsElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Entry.ControlsEntryMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Label.ControlsLabelMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Layout.ControlsLayoutMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.NavigationPage.ControlsNavigationPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Picker.ControlsPickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RadioButton.ControlsRadioButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RefreshView.ControlsRefreshViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.ScrollView.ControlsScrollViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.SearchBar.ControlsSearchBarMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Shapes.Shape.ControlsShapeViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TabbedPage.ControlsTabbedPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TimePicker.ControlsTimePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.VisualElement.ControlsVisualElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.WebView.ControlsWebViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Window.ControlsWindowMapper -> Microsoft.Maui.IPropertyMapper +~static readonly Microsoft.Maui.Controls.BaseShellItem.FlyoutItemIsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty +const Microsoft.Maui.Controls.TitleBar.ContentHiddenState = "ContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.ContentVisibleState = "ContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.IconHiddenState = "IconCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.IconVisibleState = "IconVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingHiddenState = "LeadingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingVisibleState = "LeadingContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleHiddenState = "SubTitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleVisibleState = "SubtitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TemplateRootName = "PART_Root" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarActiveState = "TitleBarTitleActive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarContent = "PART_Content" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarIcon = "PART_Icon" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarInactiveState = "TitleBarTitleInactive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarLeading = "PART_LeadingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarSubtitle = "PART_Subtitle" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTitle = "PART_Title" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTrailing = "PART_TrailingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleHiddenState = "TitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleVisibleState = "TitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingHiddenState = "TrailingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingVisibleState = "TrailingContentVisible" -> string! +Microsoft.Maui.Controls.HandlerProperties +Microsoft.Maui.Controls.HybridWebView +Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string? +Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void +Microsoft.Maui.Controls.HybridWebView.EvaluateJavaScriptAsync(string! script) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string? +Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void +Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void +Microsoft.Maui.Controls.HybridWebView.InvokeJavaScriptAsync(string! methodName, System.Text.Json.Serialization.Metadata.JsonTypeInfo! returnTypeJsonTypeInfo, object?[]? paramValues = null, System.Text.Json.Serialization.Metadata.JsonTypeInfo?[]? paramJsonTypeInfos = null) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler? +Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string? +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs.PlatformWebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.StyleableElement +Microsoft.Maui.Controls.StyleableElement.class.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.class.set -> void +Microsoft.Maui.Controls.StyleableElement.Style.get -> Microsoft.Maui.Controls.Style! +Microsoft.Maui.Controls.StyleableElement.Style.set -> void +Microsoft.Maui.Controls.StyleableElement.StyleableElement() -> void +Microsoft.Maui.Controls.StyleableElement.StyleClass.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.StyleClass.set -> void +Microsoft.Maui.Controls.TimeChangedEventArgs +Microsoft.Maui.Controls.TimeChangedEventArgs.NewTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void +Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler +Microsoft.Maui.Controls.TitleBar +Microsoft.Maui.Controls.TitleBar.Content.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.Content.set -> void +Microsoft.Maui.Controls.TitleBar.ForegroundColor.get -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Controls.TitleBar.ForegroundColor.set -> void +Microsoft.Maui.Controls.TitleBar.Icon.get -> Microsoft.Maui.Controls.ImageSource! +Microsoft.Maui.Controls.TitleBar.Icon.set -> void +Microsoft.Maui.Controls.TitleBar.LeadingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.LeadingContent.set -> void +Microsoft.Maui.Controls.TitleBar.PassthroughElements.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.TitleBar.Subtitle.get -> string! +Microsoft.Maui.Controls.TitleBar.Subtitle.set -> void +Microsoft.Maui.Controls.TitleBar.Title.get -> string! +Microsoft.Maui.Controls.TitleBar.Title.set -> void +Microsoft.Maui.Controls.TitleBar.TitleBar() -> void +Microsoft.Maui.Controls.TitleBar.TrailingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.TrailingContent.set -> void +Microsoft.Maui.Controls.VisualElement.Measure(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size +Microsoft.Maui.Controls.WebView.ProcessTerminated -> System.EventHandler +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.WebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.Window.TitleBar.get -> Microsoft.Maui.ITitleBar? +Microsoft.Maui.Controls.Window.TitleBar.set -> void +Microsoft.Maui.Controls.Xaml.RequireServiceAttribute +override Microsoft.Maui.Controls.ContentPage.LayoutChildren(double x, double y, double width, double height) -> void +*REMOVED*override Microsoft.Maui.Controls.Layout.Measure(double widthConstraint, double heightConstraint, Microsoft.Maui.Controls.MeasureFlags flags = Microsoft.Maui.Controls.MeasureFlags.None) -> Microsoft.Maui.SizeRequest +override Microsoft.Maui.Controls.TitleBar.OnApplyTemplate() -> void +static Microsoft.Maui.Controls.BindableObjectExtensions.SetBinding(this Microsoft.Maui.Controls.BindableObject! self, Microsoft.Maui.Controls.BindableProperty! targetProperty, System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> void +static Microsoft.Maui.Controls.BindingBase.Create(System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> Microsoft.Maui.Controls.BindingBase! +*REMOVED*static Microsoft.Maui.Controls.FlyoutPage.ControlsFlyoutPageMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.HandlerProperties.GetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target) -> Microsoft.Maui.HandlerDisconnectPolicy +static Microsoft.Maui.Controls.HandlerProperties.SetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target, Microsoft.Maui.HandlerDisconnectPolicy value) -> void +static Microsoft.Maui.Controls.TitleBar.DefaultTemplate.get -> Microsoft.Maui.Controls.ControlTemplate! +*REMOVED*static Microsoft.Maui.Controls.Toolbar.ControlsToolbarMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.ViewExtensions.InvalidateMeasure(this Microsoft.Maui.Controls.VisualElement! view) -> void +static readonly Microsoft.Maui.Controls.HandlerProperties.DisconnectPolicyProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.StyleableElement.StyleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ForegroundColorProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.IconProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.LeadingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.SubtitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TrailingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.Window.TitleBarProperty -> Microsoft.Maui.Controls.BindableProperty! +virtual Microsoft.Maui.Controls.Application.ActivateWindow(Microsoft.Maui.Controls.Window! window) -> void diff --git a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt index 7dc5c58110bf..d9e2224b59d9 100644 --- a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -1 +1,148 @@ #nullable enable +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.get -> Microsoft.Maui.Controls.Style +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.set -> void +~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource(System.Uri value) -> void +*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +~Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.PlatformArgs.get -> Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[] +~override Microsoft.Maui.Controls.ShellContent.OnPropertyChanged(string propertyName = null) -> void +*REMOVED*~static Microsoft.Maui.Controls.Application.ControlsApplicationMapper -> Microsoft.Maui.IPropertyMapper +~static Microsoft.Maui.Controls.Brush.DarkGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DarkSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DimGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.Grey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.SlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +*REMOVED*~static Microsoft.Maui.Controls.Button.ControlsButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.DatePicker.ControlsDatePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Editor.ControlsEditorMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Element.ControlsElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Entry.ControlsEntryMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Label.ControlsLabelMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Layout.ControlsLayoutMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.NavigationPage.ControlsNavigationPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Picker.ControlsPickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RadioButton.ControlsRadioButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RefreshView.ControlsRefreshViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.ScrollView.ControlsScrollViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.SearchBar.ControlsSearchBarMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Shapes.Shape.ControlsShapeViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TabbedPage.ControlsTabbedPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TimePicker.ControlsTimePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.VisualElement.ControlsVisualElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.WebView.ControlsWebViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Window.ControlsWindowMapper -> Microsoft.Maui.IPropertyMapper +~static readonly Microsoft.Maui.Controls.BaseShellItem.FlyoutItemIsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty +const Microsoft.Maui.Controls.TitleBar.ContentHiddenState = "ContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.ContentVisibleState = "ContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.IconHiddenState = "IconCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.IconVisibleState = "IconVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingHiddenState = "LeadingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingVisibleState = "LeadingContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleHiddenState = "SubTitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleVisibleState = "SubtitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TemplateRootName = "PART_Root" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarActiveState = "TitleBarTitleActive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarContent = "PART_Content" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarIcon = "PART_Icon" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarInactiveState = "TitleBarTitleInactive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarLeading = "PART_LeadingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarSubtitle = "PART_Subtitle" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTitle = "PART_Title" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTrailing = "PART_TrailingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleHiddenState = "TitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleVisibleState = "TitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingHiddenState = "TrailingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingVisibleState = "TrailingContentVisible" -> string! +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.HandlerProperties +Microsoft.Maui.Controls.HybridWebView +Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string? +Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void +Microsoft.Maui.Controls.HybridWebView.EvaluateJavaScriptAsync(string! script) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string? +Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void +Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void +Microsoft.Maui.Controls.HybridWebView.InvokeJavaScriptAsync(string! methodName, System.Text.Json.Serialization.Metadata.JsonTypeInfo! returnTypeJsonTypeInfo, object?[]? paramValues = null, System.Text.Json.Serialization.Metadata.JsonTypeInfo?[]? paramJsonTypeInfos = null) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler? +Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string? +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs.CoreWebView2ProcessFailedEventArgs.get -> Microsoft.Web.WebView2.Core.CoreWebView2ProcessFailedEventArgs! +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs.Sender.get -> Microsoft.Web.WebView2.Core.CoreWebView2! +Microsoft.Maui.Controls.StyleableElement +Microsoft.Maui.Controls.StyleableElement.class.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.class.set -> void +Microsoft.Maui.Controls.StyleableElement.Style.get -> Microsoft.Maui.Controls.Style! +Microsoft.Maui.Controls.StyleableElement.Style.set -> void +Microsoft.Maui.Controls.StyleableElement.StyleableElement() -> void +Microsoft.Maui.Controls.StyleableElement.StyleClass.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.StyleClass.set -> void +Microsoft.Maui.Controls.TimeChangedEventArgs +Microsoft.Maui.Controls.TimeChangedEventArgs.NewTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void +Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler +Microsoft.Maui.Controls.TitleBar +Microsoft.Maui.Controls.TitleBar.Content.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.Content.set -> void +Microsoft.Maui.Controls.TitleBar.ForegroundColor.get -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Controls.TitleBar.ForegroundColor.set -> void +Microsoft.Maui.Controls.TitleBar.Icon.get -> Microsoft.Maui.Controls.ImageSource! +Microsoft.Maui.Controls.TitleBar.Icon.set -> void +Microsoft.Maui.Controls.TitleBar.LeadingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.LeadingContent.set -> void +Microsoft.Maui.Controls.TitleBar.PassthroughElements.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.TitleBar.Subtitle.get -> string! +Microsoft.Maui.Controls.TitleBar.Subtitle.set -> void +Microsoft.Maui.Controls.TitleBar.Title.get -> string! +Microsoft.Maui.Controls.TitleBar.Title.set -> void +Microsoft.Maui.Controls.TitleBar.TitleBar() -> void +Microsoft.Maui.Controls.TitleBar.TrailingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.TrailingContent.set -> void +Microsoft.Maui.Controls.VisualElement.Measure(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size +Microsoft.Maui.Controls.WebView.ProcessTerminated -> System.EventHandler +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.WebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.Window.TitleBar.get -> Microsoft.Maui.ITitleBar? +Microsoft.Maui.Controls.Window.TitleBar.set -> void +Microsoft.Maui.Controls.Xaml.RequireServiceAttribute +override Microsoft.Maui.Controls.ContentPage.LayoutChildren(double x, double y, double width, double height) -> void +*REMOVED*override Microsoft.Maui.Controls.Layout.Measure(double widthConstraint, double heightConstraint, Microsoft.Maui.Controls.MeasureFlags flags = Microsoft.Maui.Controls.MeasureFlags.None) -> Microsoft.Maui.SizeRequest +override Microsoft.Maui.Controls.TitleBar.OnApplyTemplate() -> void +static Microsoft.Maui.Controls.BindableObjectExtensions.SetBinding(this Microsoft.Maui.Controls.BindableObject! self, Microsoft.Maui.Controls.BindableProperty! targetProperty, System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> void +static Microsoft.Maui.Controls.BindingBase.Create(System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> Microsoft.Maui.Controls.BindingBase! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.CreateEmbeddedWindowContext(this Microsoft.Maui.Hosting.MauiApp! mauiApp, Microsoft.UI.Xaml.Window! platformWindow) -> Microsoft.Maui.IMauiContext! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.ToPlatformEmbedded(this Microsoft.Maui.IElement! element, Microsoft.Maui.Hosting.MauiApp! mauiApp, Microsoft.UI.Xaml.Window! platformWindow) -> Microsoft.UI.Xaml.FrameworkElement! +static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.ToPlatformEmbedded(this Microsoft.Maui.IElement! element, Microsoft.Maui.IMauiContext! context) -> Microsoft.UI.Xaml.FrameworkElement! +*REMOVED*static Microsoft.Maui.Controls.FlyoutPage.ControlsFlyoutPageMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.HandlerProperties.GetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target) -> Microsoft.Maui.HandlerDisconnectPolicy +static Microsoft.Maui.Controls.HandlerProperties.SetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target, Microsoft.Maui.HandlerDisconnectPolicy value) -> void +static Microsoft.Maui.Controls.TitleBar.DefaultTemplate.get -> Microsoft.Maui.Controls.ControlTemplate! +*REMOVED*static Microsoft.Maui.Controls.Toolbar.ControlsToolbarMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.ViewExtensions.InvalidateMeasure(this Microsoft.Maui.Controls.VisualElement! view) -> void +static readonly Microsoft.Maui.Controls.HandlerProperties.DisconnectPolicyProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.StyleableElement.StyleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ForegroundColorProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.IconProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.LeadingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.SubtitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TrailingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.Window.TitleBarProperty -> Microsoft.Maui.Controls.BindableProperty! +virtual Microsoft.Maui.Controls.Application.ActivateWindow(Microsoft.Maui.Controls.Window! window) -> void diff --git a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt index 7dc5c58110bf..0a53e93e7fbc 100644 --- a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt @@ -1 +1,143 @@ #nullable enable +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.get -> Microsoft.Maui.Controls.Style +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.set -> void +~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource(System.Uri value) -> void +*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +~Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.PlatformArgs.get -> Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[] +~override Microsoft.Maui.Controls.ShellContent.OnPropertyChanged(string propertyName = null) -> void +*REMOVED*~static Microsoft.Maui.Controls.Application.ControlsApplicationMapper -> Microsoft.Maui.IPropertyMapper +~static Microsoft.Maui.Controls.Brush.DarkGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DarkSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DimGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.Grey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.SlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +*REMOVED*~static Microsoft.Maui.Controls.Button.ControlsButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.DatePicker.ControlsDatePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Editor.ControlsEditorMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Element.ControlsElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Entry.ControlsEntryMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Label.ControlsLabelMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Layout.ControlsLayoutMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.NavigationPage.ControlsNavigationPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Picker.ControlsPickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RadioButton.ControlsRadioButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RefreshView.ControlsRefreshViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.ScrollView.ControlsScrollViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.SearchBar.ControlsSearchBarMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Shapes.Shape.ControlsShapeViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TabbedPage.ControlsTabbedPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TimePicker.ControlsTimePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.VisualElement.ControlsVisualElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.WebView.ControlsWebViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Window.ControlsWindowMapper -> Microsoft.Maui.IPropertyMapper +~static readonly Microsoft.Maui.Controls.BaseShellItem.FlyoutItemIsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty +const Microsoft.Maui.Controls.TitleBar.ContentHiddenState = "ContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.ContentVisibleState = "ContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.IconHiddenState = "IconCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.IconVisibleState = "IconVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingHiddenState = "LeadingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingVisibleState = "LeadingContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleHiddenState = "SubTitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleVisibleState = "SubtitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TemplateRootName = "PART_Root" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarActiveState = "TitleBarTitleActive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarContent = "PART_Content" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarIcon = "PART_Icon" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarInactiveState = "TitleBarTitleInactive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarLeading = "PART_LeadingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarSubtitle = "PART_Subtitle" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTitle = "PART_Title" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTrailing = "PART_TrailingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleHiddenState = "TitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleVisibleState = "TitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingHiddenState = "TrailingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingVisibleState = "TrailingContentVisible" -> string! +Microsoft.Maui.Controls.HandlerProperties +Microsoft.Maui.Controls.HybridWebView +Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string? +Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void +Microsoft.Maui.Controls.HybridWebView.EvaluateJavaScriptAsync(string! script) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string? +Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void +Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void +Microsoft.Maui.Controls.HybridWebView.InvokeJavaScriptAsync(string! methodName, System.Text.Json.Serialization.Metadata.JsonTypeInfo! returnTypeJsonTypeInfo, object?[]? paramValues = null, System.Text.Json.Serialization.Metadata.JsonTypeInfo?[]? paramJsonTypeInfos = null) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler? +Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string? +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs.PlatformWebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.StyleableElement +Microsoft.Maui.Controls.StyleableElement.class.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.class.set -> void +Microsoft.Maui.Controls.StyleableElement.Style.get -> Microsoft.Maui.Controls.Style! +Microsoft.Maui.Controls.StyleableElement.Style.set -> void +Microsoft.Maui.Controls.StyleableElement.StyleableElement() -> void +Microsoft.Maui.Controls.StyleableElement.StyleClass.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.StyleClass.set -> void +Microsoft.Maui.Controls.TimeChangedEventArgs +Microsoft.Maui.Controls.TimeChangedEventArgs.NewTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void +Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler +Microsoft.Maui.Controls.TitleBar +Microsoft.Maui.Controls.TitleBar.Content.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.Content.set -> void +Microsoft.Maui.Controls.TitleBar.ForegroundColor.get -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Controls.TitleBar.ForegroundColor.set -> void +Microsoft.Maui.Controls.TitleBar.Icon.get -> Microsoft.Maui.Controls.ImageSource! +Microsoft.Maui.Controls.TitleBar.Icon.set -> void +Microsoft.Maui.Controls.TitleBar.LeadingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.LeadingContent.set -> void +Microsoft.Maui.Controls.TitleBar.PassthroughElements.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.TitleBar.Subtitle.get -> string! +Microsoft.Maui.Controls.TitleBar.Subtitle.set -> void +Microsoft.Maui.Controls.TitleBar.Title.get -> string! +Microsoft.Maui.Controls.TitleBar.Title.set -> void +Microsoft.Maui.Controls.TitleBar.TitleBar() -> void +Microsoft.Maui.Controls.TitleBar.TrailingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.TrailingContent.set -> void +Microsoft.Maui.Controls.VisualElement.Measure(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size +Microsoft.Maui.Controls.WebView.ProcessTerminated -> System.EventHandler +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.WebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.Window.TitleBar.get -> Microsoft.Maui.ITitleBar? +Microsoft.Maui.Controls.Window.TitleBar.set -> void +Microsoft.Maui.Controls.Xaml.RequireServiceAttribute +override Microsoft.Maui.Controls.ContentPage.LayoutChildren(double x, double y, double width, double height) -> void +*REMOVED*override Microsoft.Maui.Controls.Layout.Measure(double widthConstraint, double heightConstraint, Microsoft.Maui.Controls.MeasureFlags flags = Microsoft.Maui.Controls.MeasureFlags.None) -> Microsoft.Maui.SizeRequest +override Microsoft.Maui.Controls.TitleBar.OnApplyTemplate() -> void +static Microsoft.Maui.Controls.BindableObjectExtensions.SetBinding(this Microsoft.Maui.Controls.BindableObject! self, Microsoft.Maui.Controls.BindableProperty! targetProperty, System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> void +static Microsoft.Maui.Controls.BindingBase.Create(System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> Microsoft.Maui.Controls.BindingBase! +*REMOVED*static Microsoft.Maui.Controls.FlyoutPage.ControlsFlyoutPageMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.HandlerProperties.GetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target) -> Microsoft.Maui.HandlerDisconnectPolicy +static Microsoft.Maui.Controls.HandlerProperties.SetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target, Microsoft.Maui.HandlerDisconnectPolicy value) -> void +static Microsoft.Maui.Controls.TitleBar.DefaultTemplate.get -> Microsoft.Maui.Controls.ControlTemplate! +*REMOVED*static Microsoft.Maui.Controls.Toolbar.ControlsToolbarMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.ViewExtensions.InvalidateMeasure(this Microsoft.Maui.Controls.VisualElement! view) -> void +static readonly Microsoft.Maui.Controls.HandlerProperties.DisconnectPolicyProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.StyleableElement.StyleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ForegroundColorProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.IconProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.LeadingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.SubtitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TrailingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.Window.TitleBarProperty -> Microsoft.Maui.Controls.BindableProperty! +virtual Microsoft.Maui.Controls.Application.ActivateWindow(Microsoft.Maui.Controls.Window! window) -> void diff --git a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt index 7dc5c58110bf..0a53e93e7fbc 100644 --- a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt @@ -1 +1,143 @@ #nullable enable +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.MenuItem.StyleClass.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.class.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.get -> Microsoft.Maui.Controls.Style +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.Style.set -> void +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.get -> System.Collections.Generic.IList +*REMOVED*~Microsoft.Maui.Controls.NavigableElement.StyleClass.set -> void +~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource(System.Uri value) -> void +*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +~Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.PlatformArgs.get -> Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void +~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[] +~override Microsoft.Maui.Controls.ShellContent.OnPropertyChanged(string propertyName = null) -> void +*REMOVED*~static Microsoft.Maui.Controls.Application.ControlsApplicationMapper -> Microsoft.Maui.IPropertyMapper +~static Microsoft.Maui.Controls.Brush.DarkGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DarkSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.DimGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.Grey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.LightSlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +~static Microsoft.Maui.Controls.Brush.SlateGrey.get -> Microsoft.Maui.Controls.SolidColorBrush +*REMOVED*~static Microsoft.Maui.Controls.Button.ControlsButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.DatePicker.ControlsDatePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Editor.ControlsEditorMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Element.ControlsElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Entry.ControlsEntryMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Label.ControlsLabelMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Layout.ControlsLayoutMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.NavigationPage.ControlsNavigationPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Picker.ControlsPickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RadioButton.ControlsRadioButtonMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.RefreshView.ControlsRefreshViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.ScrollView.ControlsScrollViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.SearchBar.ControlsSearchBarMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Shapes.Shape.ControlsShapeViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TabbedPage.ControlsTabbedPageMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.TimePicker.ControlsTimePickerMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.VisualElement.ControlsVisualElementMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.WebView.ControlsWebViewMapper -> Microsoft.Maui.IPropertyMapper +*REMOVED*~static Microsoft.Maui.Controls.Window.ControlsWindowMapper -> Microsoft.Maui.IPropertyMapper +~static readonly Microsoft.Maui.Controls.BaseShellItem.FlyoutItemIsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty +const Microsoft.Maui.Controls.TitleBar.ContentHiddenState = "ContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.ContentVisibleState = "ContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.IconHiddenState = "IconCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.IconVisibleState = "IconVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingHiddenState = "LeadingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.LeadingVisibleState = "LeadingContentVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleHiddenState = "SubTitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.SubtitleVisibleState = "SubtitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TemplateRootName = "PART_Root" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarActiveState = "TitleBarTitleActive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarContent = "PART_Content" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarIcon = "PART_Icon" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarInactiveState = "TitleBarTitleInactive" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarLeading = "PART_LeadingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarSubtitle = "PART_Subtitle" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTitle = "PART_Title" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleBarTrailing = "PART_TrailingContent" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleHiddenState = "TitleCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TitleVisibleState = "TitleVisible" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingHiddenState = "TrailingContentCollapsed" -> string! +const Microsoft.Maui.Controls.TitleBar.TrailingVisibleState = "TrailingContentVisible" -> string! +Microsoft.Maui.Controls.HandlerProperties +Microsoft.Maui.Controls.HybridWebView +Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string? +Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void +Microsoft.Maui.Controls.HybridWebView.EvaluateJavaScriptAsync(string! script) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string? +Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void +Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void +Microsoft.Maui.Controls.HybridWebView.InvokeJavaScriptAsync(string! methodName, System.Text.Json.Serialization.Metadata.JsonTypeInfo! returnTypeJsonTypeInfo, object?[]? paramValues = null, System.Text.Json.Serialization.Metadata.JsonTypeInfo?[]? paramJsonTypeInfos = null) -> System.Threading.Tasks.Task! +Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler? +Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void +Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string? +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.PlatformWebViewProcessTerminatedEventArgs.PlatformWebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.StyleableElement +Microsoft.Maui.Controls.StyleableElement.class.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.class.set -> void +Microsoft.Maui.Controls.StyleableElement.Style.get -> Microsoft.Maui.Controls.Style! +Microsoft.Maui.Controls.StyleableElement.Style.set -> void +Microsoft.Maui.Controls.StyleableElement.StyleableElement() -> void +Microsoft.Maui.Controls.StyleableElement.StyleClass.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.StyleableElement.StyleClass.set -> void +Microsoft.Maui.Controls.TimeChangedEventArgs +Microsoft.Maui.Controls.TimeChangedEventArgs.NewTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan +Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void +Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler +Microsoft.Maui.Controls.TitleBar +Microsoft.Maui.Controls.TitleBar.Content.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.Content.set -> void +Microsoft.Maui.Controls.TitleBar.ForegroundColor.get -> Microsoft.Maui.Graphics.Color! +Microsoft.Maui.Controls.TitleBar.ForegroundColor.set -> void +Microsoft.Maui.Controls.TitleBar.Icon.get -> Microsoft.Maui.Controls.ImageSource! +Microsoft.Maui.Controls.TitleBar.Icon.set -> void +Microsoft.Maui.Controls.TitleBar.LeadingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.LeadingContent.set -> void +Microsoft.Maui.Controls.TitleBar.PassthroughElements.get -> System.Collections.Generic.IList! +Microsoft.Maui.Controls.TitleBar.Subtitle.get -> string! +Microsoft.Maui.Controls.TitleBar.Subtitle.set -> void +Microsoft.Maui.Controls.TitleBar.Title.get -> string! +Microsoft.Maui.Controls.TitleBar.Title.set -> void +Microsoft.Maui.Controls.TitleBar.TitleBar() -> void +Microsoft.Maui.Controls.TitleBar.TrailingContent.get -> Microsoft.Maui.IView? +Microsoft.Maui.Controls.TitleBar.TrailingContent.set -> void +Microsoft.Maui.Controls.VisualElement.Measure(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size +Microsoft.Maui.Controls.WebView.ProcessTerminated -> System.EventHandler +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs +Microsoft.Maui.Controls.WebViewProcessTerminatedEventArgs.WebViewProcessTerminatedEventArgs() -> void +Microsoft.Maui.Controls.Window.TitleBar.get -> Microsoft.Maui.ITitleBar? +Microsoft.Maui.Controls.Window.TitleBar.set -> void +Microsoft.Maui.Controls.Xaml.RequireServiceAttribute +override Microsoft.Maui.Controls.ContentPage.LayoutChildren(double x, double y, double width, double height) -> void +*REMOVED*override Microsoft.Maui.Controls.Layout.Measure(double widthConstraint, double heightConstraint, Microsoft.Maui.Controls.MeasureFlags flags = Microsoft.Maui.Controls.MeasureFlags.None) -> Microsoft.Maui.SizeRequest +override Microsoft.Maui.Controls.TitleBar.OnApplyTemplate() -> void +static Microsoft.Maui.Controls.BindableObjectExtensions.SetBinding(this Microsoft.Maui.Controls.BindableObject! self, Microsoft.Maui.Controls.BindableProperty! targetProperty, System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> void +static Microsoft.Maui.Controls.BindingBase.Create(System.Func! getter, Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, Microsoft.Maui.Controls.IValueConverter? converter = null, object? converterParameter = null, string? stringFormat = null, object? source = null, object? fallbackValue = null, object? targetNullValue = null) -> Microsoft.Maui.Controls.BindingBase! +*REMOVED*static Microsoft.Maui.Controls.FlyoutPage.ControlsFlyoutPageMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.HandlerProperties.GetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target) -> Microsoft.Maui.HandlerDisconnectPolicy +static Microsoft.Maui.Controls.HandlerProperties.SetDisconnectPolicy(Microsoft.Maui.Controls.BindableObject! target, Microsoft.Maui.HandlerDisconnectPolicy value) -> void +static Microsoft.Maui.Controls.TitleBar.DefaultTemplate.get -> Microsoft.Maui.Controls.ControlTemplate! +*REMOVED*static Microsoft.Maui.Controls.Toolbar.ControlsToolbarMapper -> Microsoft.Maui.IPropertyMapper! +static Microsoft.Maui.Controls.ViewExtensions.InvalidateMeasure(this Microsoft.Maui.Controls.VisualElement! view) -> void +static readonly Microsoft.Maui.Controls.HandlerProperties.DisconnectPolicyProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.StyleableElement.StyleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.ForegroundColorProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.IconProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.LeadingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.SubtitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TitleProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.TitleBar.TrailingContentProperty -> Microsoft.Maui.Controls.BindableProperty! +static readonly Microsoft.Maui.Controls.Window.TitleBarProperty -> Microsoft.Maui.Controls.BindableProperty! +virtual Microsoft.Maui.Controls.Application.ActivateWindow(Microsoft.Maui.Controls.Window! window) -> void diff --git a/src/Controls/src/Core/RadioButton/RadioButton.Mapper.cs b/src/Controls/src/Core/RadioButton/RadioButton.Mapper.cs index 23291481f845..03196e7fd56d 100644 --- a/src/Controls/src/Core/RadioButton/RadioButton.Mapper.cs +++ b/src/Controls/src/Core/RadioButton/RadioButton.Mapper.cs @@ -9,10 +9,6 @@ public partial class RadioButton { IMauiContext MauiContext => Handler?.MauiContext ?? throw new InvalidOperationException("MauiContext not set"); - [Obsolete("Use RadioButtonHandler.Mapper instead.")] - public static IPropertyMapper ControlsRadioButtonMapper = - new ControlsMapper(RadioButtonHandler.Mapper); - internal new static void RemapForControls() { RadioButtonHandler.Mapper.ReplaceMapping(nameof(IRadioButton.Content), MapContent); diff --git a/src/Controls/src/Core/RadioButton/RadioButton.cs b/src/Controls/src/Core/RadioButton/RadioButton.cs index 95778dbcea86..6a83884c2984 100644 --- a/src/Controls/src/Core/RadioButton/RadioButton.cs +++ b/src/Controls/src/Core/RadioButton/RadioButton.cs @@ -289,17 +289,12 @@ protected internal override void ChangeVisualState() base.ChangeVisualState(); } - IPlatformSizeService _platformSizeService; - + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { if (ControlTemplate == null) { - if (Handler != null) - return new SizeRequest(Handler.GetDesiredSize(widthConstraint, heightConstraint)); - - _platformSizeService ??= DependencyService.Get(); - return _platformSizeService.GetPlatformSize(this, widthConstraint, heightConstraint); + return Handler?.GetDesiredSize(widthConstraint, heightConstraint) ?? new(); } return base.OnMeasure(widthConstraint, heightConstraint); @@ -443,15 +438,6 @@ void HandleRadioButtonGroupValueChanged(Element layout, RadioButtonGroupValueCha SetValue(IsCheckedProperty, true, specificity: SetterSpecificity.FromHandler); } - static void BindToTemplatedParent(BindableObject bindableObject, params BindableProperty[] properties) - { - foreach (var property in properties) - { - bindableObject.SetBinding(property, new Binding(property.PropertyName, - source: RelativeBindingSource.TemplatedParent)); - } - } - static View BuildDefaultTemplate() { Border border = new Border() @@ -459,21 +445,21 @@ static View BuildDefaultTemplate() Padding = 6 }; - BindToTemplatedParent(border, BackgroundColorProperty, HorizontalOptionsProperty, - MarginProperty, OpacityProperty, RotationProperty, ScaleProperty, ScaleXProperty, ScaleYProperty, - TranslationYProperty, TranslationXProperty, VerticalOptionsProperty); - - border.SetBinding(Border.StrokeProperty, - new Binding(BorderColorProperty.PropertyName, - source: RelativeBindingSource.TemplatedParent)); - - border.SetBinding(Border.StrokeShapeProperty, - new Binding(CornerRadiusProperty.PropertyName, converter: new CornerRadiusToShape(), - source: RelativeBindingSource.TemplatedParent)); - - border.SetBinding(Border.StrokeThicknessProperty, - new Binding(BorderWidthProperty.PropertyName, - source: RelativeBindingSource.TemplatedParent)); + border.SetBinding(BackgroundColorProperty, static (RadioButton rb) => rb.BackgroundColor, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(HorizontalOptionsProperty, static (RadioButton rb) => rb.HorizontalOptions, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(MarginProperty, static (RadioButton rb) => rb.Margin, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(OpacityProperty, static (RadioButton rb) => rb.Opacity, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(RotationProperty, static (RadioButton rb) => rb.Rotation, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(ScaleProperty, static (RadioButton rb) => rb.Scale, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(ScaleXProperty, static (RadioButton rb) => rb.ScaleX, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(ScaleYProperty, static (RadioButton rb) => rb.ScaleY, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(TranslationYProperty, static (RadioButton rb) => rb.TranslationY, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(TranslationXProperty, static (RadioButton rb) => rb.TranslationX, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(VerticalOptionsProperty, static (RadioButton rb) => rb.VerticalOptions, source: RelativeBindingSource.TemplatedParent); + + border.SetBinding(Border.StrokeProperty, static (RadioButton rb) => rb.BorderColor, source: RelativeBindingSource.TemplatedParent); + border.SetBinding(Border.StrokeShapeProperty, static (RadioButton rb) => rb.CornerRadius, source: RelativeBindingSource.TemplatedParent, converter: new CornerRadiusToShape()); + border.SetBinding(Border.StrokeThicknessProperty, static (RadioButton rb) => rb.BorderWidth, source: RelativeBindingSource.TemplatedParent); var grid = new Grid { @@ -572,9 +558,8 @@ static View BuildDefaultTemplate() out checkMarkFillVisualStateDark); } - contentPresenter.SetBinding(MarginProperty, new Binding("Padding", source: RelativeBindingSource.TemplatedParent)); - contentPresenter.SetBinding(BackgroundColorProperty, new Binding(BackgroundColorProperty.PropertyName, - source: RelativeBindingSource.TemplatedParent)); + contentPresenter.SetBinding(MarginProperty, static (RadioButton radio) => radio.Padding, BindingMode.OneWay, source: RelativeBindingSource.TemplatedParent); + contentPresenter.SetBinding(BackgroundColorProperty, static (RadioButton radio) => radio.BackgroundColor, BindingMode.OneWay, source: RelativeBindingSource.TemplatedParent); grid.Add(normalEllipse); grid.Add(checkMark); diff --git a/src/Controls/src/Core/ReferenceTypeConverter.cs b/src/Controls/src/Core/ReferenceTypeConverter.cs index 5dad8b6ecd35..e42452b36797 100644 --- a/src/Controls/src/Core/ReferenceTypeConverter.cs +++ b/src/Controls/src/Core/ReferenceTypeConverter.cs @@ -10,6 +10,7 @@ namespace Microsoft.Maui.Controls { /// + [RequireService([typeof(IReferenceProvider), typeof(IProvideParentValues)])] public sealed class ReferenceTypeConverter : TypeConverter, IExtendedTypeConverter { diff --git a/src/Controls/src/Core/RefreshView/RefreshView.Mapper.cs b/src/Controls/src/Core/RefreshView/RefreshView.Mapper.cs index b4bbe23918cb..41329181883d 100644 --- a/src/Controls/src/Core/RefreshView/RefreshView.Mapper.cs +++ b/src/Controls/src/Core/RefreshView/RefreshView.Mapper.cs @@ -6,9 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class RefreshView { - [Obsolete("Use RefreshViewHandler.Mapper instead.")] - public static IPropertyMapper ControlsRefreshViewMapper = new ControlsMapper(RefreshViewHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.RefreshView legacy behaviors diff --git a/src/Controls/src/Core/Registrar.cs b/src/Controls/src/Core/Registrar.cs index 891d14bb0703..ac47c8cc0ec9 100644 --- a/src/Controls/src/Core/Registrar.cs +++ b/src/Controls/src/Core/Registrar.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using Microsoft.Extensions.DependencyInjection; @@ -21,37 +22,58 @@ public enum InitializationFlags : long namespace Microsoft.Maui.Controls.Internals { + internal struct HandlerType + { + internal const DynamicallyAccessedMemberTypes TargetMembers = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; + + [DynamicallyAccessedMembers(TargetMembers)] + public readonly Type Target; + public readonly short Priority; + + public HandlerType( + [DynamicallyAccessedMembers(TargetMembers)] Type target, + short priority) + { + Target = target; + Priority = priority; + } + } + [EditorBrowsable(EditorBrowsableState.Never)] public class Registrar where TRegistrable : class { - readonly Dictionary> _handlers = new Dictionary>(); + readonly Dictionary> _handlers = new Dictionary>(); static Type _defaultVisualType = typeof(VisualMarker.DefaultVisual); //static Type _materialVisualType = typeof(VisualMarker.MaterialVisual); static Type[] _defaultVisualRenderers = new[] { _defaultVisualType }; - public void Register(Type tview, Type trender, Type[] supportedVisuals, short priority) + public void Register( + Type tview, + [DynamicallyAccessedMembers(HandlerType.TargetMembers)] Type trender, + Type[] supportedVisuals, + short priority) { supportedVisuals = supportedVisuals ?? _defaultVisualRenderers; //avoid caching null renderers if (trender == null) return; - if (!_handlers.TryGetValue(tview, out Dictionary visualRenderers)) + if (!_handlers.TryGetValue(tview, out Dictionary visualRenderers)) { - visualRenderers = new Dictionary(); + visualRenderers = new Dictionary(); _handlers[tview] = visualRenderers; } for (int i = 0; i < supportedVisuals.Length; i++) { - if (visualRenderers.TryGetValue(supportedVisuals[i], out (Type target, short priority) existingTargetValue)) + if (visualRenderers.TryGetValue(supportedVisuals[i], out HandlerType existingTargetValue)) { - if (existingTargetValue.priority <= priority) - visualRenderers[supportedVisuals[i]] = (trender, priority); + if (existingTargetValue.Priority <= priority) + visualRenderers[supportedVisuals[i]] = new(trender, priority); } else - visualRenderers[supportedVisuals[i]] = (trender, priority); + visualRenderers[supportedVisuals[i]] = new(trender, priority); } // This registers a factory into the Handler version of the registrar. @@ -71,9 +93,11 @@ public void Register(Type tview, Type trender, Type[] supportedVisuals, short pr // }); } - public void Register(Type tview, Type trender, Type[] supportedVisual) => Register(tview, trender, supportedVisual, 0); + public void Register(Type tview, [DynamicallyAccessedMembers(HandlerType.TargetMembers)] Type trender, Type[] supportedVisual) + => Register(tview, trender, supportedVisual, 0); - public void Register(Type tview, Type trender) => Register(tview, trender, _defaultVisualRenderers); + public void Register(Type tview, [DynamicallyAccessedMembers(HandlerType.TargetMembers)] Type trender) + => Register(tview, trender, _defaultVisualRenderers); internal TRegistrable GetHandler(Type type) => GetHandler(type, _defaultVisualType); @@ -143,27 +167,28 @@ public TOut GetHandlerForObject(object obj, params object[] args) where TO public Type GetHandlerType(Type viewType) => GetHandlerType(viewType, _defaultVisualType); + [return: DynamicallyAccessedMembers(HandlerType.TargetMembers)] public Type GetHandlerType(Type viewType, Type visualType) { visualType = visualType ?? _defaultVisualType; // 1. Do we have this specific type registered already? - if (_handlers.TryGetValue(viewType, out Dictionary visualRenderers)) - if (visualRenderers.TryGetValue(visualType, out (Type target, short priority) specificTypeRenderer)) - return specificTypeRenderer.target; + if (_handlers.TryGetValue(viewType, out Dictionary visualRenderers)) + if (visualRenderers.TryGetValue(visualType, out HandlerType specificTypeRenderer)) + return specificTypeRenderer.Target; //else if (visualType == _materialVisualType) // VisualMarker.MaterialCheck(); if (visualType != _defaultVisualType && visualRenderers != null) - if (visualRenderers.TryGetValue(_defaultVisualType, out (Type target, short priority) specificTypeRenderer)) - return specificTypeRenderer.target; + if (visualRenderers.TryGetValue(_defaultVisualType, out HandlerType specificTypeRenderer)) + return specificTypeRenderer.Target; // 2. Do we have a RenderWith for this type or its base types? Register them now. RegisterRenderWithTypes(viewType, visualType); // 3. Do we have a custom renderer for a base type or did we just register an appropriate renderer from RenderWith? - if (LookupHandlerType(viewType, visualType, out (Type target, short priority) baseTypeRenderer)) - return baseTypeRenderer.target; + if (LookupHandlerType(viewType, visualType, out HandlerType baseTypeRenderer)) + return baseTypeRenderer.Target; else return null; } @@ -179,12 +204,12 @@ public Type GetHandlerTypeForObject(object obj) return GetHandlerType(type); } - bool LookupHandlerType(Type viewType, Type visualType, out (Type target, short priority) handlerType) + bool LookupHandlerType(Type viewType, Type visualType, out HandlerType handlerType) { visualType = visualType ?? _defaultVisualType; while (viewType != null && viewType != typeof(Element)) { - if (_handlers.TryGetValue(viewType, out Dictionary visualRenderers)) + if (_handlers.TryGetValue(viewType, out Dictionary visualRenderers)) if (visualRenderers.TryGetValue(visualType, out handlerType)) return true; @@ -195,7 +220,7 @@ bool LookupHandlerType(Type viewType, Type visualType, out (Type target, short p viewType = viewType.BaseType; } - handlerType = (null, 0); + handlerType = new(null, 0); return false; } @@ -211,7 +236,7 @@ void RegisterRenderWithTypes(Type viewType, Type visualType) // Only go through this process if we have not registered something for this type; // we don't want RenderWith renderers to override ExportRenderers that are already registered. // Plus, there's no need to do this again if we already have a renderer registered. - if (!_handlers.TryGetValue(viewType, out Dictionary visualRenderers) || + if (!_handlers.TryGetValue(viewType, out Dictionary visualRenderers) || !(visualRenderers.ContainsKey(visualType) || visualRenderers.ContainsKey(_defaultVisualType))) { @@ -272,7 +297,19 @@ static Registrar() Registered = new Registrar(); } - internal static Dictionary Effects { get; } = new(StringComparer.Ordinal); + internal struct EffectType + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + public readonly Type Type; + + public EffectType( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type) + { + Type = type; + } + } + + internal static Dictionary Effects { get; } = new(StringComparer.Ordinal); internal static Dictionary> StyleProperties => LazyStyleProperties.Value; @@ -369,9 +406,12 @@ public static void RegisterEffects(string resolutionName, ExportEffectAttribute[ } } - public static void RegisterEffect(string resolutionName, string id, Type effectType) + public static void RegisterEffect( + string resolutionName, + string id, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type effectType) { - Effects[resolutionName + "." + id] = effectType; + Effects[resolutionName + "." + id] = new(effectType); } /// diff --git a/src/Controls/src/Core/RelativeBindingSource.cs b/src/Controls/src/Core/RelativeBindingSource.cs index 8fb5a78ab099..af822ec99a3a 100644 --- a/src/Controls/src/Core/RelativeBindingSource.cs +++ b/src/Controls/src/Core/RelativeBindingSource.cs @@ -1,5 +1,8 @@ #nullable disable using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls { @@ -65,5 +68,166 @@ public static RelativeBindingSource TemplatedParent return _templatedParent ?? (_templatedParent = new RelativeBindingSource(RelativeBindingSourceMode.TemplatedParent)); } } + +#nullable enable + + internal async Task Apply(BindingExpression expression, Element relativeSourceTarget, BindableObject targetObject, BindableProperty targetProperty, SetterSpecificity specificity) + { + var bindingAdapter = new BindingExpressionAdapter(expression, targetObject, targetProperty, specificity); + await Apply(bindingAdapter, relativeSourceTarget); + } + + internal async Task Apply(TypedBindingBase binding, Element relativeSourceTarget, BindableObject targetObject, BindableProperty targetProperty, SetterSpecificity specificity) + { + var bindingAdapter = new TypedBindingAdapter(binding, targetObject, targetProperty, specificity); + await Apply(bindingAdapter, relativeSourceTarget); + } + + private async Task Apply(IBindingAdapter bindingAdapter, Element relativeSourceTarget) + { + object? resolvedSource = null; + switch (Mode) + { + case RelativeBindingSourceMode.Self: + resolvedSource = relativeSourceTarget; + break; + + case RelativeBindingSourceMode.TemplatedParent: + resolvedSource = await TemplateUtilities.FindTemplatedParentAsync(relativeSourceTarget); + break; + + case RelativeBindingSourceMode.FindAncestor: + case RelativeBindingSourceMode.FindAncestorBindingContext: + ApplyAncestorTypeBinding( + bindingAdapter, + relativeSourceTarget, + chain: new List { relativeSourceTarget }, + currentLevel: 0); + return; + + default: + throw new InvalidOperationException(); + } + + bindingAdapter.Apply(resolvedSource); + } + + private void ApplyAncestorTypeBinding( + IBindingAdapter bindingAdapter, + Element currentElement, + int currentLevel, + List chain, + object? lastMatchingBctx = null) + { + if (currentElement.RealParent is Application || + currentElement.RealParent == null) + { + // Couldn't find the desired ancestor type in the chain, but it may be added later, + // so apply with a null source for now. + bindingAdapter.Apply(null); + bindingAdapter.SubscribeToAncestryChanges( + chain, includeBindingContext: Mode == RelativeBindingSourceMode.FindAncestorBindingContext, rootIsSource: false); + } + else if (currentElement.RealParent != null) + { + chain.Add(currentElement.RealParent); + if (ElementFitsAncestorTypeAndLevel(currentElement.RealParent, ref currentLevel, ref lastMatchingBctx)) + { + object? resolvedSource; + if (Mode == RelativeBindingSourceMode.FindAncestor) + resolvedSource = currentElement.RealParent; + else + resolvedSource = currentElement.RealParent?.BindingContext; + bindingAdapter.Apply(resolvedSource); + bindingAdapter.SubscribeToAncestryChanges( + chain, includeBindingContext: Mode == RelativeBindingSourceMode.FindAncestorBindingContext, rootIsSource: true); + } + else + { + ApplyAncestorTypeBinding(bindingAdapter, currentElement.RealParent, currentLevel, chain, lastMatchingBctx); + } + } + else + { + EventHandler? onElementParentSet = null; + onElementParentSet = (sender, e) => + { + currentElement.ParentSet -= onElementParentSet; + ApplyAncestorTypeBinding(bindingAdapter, currentElement, currentLevel, chain, lastMatchingBctx); + }; + currentElement.ParentSet += onElementParentSet; + } + } + + private bool ElementFitsAncestorTypeAndLevel(Element element, ref int level, ref object? lastPotentialBctx) + { + bool fitsElementType = + Mode == RelativeBindingSourceMode.FindAncestor && + AncestorType!.IsAssignableFrom(element.GetType()); + + bool fitsBindingContextType = + element.BindingContext != null && + Mode == RelativeBindingSourceMode.FindAncestorBindingContext && + AncestorType!.IsAssignableFrom(element.BindingContext.GetType()); + + if (!fitsElementType && !fitsBindingContextType) + return false; + + if (fitsBindingContextType) + { + if (!object.ReferenceEquals(lastPotentialBctx, element.BindingContext)) + { + lastPotentialBctx = element.BindingContext; + level++; + } + } + else + { + level++; + } + + return level >= AncestorLevel; + } + + private interface IBindingAdapter + { + void Apply(object? resolvedSource); + void Unapply(); + void SubscribeToAncestryChanges(List chain, bool includeBindingContext, bool rootIsSource); + } + + private struct BindingExpressionAdapter( + BindingExpression expression, + BindableObject target, + BindableProperty property, + SetterSpecificity specificity) + : IBindingAdapter + { + public void Apply(object? resolvedSource) + => expression.Apply(resolvedSource, target, property, specificity); + + public void Unapply() + => expression.Unapply(); + + public void SubscribeToAncestryChanges(List chain, bool includeBindingContext, bool rootIsSource) + => expression.SubscribeToAncestryChanges(chain, includeBindingContext, rootIsSource); + } + + private struct TypedBindingAdapter( + TypedBindingBase binding, + BindableObject target, + BindableProperty property, + SetterSpecificity specificity) + : IBindingAdapter + { + public void Apply(object? resolvedSource) + => binding.ApplyToResolvedSource(resolvedSource, target, property, false, specificity); + + public void Unapply() + => binding.Unapply(); + + public void SubscribeToAncestryChanges(List chain, bool includeBindingContext, bool rootIsSource) + => binding.SubscribeToAncestryChanges(chain, includeBindingContext, rootIsSource); + } } } diff --git a/src/Controls/src/Core/RenderWithAttribute.cs b/src/Controls/src/Core/RenderWithAttribute.cs index 56028e5849e9..40974bae652a 100644 --- a/src/Controls/src/Core/RenderWithAttribute.cs +++ b/src/Controls/src/Core/RenderWithAttribute.cs @@ -1,5 +1,6 @@ #nullable disable using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls { @@ -7,14 +8,15 @@ namespace Microsoft.Maui.Controls [AttributeUsage(AttributeTargets.Class)] public sealed class RenderWithAttribute : Attribute { - /// - public RenderWithAttribute(Type type) : this(type, new[] { typeof(VisualMarker.DefaultVisual) }) + public RenderWithAttribute([DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type type) : this(type, new[] { typeof(VisualMarker.DefaultVisual) }) { } /// - public RenderWithAttribute(Type type, Type[] supportedVisuals) + public RenderWithAttribute( + [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] Type type, + Type[] supportedVisuals) { Type = type; SupportedVisuals = supportedVisuals ?? new[] { typeof(VisualMarker.DefaultVisual) }; @@ -22,7 +24,9 @@ public RenderWithAttribute(Type type, Type[] supportedVisuals) /// public Type[] SupportedVisuals { get; } + /// + [DynamicallyAccessedMembers(Internals.HandlerType.TargetMembers)] public Type Type { get; } } } \ No newline at end of file diff --git a/src/Controls/src/Core/ResourceDictionary.cs b/src/Controls/src/Core/ResourceDictionary.cs index 5cb81399d0df..f28b4086e7ae 100644 --- a/src/Controls/src/Core/ResourceDictionary.cs +++ b/src/Controls/src/Core/ResourceDictionary.cs @@ -5,13 +5,13 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using Microsoft.Maui.Controls.Internals; -using Microsoft.Maui.Controls.Xaml; namespace Microsoft.Maui.Controls { @@ -24,6 +24,9 @@ public class ResourceDictionary : IResourceDictionary, IDictionary s_setAndLoadSource; + /// [System.ComponentModel.TypeConverter(typeof(RDSourceTypeConverter))] public Uri Source @@ -33,23 +36,42 @@ public Uri Source { if (_source == value) return; - throw new InvalidOperationException("Source can only be set from XAML."); //through the RDSourceTypeConverter + throw new InvalidOperationException("Source can only be set from XAML."); // through SetSource } } //Used by the XamlC compiled converter - /// + /// [EditorBrowsable(EditorBrowsableState.Never)] - public void SetAndLoadSource(Uri value, string resourcePath, Assembly assembly, global::System.Xml.IXmlLineInfo lineInfo) + public void SetAndCreateSource(Uri value) + where T : ResourceDictionary, new() { - _source = value; + var instance = s_instances.GetValue(typeof(T), static _ => new T()); + SetSource(value, instance); + } - //this will return a type if the RD as an x:Class element, and codebehind - var type = XamlResourceIdAttribute.GetTypeForPath(assembly, resourcePath); - if (type != null) - _mergedInstance = s_instances.GetValue(type, _ => (ResourceDictionary)Activator.CreateInstance(type)); - else - _mergedInstance = DependencyService.Get().CreateFromResource(resourcePath, assembly, lineInfo); + // Used by hot reload + /// + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] + internal void SetAndLoadSource(Uri value, string resourcePath, Assembly assembly, global::System.Xml.IXmlLineInfo lineInfo) + { + if (s_setAndLoadSource is null) + { + throw new InvalidOperationException("ResourceDictionary.SetAndLoadSource was not initialized"); + } + + s_setAndLoadSource(this, value, resourcePath, assembly, lineInfo); + } + + internal static ResourceDictionary GetOrCreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) + { + return s_instances.GetValue(type, _ => (ResourceDictionary)Activator.CreateInstance(type)); + } + + internal void SetSource(Uri source, ResourceDictionary sourceInstance) + { + _source = source; + _mergedInstance = sourceInstance; OnValuesChanged(_mergedInstance.ToArray()); } @@ -390,26 +412,29 @@ object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceP if (rootObjectType == null) return null; - var lineInfo = (serviceProvider.GetService(typeof(Xaml.IXmlLineInfoProvider)) as Xaml.IXmlLineInfoProvider)?.XmlLineInfo; - var rootTargetPath = XamlResourceIdAttribute.GetPathForType(rootObjectType); - var assembly = rootObjectType.Assembly; + return GetUriWithExplicitAssembly(value, rootObjectType.Assembly); + } + internal static Uri GetUriWithExplicitAssembly(string value, Assembly defaultAssembly) + { + (value, var assembly) = SplitUriAndAssembly(value, defaultAssembly); + return CombineUriAndAssembly(value, assembly); + } + + internal static ValueTuple SplitUriAndAssembly(string value, Assembly defaultAssembly) + { if (value.IndexOf(";assembly=", StringComparison.Ordinal) != -1) { var parts = value.Split(new[] { ";assembly=" }, StringSplitOptions.RemoveEmptyEntries); - value = parts[0]; - var asmName = parts[1]; - assembly = Assembly.Load(asmName); + return (parts[0], Assembly.Load(parts[1])); } - var uri = new Uri(value, UriKind.Relative); //we don't want file:// uris, even if they start with '/' - var resourcePath = GetResourcePath(uri, rootTargetPath); - - //Re-add the assembly= in all cases, so HotReload doesn't have to make assumptions - uri = new Uri($"{value};assembly={assembly.GetName().Name}", UriKind.Relative); - targetRD.SetAndLoadSource(uri, resourcePath, assembly, lineInfo); + return (value, defaultAssembly); + } - return uri; + internal static Uri CombineUriAndAssembly(string value, Assembly assembly) + { + return new Uri($"{value};assembly={assembly.GetName().Name}", UriKind.Relative); } internal static string GetResourcePath(Uri uri, string rootTargetPath) diff --git a/src/Controls/src/Core/Routing.cs b/src/Controls/src/Core/Routing.cs index 675a9b6d5595..f18435e6c18c 100644 --- a/src/Controls/src/Core/Routing.cs +++ b/src/Controls/src/Core/Routing.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Text.RegularExpressions; namespace Microsoft.Maui.Controls { @@ -225,7 +224,7 @@ public static void UnRegisterRoute(string route) /// public static void RegisterRoute( string route, - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) { RegisterRoute(route, new TypeRouteFactory(type)); } @@ -259,11 +258,11 @@ static void ValidateRoute(string route, RouteFactory routeFactory) class TypeRouteFactory : RouteFactory { - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] readonly Type _type; public TypeRouteFactory( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) { _type = type; } @@ -277,7 +276,7 @@ public override Element GetOrCreate(IServiceProvider services) { if (services != null) { - return (Element)(services.GetService(_type) ?? Activator.CreateInstance(_type)); + return (Element)Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(services, _type); } return (Element)Activator.CreateInstance(_type); diff --git a/src/Controls/src/Core/ScrollView/ScrollView.Mapper.cs b/src/Controls/src/Core/ScrollView/ScrollView.Mapper.cs index 2b555274a8fb..0d522dbf0e56 100644 --- a/src/Controls/src/Core/ScrollView/ScrollView.Mapper.cs +++ b/src/Controls/src/Core/ScrollView/ScrollView.Mapper.cs @@ -6,10 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class ScrollView { - [Obsolete("Use ScrollViewHandler.Mapper instead.")] - public static IPropertyMapper ControlsScrollViewMapper = - new ControlsMapper(ScrollViewHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.ScrollView legacy behaviors diff --git a/src/Controls/src/Core/ScrollView/ScrollView.cs b/src/Controls/src/Core/ScrollView/ScrollView.cs index f4e555d44b1d..56f193939d9e 100644 --- a/src/Controls/src/Core/ScrollView/ScrollView.cs +++ b/src/Controls/src/Core/ScrollView/ScrollView.cs @@ -10,12 +10,15 @@ namespace Microsoft.Maui.Controls { /// [ContentProperty(nameof(Content))] +#pragma warning disable CS0618 // Type or member is obsolete public partial class ScrollView : Compatibility.Layout, IScrollViewController, IElementConfiguration, IFlowDirectionController, IScrollView, IContentView +#pragma warning restore CS0618 // Type or member is obsolete { #region IScrollViewController /// [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete] public Rect LayoutAreaOverride { get => _layoutAreaOverride; @@ -271,10 +274,12 @@ public Task ScrollToAsync(Element element, ScrollToPosition position, bool anima bool IFlowDirectionController.ApplyEffectiveFlowDirectionToChildContainer => false; + [Obsolete("Use ArrangeOverride instead")] protected override void LayoutChildren(double x, double y, double width, double height) { } + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { if (Content == null) @@ -361,26 +366,6 @@ double GetCoordinate(Element item, string coordinateName, double coordinate) return visualParentElement != null ? GetCoordinate(visualParentElement, coordinateName, coordinate) : coordinate; } - double GetMaxHeight(double height) - { - return Math.Max(height, _content.Bounds.Top + Padding.Top + _content.Bounds.Bottom + Padding.Bottom); - } - - static double GetMaxHeight(double height, SizeRequest size) - { - return Math.Max(size.Request.Height, height); - } - - double GetMaxWidth(double width) - { - return Math.Max(width, _content.Bounds.Left + Padding.Left + _content.Bounds.Right + Padding.Right); - } - - static double GetMaxWidth(double width, SizeRequest size) - { - return Math.Max(size.Request.Width, width); - } - void OnScrollToRequested(ScrollToRequestedEventArgs e) { CheckTaskCompletionSource(); diff --git a/src/Controls/src/Core/SearchBar/SearchBar.Mapper.cs b/src/Controls/src/Core/SearchBar/SearchBar.Mapper.cs index 960a8214eaf7..0bfd6cc6806f 100644 --- a/src/Controls/src/Core/SearchBar/SearchBar.Mapper.cs +++ b/src/Controls/src/Core/SearchBar/SearchBar.Mapper.cs @@ -6,10 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class SearchBar { - [Obsolete("Use SearchBarHandler.Mapper instead.")] - public static IPropertyMapper ControlsSearchBarMapper = - new ControlsMapper(SearchBarHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.SearchBar legacy behaviors diff --git a/src/Controls/src/Core/Setter.cs b/src/Controls/src/Core/Setter.cs index f21b1f8b863e..6634cb006288 100644 --- a/src/Controls/src/Core/Setter.cs +++ b/src/Controls/src/Core/Setter.cs @@ -11,6 +11,9 @@ namespace Microsoft.Maui.Controls /// [ContentProperty(nameof(Value))] [ProvideCompiled("Microsoft.Maui.Controls.XamlC.SetterValueProvider")] + [RequireService( + [typeof(IValueConverterProvider), + typeof(IXmlLineInfoProvider)])] public sealed class Setter : IValueProvider { /// diff --git a/src/Controls/src/Core/SetterSpecificity.cs b/src/Controls/src/Core/SetterSpecificity.cs index 04ddb2c84830..9189b6439ae8 100644 --- a/src/Controls/src/Core/SetterSpecificity.cs +++ b/src/Controls/src/Core/SetterSpecificity.cs @@ -1,107 +1,206 @@ #nullable disable using System; +using System.Runtime.CompilerServices; namespace Microsoft.Maui.Controls { - //NOTE: IDEA: review this: merge FROM into a single int (vsm, manual, dynamicR, binding), and CSS into another - internal readonly struct SetterSpecificity : IComparable, IEquatable + /// + /// Defines a setter specificity + /// + /// + /// We still can refine the specificities, but here is how they're compared right now: + /// - DefaultValue has the lowest priority + /// - Everything coming from a Style is low priority + /// - Binding, DynamicResource, Manual (in that order) + /// - Values set from VSM have a higher priority + /// + /// Then everything coming from the Handlers has a special priority. it is always applied, but is overridden by almost everything else + /// + internal readonly struct SetterSpecificity { - public static readonly SetterSpecificity DefaultValue = new(-1, 0, 0, 0, -1, 0, 0, 0); - public static readonly SetterSpecificity VisualStateSetter = new SetterSpecificity(1, 0, 0, 0, 0, 0, 0, 0); + const byte ExtrasVsm = 0x01; + const byte ExtrasHandler = 0xFF; + + public const ushort ManualTriggerBaseline = 2; + + public const ushort StyleImplicit = 0x080; + public const ushort StyleLocal = 0x100; + + public static readonly SetterSpecificity DefaultValue = new SetterSpecificity(0); + public static readonly SetterSpecificity VisualStateSetter = new SetterSpecificity(ExtrasVsm, 0, 0, 0, 0, 0, 0, 0); public static readonly SetterSpecificity FromBinding = new SetterSpecificity(0, 0, 0, 1, 0, 0, 0, 0); - public static readonly SetterSpecificity ManualValueSetter = new SetterSpecificity(0, 100, 0, 0, 0, 0, 0, 0); - public static readonly SetterSpecificity Trigger = new SetterSpecificity(0, 101, 0, 0, 0, 0, 0, 0); + public static readonly SetterSpecificity ManualValueSetter = new SetterSpecificity(0, 1, 0, 0, 0, 0, 0, 0); + public static readonly SetterSpecificity Trigger = new SetterSpecificity(0, ManualTriggerBaseline, 0, 0, 0, 0, 0, 0); public static readonly SetterSpecificity DynamicResourceSetter = new SetterSpecificity(0, 0, 1, 0, 0, 0, 0, 0); - //handler always apply, but are removed when anything else comes in. see SetValueActual - public static readonly SetterSpecificity FromHandler = new SetterSpecificity(1000, 0, 0, 0, 0, 0, 0, 0); + // handler always apply, but are removed when anything else comes in. see SetValueActual + public static readonly SetterSpecificity FromHandler = new SetterSpecificity(0xFF, 0, 0, 0, 0, 0, 0, 0); + + // We store all information in one single UInt64 value to have the fastest comparison possible + readonly ulong _value; - //100-n: direct VSM (not from Style), n = max(99, distance between the RD and the target) - public int Vsm { get; } - //1: SetValue, SetBinding - public int Manual { get; } + public bool IsDefault => _value == 0ul; + public bool IsHandler => _value == 0xFFFFFFFFFFFFFFFF; + public bool IsVsm => (_value & 0x0100000000000000) != 0; + public bool IsVsmImplicit => (_value & 0x0000000004000000) != 0; + public bool IsManual => ((_value >> 28) & 0xFFFF) == 1; + public ushort TriggerIndex => GetTriggerIndex(); + public bool IsDynamicResource => ((_value >> 24) & 0x02) != 0; + public bool IsBinding => ((_value >> 24) & 0x01) != 0; + public (ushort Style, byte Id, byte Class, byte Type) StyleInfo => GetStyleInfo(); - //1: DynamicResource - public int DynamicResource { get; } - - //1: SetBinding - public int Binding { get; } - - //XAML Style specificity - //100-n: implicit style, n = max(99, distance between the RD and the target) - //200-n: RD Style, n = max(99, distance between the RD and the target) - //200: local style, inline css, - //300-n: VSM, n = max(99, distance between the RD and the target) - //300: !important (not implemented) - public int Style { get; } + ushort GetTriggerIndex() + { + var manual = (ushort)((_value >> 28) & 0xFFFF); + if (manual <= 1) return 0; + return (ushort)(manual - 2); + } - public const int StyleImplicit = 100; - public const int StyleRD = 200; - public const int StyleLocal = 200; - public const int StyleVSM = 300; + (ushort Style, byte Id, byte Class, byte Type) GetStyleInfo() + { + var style = (ushort)((_value >> 44) & 0xFFF); + if (style == 0xFFF) return default; + return (style, (byte)((_value >> 16) & 0xFF), (byte)((_value >> 8) & 0xFF), (byte)(_value & 0xFF)); + } - //CSS Specificity, see https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity - public int Id { get; } - public int Class { get; } - public int Type { get; } - public SetterSpecificity(int vsm, int manual, int dynamicresource, int binding, int style, int id, int @class, int type) + /// + /// Creates a new setter specificity + /// + /// + /// Specifies special setter sources
+ /// - 1: from VSM
+ /// - 0xFF: from Handler + /// + /// + /// Determines manual specificity, also covers triggers
+ /// - 0: not manual
+ /// - 1..100: manual
+ /// - 101..N: triggers
+ /// + /// Set to 1 when value comes from dynamic resource, otherwise 0 + /// Set to 1 when value comes from binding, otherwise 0 + /// + /// XAML Style specificity
+ /// - 0: not from Style
+ /// - 127: base implicit style + /// - 128-n: implicit style, n = max(99, distance between the RD and the target)
+ /// - 255: base local style + /// - 256-n: local style, inline css,
+ /// + /// + /// CSS Id Specificity
+ /// See https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity + /// + /// + /// CSS Class Specificity
+ /// See https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity + /// + /// + /// CSS Type Specificity
+ /// See https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity + /// + /// + public SetterSpecificity(byte extras, ushort manual, byte isDynamicResource, byte isBinding, ushort style, byte id, byte @class, byte type) { - Vsm = vsm; - Manual = manual; - DynamicResource = dynamicresource; - Binding = binding; - Style = style; - Id = id; - Class = @class; - Type = type; + // Handlers are special, they win on everything else + if (extras == ExtrasHandler) + { + _value = 0xFFFFFFFFFFFFFFFF; + return; + } + + // If no style is set, set it to a value which supersedes any other style value + if (style == 0) + { + style = 0xFFF; + id = @class = type = 0xFF; + } + + // Priority order: + // 64bit ulong value + // 1. VSM 0x0100000000000000 + // 2. Style 0x00FFF00000000000 + // 3. Manual(& Trigger) 0x00000FFFF0000000 + // 4. Implicit VSM 0x0000000004000000 + // 4. DynamicResource 0x0000000002000000 + // 5. Binding 0x0000000001000000 + // 6. Id 0x0000000000FF0000 + // 7. Class 0x000000000000FF00 + // 8. Type 0x00000000000000FF + + var implicitVsm = 0; + var vsm = extras == ExtrasVsm ? 0x01 : 0; + var binding = isBinding > 0 ? 0x01 : 0; + var dynamicResource = isDynamicResource > 0 ? 0x02 : 0; + + // Implicit style VSM has less priority than manually set values + // See https://github.com/dotnet/maui/issues/18103 + const int styleImplicitUpperBound = StyleLocal - 1; + if (vsm != 0 && style < styleImplicitUpperBound) + { + implicitVsm = 0x04; + vsm = 0; + } + + _value = type + | (ulong)@class << 8 + | (ulong)id << 16 + | (ulong)(implicitVsm | dynamicResource | binding) << 24 + | (ulong)manual << 28 + | (ulong)style << 44 + | (ulong)vsm << 56 + ; } - public SetterSpecificity(int style, int id, int @class, int type) : this(0, 0, 0, 0, style, id, @class, type) + public SetterSpecificity(ushort style, byte id, byte @class, byte type) : this(0, 0, 0, 0, style, id, @class, type) { } - public int CompareTo(SetterSpecificity other) + public SetterSpecificity() { - //VSM setters win over Manual value, except for implicit style VSMs - if (Vsm != other.Vsm && ( - Style != 0 && Style < StyleRD && other.Manual <= 0 - || other.Style != 0 && other.Style < StyleRD && Manual <= 0 - || Style >= StyleRD || other.Style >= StyleRD - || Style <= 0 && other.Style <= 0)) - return Vsm.CompareTo(other.Vsm); - - //everything coming from Style has lower priority than something that does not - if (Style != other.Style && Style == 0) - return 1; - if (Style != other.Style && other.Style == 0) - return -1; - if (Style != other.Style) - return Style.CompareTo(other.Style); - - if (Manual != other.Manual) - return Manual.CompareTo(other.Manual); - if (DynamicResource != other.DynamicResource) - return DynamicResource.CompareTo(other.DynamicResource); - if (Binding != other.Binding) - return Binding.CompareTo(other.Binding); - if (Id != other.Id) - return Id.CompareTo(other.Id); - if (Class != other.Class) - return Class.CompareTo(other.Class); - return Type.CompareTo(other.Type); + // When no parameter have been specified for the specificity, just use the lowest value possible + // This value is still higher than the DefaultValue, so it will be applied + _value = 1; } - public override bool Equals(object obj) => obj is SetterSpecificity s && Equals(s); - - public bool Equals(SetterSpecificity other) => CompareTo(other) == 0; + /// + /// Special private constructor to create DefaultValue specificity + /// + SetterSpecificity(ulong value) + { + _value = value; + } - public override int GetHashCode() => (Vsm, Manual, DynamicResource, Binding, Style, Id, Class, Type).GetHashCode(); + public SetterSpecificity CopyStyle(byte extras, ushort manual, byte isDynamicResource, byte isBinding) + { + return new SetterSpecificity( + extras, + manual, + isDynamicResource, + isBinding, + style: (ushort)((_value >> 44) & 0xFFF), + id: (byte)((_value >> 16) & 0xFF), + @class: (byte)((_value >> 8) & 0xFF), + type: (byte)(_value & 0xFF)); + } - public static bool operator ==(SetterSpecificity left, SetterSpecificity right) => left.Equals(right); - public static bool operator !=(SetterSpecificity left, SetterSpecificity right) => !left.Equals(right); + public SetterSpecificity AsBaseStyle() + { + return new SetterSpecificity(_value - 0x0000100000000000); + } + + public override bool Equals(object obj) => obj is SetterSpecificity s && s._value == _value; + public override int GetHashCode() => _value.GetHashCode(); + + public static bool operator <(SetterSpecificity left, SetterSpecificity right) => left._value < right._value; + public static bool operator >(SetterSpecificity left, SetterSpecificity right) => left._value > right._value; + public static bool operator >=(SetterSpecificity left, SetterSpecificity right) => left._value >= right._value; + public static bool operator <=(SetterSpecificity left, SetterSpecificity right) => left._value <= right._value; + public static bool operator ==(SetterSpecificity left, SetterSpecificity right) => left._value == right._value; + public static bool operator !=(SetterSpecificity left, SetterSpecificity right) => left._value != right._value; } -} \ No newline at end of file +} diff --git a/src/Controls/src/Core/SetterSpecificityList.cs b/src/Controls/src/Core/SetterSpecificityList.cs index 90658c927737..12e59eddc6c6 100644 --- a/src/Controls/src/Core/SetterSpecificityList.cs +++ b/src/Controls/src/Core/SetterSpecificityList.cs @@ -1,142 +1,234 @@ -using System; +#nullable disable + +using System; using System.Collections.Generic; -using System.Linq; +using System.Runtime.CompilerServices; namespace Microsoft.Maui.Controls { /// - /// Class for managing up to two Specificity values, and falling back to a SortedList once three values are present. - /// This yields better performance in cases where a BP has one or two Specificity values set. + /// Stores values for a property with different specificities. /// - internal class SetterSpecificityList + internal class SetterSpecificityList where T : class { - KeyValuePair? _first; - KeyValuePair? _second; - SortedList? _values; - - object _lock = new(); - - public object this[SetterSpecificity key] - { - set => SetValue(key, value); - } - - public void SetValue(SetterSpecificity specificity, object value) - { - if (_first is null || _first.Value.Key == specificity) - { - _first = new KeyValuePair(specificity, value); - lock(_lock) { - if (_values is not null) - _values[specificity] = value; - } - return; - } + const int CapacityDelta = 3; + + SetterSpecificity[] _keys; + T[] _values; + int _count; + + public int Count => _count; - if (_second is null || _second.Value.Key == specificity) - { - _second = new KeyValuePair(specificity, value); - lock(_lock) { - if (_values is not null) - _values[specificity] = value; - } - return; - } + public T this[SetterSpecificity key] + { + set => SetValue(key, value); + get => GetValue(key); + } - lock(_lock) { - if (_values is null) - { - _values = new() - { - [_first.Value.Key] = _first.Value.Value, - [_second.Value.Key] = _second.Value.Value, - }; - // Clear the fields, to reduce duplication in memory - _first = null; - _second = null; - } - - _values[specificity] = value; - } - } - - public void Remove(SetterSpecificity specificity) - { - lock(_lock) - { - if (_values is not null) - _values.Remove(specificity); - } - if (_first is not null && _first.Value.Key == specificity) - _first = null; - if (_second is not null && _second.Value.Key == specificity) - _second = null; - } - - public KeyValuePair GetSpecificityAndValue() - { - // Slow path calls SortedList.Last() - lock(_lock) { - if (_values is not null) { - return _values.Last(); - } - } - // Fast path accesses _first and _second - if (_first is not null && _second is not null) - { - if (_first.Value.Key.CompareTo(_second.Value.Key) >= 0) - { - return _first.Value; - } - else - { - return _second.Value; - } - } - else if (_first is not null) - { - return _first.Value; - } - else if (_second is not null) - { - return _second.Value; - } + public SetterSpecificityList() + { + _keys = Array.Empty(); + _values = Array.Empty(); + } - throw new InvalidOperationException("No BindablePropertyContext Value specified!"); - } + public SetterSpecificityList(int initialCapacity) + { + if (initialCapacity == 0) + { + _keys = Array.Empty(); + _values = Array.Empty(); + } + else + { + _keys = new SetterSpecificity[initialCapacity]; + _values = new T[initialCapacity]; + } + } + + /// + /// Gets the highest specificity + /// + /// + public SetterSpecificity GetSpecificity() + { + var index = _count - 1; + return index < 0 ? default : _keys[index]; + } + + /// + /// Gets the value for the highest specificity + /// + /// + public T GetValue() + { + var index = _count - 1; + return index < 0 ? default : _values[index]; + } + + /// + /// Returns what the value would be if the current value was removed + /// + public T GetClearedValue() + { + var index = _count - 2; + return index < 0 ? default : _values[index]; + } /// - /// Called by ClearValueCore, returns what the top value would be if cleared - /// - public object? GetClearedValue(SetterSpecificity clearedSpecificity) - { - lock(_lock) { - if (_values is not null) - { - var index = _values.IndexOfKey(clearedSpecificity); - if (index == _values.Count - 1) //last value will be cleared - return _values.Count >= 2 ? _values[_values.Keys[_values.Count - 2]] : null; - return _values.Last().Value; - } + /// Returns what the value would be if the specificity value was removed + /// + public T GetClearedValue(SetterSpecificity specificity) + { + var index = _count - 1; + if (index >= 0 && _keys[index] == specificity) { + --index; } + return index < 0 ? default : _values[index]; + } + + /// + /// Returns what the SetterSpecificity would be if the current value was removed + /// + public SetterSpecificity GetClearedSpecificity() + { + var index = _count - 2; + return index < 0 ? default : _keys[index]; + } + + /// + /// Gets the highest specificity and value + /// + /// + public KeyValuePair GetSpecificityAndValue() + { + var index = _count - 1; + return index < 0 ? default : new KeyValuePair(_keys[index], _values[index]); + } - // Fast path should return the "lower" value - if (_first is not null && _second is not null) - { - if (_first.Value.Key == clearedSpecificity) - return _second.Value.Value; - return _first.Value.Value; - } - else if (_first is not null) - { - return _first.Value.Value; - } - else if (_second is not null) - { - return _second.Value.Value; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void SetValue(SetterSpecificity key, T value) + { + var count = _count; + var lo = 0; + var hi = count - 1; + while (lo <= hi) + { + var index = lo + ((hi - lo) >> 1); + + var indexSpecificity = _keys[index]; + if (indexSpecificity == key) + { + _values[index] = value; + return; + } + + if (indexSpecificity < key) + { + lo = index + 1; + } + else + { + hi = index - 1; + } + } + + if (_keys.Length == count) + { + SetCapacity(count, count + CapacityDelta); + } + + if (count > lo) + { + Array.Copy(_keys, lo, _keys, lo + 1, count - lo); + Array.Copy(_values, lo, _values, lo + 1, count - lo); + } + + _keys[lo] = key; + _values[lo] = value; + + ++_count; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + T GetValue(SetterSpecificity key) + { + var count = _count; + var lo = 0; + var hi = count - 1; + while (lo <= hi) + { + var index = lo + ((hi - lo) >> 1); + + var indexSpecificity = _keys[index]; + if (indexSpecificity == key) + { + return _values[index]; + } + + if (indexSpecificity < key) + { + lo = index + 1; + } + else + { + hi = index - 1; + } + } + + return default; + } + + public void Remove(SetterSpecificity key) + { + var count = _count; + var lo = 0; + var hi = count - 1; + while (lo <= hi) + { + var index = lo + ((hi - lo) >> 1); + + var indexSpecificity = _keys[index]; + if (indexSpecificity == key) + { + var nextIndex = index + 1; + if (nextIndex < count) + { + Array.Copy(_keys, nextIndex, _keys, index, count - nextIndex); + Array.Copy(_values, nextIndex, _values, index, count - nextIndex); + _values[count - 1] = null; + } + else + { + _values[index] = null; + } + + --_count; + return; + } + + if (indexSpecificity < key) + { + lo = index + 1; + } + else + { + hi = index - 1; + } + } + } - return null; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void SetCapacity(int currentCapacity, int capacity) + { + var newKeys = new SetterSpecificity[capacity]; + var newValues = new T[capacity]; + if (currentCapacity > 0) + { + Array.Copy(_keys, newKeys, currentCapacity); + Array.Copy(_values, newValues, currentCapacity); + } + _keys = newKeys; + _values = newValues; + } } -} +} \ No newline at end of file diff --git a/src/Controls/src/Core/Shape/Shape.Mapper.cs b/src/Controls/src/Core/Shape/Shape.Mapper.cs index 866026aa73b2..1aacac625557 100644 --- a/src/Controls/src/Core/Shape/Shape.Mapper.cs +++ b/src/Controls/src/Core/Shape/Shape.Mapper.cs @@ -11,9 +11,6 @@ namespace Microsoft.Maui.Controls.Shapes { public partial class Shape { - [Obsolete("Use ShapeViewHandler.Mapper instead.")] - public static IPropertyMapper ControlsShapeViewMapper = new ControlsMapper(ShapeViewHandler.Mapper); - internal new static void RemapForControls() { ShapeViewHandler.Mapper.ReplaceMapping(nameof(StrokeDashArray), MapStrokeDashArray); diff --git a/src/Controls/src/Core/Shapes/PointCollectionConverter.cs b/src/Controls/src/Core/Shapes/PointCollectionConverter.cs index 94d5754cabbb..931e3c427b83 100644 --- a/src/Controls/src/Core/Shapes/PointCollectionConverter.cs +++ b/src/Controls/src/Core/Shapes/PointCollectionConverter.cs @@ -12,13 +12,18 @@ namespace Microsoft.Maui.Controls.Shapes public class PointCollectionConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - => sourceType == typeof(string); + => sourceType == typeof(string) || sourceType == typeof(Point[]); public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => destinationType == typeof(string); public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { + if (value is Point[] pointArray) + { + return (PointCollection)pointArray; + } + var strValue = value?.ToString(); string[] points = strValue.Split(new char[] { ' ', ',' }); var pointCollection = new PointCollection(); diff --git a/src/Controls/src/Core/Shell/BackButtonBehavior.cs b/src/Controls/src/Core/Shell/BackButtonBehavior.cs index 103030cf59a2..00cda2e1b393 100644 --- a/src/Controls/src/Core/Shell/BackButtonBehavior.cs +++ b/src/Controls/src/Core/Shell/BackButtonBehavior.cs @@ -23,11 +23,11 @@ public class BackButtonBehavior : BindableObject /// Bindable property for . public static readonly BindableProperty IsEnabledProperty = - BindableProperty.Create(nameof(IsEnabled), typeof(bool), typeof(BackButtonBehavior), true, BindingMode.OneTime); + BindableProperty.Create(nameof(IsEnabled), typeof(bool), typeof(BackButtonBehavior), true, BindingMode.OneWay); /// Bindable property for . public static readonly BindableProperty IsVisibleProperty = - BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(BackButtonBehavior), true, BindingMode.OneTime); + BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(BackButtonBehavior), true, BindingMode.OneWay); /// Bindable property for . public static readonly BindableProperty TextOverrideProperty = diff --git a/src/Controls/src/Core/Shell/BaseShellItem.cs b/src/Controls/src/Core/Shell/BaseShellItem.cs index 2e677cb1a70c..b32e5e4b9726 100644 --- a/src/Controls/src/Core/Shell/BaseShellItem.cs +++ b/src/Controls/src/Core/Shell/BaseShellItem.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; @@ -57,6 +56,10 @@ public class BaseShellItem : NavigableElement, IPropertyPropagationController, I public static readonly BindableProperty IsVisibleProperty = BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(BaseShellItem), true); + /// Bindable property for . + public static readonly BindableProperty FlyoutItemIsVisibleProperty = + BindableProperty.Create(nameof(FlyoutItemIsVisible), typeof(bool), typeof(BaseShellItem), true, propertyChanged: OnFlyoutItemIsVisibleChanged); + public BaseShellItem() { DeclaredChildren.CollectionChanged += (_, args) => @@ -116,10 +119,11 @@ public bool IsVisible set => SetValue(IsVisibleProperty, value); } + /// public bool FlyoutItemIsVisible { - get => (bool)GetValue(Shell.FlyoutItemIsVisibleProperty); - set => SetValue(Shell.FlyoutItemIsVisibleProperty, value); + get => (bool)GetValue(FlyoutItemIsVisibleProperty); + set => SetValue(FlyoutItemIsVisibleProperty, value); } @@ -225,6 +229,11 @@ static void OnIconChanged(BindableObject bindable, object oldValue, object newVa shellItem.FlyoutIcon = (ImageSource)newValue; } + static void OnFlyoutItemIsVisibleChanged(BindableObject bindable, object oldValue, object newValue) + { + Shell.SetFlyoutItemIsVisible(bindable, (bool)newValue); + } + protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) { base.OnPropertyChanged(propertyName); @@ -339,7 +348,7 @@ BindableObject NonImplicitParent } } - internal static DataTemplate CreateDefaultFlyoutItemCell(string textBinding, string iconBinding) + internal static DataTemplate CreateDefaultFlyoutItemCell(BindableObject bo) { return new DataTemplate(() => { @@ -426,9 +435,22 @@ internal static DataTemplate CreateDefaultFlyoutItemCell(string textBinding, str columnDefinitions.Add(new ColumnDefinition { Width = GridLength.Star }); defaultGridClass.Setters.Add(new Setter { Property = Grid.ColumnDefinitionsProperty, Value = columnDefinitions }); - Binding automationIdBinding = new Binding(Element.AutomationIdProperty.PropertyName); + BindingBase automationIdBinding = Binding.Create(static (Element element) => element.AutomationId); defaultGridClass.Setters.Add(new Setter { Property = Element.AutomationIdProperty, Value = automationIdBinding }); + BindingBase imageBinding = null; + BindingBase labelBinding = null; + if (bo is MenuItem) + { + imageBinding = Binding.Create(static (MenuItem item) => item.IconImageSource); + labelBinding = Binding.Create(static (MenuItem item) => item.Text); + } + else + { + imageBinding = Binding.Create(static (BaseShellItem item) => item.FlyoutIcon); + labelBinding = Binding.Create(static (BaseShellItem item) => item.Title); + } + var image = new Image(); double sizeRequest = -1; @@ -453,13 +475,11 @@ internal static DataTemplate CreateDefaultFlyoutItemCell(string textBinding, str defaultImageClass.Setters.Add(new Setter { Property = Image.MarginProperty, Value = new Thickness(12, 0, 12, 0) }); } - Binding imageBinding = new Binding(iconBinding); defaultImageClass.Setters.Add(new Setter { Property = Image.SourceProperty, Value = imageBinding }); grid.Add(image); var label = new Label(); - Binding labelBinding = new Binding(textBinding); defaultLabelClass.Setters.Add(new Setter { Property = Label.TextProperty, Value = labelBinding }); grid.Add(label, 1, 0); @@ -527,7 +547,7 @@ internal static DataTemplate CreateDefaultFlyoutItemCell(string textBinding, str // just bind the semantic description to the title if (!g.IsSet(SemanticProperties.DescriptionProperty)) { - g.SetBinding(SemanticProperties.DescriptionProperty, TitleProperty.PropertyName); + g.SetBinding(SemanticProperties.DescriptionProperty, static (BaseShellItem item) => item.Title); } } } diff --git a/src/Controls/src/Core/Shell/MenuShellItem.cs b/src/Controls/src/Core/Shell/MenuShellItem.cs index a0dcdaaf9d59..afae10213a9e 100644 --- a/src/Controls/src/Core/Shell/MenuShellItem.cs +++ b/src/Controls/src/Core/Shell/MenuShellItem.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; +using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.StyleSheets; namespace Microsoft.Maui.Controls @@ -13,10 +14,11 @@ internal MenuShellItem(MenuItem menuItem) MenuItem = menuItem; MenuItem.Parent = this; Shell.SetFlyoutItemIsVisible(this, Shell.GetFlyoutItemIsVisible(menuItem)); - SetBinding(TitleProperty, new Binding(nameof(MenuItem.Text), BindingMode.OneWay, source: menuItem)); - SetBinding(IconProperty, new Binding(nameof(MenuItem.IconImageSource), BindingMode.OneWay, source: menuItem)); - SetBinding(FlyoutIconProperty, new Binding(nameof(MenuItem.IconImageSource), BindingMode.OneWay, source: menuItem)); - SetBinding(AutomationIdProperty, new Binding(nameof(MenuItem.AutomationId), BindingMode.OneWay, source: menuItem)); + + this.SetBinding(TitleProperty, static (MenuItem item) => item.Text, BindingMode.OneWay, source: menuItem); + this.SetBinding(IconProperty, static (MenuItem item) => item.IconImageSource, BindingMode.OneWay, source: menuItem); + this.SetBinding(FlyoutIconProperty, static (MenuItem item) => item.IconImageSource, BindingMode.OneWay, source: menuItem); + this.SetBinding(AutomationIdProperty, static (MenuItem item) => item.AutomationId, BindingMode.OneWay, source: menuItem); MenuItem.PropertyChanged += OnMenuItemPropertyChanged; } diff --git a/src/Controls/src/Core/Shell/QueryPropertyAttribute.cs b/src/Controls/src/Core/Shell/QueryPropertyAttribute.cs index 550aee78ceae..191cb3af6e6d 100644 --- a/src/Controls/src/Core/Shell/QueryPropertyAttribute.cs +++ b/src/Controls/src/Core/Shell/QueryPropertyAttribute.cs @@ -1,10 +1,12 @@ #nullable disable using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls { /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + [RequiresUnreferencedCode(TrimmerConstants.QueryPropertyAttributeWarning, Url = TrimmerConstants.QueryPropertyDocsUrl)] public class QueryPropertyAttribute : Attribute { /// diff --git a/src/Controls/src/Core/Shell/SearchHandler.cs b/src/Controls/src/Core/Shell/SearchHandler.cs index ff6c8507dcc1..bf6e893d5197 100644 --- a/src/Controls/src/Core/Shell/SearchHandler.cs +++ b/src/Controls/src/Core/Shell/SearchHandler.cs @@ -361,9 +361,11 @@ void ISearchHandlerController.QueryConfirmed() BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(SearchHandler), null, BindingMode.OneTime, propertyChanged: OnCommandChanged); +#pragma warning disable CS0618 /// Bindable property for . public static readonly BindableProperty DisplayMemberNameProperty = BindableProperty.Create(nameof(DisplayMemberName), typeof(string), typeof(SearchHandler), null, BindingMode.OneTime); +#pragma warning restore CS0618 /// Bindable property for . public static readonly BindableProperty IsSearchEnabledProperty = @@ -498,6 +500,7 @@ public object CommandParameter } /// + [Obsolete("Use ItemTemplate instead.")] public string DisplayMemberName { get { return (string)GetValue(DisplayMemberNameProperty); } diff --git a/src/Controls/src/Core/Shell/Shell.cs b/src/Controls/src/Core/Shell/Shell.cs index 293869decb4b..378d0a624aa1 100644 --- a/src/Controls/src/Core/Shell/Shell.cs +++ b/src/Controls/src/Core/Shell/Shell.cs @@ -37,10 +37,10 @@ public partial class Shell : Page, IShellController, IPropertyPropagationControl static void OnBackButonBehaviorPropertyChanged(BindableObject bindable, object oldValue, object newValue) { - if (oldValue is BackButtonBehavior oldHandlerBehavior) - SetInheritedBindingContext(oldHandlerBehavior, null); - if (newValue is BackButtonBehavior newHandlerBehavior) - SetInheritedBindingContext(newHandlerBehavior, bindable.BindingContext); + if (oldValue is BackButtonBehavior oldHandlerProperties) + SetInheritedBindingContext(oldHandlerProperties, null); + if (newValue is BackButtonBehavior newHandlerProperties) + SetInheritedBindingContext(newHandlerProperties, bindable.BindingContext); } /// @@ -121,6 +121,9 @@ static void OnFlyoutItemIsVisibleChanged(BindableObject bindable, object oldValu element .FindParentOfType() ?.SendFlyoutItemsChanged(); + + if(bindable is BaseShellItem baseShellItem && baseShellItem.FlyoutItemIsVisible != (bool)newValue) + baseShellItem.FlyoutItemIsVisible = (bool)newValue; } /// @@ -643,24 +646,9 @@ internal static BindableObject GetBindableObjectWithFlyoutItemTemplate(BindableO DataTemplate IShellController.GetFlyoutItemDataTemplate(BindableObject bo) { - BindableProperty bp = null; - string textBinding; - string iconBinding; + BindableProperty bp = bo is IMenuItemController ? MenuItemTemplateProperty : ItemTemplateProperty; var bindableObjectWithTemplate = GetBindableObjectWithFlyoutItemTemplate(bo); - if (bo is IMenuItemController) - { - bp = MenuItemTemplateProperty; - textBinding = "Text"; - iconBinding = "Icon"; - } - else - { - bp = ItemTemplateProperty; - textBinding = "Title"; - iconBinding = "FlyoutIcon"; - } - if (bindableObjectWithTemplate.IsSet(bp)) { return (DataTemplate)bindableObjectWithTemplate.GetValue(bp); @@ -671,7 +659,7 @@ DataTemplate IShellController.GetFlyoutItemDataTemplate(BindableObject bo) return (DataTemplate)GetValue(bp); } - return BaseShellItem.CreateDefaultFlyoutItemCell(textBinding, iconBinding); + return BaseShellItem.CreateDefaultFlyoutItemCell(bo); } event EventHandler IShellController.StructureChanged @@ -965,14 +953,51 @@ public static Shell Current { get { - if (Application.Current == null) + if (Application.Current is null || Application.Current.Windows.Count == 0) return null; + if (Application.Current.Windows.Count == 1) + { + return Application.Current.Windows[0].Page as Shell; + } + + // Check if shell is activated + Shell currentShell = null; + Shell returnIfThereIsJustOneShell = null; + bool tooManyShells = false; foreach (var window in Application.Current.Windows) - if (window is Window && window.IsActivated && window.Page is Shell shell) - return shell; + { + if (window.Page is Shell shell) + { + if (window.IsActivated) + { + if(currentShell is not null) + { + currentShell = null; + break; + } + + currentShell = shell; + } - return Application.Current?.MainPage as Shell; + if (returnIfThereIsJustOneShell is not null) + { + tooManyShells = true; + } + } + } + + if (currentShell is not null) + { + return currentShell; + } + + if (!tooManyShells && returnIfThereIsJustOneShell is not null) + { + return returnIfThereIsJustOneShell; + } + + throw new InvalidOperationException($"Unable to determine the current Shell instance you want to use. Please access Shell via the Windows property on {Application.Current.GetType()}."); } } @@ -1541,7 +1566,34 @@ void SendNavigated(ShellNavigatedEventArgs args) if (_previousPage != null) _previousPage.PropertyChanged -= OnCurrentPagePropertyChanged; - _previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage)); + NavigationType navigationType = NavigationType.PageSwap; + + switch(args.Source) + { + case ShellNavigationSource.Pop: + navigationType = NavigationType.Pop; + break; + case ShellNavigationSource.ShellItemChanged: + navigationType = NavigationType.PageSwap; + break; + case ShellNavigationSource.ShellSectionChanged: + navigationType = NavigationType.PageSwap; + break; + case ShellNavigationSource.ShellContentChanged: + navigationType = NavigationType.PageSwap; + break; + case ShellNavigationSource.Push: + navigationType = NavigationType.Push; + break; + case ShellNavigationSource.PopToRoot: + navigationType = NavigationType.PopToRoot; + break; + case ShellNavigationSource.Insert: + navigationType = NavigationType.Insert; + break; + } + + _previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage, navigationType)); CurrentPage?.SendNavigatedTo(new NavigatedToEventArgs(_previousPage)); _previousPage = null; @@ -1585,8 +1637,18 @@ protected virtual void OnNavigating(ShellNavigatingEventArgs args) static void OnCurrentItemChanged(BindableObject bindable, object oldValue, object newValue) { if (oldValue is ShellItem oldShellItem) + { oldShellItem.SendDisappearing(); + foreach(var section in oldShellItem.Items) + { + foreach(var content in section.Items) + { + content.EvaluateDisconnect(); + } + } + } + if (newValue == null) return; @@ -1910,6 +1972,7 @@ void IPropertyPropagationController.PropagatePropertyChanged(string propertyName PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, ((IVisualTreeElement)this).GetVisualChildren()); } + [Obsolete("Use ArrangeOverride instead")] protected override void LayoutChildren(double x, double y, double width, double height) { // Page by default tries to layout all logical children diff --git a/src/Controls/src/Core/Shell/ShellContent.cs b/src/Controls/src/Core/Shell/ShellContent.cs index c0c06b8d0ef3..ec3c91ba1007 100644 --- a/src/Controls/src/Core/Shell/ShellContent.cs +++ b/src/Controls/src/Core/Shell/ShellContent.cs @@ -11,6 +11,7 @@ namespace Microsoft.Maui.Controls { /// [ContentProperty(nameof(Content))] + [TypeConverter(typeof(ShellContentConverter))] public class ShellContent : BaseShellItem, IShellContentController, IVisualTreeElement { static readonly BindablePropertyKey MenuItemsPropertyKey = @@ -53,36 +54,45 @@ public DataTemplate ContentTemplate EventHandler _isPageVisibleChanged; event EventHandler IShellContentController.IsPageVisibleChanged { add => _isPageVisibleChanged += value; remove => _isPageVisibleChanged -= value; } + bool _createdViaService; Page IShellContentController.GetOrCreateContent() { var template = ContentTemplate; var content = Content; Page result = null; - if (template == null) + if (template is null) { if (content is Page page) result = page; } else { - if (template.Type != null) + if (template.Type is not null) { template.LoadTemplate = () => { var services = Parent?.FindMauiContext()?.Services; - if (services != null) + if (services is not null) { - return services.GetService(template.Type) ?? Activator.CreateInstance(template.Type); + var result = services.GetService(template.Type); + if (result is not null) + { + _createdViaService = true; + return result; + } } - return Activator.CreateInstance(template.Type); + + _createdViaService = false; + return Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(services, template.Type); }; } + result = ContentCache ?? (Page)template.CreateContent(content, this); ContentCache = result; } - if (result == null) + if (result is null) throw new InvalidOperationException($"No Content found for {nameof(ShellContent)}, Title:{Title}, Route {Route}"); if (result is TabbedPage) @@ -107,7 +117,10 @@ void IShellContentController.RecyclePage(Page page) Page _contentCache; /// - public ShellContent() => ((INotifyCollectionChanged)MenuItems).CollectionChanged += MenuItemsCollectionChanged; + public ShellContent() + { + ((INotifyCollectionChanged)MenuItems).CollectionChanged += MenuItemsCollectionChanged; + } internal bool IsVisibleContent => Parent is ShellSection shellSection && shellSection.IsVisibleSection && shellSection.CurrentItem == this; @@ -186,18 +199,77 @@ Page ContentCache var oldCache = _contentCache; _contentCache = value; if (oldCache != null) + { RemoveLogicalChild(oldCache); + oldCache.Unloaded -= OnPageUnloaded; + } - if (value != null && value.Parent != this) + if (value is not null && value.Parent != this) { AddLogicalChild(value); + + if (_createdViaService) + { + value.Unloaded += OnPageUnloaded; + } } - if (Parent != null) + if (Parent is not null) + { ((ShellSection)Parent).UpdateDisplayedPage(); + } } } + internal void EvaluateDisconnect() + { + if(!_createdViaService) + return; + + // If the user has set the IsVisible property on this shell content to false + bool disconnect = true; + + if(Parent is ShellSection shellSection && + shellSection.Parent is ShellItem shellItem && + shellItem.Parent is Shell shell) + { + disconnect = + !this.IsVisible || // user has set the IsVisible property to false + (_contentCache is not null && !_contentCache.IsVisible) || // user has set IsVisible on the Page to false + shell.CurrentItem != shellItem || // user has navigated to a different TabBar or a different FlyoutItem + !shellSection.IsVisible || // user has set IsVisible on the ShellSection to false + this.Window is null; // user has set the main page to a different shell instance + } + + if (!disconnect) + { + return; + } + + if (_contentCache is not null) + { + _contentCache.Unloaded -= OnPageUnloaded; + RemoveLogicalChild(_contentCache); + } + + _contentCache = null; + } + + protected override void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + base.OnPropertyChanged(propertyName); + + if (propertyName == WindowProperty.PropertyName) + { + if(_contentCache?.IsLoaded == true) + return; + + EvaluateDisconnect(); + } + } + + void OnPageUnloaded(object sender, EventArgs e) => EvaluateDisconnect(); + public static implicit operator ShellContent(TemplatedPage page) { if (page.Parent != null) @@ -212,9 +284,9 @@ public static implicit operator ShellContent(TemplatedPage page) shellContent.Route = Routing.GenerateImplicitRoute(pageRoute); shellContent.Content = page; - shellContent.SetBinding(TitleProperty, new Binding(nameof(Title), BindingMode.OneWay, source: page)); - shellContent.SetBinding(IconProperty, new Binding(nameof(Icon), BindingMode.OneWay, source: page)); - shellContent.SetBinding(FlyoutIconProperty, new Binding(nameof(FlyoutIcon), BindingMode.OneWay, source: page)); + shellContent.SetBinding(TitleProperty, static (TemplatedPage page) => page.Title, BindingMode.OneWay, source: page); + shellContent.SetBinding(IconProperty, static (TemplatedPage page) => page.IconImageSource, BindingMode.OneWay, source: page); + shellContent.SetBinding(FlyoutIconProperty, static (TemplatedPage page) => page.IconImageSource, BindingMode.OneWay, source: page); return shellContent; } @@ -222,6 +294,7 @@ public static implicit operator ShellContent(TemplatedPage page) static void OnContentChanged(BindableObject bindable, object oldValue, object newValue) { var shellContent = (ShellContent)bindable; + shellContent._createdViaService = false; // This check is wrong but will work for testing if (shellContent.ContentTemplate == null) { @@ -295,42 +368,45 @@ static void ApplyQueryAttributes(object content, ShellRouteParameters query, She if (content is BindableObject bindable && bindable.BindingContext != null && content != bindable.BindingContext) ApplyQueryAttributes(bindable.BindingContext, query, oldQuery); - var type = content.GetType(); - var queryPropertyAttributes = type.GetCustomAttributes(typeof(QueryPropertyAttribute), true); - if (queryPropertyAttributes.Length == 0) - { - ClearQueryIfAppliedToPage(query, content); - return; - } - - foreach (QueryPropertyAttribute attrib in queryPropertyAttributes) + if (RuntimeFeature.IsQueryPropertyAttributeSupported) { - if (query.TryGetValue(attrib.QueryId, out var value)) + var type = content.GetType(); + var queryPropertyAttributes = type.GetCustomAttributes(typeof(QueryPropertyAttribute), true); + if (queryPropertyAttributes.Length == 0) { - PropertyInfo prop = type.GetRuntimeProperty(attrib.Name); + ClearQueryIfAppliedToPage(query, content); + return; + } - if (prop != null && prop.CanWrite && prop.SetMethod.IsPublic) + foreach (QueryPropertyAttribute attrib in queryPropertyAttributes) + { + if (query.TryGetValue(attrib.QueryId, out var value)) { - if (prop.PropertyType == typeof(string)) - { - if (value != null) - value = global::System.Net.WebUtility.UrlDecode((string)value); + PropertyInfo prop = type.GetRuntimeProperty(attrib.Name); - prop.SetValue(content, value); - } - else + if (prop != null && prop.CanWrite && prop.SetMethod.IsPublic) { - var castValue = Convert.ChangeType(value, prop.PropertyType); - prop.SetValue(content, castValue); + if (prop.PropertyType == typeof(string)) + { + if (value != null) + value = global::System.Net.WebUtility.UrlDecode((string)value); + + prop.SetValue(content, value); + } + else + { + var castValue = Convert.ChangeType(value, prop.PropertyType); + prop.SetValue(content, castValue); + } } } - } - else if (oldQuery.TryGetValue(attrib.QueryId, out var oldValue)) - { - PropertyInfo prop = type.GetRuntimeProperty(attrib.Name); + else if (oldQuery.TryGetValue(attrib.QueryId, out var oldValue)) + { + PropertyInfo prop = type.GetRuntimeProperty(attrib.Name); - if (prop != null && prop.CanWrite && prop.SetMethod.IsPublic) - prop.SetValue(content, null); + if (prop != null && prop.CanWrite && prop.SetMethod.IsPublic) + prop.SetValue(content, null); + } } } @@ -344,5 +420,29 @@ static void ClearQueryIfAppliedToPage(ShellRouteParameters query, object content query.ResetToQueryParameters(); } } + + private sealed class ShellContentConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + => sourceType == typeof(TemplatedPage); + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + => false; + + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + if (value is TemplatedPage templatedPage) + { + return (ShellContent)templatedPage; + } + + throw new NotSupportedException(); + } + + public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + { + throw new NotSupportedException(); + } + } } } diff --git a/src/Controls/src/Core/Shell/ShellItem.cs b/src/Controls/src/Core/Shell/ShellItem.cs index 40bd26c3a6c4..75f5802cd0b3 100644 --- a/src/Controls/src/Core/Shell/ShellItem.cs +++ b/src/Controls/src/Core/Shell/ShellItem.cs @@ -50,6 +50,7 @@ public TabBar() /// [ContentProperty(nameof(Items))] [EditorBrowsable(EditorBrowsableState.Never)] + [TypeConverter(typeof(ShellItemConverter))] public class ShellItem : ShellGroupItem, IShellItemController, IElementConfiguration, IPropertyPropagationController, IVisualTreeElement { #region PropertyKeys @@ -222,10 +223,10 @@ internal static ShellItem CreateFromShellSection(ShellSection shellSection) result.Route = Routing.GenerateImplicitRoute(shellSection.Route); result.Items.Add(shellSection); - result.SetBinding(TitleProperty, new Binding(nameof(Title), BindingMode.OneWay, source: shellSection)); - result.SetBinding(IconProperty, new Binding(nameof(Icon), BindingMode.OneWay, source: shellSection)); - result.SetBinding(FlyoutDisplayOptionsProperty, new Binding(nameof(FlyoutDisplayOptions), BindingMode.OneTime, source: shellSection)); - result.SetBinding(FlyoutIconProperty, new Binding(nameof(FlyoutIcon), BindingMode.OneWay, source: shellSection)); + result.SetBinding(TitleProperty, static (ShellSection section) => section.Title, BindingMode.OneWay, source: shellSection); + result.SetBinding(IconProperty, static (ShellSection section) => section.Icon, BindingMode.OneWay, source: shellSection); + result.SetBinding(FlyoutDisplayOptionsProperty, static (ShellSection section) => section.FlyoutDisplayOptions, BindingMode.OneTime, source: shellSection); + result.SetBinding(FlyoutIconProperty, static (ShellSection section) => section.FlyoutIcon, BindingMode.OneWay, source: shellSection); return result; } @@ -342,5 +343,30 @@ protected override void OnParentSet() if (this.IsVisibleItem && CurrentItem != null) ((IShellController)Parent)?.AppearanceChanged(CurrentItem, false); } + + private sealed class ShellItemConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + => sourceType == typeof(ShellSection) + || sourceType == typeof(ShellContent) + || sourceType == typeof(TemplatedPage) + || sourceType == typeof(MenuItem); + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + => false; + + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + => value switch + { + ShellSection shellSection => (ShellItem)shellSection, + ShellContent shellContent => (ShellItem)shellContent, + TemplatedPage page => (ShellItem)page, + MenuItem menuItem => (ShellItem)menuItem, + _ => throw new NotSupportedException(), + }; + + public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + => throw new NotSupportedException(); + } } } diff --git a/src/Controls/src/Core/Shell/ShellNavigationState.cs b/src/Controls/src/Core/Shell/ShellNavigationState.cs index 56e643f4206e..7f6ad30af612 100644 --- a/src/Controls/src/Core/Shell/ShellNavigationState.cs +++ b/src/Controls/src/Core/Shell/ShellNavigationState.cs @@ -1,12 +1,15 @@ #nullable disable using System; using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; using System.Diagnostics; namespace Microsoft.Maui.Controls { /// [DebuggerDisplay("Location = {Location}")] + [TypeConverter(typeof(ShellNavigationStateTypeConverter))] public class ShellNavigationState { Uri _fullLocation; @@ -97,5 +100,22 @@ static Uri TrimDownImplicitAndDefaultPaths(Uri uri) toKeep.Insert(0, ""); return new Uri(string.Join(Routing.PathSeparator, toKeep), UriKind.Relative); } + + private sealed class ShellNavigationStateTypeConverter : TypeConverter + { + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => false; + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cultureInfo, object value, Type destinationType) => throw new NotSupportedException(); + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + => sourceType == typeof(string) || sourceType == typeof(Uri); + + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + => value switch + { + string str => (ShellNavigationState)str, + Uri uri => (ShellNavigationState)uri, + _ => throw new NotSupportedException(), + }; + } } } diff --git a/src/Controls/src/Core/Shell/ShellSection.cs b/src/Controls/src/Core/Shell/ShellSection.cs index 9778bc5acebd..e5b62bc83075 100644 --- a/src/Controls/src/Core/Shell/ShellSection.cs +++ b/src/Controls/src/Core/Shell/ShellSection.cs @@ -4,6 +4,7 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -20,6 +21,7 @@ public class Tab : ShellSection /// [ContentProperty(nameof(Items))] [EditorBrowsable(EditorBrowsableState.Never)] + [TypeConverter(typeof(ShellSectionTypeConverter))] public partial class ShellSection : ShellGroupItem, IShellSectionController, IPropertyPropagationController, IVisualTreeElement, IStackNavigation { #region PropertyKeys @@ -291,9 +293,9 @@ internal static ShellSection CreateFromShellContent(ShellContent shellContent) shellSection.Items.Add(shellContent); - shellSection.SetBinding(TitleProperty, new Binding(nameof(Title), BindingMode.OneWay, source: shellContent)); - shellSection.SetBinding(IconProperty, new Binding(nameof(Icon), BindingMode.OneWay, source: shellContent)); - shellSection.SetBinding(FlyoutIconProperty, new Binding(nameof(FlyoutIcon), BindingMode.OneWay, source: shellContent)); + shellSection.SetBinding(TitleProperty, static (BaseShellItem item) => item.Title, BindingMode.OneWay, source: shellContent); + shellSection.SetBinding(IconProperty, static (BaseShellItem item) => item.Icon, BindingMode.OneWay, source: shellContent); + shellSection.SetBinding(FlyoutIconProperty, static (BaseShellItem item) => item.FlyoutIcon, BindingMode.OneWay, source: shellContent); return shellSection; } @@ -1242,5 +1244,20 @@ void IStackNavigation.NavigationFinished(IReadOnlyList newStack) } #nullable disable + private sealed class ShellSectionTypeConverter : TypeConverter + { + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => false; + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cultureInfo, object value, Type destinationType) => throw new NotSupportedException(); + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + => sourceType == typeof(ShellContent) || sourceType == typeof(TemplatedPage); + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + => value switch + { + ShellContent shellContent => (ShellSection)shellContent, + TemplatedPage page => (ShellSection)page, + _ => throw new NotSupportedException(), + }; + } } } diff --git a/src/Controls/src/Core/Style.cs b/src/Controls/src/Core/Style.cs index d7c2c288bffd..539d60180905 100644 --- a/src/Controls/src/Core/Style.cs +++ b/src/Controls/src/Core/Style.cs @@ -163,7 +163,7 @@ static void OnBasedOnResourceChanged(BindableObject bindable, object oldValue, o void ApplyCore(BindableObject bindable, Style basedOn, SetterSpecificity specificity) { if (basedOn != null) - ((IStyle)basedOn).Apply(bindable, new SetterSpecificity(specificity.Style - 1, 0, 0, 0)); + ((IStyle)basedOn).Apply(bindable, specificity.AsBaseStyle()); #if NETSTANDARD2_0 specificities.Remove(bindable); diff --git a/src/Controls/src/Core/StyleSheets/StylePropertyAttribute.cs b/src/Controls/src/Core/StyleSheets/StylePropertyAttribute.cs index bb0355cabd84..c499528029bf 100644 --- a/src/Controls/src/Core/StyleSheets/StylePropertyAttribute.cs +++ b/src/Controls/src/Core/StyleSheets/StylePropertyAttribute.cs @@ -1,5 +1,6 @@ #nullable disable using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls.StyleSheets { @@ -8,13 +9,19 @@ sealed class StylePropertyAttribute : Attribute { public string CssPropertyName { get; } public string BindablePropertyName { get; } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] public Type TargetType { get; } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] public Type PropertyOwnerType { get; set; } public BindableProperty BindableProperty { get; set; } public bool Inherited { get; set; } = false; - public StylePropertyAttribute(string cssPropertyName, Type targetType, string bindablePropertyName) + public StylePropertyAttribute( + string cssPropertyName, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] + Type targetType, + string bindablePropertyName) { CssPropertyName = cssPropertyName; BindablePropertyName = bindablePropertyName; diff --git a/src/Controls/src/Core/StyleSheets/StyleSheet.cs b/src/Controls/src/Core/StyleSheets/StyleSheet.cs index 11967a97bb0e..69bf4d6dbb55 100644 --- a/src/Controls/src/Core/StyleSheets/StyleSheet.cs +++ b/src/Controls/src/Core/StyleSheets/StyleSheet.cs @@ -7,6 +7,8 @@ using System.Runtime.CompilerServices; using System.Xml; +using Microsoft.Maui.Controls.Xaml; + namespace Microsoft.Maui.Controls.StyleSheets { /// @@ -24,7 +26,7 @@ public sealed class StyleSheet : IStyle public static StyleSheet FromResource(string resourcePath, Assembly assembly, IXmlLineInfo lineInfo = null) { var styleSheet = new StyleSheet(); - var resString = DependencyService.Get().GetResource(resourcePath, assembly, styleSheet, lineInfo); + var resString = GetResource(resourcePath, assembly, styleSheet, lineInfo); using (var textReader = new StringReader(resString)) using (var cssReader = new CssReader(textReader)) Parse(styleSheet, cssReader); @@ -114,5 +116,31 @@ void Apply(Element styleable) } void IStyle.UnApply(BindableObject bindable) => throw new NotImplementedException(); + + private static string GetResource(string resourcePath, Assembly assembly, object target, IXmlLineInfo lineInfo) + { + var resourceLoadingResponse = Maui.Controls.Internals.ResourceLoader.ResourceProvider2?.Invoke(new Maui.Controls.Internals.ResourceLoader.ResourceLoadingQuery + { + AssemblyName = assembly.GetName(), + ResourcePath = resourcePath, + Instance = target + }); + + var alternateResource = resourceLoadingResponse?.ResourceContent; + if (alternateResource != null) + return alternateResource; + + var resourceId = XamlResourceIdAttribute.GetResourceIdForPath(assembly, resourcePath); + if (resourceId == null) + throw new XamlParseException($"Resource '{resourcePath}' not found.", lineInfo); + + using (var stream = assembly.GetManifestResourceStream(resourceId)) + { + if (stream == null) + throw new XamlParseException($"No resource found for '{resourceId}'.", lineInfo); + using (var reader = new StreamReader(stream)) + return reader.ReadToEnd(); + } + } } } diff --git a/src/Controls/src/Core/StyleableElement/StyleableElement.cs b/src/Controls/src/Core/StyleableElement/StyleableElement.cs new file mode 100644 index 000000000000..c48ac15777b4 --- /dev/null +++ b/src/Controls/src/Core/StyleableElement/StyleableElement.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Controls.StyleSheets; + +namespace Microsoft.Maui.Controls +{ + /// Represents an with base functionality for styling. Does not necessarily render on screen. + public abstract class StyleableElement : Element, IStyleSelectable + { + /// Bindable property for . + public static readonly BindableProperty StyleProperty = + BindableProperty.Create(nameof(Style), typeof(Style), typeof(StyleableElement), default(Style), + propertyChanged: (bindable, oldvalue, newvalue) => ((StyleableElement)bindable)._mergedStyle.Style = (Style)newvalue); + + internal readonly MergedStyle _mergedStyle; + + public StyleableElement() + { + _mergedStyle = new MergedStyle(GetType(), this); + } + + /// Gets or sets the unique for this element. + public Style Style + { + get { return (Style)GetValue(StyleProperty); } + set { SetValue(StyleProperty, value); } + } + + /// Gets or sets the style classes for the element. + /// + /// Equiavalent to . + /// Style classes enable multiple styles to be applied to a control, without resorting to style inheritance. + /// + /// Conceptual documentation on style classes + [System.ComponentModel.TypeConverter(typeof(ListStringTypeConverter))] + public IList StyleClass + { + get => @class; + set => @class = value; + } + + /// Gets or sets the style classes for the element. + /// + /// Equiavalent to . + /// Style classes enable multiple styles to be applied to a control, without resorting to style inheritance. + /// + /// Conceptual documentation on style classes + [System.ComponentModel.TypeConverter(typeof(ListStringTypeConverter))] + public IList @class + { + get => _mergedStyle.StyleClass; + set => _mergedStyle.StyleClass = value; + } + + IList IStyleSelectable.Classes => StyleClass; + } +} diff --git a/src/Controls/src/Core/SwipeView/SwipeView.Mapper.cs b/src/Controls/src/Core/SwipeView/SwipeView.Mapper.cs index 1b1f918451d6..d555790e5b0c 100644 --- a/src/Controls/src/Core/SwipeView/SwipeView.Mapper.cs +++ b/src/Controls/src/Core/SwipeView/SwipeView.Mapper.cs @@ -5,10 +5,6 @@ namespace Microsoft.Maui.Controls { public partial class SwipeView { - [Obsolete("Use SwipeViewHandler.Mapper instead.")] - internal static IPropertyMapper ControlsSwipeMapper = - new ControlsMapper(SwipeViewHandler.Mapper); - internal static new void RemapForControls() { // Adjusted the mapping to preserve SwipeView.Entry legacy behavior diff --git a/src/Controls/src/Core/TabbedPage/TabbedPage.Mapper.cs b/src/Controls/src/Core/TabbedPage/TabbedPage.Mapper.cs index 8dc05d087a72..7d3e8277c0b2 100644 --- a/src/Controls/src/Core/TabbedPage/TabbedPage.Mapper.cs +++ b/src/Controls/src/Core/TabbedPage/TabbedPage.Mapper.cs @@ -8,9 +8,6 @@ namespace Microsoft.Maui.Controls { public partial class TabbedPage { - [Obsolete("Use TabbedViewHandler.Mapper instead.")] - public static IPropertyMapper ControlsTabbedPageMapper = new ControlsMapper(TabbedViewHandler.Mapper); - internal new static void RemapForControls() { TabbedViewHandler.Mapper.ReplaceMapping(nameof(BarBackground), MapBarBackground); diff --git a/src/Controls/src/Core/TabbedPage/TabbedPage.Tizen.cs b/src/Controls/src/Core/TabbedPage/TabbedPage.Tizen.cs index 9ca7f2a92406..11cf62260843 100644 --- a/src/Controls/src/Core/TabbedPage/TabbedPage.Tizen.cs +++ b/src/Controls/src/Core/TabbedPage/TabbedPage.Tizen.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using Microsoft.Maui.Controls.Handlers.Items; +using Microsoft.Maui.Controls.Internals; using Tizen.NUI; using Tizen.UIExtensions.NUI; using GColor = Microsoft.Maui.Graphics.Color; @@ -159,7 +160,9 @@ static DataTemplate GetTemplate(TabbedPage page) } } +#pragma warning disable CS0618 // Type or member is obsolete class TabbedItem : Frame +#pragma warning restore CS0618 // Type or member is obsolete { static readonly BindableProperty SelectedStateProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(TabbedItem), false, propertyChanged: (b, o, n) => ((TabbedItem)b).UpdateSelectedState()); static readonly BindableProperty SelectedTabColorProperty = BindableProperty.Create(nameof(SelectedTabColor), typeof(GColor), typeof(TabbedItem), default(Color), propertyChanged: (b, o, n) => ((TabbedItem)b).UpdateSelectedState()); @@ -199,10 +202,10 @@ void InitializeComponent() Padding = new Thickness(0); HasShadow = false; BorderColor = GColors.DarkGray; - SetBinding(BackgroundProperty, new Binding("BarBackground", source: _page)); - SetBinding(BackgroundColorProperty, new Binding("BarBackgroundColor", source: _page)); - SetBinding(SelectedTabColorProperty, new Binding("SelectedTabColor", source: _page)); - SetBinding(UnselectedTabColorProperty, new Binding("UnselectedTabColor", source: _page)); + this.SetBinding(BackgroundProperty, static (TabbedPage page) => page.BarBackground, source: _page); + this.SetBinding(BackgroundColorProperty, static (TabbedPage page) => page.BarBackgroundColor, source: _page); + this.SetBinding(SelectedTabColorProperty, static (TabbedPage page) => page.SelectedTabColor, source: _page); + this.SetBinding(UnselectedTabColorProperty, static (TabbedPage page) => page.UnselectedTabColor, source: _page); var label = new XLabel { @@ -211,8 +214,8 @@ void InitializeComponent() HorizontalTextAlignment = TextAlignment.Center, VerticalTextAlignment = TextAlignment.Center, }; - label.SetBinding(XLabel.TextProperty, new Binding("Title")); - label.SetBinding(XLabel.TextColorProperty, new Binding("BarTextColor", source: _page)); + label.SetBinding(XLabel.TextProperty, static (TabbedPage page) => page.Title, source: _page); + label.SetBinding(XLabel.TextColorProperty, static (TabbedPage page) => page.BarTextColor, source: _page); _bar = new BoxView { diff --git a/src/Controls/src/Core/TabbedPage/TabbedPage.cs b/src/Controls/src/Core/TabbedPage/TabbedPage.cs index 563ec1482e15..5f247f311661 100644 --- a/src/Controls/src/Core/TabbedPage/TabbedPage.cs +++ b/src/Controls/src/Core/TabbedPage/TabbedPage.cs @@ -80,6 +80,7 @@ public TabbedPage() return _platformConfigurationRegistry.Value.On(); } + [Obsolete("Use ArrangeOverride instead")] protected override void LayoutChildren(double x, double y, double width, double height) { // We don't want forcelayout to call the legacy diff --git a/src/Controls/src/Core/TableView/TableView.cs b/src/Controls/src/Core/TableView/TableView.cs index 0c895cec19b5..eb66239603e4 100644 --- a/src/Controls/src/Core/TableView/TableView.cs +++ b/src/Controls/src/Core/TableView/TableView.cs @@ -131,6 +131,7 @@ protected virtual void OnModelChanged() ModelChanged?.Invoke(this, EventArgs.Empty); } + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { var minimumSize = new Size(40, 40); diff --git a/src/Controls/src/Core/TemplateBinding.cs b/src/Controls/src/Core/TemplateBinding.cs index 6839ceab2cbf..288bae4a56a6 100644 --- a/src/Controls/src/Core/TemplateBinding.cs +++ b/src/Controls/src/Core/TemplateBinding.cs @@ -1,11 +1,13 @@ #nullable disable using System; +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace Microsoft.Maui.Controls { /// [Obsolete("Use Binding.Source=RelativeBindingSource.TemplatedParent")] + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public sealed class TemplateBinding : BindingBase { internal const string SelfPath = "."; diff --git a/src/Controls/src/Core/TemplateExtensions.cs b/src/Controls/src/Core/TemplateExtensions.cs index 1e4b4d0e7c85..0202f687e409 100644 --- a/src/Controls/src/Core/TemplateExtensions.cs +++ b/src/Controls/src/Core/TemplateExtensions.cs @@ -1,5 +1,6 @@ #nullable disable using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls { @@ -7,6 +8,7 @@ namespace Microsoft.Maui.Controls public static class TemplateExtensions { /// + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public static void SetBinding(this DataTemplate self, BindableProperty targetProperty, string path) { if (self == null) diff --git a/src/Controls/src/Core/TemplatedItemsList.cs b/src/Controls/src/Core/TemplatedItemsList.cs index 967e6ae90643..d4c2bd035313 100644 --- a/src/Controls/src/Core/TemplatedItemsList.cs +++ b/src/Controls/src/Core/TemplatedItemsList.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Cadenza.Collections; using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Controls.Xaml; using Microsoft.Maui.Devices; namespace Microsoft.Maui.Controls.Internals @@ -45,7 +46,7 @@ public sealed class TemplatedItemsList> _groupedItems; + Cadenza.Collections.OrderedDictionary> _groupedItems; DataTemplate _groupHeaderTemplate; BindingBase _groupShortNameBinding; ShortNamesProxy _shortNames; @@ -100,6 +101,7 @@ event PropertyChangedEventHandler ITemplatedItemsList.PropertyChanged remove { PropertyChanged -= value; } } + [DoesNotInheritDataType] public BindingBase GroupDisplayBinding { get { return _groupDisplayBinding; } @@ -133,6 +135,7 @@ public DataTemplate GroupHeaderTemplate public BindableProperty GroupHeaderTemplateProperty { get; set; } + [DoesNotInheritDataType] public BindingBase GroupShortNameBinding { get { return _groupShortNameBinding; } @@ -755,7 +758,14 @@ TemplatedItemsList InsertGrouped(object item, int index) // time for right now. groupProxy.HeaderContent = _itemsView.CreateDefault(ListProxy.ProxiedEnumerable); groupProxy.HeaderContent.BindingContext = groupProxy; - groupProxy.HeaderContent.SetBinding(TextCell.TextProperty, "Name"); + // TODO: the interceptor doesn't support generics at the moment + // groupProxy.HeaderContent.SetBinding(TextCell.TextProperty, static (TemplatedItemsList list) => list.Name); + groupProxy.HeaderContent.SetBinding( + TextCell.TextProperty, + TypedBinding.ForSingleNestingLevel( + nameof(TemplatedItemsList.Name), + getter: static (TemplatedItemsList list) => list.Name, + setter: static (list, val) => list.Name = val)); } SetIndex(groupProxy.HeaderContent, index); @@ -781,7 +791,7 @@ void OnCollectionChanged(NotifyCollectionChangedEventArgs e) void OnCollectionChangedGrouped(NotifyCollectionChangedEventArgs e) { if (_groupedItems == null) - _groupedItems = new OrderedDictionary>(); + _groupedItems = new Cadenza.Collections.OrderedDictionary>(); List> newItems = null, oldItems = null; diff --git a/src/Controls/src/Core/TemplatedView/TemplatedView.cs b/src/Controls/src/Core/TemplatedView/TemplatedView.cs index 4f05c6524c23..f884847eccf1 100644 --- a/src/Controls/src/Core/TemplatedView/TemplatedView.cs +++ b/src/Controls/src/Core/TemplatedView/TemplatedView.cs @@ -7,7 +7,9 @@ namespace Microsoft.Maui.Controls { /// +#pragma warning disable CS0618 // Type or member is obsolete public partial class TemplatedView : Compatibility.Layout, IControlTemplated, IContentView +#pragma warning restore CS0618 // Type or member is obsolete { /// Bindable property for . public static readonly BindableProperty ControlTemplateProperty = BindableProperty.Create(nameof(ControlTemplate), typeof(ControlTemplate), typeof(TemplatedView), null, @@ -24,17 +26,23 @@ public ControlTemplate ControlTemplate Element IControlTemplated.TemplateRoot { get; set; } + [Obsolete("Use InvalidateArrange if you need to trigger a new arrange and then put your arrange logic inside ArrangeOverride instead")] protected override void LayoutChildren(double x, double y, double width, double height) { for (var i = 0; i < LogicalChildrenInternal.Count; i++) { Element element = LogicalChildrenInternal[i]; var child = element as View; + + // For now we just leave the old path in place to avoid too much change in behavior + // All of our types that inherit from TemplatedView overrides LayoutChildren and replaces + // this behavior if (child != null) LayoutChildIntoBoundingRegion(child, new Rect(x, y, width, height)); } } + [Obsolete("Use MeasureOverride instead")] protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { double widthRequest = WidthRequest; diff --git a/src/Controls/src/Core/TimeChangedEventArgs.cs b/src/Controls/src/Core/TimeChangedEventArgs.cs new file mode 100644 index 000000000000..75a5580a3a9a --- /dev/null +++ b/src/Controls/src/Core/TimeChangedEventArgs.cs @@ -0,0 +1,30 @@ +#nullable disable +using System; + +namespace Microsoft.Maui.Controls +{ + /// Event arguments for event. + /// To be added. + public class TimeChangedEventArgs : EventArgs + { + /// Creates a new object that represents a change from to . + /// + /// + /// To be added. + public TimeChangedEventArgs(TimeSpan oldTime, TimeSpan newTime) + { + OldTime = oldTime; + NewTime = newTime; + } + + /// The time that the user entered. + /// To be added. + /// To be added. + public TimeSpan NewTime { get; private set; } + + /// The time that was on the element at the time that the user selected it. + /// To be added. + /// To be added. + public TimeSpan OldTime { get; private set; } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/TimePicker/TimePicker.Mapper.cs b/src/Controls/src/Core/TimePicker/TimePicker.Mapper.cs index 11f4a985cf4b..5fa874db652f 100644 --- a/src/Controls/src/Core/TimePicker/TimePicker.Mapper.cs +++ b/src/Controls/src/Core/TimePicker/TimePicker.Mapper.cs @@ -6,9 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class TimePicker { - [Obsolete("Use TimePickerHandler.Mapper instead.")] - public static IPropertyMapper ControlsTimePickerMapper = new ControlsMapper(TimePickerHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.TimePicker legacy behaviors diff --git a/src/Controls/src/Core/TimePicker/TimePicker.cs b/src/Controls/src/Core/TimePicker/TimePicker.cs index 37f90dd08bc4..6dda0f9eaa3a 100644 --- a/src/Controls/src/Core/TimePicker/TimePicker.cs +++ b/src/Controls/src/Core/TimePicker/TimePicker.cs @@ -20,10 +20,11 @@ public partial class TimePicker : View, IFontElement, ITextElement, IElementConf /// Bindable property for . public static readonly BindableProperty TimeProperty = BindableProperty.Create(nameof(Time), typeof(TimeSpan), typeof(TimePicker), new TimeSpan(0), BindingMode.TwoWay, validateValue: (bindable, value) => - { - var time = (TimeSpan)value; - return time.TotalHours < 24 && time.TotalMilliseconds >= 0; - }); + { + var time = (TimeSpan)value; + return time.TotalHours < 24 && time.TotalMilliseconds >= 0; + }, + propertyChanged: TimePropertyChanged); /// Bindable property for . public static readonly BindableProperty FontFamilyProperty = FontElement.FontFamilyProperty; @@ -107,6 +108,8 @@ TextTransform ITextElement.TextTransform set { } } + public event EventHandler TimeSelected; + /// public virtual string UpdateFormsText(string source, TextTransform textTransform) => TextTransformUtilites.GetTransformedText(source, textTransform); @@ -157,5 +160,11 @@ TimeSpan ITimePicker.Time get => Time; set => SetValue(TimeProperty, value, SetterSpecificity.FromHandler); } + + static void TimePropertyChanged(BindableObject bindable, object oldValue, object newValue) + { + if (bindable is TimePicker timePicker) + timePicker.TimeSelected?.Invoke(timePicker, new TimeChangedEventArgs((TimeSpan)oldValue, (TimeSpan)newValue)); + } } } diff --git a/src/Controls/src/Core/TitleBar/TitleBar.Windows.cs b/src/Controls/src/Core/TitleBar/TitleBar.Windows.cs new file mode 100644 index 000000000000..3eadeb4fb870 --- /dev/null +++ b/src/Controls/src/Core/TitleBar/TitleBar.Windows.cs @@ -0,0 +1,13 @@ +namespace Microsoft.Maui.Controls +{ + public partial class TitleBar + { + internal override void OnIsVisibleChanged(bool oldValue, bool newValue) + { + base.OnIsVisibleChanged(oldValue, newValue); + + var navRootManager = Handler?.MauiContext?.GetNavigationRootManager(); + navRootManager?.SetTitleBarVisibility(newValue); + } + } +} diff --git a/src/Controls/src/Core/TitleBar/TitleBar.cs b/src/Controls/src/Core/TitleBar/TitleBar.cs new file mode 100644 index 000000000000..e0c7ebbc124f --- /dev/null +++ b/src/Controls/src/Core/TitleBar/TitleBar.cs @@ -0,0 +1,575 @@ +using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Graphics; +using System.Collections.Generic; + +namespace Microsoft.Maui.Controls +{ + /// + /// A control that provides title bar functionality for a window. + ///

+ /// The standard title bar height is 32px, but can be set to a larger value. + ///

+ /// The title bar can also be hidden by setting the property, which + /// will cause the window content to be displayed in the title bar region. + ///
+ public partial class TitleBar : TemplatedView, ITitleBar, ISafeAreaView + { + public const string TemplateRootName = "PART_Root"; + + public const string TitleBarIcon = "PART_Icon"; + public const string IconVisibleState = "IconVisible"; + public const string IconHiddenState = "IconCollapsed"; + + public const string TitleBarTitle = "PART_Title"; + public const string TitleVisibleState = "TitleVisible"; + public const string TitleHiddenState = "TitleCollapsed"; + + public const string TitleBarSubtitle = "PART_Subtitle"; + public const string SubtitleVisibleState = "SubtitleVisible"; + public const string SubtitleHiddenState = "SubTitleCollapsed"; + + public const string TitleBarLeading = "PART_LeadingContent"; + public const string LeadingVisibleState = "LeadingContentVisible"; + public const string LeadingHiddenState = "LeadingContentCollapsed"; + + public const string TitleBarContent = "PART_Content"; + public const string ContentVisibleState = "ContentVisible"; + public const string ContentHiddenState = "ContentCollapsed"; + + public const string TitleBarTrailing = "PART_TrailingContent"; + public const string TrailingVisibleState = "TrailingContentVisible"; + public const string TrailingHiddenState = "TrailingContentCollapsed"; + + public const string TitleBarActiveState = "TitleBarTitleActive"; + public const string TitleBarInactiveState = "TitleBarTitleInactive"; + + /// Bindable property for . + public static readonly BindableProperty IconProperty = BindableProperty.Create(nameof(Icon), typeof(ImageSource), + typeof(TitleBar), null, propertyChanged: OnIconChanged); + + /// Bindable property for . + public static readonly BindableProperty LeadingContentProperty = BindableProperty.Create(nameof(LeadingContent), typeof(IView), + typeof(TitleBar), null, propertyChanged: OnLeadingChanged); + + /// Bindable property for . + public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(IView), + typeof(TitleBar), null, propertyChanged: OnContentChanged); + + /// Bindable property for . + public static readonly BindableProperty TrailingContentProperty = BindableProperty.Create(nameof(TrailingContent), typeof(IView), + typeof(TitleBar), null, propertyChanged: OnTrailingContentChanged); + + /// Bindable property for . + public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), + typeof(TitleBar), null, propertyChanged: OnTitleChanged); + + /// Bindable property for . + public static readonly BindableProperty SubtitleProperty = BindableProperty.Create(nameof(Subtitle), typeof(string), + typeof(TitleBar), null, propertyChanged: OnSubtitleChanged); + + /// Bindable property for . + public static readonly BindableProperty ForegroundColorProperty = BindableProperty.Create(nameof(ForegroundColor), + typeof(Color), typeof(TitleBar)); + + static void OnLeadingChanged(BindableObject bindable, object oldValue, object newValue) + { + var titlebar = (TitleBar)bindable; + if (newValue is null) + { + titlebar.ApplyVisibleState(LeadingHiddenState); + } + else + { + titlebar.ApplyVisibleState(LeadingVisibleState); + } + } + + static void OnIconChanged(BindableObject bindable, object oldValue, object newValue) + { + var titlebar = (TitleBar)bindable; + var imageSource = newValue as ImageSource; + if (imageSource is null || imageSource.IsEmpty) + { + titlebar.ApplyVisibleState(IconHiddenState); + } + else + { + titlebar.ApplyVisibleState(IconVisibleState); + } + } + + static void OnTitleChanged(BindableObject bindable, object oldValue, object newValue) + { + var titlebar = (TitleBar)bindable; + if (newValue is null) + { + titlebar.ApplyVisibleState(TitleHiddenState); + } + else + { + titlebar.ApplyVisibleState(TitleVisibleState); + } + } + + static void OnSubtitleChanged(BindableObject bindable, object oldValue, object newValue) + { + var titlebar = (TitleBar)bindable; + if (newValue is null) + { + titlebar.ApplyVisibleState(SubtitleHiddenState); + } + else + { + titlebar.ApplyVisibleState(SubtitleVisibleState); + } + } + + static void OnContentChanged(BindableObject bindable, object oldValue, object newValue) + { + var titlebar = (TitleBar)bindable; + if (newValue is null) + { + titlebar.ApplyVisibleState(ContentHiddenState); + } + else + { + titlebar.ApplyVisibleState(ContentVisibleState); + } + } + + static void OnTrailingContentChanged(BindableObject bindable, object oldValue, object newValue) + { + var titlebar = (TitleBar)bindable; + if (newValue is null) + { + titlebar.ApplyVisibleState(TrailingHiddenState); + } + else + { + titlebar.ApplyVisibleState(TrailingVisibleState); + } + } + + /// + /// Gets or sets an optional icon image of the title bar. Icon images should be + /// 16x16 pixels in size. + ///

+ /// Setting this property to an empty value will hide the icon. + ///
+ public ImageSource Icon + { + get { return (ImageSource)GetValue(IconProperty); } + set { SetValue(IconProperty, value); } + } + + /// + /// Gets or sets a control that represents the leading content.

+ /// The leading content follows the optional and is aligned to + /// the left or right of the title bar, depending on the . Views + /// set here will be allocated as much space as they require. + ///

+ /// Views set here will block all input to the title bar region and handle input directly. + ///
+ public IView? LeadingContent + { + get { return (View?)GetValue(LeadingContentProperty); } + set { SetValue(LeadingContentProperty, value); } + } + + /// + /// Gets or sets the title text of the title bar. The title usually specifies + /// the name of the application or indicates the purpose of the window + /// + public string Title + { + get { return (string)GetValue(TitleProperty); } + set { SetValue(TitleProperty, value); } + } + + /// + /// Gets or sets the subtitle text of the title bar. The subtitle usually specifies + /// the secondary information about the application or window + /// + public string Subtitle + { + get { return (string)GetValue(SubtitleProperty); } + set { SetValue(SubtitleProperty, value); } + } + + /// + /// Gets or sets a control that represents the content.

+ /// This content is centered in the title bar, and is allocated the remaining space + /// between the leading and trailing content.
+ ///

+ /// Views set here will block all input to the title bar region and handle input directly. + ///
+ public IView? Content + { + get { return (View?)GetValue(TitleBar.ContentProperty); } + set { SetValue(TitleBar.ContentProperty, value); } + } + + /// + /// Gets or sets a control that represents the trailing content.

+ /// The trailing content is aligned to the right or left of the title bar, depending + /// on the . Views set here will be allocated as much space + /// as they require. + ///

+ /// Views set here will block all input to the title bar region and handle input directly. + ///
+ public IView? TrailingContent + { + get { return (View?)GetValue(TrailingContentProperty); } + set { SetValue(TrailingContentProperty, value); } + } + + /// + /// Gets or sets the foreground color of the title bar. This color is used for the + /// title and subtitle text. + /// + public Color ForegroundColor + { + get { return (Color)GetValue(ForegroundColorProperty); } + set { SetValue(ForegroundColorProperty, value); } + } + + /// + public IList PassthroughElements { get; private set; } + + bool ISafeAreaView.IgnoreSafeArea => true; + +#nullable disable + IView IContentView.PresentedContent => (this as IControlTemplated).TemplateRoot as IView; +#nullable enable + + static ControlTemplate? _defaultTemplate; + View? _templateRoot; + + public TitleBar() + { + PassthroughElements = new List(); + PropertyChanged += TitleBar_PropertyChanged; + + if (ControlTemplate is null) + { + ControlTemplate = DefaultTemplate; + } + } + + private void TitleBar_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(Window) && Window is not null) + { + Window.Activated -= Window_Activated; + Window.Deactivated -= Window_Deactivated; + + Window.Activated += Window_Activated; + Window.Deactivated += Window_Deactivated; + } + } + + internal void ApplyVisibleState(string stateGroup) + { + VisualStateManager.GoToState(this, stateGroup); + + if (_templateRoot is not null) + { + VisualStateManager.GoToState(_templateRoot, stateGroup); + } + } + + /// + /// Gets the default template for the title bar + /// + public static ControlTemplate DefaultTemplate + { + get + { + _defaultTemplate ??= new ControlTemplate(() => BuildDefaultTemplate()); + + return _defaultTemplate; + } + } + + protected override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + var controlTemplate = (this as IControlTemplated); + + _templateRoot = controlTemplate?.TemplateRoot as View; + + if (controlTemplate?.GetTemplateChild(TitleBarLeading) is IView leadingContent) + { + PassthroughElements.Add(leadingContent); + } + + if (controlTemplate?.GetTemplateChild(TitleBarContent) is IView content) + { + PassthroughElements.Add(content); + } + + if (controlTemplate?.GetTemplateChild(TitleBarTrailing) is IView trailingContent) + { + PassthroughElements.Add(trailingContent); + } + + ApplyVisibleState(TitleBarActiveState); + } + + private void Window_Activated(object? sender, System.EventArgs e) + { + ApplyVisibleState(TitleBarActiveState); + } + + private void Window_Deactivated(object? sender, System.EventArgs e) + { + ApplyVisibleState(TitleBarInactiveState); + } + + static View BuildDefaultTemplate() + { + VisualStateGroupList visualStateGroups = new VisualStateGroupList(); + + #region Root Grid + var contentGrid = new Grid() + { +#if MACCATALYST + Margin = new Thickness(80, 0, 0, 0), +#endif + HorizontalOptions = LayoutOptions.Fill, + ColumnDefinitions = + { + new ColumnDefinition(GridLength.Auto), // Leading content + new ColumnDefinition(GridLength.Auto), // Icon content + new ColumnDefinition(GridLength.Auto), // Title content + new ColumnDefinition(GridLength.Auto), // Subtitle content + new ColumnDefinition(GridLength.Star), // Content + new ColumnDefinition(GridLength.Auto), // Trailing content +#if !MACCATALYST + new ColumnDefinition(150), // Min drag region + padding for system buttons +#endif + } + }; + + contentGrid.SetBinding( + BackgroundColorProperty, + static (TitleBar tb) => tb.BackgroundColor, + source: RelativeBindingSource.TemplatedParent); + + contentGrid.SetBinding( + BackgroundProperty, + static (TitleBar tb) => tb.Background, + source: RelativeBindingSource.TemplatedParent); + + contentGrid.SetBinding( + OpacityProperty, + static (TitleBar tb) => tb.Opacity, + source: RelativeBindingSource.TemplatedParent); + #endregion + + #region Leading content + var leadingContent = new ContentView() + { + IsVisible = false + }; + + contentGrid.Add(leadingContent); + contentGrid.SetColumn(leadingContent, 0); + + leadingContent.SetBinding( + ContentView.ContentProperty, + static (TitleBar tb) => tb.LeadingContent, + source: RelativeBindingSource.TemplatedParent); + + var leadingVisibleGroup = GetVisibleStateGroup(TitleBarLeading, LeadingVisibleState, LeadingHiddenState); + leadingVisibleGroup.Name = "LeadingContentGroup"; + visualStateGroups.Add(leadingVisibleGroup); + #endregion + + #region Icon + var icon = new Image() + { + WidthRequest = 16, + HeightRequest = 16, + VerticalOptions = LayoutOptions.Center, + Margin = new Thickness(16, 0, 0, 0), + IsVisible = false, + }; + + contentGrid.Add(icon); + contentGrid.SetColumn(icon, 1); + + icon.SetBinding( + Image.SourceProperty, + static (TitleBar tb) => tb.Icon, + source: RelativeBindingSource.TemplatedParent); + + var iconVisibleGroup = GetVisibleStateGroup(TitleBarIcon, IconVisibleState, IconHiddenState); + iconVisibleGroup.Name = "IconGroup"; + visualStateGroups.Add(iconVisibleGroup); + #endregion + + #region Title + var titleLabel = new Label() + { + Margin = new Thickness(16, 0), + LineBreakMode = LineBreakMode.NoWrap, + HorizontalOptions = LayoutOptions.Start, + VerticalOptions = LayoutOptions.Center, + MinimumWidthRequest = 48, + FontSize = 12, + IsVisible = false + }; + + contentGrid.Add(titleLabel); + contentGrid.SetColumn(titleLabel, 2); + + titleLabel.SetBinding( + Label.TextProperty, + static (TitleBar tb) => tb.Title, + source: RelativeBindingSource.TemplatedParent); + + titleLabel.SetBinding( + Label.TextColorProperty, + static (TitleBar tb) => tb.ForegroundColor, + source: RelativeBindingSource.TemplatedParent); + + var activeVisualState = new VisualState() { Name = TitleBarActiveState }; + activeVisualState.Setters.Add( + new Setter() + { + Property = Label.OpacityProperty, + TargetName = TitleBarTitle, + Value = 1.0 + }); + + var inactiveVisualState = new VisualState() { Name = TitleBarInactiveState }; + inactiveVisualState.Setters.Add( + new Setter() + { + Property = Label.OpacityProperty, + TargetName = TitleBarTitle, + Value = 0.7 + }); + + var labelActiveStateGroup = new VisualStateGroup() { Name = "TitleActiveStates" }; + labelActiveStateGroup.States.Add(activeVisualState); + labelActiveStateGroup.States.Add(inactiveVisualState); + visualStateGroups.Add(labelActiveStateGroup); + + var titleVisibleGroup = GetVisibleStateGroup(TitleBarTitle, TitleVisibleState, TitleHiddenState); + titleVisibleGroup.Name = "TitleTextGroup"; + visualStateGroups.Add(titleVisibleGroup); + #endregion + + #region Subtitle + var subtitleLabel = new Label() + { + Margin = new Thickness(0, 0, 16, 0), + LineBreakMode = LineBreakMode.NoWrap, + HorizontalOptions = LayoutOptions.Start, + VerticalOptions = LayoutOptions.Center, + MinimumWidthRequest = 48, + FontSize = 12, + Opacity = 0.7, + IsVisible = false + }; + + contentGrid.Add(subtitleLabel); + contentGrid.SetColumn(subtitleLabel, 3); + + subtitleLabel.SetBinding( + Label.TextProperty, + static (TitleBar tb) => tb.Subtitle, + source: RelativeBindingSource.TemplatedParent); + + subtitleLabel.SetBinding( + Label.TextColorProperty, + static (TitleBar tb) => tb.ForegroundColor, + source: RelativeBindingSource.TemplatedParent); + + var subtitleVisibleGroup = GetVisibleStateGroup(TitleBarSubtitle, SubtitleVisibleState, SubtitleHiddenState); + subtitleVisibleGroup.Name = "SubtitleTextGroup"; + visualStateGroups.Add(subtitleVisibleGroup); + #endregion + + #region Content + var content = new ContentView() + { + IsVisible = false + }; + + contentGrid.Add(content); + contentGrid.SetColumn(content, 4); + + content.SetBinding( + ContentView.ContentProperty, + static (TitleBar tb) => tb.Content, + source: RelativeBindingSource.TemplatedParent); + + var contentVisibleGroup = GetVisibleStateGroup(TitleBarContent, ContentVisibleState, ContentHiddenState); + contentVisibleGroup.Name = "ContentGroup"; + visualStateGroups.Add(contentVisibleGroup); + #endregion + + #region Trailing content + var trailingContent = new ContentView() + { + IsVisible = false + }; + + contentGrid.Add(trailingContent); + contentGrid.SetColumn(trailingContent, 5); + + trailingContent.SetBinding( + ContentView.ContentProperty, + static (TitleBar tb) => tb.TrailingContent, + source: RelativeBindingSource.TemplatedParent); + + var trailingContentVisibleGroup = GetVisibleStateGroup(TitleBarTrailing, TrailingVisibleState, TrailingHiddenState); + trailingContentVisibleGroup.Name = "TrailingContentGroup"; + visualStateGroups.Add(trailingContentVisibleGroup); + #endregion + + INameScope nameScope = new NameScope(); + NameScope.SetNameScope(contentGrid, nameScope); + nameScope.RegisterName(TemplateRootName, contentGrid); + nameScope.RegisterName(TitleBarLeading, leadingContent); + nameScope.RegisterName(TitleBarIcon, icon); + nameScope.RegisterName(TitleBarTitle, titleLabel); + nameScope.RegisterName(TitleBarSubtitle, subtitleLabel); + nameScope.RegisterName(TitleBarContent, content); + nameScope.RegisterName(TitleBarTrailing, trailingContent); + + VisualStateManager.SetVisualStateGroups(contentGrid, visualStateGroups); + + return contentGrid; + } + + static VisualStateGroup GetVisibleStateGroup(string targetName, string visibleState, string hiddenState) + { + var visualGroup = new VisualStateGroup(); + var visualVisibleState = new VisualState() { Name = visibleState }; + visualVisibleState.Setters.Add( + new Setter() + { + Property = IsVisibleProperty, + TargetName = targetName, + Value = true + }); + visualGroup.States.Add(visualVisibleState); + + var collapsedState = new VisualState() { Name = hiddenState }; + collapsedState.Setters.Add( + new Setter() + { + Property = IsVisibleProperty, + TargetName = targetName, + Value = false + }); + visualGroup.States.Add(collapsedState); + return visualGroup; + } + } +} diff --git a/src/Controls/src/Core/Toolbar/Toolbar.Mapper.cs b/src/Controls/src/Core/Toolbar/Toolbar.Mapper.cs index 070b18587b60..e21ca43cb708 100644 --- a/src/Controls/src/Core/Toolbar/Toolbar.Mapper.cs +++ b/src/Controls/src/Core/Toolbar/Toolbar.Mapper.cs @@ -13,10 +13,6 @@ public partial class Toolbar { IMauiContext MauiContext => Handler?.MauiContext ?? throw new InvalidOperationException("MauiContext not set"); - [Obsolete("Use ToolbarHandler.Mapper instead.")] - public static IPropertyMapper ControlsToolbarMapper = - new ControlsMapper(ToolbarHandler.Mapper); - internal static void RemapForControls() { #if ANDROID || WINDOWS || TIZEN diff --git a/src/Controls/src/Core/TrimmerConstants.cs b/src/Controls/src/Core/TrimmerConstants.cs index c35314ab26e6..f87c98624403 100644 --- a/src/Controls/src/Core/TrimmerConstants.cs +++ b/src/Controls/src/Core/TrimmerConstants.cs @@ -5,5 +5,14 @@ class TrimmerConstants // https://github.com/dotnet/runtime/blob/f130138b337b57342e94dabf499b818531effed5/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs#L31-L32 internal const string SerializerTrimmerWarning = "Data Contract Serialization and Deserialization might require types that cannot be statically analyzed. Make sure all of the required types are preserved."; - internal const string NativeBindingService = "This method properly handles missing properties, and there is not a way to preserve them from this method."; + internal const string StringPathBindingWarning = "Using bindings with string paths is not trim safe. Use expression-based binding instead."; + + internal const string? ExpressionBasedBindingsDocsUrl = null; // TODO: we don't have this page yet + + internal const string XamlRuntimeParsingNotSupportedWarning = "Loading XAML at runtime might require types and members that cannot be statically analyzed. Make sure all of the required types and members are preserved."; + + internal const string SearchHandlerDisplayMemberNameNotSupportedWarning = "DisplayMemberName is not supported. Consider implementing custom ItemTemplate instead. Alternatively, enable DisplayMemberName by setting the $(MauiShellSearchResultsRendererDisplayMemberNameSupported) MSBuild property to true. Note: DisplayMemberName is not trimming-safe and it might not work as expected in NativeAOT or fully trimmed apps."; + + internal const string QueryPropertyAttributeWarning = "Using QueryPropertyAttribute is not trimming friendly and might not work correctly. Implement the IQueryAttributable interface instead."; + internal const string QueryPropertyDocsUrl = "https://learn.microsoft.com/dotnet/maui/fundamentals/shell/navigation#process-navigation-data-using-a-single-method"; } \ No newline at end of file diff --git a/src/Controls/src/Core/TypeConversionHelper.cs b/src/Controls/src/Core/TypeConversionHelper.cs new file mode 100644 index 000000000000..65029a951cd7 --- /dev/null +++ b/src/Controls/src/Core/TypeConversionHelper.cs @@ -0,0 +1,182 @@ +#nullable enable + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using Microsoft.Extensions.Logging; +using Microsoft.Maui.Controls.Xaml; +using Microsoft.Maui.Hosting; + +namespace Microsoft.Maui.Controls +{ + internal static class TypeConversionHelper + { + internal static bool TryConvert(object value, Type targetType, out object? convertedValue) + { + Type valueType = value.GetType(); + + if (value is IWrappedValue { Value: var wrappedValue, ValueType: var wrappedType }) + { + if (wrappedValue is null) + { + convertedValue = null; + return !targetType.IsValueType || targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>); + } + + // It might be enough just to unwrap the value + if (targetType.IsAssignableFrom(wrappedType)) + { + convertedValue = wrappedValue; + return true; + } + + value = wrappedValue; + valueType = wrappedType; + } + + if (RuntimeFeature.IsImplicitCastOperatorsUsageViaReflectionSupported) + { +#if NET8_0 +#pragma warning disable IL2026 // FeatureGuardAttribute is not supported on .NET 8 +#endif + if (TryConvertUsingImplicitCastOperator(value, targetType, out convertedValue)) +#if NET8_0 +#pragma warning restore IL2026 // FeatureGuardAttribute is not supported on .NET 8 +#endif + { + return true; + } + } + else + { + if (TryGetTypeConverter(valueType, out var converter) && converter is not null && converter.CanConvertTo(targetType)) + { + convertedValue = converter.ConvertTo(value, targetType) ?? throw new InvalidOperationException($"The {converter.GetType()} returned null when converting {valueType} to {targetType}"); + return true; + } + + if (TryGetTypeConverter(targetType, out converter) && converter is not null && converter.CanConvertFrom(valueType)) + { + convertedValue = converter.ConvertFrom(value) ?? throw new InvalidOperationException($"The {converter.GetType()} returned null when converting from {valueType}"); + return true; + } + + WarnIfImplicitOperatorIsAvailable(value, targetType); + } + + convertedValue = null; + return false; + } + + private static bool TryGetTypeConverter(Type type, [NotNullWhen(true)] out TypeConverter? converter) + => type.TryGetTypeConverter(out converter); + + private static bool ShouldCheckForImplicitConversionOperator(Type type) => + type != typeof(string) && !BindableProperty.SimpleConvertTypes.ContainsKey(type); + + [RequiresUnreferencedCode("The method uses reflection to find implicit conversion operators. " + + "It is not possible to guarantee that trimming does not remove some of the implicit operators. " + + "Consider adding a custom TypeConverter that can perform the conversion instead.")] + private static bool TryConvertUsingImplicitCastOperator(object value, Type targetType, [NotNullWhen(true)] out object? result) + { + Type valueType = value.GetType(); + MethodInfo? opImplicit = GetImplicitConversionOperator(valueType, fromType: valueType, toType: targetType) + ?? GetImplicitConversionOperator(targetType, fromType: valueType, toType: targetType); + + object? convertedValue = opImplicit?.Invoke(null, new[] { value }); + if (convertedValue is not null) + { + result = convertedValue; + return true; + } + + result = null; + return false; + + [RequiresUnreferencedCode("The method looks for op_Implicit methods using reflection. " + + "We cannot guarantee that the method is preserved when the code is trimmed.")] + static MethodInfo? GetImplicitConversionOperator(Type onType, Type fromType, Type toType) + { + if (!ShouldCheckForImplicitConversionOperator(onType)) + return null; + + const BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy; + + try + { + var method = onType.GetMethod("op_Implicit", bindingAttr, null, new[] { fromType }, null); + if (method is not null + && IsImplicitOperator(method) + && HasSuitableReturnType(method, toType)) + { + return method; + } + } + catch (AmbiguousMatchException) + { + // Ignore the exception and fall back to custom filtering of all methods. + // This happens when there are multiple implicit operators with the same parameter type, + // but with different return types. + } + + foreach (var method in onType.GetMethods(bindingAttr)) + { + if (IsImplicitOperator(method) + && HasSuitableParameterType(method, fromType) + && HasSuitableReturnType(method, toType)) + { + return method; + } + } + + return null; + } + + static bool IsImplicitOperator(MethodInfo method) + => method.IsSpecialName + && method.IsPublic + && method.IsStatic + && method.Name == "op_Implicit"; + + // Note: our custom type compatiblity checks are much less permissie than what .NET does internally. + // The `IsAssignableFrom` method will for example return `false` when asking if `int` can be assigned + // to `long`. This will filter out some valid matches and can lead to unexpected behavior. + // The converison method has behaved this way for many years so we should probably keep it this way, + // especially since we're trying to replace these implicit operators with type converters. + + static bool HasSuitableParameterType(MethodInfo method, Type fromType) + => method.GetParameters() is ParameterInfo[] parameters + && parameters.Length == 1 + && parameters[0].ParameterType.IsAssignableFrom(fromType); + + static bool HasSuitableReturnType(MethodInfo method, Type toType) + => toType.IsAssignableFrom(method.ReturnType); + } + + private static void WarnIfImplicitOperatorIsAvailable(object value, Type targetType) + { + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The method tries finding implicit cast operators reflection to help developers " + + "catch the cases where they are missing type converters during development mostly in debug builds. " + + "The method is expected not to find anything when the app code is trimmed.")] + bool HasImplicitOperatorConversion() + { + return TryConvertUsingImplicitCastOperator(value, targetType, out _); + } + + if (HasImplicitOperatorConversion()) + { + // If we reach this point, it means that the implicit cast operator exists, but we are not allowed to use it. This can happen for example in debug builds + // when the app is not trimmed. This is the best effort to help developers catch the cases where they are missing type converters during development. + // Unforutnately, we cannot just add a build warning at this moment. + Application.Current?.FindMauiContext()?.CreateLogger(nameof(TypeConversionHelper))?.LogWarning( + $"It is not possible to convert value of type {value.GetType()} to {targetType} via an implicit cast " + + "because this feature is disabled. You should add a type converter that will implement this conversion and attach it to either of " + + "these types using the [TypeConverter] attribute. Alternatively, you " + + "can enable this feature by setting the MauiImplicitCastOperatorsUsageViaReflectionSupport MSBuild property to true in your project file. " + + "Note: this feature is not compatible with trimming and with NativeAOT."); + } + } + } +} diff --git a/src/Controls/src/Core/TypedBinding.cs b/src/Controls/src/Core/TypedBinding.cs index eae31ed6fc40..cdbe7d6a9b5b 100644 --- a/src/Controls/src/Core/TypedBinding.cs +++ b/src/Controls/src/Core/TypedBinding.cs @@ -66,6 +66,54 @@ internal string UpdateSourceEventName internal TypedBindingBase() { } + + internal abstract void ApplyToResolvedSource(object sourceObject, BindableObject target, BindableProperty property, bool fromTarget, SetterSpecificity specificity); + internal abstract void SubscribeToAncestryChanges(List chain, bool includeBindingContext, bool rootIsSource); + } + + internal class TypedBinding + { + /// + /// This factory method was added to simplify creating typed bindings for a property that + /// isn't nested which is the most common scenario. + /// This factory method must be used carefully. As the name implies, it is only applicable + /// when the getter and setter access a property directly on the source object. Whenever the + /// property is nested two or more levels deep, create the binding manually and construct the + /// handlers array for that usecase. + /// + /// The type of the source object. + /// The type of the property. + /// The name of the property. + /// The getter function to retrieve the property value from the source object. + /// The optional setter action to set the property value on the source object. + /// The binding mode. + /// The value converter. + /// The converter parameter. + /// The source object. + /// The typed binding. + internal static TypedBinding ForSingleNestingLevel( + string propertyName, + Func getter, + Action setter = null, + BindingMode mode = BindingMode.Default, + IValueConverter converter = null, + object converterParameter = null, + object source = null) + { + return new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, propertyName), + }) + { + Converter = converter, + ConverterParameter = converterParameter, + Mode = mode, + Source = source, + }; + } } [EditorBrowsable(EditorBrowsableState.Never)] @@ -96,6 +144,8 @@ public TypedBinding(Func getter, Actio readonly WeakReference _weakTarget = new WeakReference(null); SetterSpecificity _specificity; BindableProperty _targetProperty; + List> _ancestryChain; + bool _isBindingContextRelativeSource; // Applies the binding to a previously set source and target. internal override void Apply(bool fromTarget = false) @@ -130,19 +180,32 @@ internal override void Apply(object context, BindableObject bindObj, BindablePro base.Apply(source, bindObj, targetProperty, fromBindingContextChanged, specificity); -#if (!DO_NOT_CHECK_FOR_BINDING_REUSE) - BindableObject prevTarget; - if (_weakTarget.TryGetTarget(out prevTarget) && !ReferenceEquals(prevTarget, bindObj)) - throw new InvalidOperationException("Binding instances cannot be reused"); + if (Source is RelativeBindingSource relativeSource) + { + var relativeSourceTarget = RelativeSourceTargetOverride ?? bindObj as Element; + if (relativeSourceTarget is not Element) + { + var message = bindObj is not null + ? $"Cannot apply relative binding to {bindObj.GetType().FullName} because it is not a superclass of Element." + : "Cannot apply relative binding when the target object is null."; - object previousSource; - if (_weakSource.TryGetTarget(out previousSource) && !ReferenceEquals(previousSource, source)) - throw new InvalidOperationException("Binding instances cannot be reused"); -#endif - _weakSource.SetTarget(source); - _weakTarget.SetTarget(bindObj); + throw new InvalidOperationException(message); + } + + ApplyRelativeSourceBinding(relativeSource, relativeSourceTarget, bindObj, targetProperty, specificity); + } + else + { + ApplyToResolvedSource(source, bindObj, targetProperty, false, specificity); + } + } - ApplyCore(source, bindObj, targetProperty, false, specificity); +#pragma warning disable RECS0165 // Asynchronous methods should return a Task instead of void + async void ApplyRelativeSourceBinding( + RelativeBindingSource relativeSource, Element relativeSourceTarget, BindableObject targetObject, BindableProperty targetProperty, SetterSpecificity specificity) +#pragma warning restore RECS0165 // Asynchronous methods should return a Task instead of void + { + await relativeSource.Apply(this, relativeSourceTarget, targetObject, targetProperty, specificity); } internal override BindingBase Clone() @@ -168,6 +231,23 @@ internal override BindingBase Clone() }; } + internal override void ApplyToResolvedSource(object source, BindableObject target, BindableProperty targetProperty, bool fromBindingContextChanged, SetterSpecificity specificity) + { +#if (!DO_NOT_CHECK_FOR_BINDING_REUSE) + BindableObject prevTarget; + if (_weakTarget.TryGetTarget(out prevTarget) && !ReferenceEquals(prevTarget, target)) + throw new InvalidOperationException("Binding instances cannot be reused"); + + object previousSource; + if (_weakSource.TryGetTarget(out previousSource) && !ReferenceEquals(previousSource, source)) + throw new InvalidOperationException("Binding instances cannot be reused"); +#endif + _weakTarget.SetTarget(target); + _weakSource.SetTarget(source); + + ApplyCore(source, target, targetProperty, fromBindingContextChanged, specificity); + } + internal override object GetSourceValue(object value, Type targetPropertyType) { if (Converter != null) @@ -208,6 +288,11 @@ internal override void Unapply(bool fromBindingContextChanged = false) internal void ApplyCore(object sourceObject, BindableObject target, BindableProperty property, bool fromTarget, SetterSpecificity specificity) { var isTSource = sourceObject is TSource; + if (!isTSource && sourceObject is not null) + { + BindingDiagnostics.SendBindingFailure(this, "Binding", $"Mismatch between the specified x:DataType ({typeof(TSource)}) and the current binding context ({sourceObject.GetType()})"); + } + var mode = this.GetRealizedMode(property); if ((mode == BindingMode.OneWay || mode == BindingMode.OneTime) && fromTarget) return; @@ -232,7 +317,7 @@ internal void ApplyCore(object sourceObject, BindableObject target, BindableProp { } } - if (!BindingExpression.TryConvert(ref value, property, property.ReturnType, true)) + if (!BindingExpressionHelper.TryConvert(ref value, property, property.ReturnType, true)) { BindingDiagnostics.SendBindingFailure(this, sourceObject, target, property, "Binding", BindingExpression.CannotConvertTypeErrorMessage, value, property.ReturnType); return; @@ -245,7 +330,7 @@ internal void ApplyCore(object sourceObject, BindableObject target, BindableProp if (needsSetter && _setter != null && isTSource) { var value = GetTargetValue(target.GetValue(property), typeof(TProperty)); - if (!BindingExpression.TryConvert(ref value, property, typeof(TProperty), false)) + if (!BindingExpressionHelper.TryConvert(ref value, property, typeof(TProperty), false)) { BindingDiagnostics.SendBindingFailure(this, sourceObject, target, property, "Binding", BindingExpression.CannotConvertTypeErrorMessage, value, typeof(TProperty)); return; @@ -254,6 +339,121 @@ internal void ApplyCore(object sourceObject, BindableObject target, BindableProp } } + // SubscribeToAncestryChanges, ClearAncestryChangeSubscriptions, FindAncestryIndex, and + // OnElementParentSet are used with RelativeSource ancestor-type bindings, to detect when + // there has been an ancestry change requiring re-applying the binding, and to minimize + // re-applications especially during visual tree building. + internal override void SubscribeToAncestryChanges(List chain, bool includeBindingContext, bool rootIsSource) + { + ClearAncestryChangeSubscriptions(); + if (chain == null) + return; + _isBindingContextRelativeSource = includeBindingContext; + _ancestryChain = new List>(); + for (int i = 0; i < chain.Count; i++) + { + var elem = chain[i]; + if (i != chain.Count - 1 || !rootIsSource) + // don't care about a successfully resolved source's parents + elem.ParentSet += OnElementParentSet; + if (_isBindingContextRelativeSource) + elem.BindingContextChanged += OnElementBindingContextChanged; + _ancestryChain.Add(new WeakReference(elem)); + } + } + + void ClearAncestryChangeSubscriptions(int beginningWith = 0) + { + if (_ancestryChain == null || _ancestryChain.Count == 0) + return; + int count = _ancestryChain.Count; + for (int i = beginningWith; i < count; i++) + { + Element elem; + var weakElement = _ancestryChain.Last(); + if (weakElement.TryGetTarget(out elem)) + { + elem.ParentSet -= OnElementParentSet; + if (_isBindingContextRelativeSource) + elem.BindingContextChanged -= OnElementBindingContextChanged; + } + _ancestryChain.RemoveAt(_ancestryChain.Count - 1); + } + } + + // Returns -1 if the member is not in the chain or the + // chain is no longer valid. + int FindAncestryIndex(Element elem) + { + for (int i = 0; i < _ancestryChain.Count; i++) + { + WeakReference weak = _ancestryChain[i]; + Element chainMember = null; + if (!weak.TryGetTarget(out chainMember)) + return -1; + else if (object.Equals(elem, chainMember)) + return i; + } + return -1; + } + + void OnElementBindingContextChanged(object sender, EventArgs e) + { + if (!(sender is Element elem)) + return; + + BindableObject target = null; + if (_weakTarget?.TryGetTarget(out target) != true) + return; + + object currentSource = null; + if (_weakSource?.TryGetTarget(out currentSource) == true) + { + // make sure that this isn't just a repeat notice + // from someone else in the chain about our already-resolved + // binding source + if (object.ReferenceEquals(currentSource, elem.BindingContext)) + return; + } + + Unapply(); + Apply(null, target, _targetProperty, false, SetterSpecificity.FromBinding); + } + + void OnElementParentSet(object sender, EventArgs e) + { + if (!(sender is Element elem)) + return; + + BindableObject target = null; + if (_weakTarget?.TryGetTarget(out target) != true) + return; + + if (elem.Parent == null) + { + // Remove anything further up in the chain + // than the element with the null parent + int index = FindAncestryIndex(elem); + if (index == -1) + { + Unapply(); + return; + } + if (index + 1 < _ancestryChain.Count) + ClearAncestryChangeSubscriptions(index + 1); + + // Force the binding expression to resolve to null + // for now, until someone in the chain gets a new + // non-null parent. + ApplyCore(null, target, _targetProperty, false, _specificity); + } + else + { + Unapply(); + Apply(null, target, _targetProperty, false, _specificity); + } + } + class PropertyChangedProxy { public Func PartGetter { get; } diff --git a/src/Controls/src/Core/ViewExtensions.cs b/src/Controls/src/Core/ViewExtensions.cs index e82431bbace6..1cafcdd80a77 100644 --- a/src/Controls/src/Core/ViewExtensions.cs +++ b/src/Controls/src/Core/ViewExtensions.cs @@ -519,5 +519,20 @@ static internal void MapFocus(this VisualElement view, FocusRequest focusRequest return window.Handler?.MauiContext; } + + /// + /// Layout updates can be forced by app code rather than relying on the built-in layout system behavior. However, that is not generally recommended. + /// Calling InvalidateArrange, InvalidateMeasure or UpdateLayout is usually unnecessary and can cause poor performance if overused. + /// In many situations where app code might be changing layout properties, the layout system will probably already be processing updates asynchronously. + /// The layout system also has optimizations for dealing with cascades of layout changes through parent-child relationships, + /// and forcing layout with app code can work against such optimizations. Nevertheless, + /// it's possible that layout situations exist in more complicated scenarios where forcing layout is the best option for resolving a timing issue or other issue with layout. + /// Just use it deliberately and sparingly. + /// + /// The view on which this method operates. + public static void InvalidateMeasure(this VisualElement view) + { + (view as IView)?.InvalidateMeasure(); + } } -} +} \ No newline at end of file diff --git a/src/Controls/src/Core/VisualElement/VisualElement.Mapper.cs b/src/Controls/src/Core/VisualElement/VisualElement.Mapper.cs index 6ba0ca101cb0..c5cb1b6ff8a1 100644 --- a/src/Controls/src/Core/VisualElement/VisualElement.Mapper.cs +++ b/src/Controls/src/Core/VisualElement/VisualElement.Mapper.cs @@ -8,10 +8,6 @@ namespace Microsoft.Maui.Controls /// public partial class VisualElement { - [Obsolete("Use ViewHandler.ViewMapper instead.")] - public static IPropertyMapper ControlsVisualElementMapper = new ControlsMapper(Element.ControlsElementMapper); - - internal static new void RemapForControls() { RemapForControls(ViewHandler.ViewMapper, ViewHandler.ViewCommandMapper); diff --git a/src/Controls/src/Core/VisualElement/VisualElement.cs b/src/Controls/src/Core/VisualElement/VisualElement.cs index 24946eb7c3d5..bb6c4be7490f 100644 --- a/src/Controls/src/Core/VisualElement/VisualElement.cs +++ b/src/Controls/src/Core/VisualElement/VisualElement.cs @@ -23,7 +23,7 @@ public partial class VisualElement : NavigableElement, IAnimatable, IVisualEleme /// Bindable property for . public new static readonly BindableProperty NavigationProperty = NavigableElement.NavigationProperty; - /// Bindable property for . + /// public new static readonly BindableProperty StyleProperty = NavigableElement.StyleProperty; bool _inputTransparentExplicit = (bool)InputTransparentProperty.DefaultValue; @@ -490,7 +490,9 @@ Window IWindowController.Window set => SetValue(WindowPropertyKey, value); } +#pragma warning disable CS0618 // Type or member is obsolete readonly Dictionary _measureCache = new Dictionary(); +#pragma warning restore CS0618 // Type or member is obsolete int _batched; LayoutConstraint _computedConstraint; @@ -1115,6 +1117,7 @@ public bool Focus() => ///
public event EventHandler Focused; + [Obsolete] SizeRequest GetSizeRequest(double widthConstraint, double heightConstraint) { var constraintSize = new Size(widthConstraint, heightConstraint); @@ -1166,6 +1169,20 @@ SizeRequest GetSizeRequest(double widthConstraint, double heightConstraint) return r; } + /// + /// Returns the minimum size that an element needs in order to be displayed on the device. Margins are excluded from the measurement, but returned with the size. + /// It is not recommended to call this method outside of the `MeasureOverride` pass on the parent element. + /// + /// The suggested maximum width constraint for the element to render. + /// The suggested maximum height constraint for the element to render. + /// The minimum size that an element needs in order to be displayed on the device. + /// If the minimum size that the element needs in order to be displayed on the device is larger than can be accommodated by and , the return value may represent a rectangle that is larger in either one or both of those parameters. + public Size Measure(double widthConstraint, double heightConstraint) + { + var result = (this as IView).Measure(widthConstraint, heightConstraint); + return result; + } + /// /// Returns the minimum size that an element needs in order to be displayed on the device. /// @@ -1174,6 +1191,7 @@ SizeRequest GetSizeRequest(double widthConstraint, double heightConstraint) /// A value that controls whether margins are included in the returned size. /// The minimum size that an element needs in order to be displayed on the device. /// If the minimum size that the element needs in order to be displayed on the device is larger than can be accommodated by and , the return value may represent a rectangle that is larger in either one or both of those parameters. + [Obsolete("Use Measure with no flags.")] public virtual SizeRequest Measure(double widthConstraint, double heightConstraint, MeasureFlags flags = MeasureFlags.None) { bool includeMargins = (flags & MeasureFlags.IncludeMargins) != 0; @@ -1279,24 +1297,19 @@ protected override void OnChildRemoved(Element child, int oldLogicalIndex) protected void OnChildrenReordered() => ChildrenReordered?.Invoke(this, EventArgs.Empty); - IPlatformSizeService _platformSizeService; - /// /// Method that is called when a layout measurement happens. /// /// The width constraint to request. /// The height constraint to request. /// The requested size that the element requires in order to be displayed on the device. + [Obsolete("Use MeasureOverride instead")] protected virtual SizeRequest OnMeasure(double widthConstraint, double heightConstraint) { if (!IsPlatformEnabled) return new SizeRequest(new Size(-1, -1)); - if (Handler != null) - return new SizeRequest(Handler.GetDesiredSize(widthConstraint, heightConstraint)); - - _platformSizeService ??= DependencyService.Get(); - return _platformSizeService.GetPlatformSize(this, widthConstraint, heightConstraint); + return Handler?.GetDesiredSize(widthConstraint, heightConstraint) ?? new(); } /// @@ -1350,6 +1363,7 @@ internal void InvokeFocusChangeRequested(FocusRequestArgs args) => /// /// For internal use only. This API can be changed or removed without notice at any time. [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Use InvalidateMeasure instead.")] public void InvalidateMeasureNonVirtual(InvalidationTrigger trigger) { InvalidateMeasureInternal(trigger); @@ -1745,6 +1759,7 @@ void UpdateBoundsComponents(Rect bounds) /// /// Gets or sets the frame this element resides in on screen. /// + /// Setting this property outside of won't do anything. If you want to influence this property you'll need to override public Rect Frame { get => _frame; @@ -1849,10 +1864,13 @@ public int ZIndex /// Positions child objects and determines a size for an element. ///
/// The final size that the parent computes for the child in layout, provided as a value. - /// Parent objects that implement custom layout for their child elements should call this method from their layout override implementations to form a recursive layout update. + /// + /// Parent objects that implement custom layout for their child elements should call this method from their layout override implementations to form a recursive layout update. + /// Prior to .NET 9, this method simply called . If you need to revert to the old behavior, just call . + /// public void Arrange(Rect bounds) { - Layout(bounds); + ArrangeOverride(bounds); } /// @@ -1862,11 +1880,11 @@ Size IView.Arrange(Rect bounds) } /// - /// Allows subclasses to override even though - /// the interface has to be explicitly implemented to avoid conflict with the old method. + /// Allows subclasses to implement custom Arrange logic during a controls layout pass. /// /// The new bounds of the element. /// The resulting size of this element's frame by the platform. + /// Subclasses will stil want to call on the base class or call on the . protected virtual Size ArrangeOverride(Rect bounds) { Frame = this.ComputeFrame(bounds); @@ -1891,8 +1909,7 @@ void IView.InvalidateMeasure() } /// - /// Provides a way to allow subclasses (e.g., Layout) to override even though - /// the interface has to be explicitly implemented to avoid conflict with the method. + /// Provides a way to allow subclasses (e.g., Layout) to override /// protected virtual void InvalidateMeasureOverride() => Handler?.Invoke(nameof(IView.InvalidateMeasure)); @@ -1909,8 +1926,7 @@ Size IView.Measure(double widthConstraint, double heightConstraint) } /// - /// Provides a way to allow subclasses to override even though - /// the interface has to be explicitly implemented to avoid conflict with the old Measure method. + /// Allows subclasses to implement custom Measure logic during a controls measure pass. /// /// The width constraint to request. /// The height constraint to request. @@ -1969,17 +1985,17 @@ static double EnsurePositive(double value) return value; } - private protected override void UpdateHandlerValue(string property) + private protected override void UpdateHandlerValue(string property, bool valueChanged) { // The HeightProperty and WidthProperty are not designed to propagate back to the handler. // Instead, we use WidthRequestProperty and HeightRequestProperty to propagate changes to the handler. // HeightProperty and WidthProperty are readonly and only update when the VisualElement.Frame property is set // during an arrange pass, which indicates the actual width and height of the platform element. // Changes to WidthRequestProperty and HeightRequestProperty will propagate to the handler via the `OnRequestChanged` method. - if (this.Batched && (property == HeightProperty.PropertyName || property == WidthProperty.PropertyName)) + if (valueChanged && this.Batched && (property == HeightProperty.PropertyName || property == WidthProperty.PropertyName)) return; - base.UpdateHandlerValue(property); + base.UpdateHandlerValue(property, valueChanged); } /// diff --git a/src/Controls/src/Core/VisualElement/VisualElement_StyleSheet.cs b/src/Controls/src/Core/VisualElement/VisualElement_StyleSheet.cs index 2f376722e2cd..97121851de20 100644 --- a/src/Controls/src/Core/VisualElement/VisualElement_StyleSheet.cs +++ b/src/Controls/src/Core/VisualElement/VisualElement_StyleSheet.cs @@ -1,5 +1,6 @@ #nullable disable using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using Microsoft.Maui.Controls.Internals; @@ -8,6 +9,7 @@ namespace Microsoft.Maui.Controls { /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] public partial class VisualElement : IStylable { BindableProperty IStylable.GetProperty(string key, bool inheriting) diff --git a/src/Controls/src/Core/VisualStateManager.cs b/src/Controls/src/Core/VisualStateManager.cs index 154d83dc880e..e87374293482 100644 --- a/src/Controls/src/Core/VisualStateManager.cs +++ b/src/Controls/src/Core/VisualStateManager.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Runtime.CompilerServices; using Microsoft.Maui.Controls.Xaml; namespace Microsoft.Maui.Controls @@ -30,14 +29,14 @@ public class CommonStates static void VisualStateGroupsPropertyChanged(BindableObject bindable, object oldValue, object newValue) { - if (oldValue is VisualStateGroupList oldVisualStateGroupList && oldVisualStateGroupList.VisualElement is VisualElement oldElement) + if (oldValue is VisualStateGroupList { VisualElement: { } oldElement } oldVisualStateGroupList) { - var vsgSpecificity = ((VisualStateGroupList)oldValue).Specificity; - var specificity = new SetterSpecificity(1, 0, 0, 0, vsgSpecificity.Style, vsgSpecificity.Id, vsgSpecificity.Class, vsgSpecificity.Type); + var vsgSpecificity = oldVisualStateGroupList.Specificity; + var specificity = vsgSpecificity.CopyStyle(1, 0, 0, 0); foreach (var group in oldVisualStateGroupList) { - if (group.CurrentState is VisualState state) + if (group.CurrentState is { } state) foreach (var setter in state.Setters) setter.UnApply(oldElement, specificity); } @@ -65,18 +64,23 @@ public static void SetVisualStateGroups(VisualElement visualElement, VisualState /// public static bool GoToState(VisualElement visualElement, string name) { - if (!visualElement.HasVisualStateGroups()) + var context = visualElement.GetContext(VisualStateGroupsProperty); + if (context is null) { return false; } - var groups = (VisualStateGroupList)visualElement.GetValue(VisualStateGroupsProperty); - var context = visualElement.GetContext(VisualStateGroupsProperty); - var vsgSpecificity = context.Values.GetSpecificityAndValue().Key; - if (vsgSpecificity == SetterSpecificity.DefaultValue) - vsgSpecificity = new SetterSpecificity(); + var vsgSpecificityValue = context.Values.GetSpecificityAndValue(); + var groups = (VisualStateGroupList)vsgSpecificityValue.Value; + if (groups?.IsDefault != false) + { + return false; + } + + var vsgSpecificity = vsgSpecificityValue.Key; groups.Specificity = vsgSpecificity; - var specificity = new SetterSpecificity(1, 0, 0, 0, vsgSpecificity.Style, vsgSpecificity.Id, vsgSpecificity.Class, vsgSpecificity.Type); + + var specificity = vsgSpecificity.CopyStyle(1, 0, 0, 0); foreach (VisualStateGroup group in groups) { @@ -407,7 +411,7 @@ internal VisualState GetState(string name) { foreach (VisualState state in States) { - if (string.CompareOrdinal(state.Name, name) == 0) + if (string.Equals(state.Name, name, StringComparison.Ordinal)) { return state; } diff --git a/src/Controls/src/Core/Visuals/VisualTypeConverter.cs b/src/Controls/src/Core/Visuals/VisualTypeConverter.cs index 9bcf366c9959..4cb804be8ac2 100644 --- a/src/Controls/src/Core/Visuals/VisualTypeConverter.cs +++ b/src/Controls/src/Core/Visuals/VisualTypeConverter.cs @@ -26,15 +26,39 @@ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinati void InitMappings() { var mappings = new Dictionary(StringComparer.OrdinalIgnoreCase); + + if (RuntimeFeature.IsIVisualAssemblyScanningEnabled) + { +#if NET8_0 +#pragma warning disable IL2026 // FeatureGuardAttribute is not supported on .NET 8 +#endif + ScanAllAssemblies(mappings); +#if NET8_0 +#pragma warning restore IL2026 // FeatureGuardAttribute is not supported on .NET 8 +#endif + } + else + { + Register(typeof(VisualMarker.MaterialVisual), mappings); + Register(typeof(VisualMarker.DefaultVisual), mappings); + Register(typeof(VisualMarker.MatchParentVisual), mappings); + } + + _visualTypeMappings = mappings; + } + + [RequiresUnreferencedCode("The IVisual types might be removed by trimming and automatic registration via assembly scanning may not work as expected.")] + void ScanAllAssemblies(Dictionary mappings) + { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); // Check for IVisual Types foreach (var assembly in assemblies) - Register(assembly, mappings); + RegisterAllIVisualTypesInAssembly(assembly, mappings); if (Internals.Registrar.ExtraAssemblies != null) foreach (var assembly in Internals.Registrar.ExtraAssemblies) - Register(assembly, mappings); + RegisterAllIVisualTypesInAssembly(assembly, mappings); // Check for visual assembly attributes after scanning for IVisual Types @@ -46,46 +70,44 @@ void InitMappings() foreach (var assembly in Internals.Registrar.ExtraAssemblies) RegisterFromAttributes(assembly, mappings); - _visualTypeMappings = mappings; - } - - static void RegisterFromAttributes(Assembly assembly, Dictionary mappings) - { - object[] attributes = assembly.GetCustomAttributesSafe(typeof(VisualAttribute)); - - if (attributes != null) + static void RegisterAllIVisualTypesInAssembly(Assembly assembly, Dictionary mappings) { - foreach (VisualAttribute attribute in attributes) + if (assembly.IsDynamic) + return; + + try + { + foreach (var type in assembly.GetExportedTypes()) + if (typeof(IVisual).IsAssignableFrom(type) && type != typeof(IVisual)) + Register(type, mappings); + } + catch (NotSupportedException) + { + Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning("Cannot scan assembly {assembly} for Visual types.", assembly.FullName); + } + catch (FileNotFoundException) { - var visual = CreateVisual(attribute.Visual); - if (visual != null) - mappings[attribute.Key] = visual; + Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning("Unable to load a dependent assembly for {assembly}. It cannot be scanned for Visual types.", assembly.FullName); + } + catch (ReflectionTypeLoadException) + { + Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning("Unable to load a dependent assembly for {assembly}. Types cannot be loaded.", assembly.FullName); } } - } - - static void Register(Assembly assembly, Dictionary mappings) - { - if (assembly.IsDynamic) - return; - try + static void RegisterFromAttributes(Assembly assembly, Dictionary mappings) { - foreach (var type in assembly.GetExportedTypes()) - if (typeof(IVisual).IsAssignableFrom(type) && type != typeof(IVisual)) - Register(type, mappings); - } - catch (NotSupportedException) - { - Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning("Cannot scan assembly {assembly} for Visual types.", assembly.FullName); - } - catch (FileNotFoundException) - { - Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning("Unable to load a dependent assembly for {assembly}. It cannot be scanned for Visual types.", assembly.FullName); - } - catch (ReflectionTypeLoadException) - { - Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning("Unable to load a dependent assembly for {assembly}. Types cannot be loaded.", assembly.FullName); + object[] attributes = assembly.GetCustomAttributesSafe(typeof(VisualAttribute)); + + if (attributes != null) + { + foreach (VisualAttribute attribute in attributes) + { + var visual = CreateVisual(attribute.Visual); + if (visual != null) + mappings[attribute.Key] = visual; + } + } } } @@ -138,6 +160,13 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c if (_visualTypeMappings.TryGetValue(strValue, out IVisual returnValue)) return returnValue; + if (!RuntimeFeature.IsIVisualAssemblyScanningEnabled) + { + Application.Current?.FindMauiContext()?.CreateLogger()?.LogWarning( + "Unable to find visual {key}. Automatic discovery of IVisual types is disabled. You can enabled it by setting the $(MauiEnableIVisualAssemblyScanning)=true MSBuild property. " + + "Note: automatic registration of IVisual types through assembly scanning is not trimming-compatible and it can lead to slower app startup.", strValue); + } + return VisualMarker.Default; } diff --git a/src/Controls/src/Core/WebView/PlatformWebViewProcessTerminatedEventArgs.cs b/src/Controls/src/Core/WebView/PlatformWebViewProcessTerminatedEventArgs.cs new file mode 100644 index 000000000000..41f2563fac75 --- /dev/null +++ b/src/Controls/src/Core/WebView/PlatformWebViewProcessTerminatedEventArgs.cs @@ -0,0 +1,50 @@ +namespace Microsoft.Maui.Controls +{ + public class PlatformWebViewProcessTerminatedEventArgs + { +#if ANDROID + internal PlatformWebViewProcessTerminatedEventArgs(Android.Views.View? sender, Android.Webkit.RenderProcessGoneDetail? renderProcessGoneDetail) + { + Sender = sender; + RenderProcessGoneDetail = renderProcessGoneDetail; + } + + /// + /// Gets the native view attached to the event. + /// + public Android.Views.View? Sender { get; } + + /// + /// Gets the native event or handler attached to the view. + /// + public Android.Webkit.RenderProcessGoneDetail? RenderProcessGoneDetail { get; } +#elif IOS || MACCATALYST + internal PlatformWebViewProcessTerminatedEventArgs(WebKit.WKWebView sender) + { + Sender = sender; + } + + /// + /// Gets the native view attached to the event. + /// + public WebKit.WKWebView Sender { get; } +#elif WINDOWS + + internal PlatformWebViewProcessTerminatedEventArgs(Web.WebView2.Core.CoreWebView2 sender, Web.WebView2.Core.CoreWebView2ProcessFailedEventArgs coreWebView2ProcessFailedEventArgs) + { + Sender = sender; + CoreWebView2ProcessFailedEventArgs = coreWebView2ProcessFailedEventArgs; + } + + /// + /// Gets the native view attached to the event. + /// + public Web.WebView2.Core.CoreWebView2 Sender { get; } + + /// + /// Gets the native event or handler attached to the view. + /// + public Web.WebView2.Core.CoreWebView2ProcessFailedEventArgs CoreWebView2ProcessFailedEventArgs { get; } +#endif + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/WebView/WebView.Mapper.cs b/src/Controls/src/Core/WebView/WebView.Mapper.cs index 7f06e8dd4586..b76425797908 100644 --- a/src/Controls/src/Core/WebView/WebView.Mapper.cs +++ b/src/Controls/src/Core/WebView/WebView.Mapper.cs @@ -6,9 +6,6 @@ namespace Microsoft.Maui.Controls { public partial class WebView { - [Obsolete("Use WebViewHandler.Mapper instead.")] - public static IPropertyMapper ControlsWebViewMapper = new ControlsMapper(WebViewHandler.Mapper); - internal static new void RemapForControls() { // Adjust the mappings to preserve Controls.WebView legacy behaviors diff --git a/src/Controls/src/Core/WebView/WebView.cs b/src/Controls/src/Core/WebView/WebView.cs index bce0f87038d5..085b92bfe192 100644 --- a/src/Controls/src/Core/WebView/WebView.cs +++ b/src/Controls/src/Core/WebView/WebView.cs @@ -191,6 +191,11 @@ public void Reload() /// public event EventHandler Navigating; + /// + /// Raised when a WebView process ends unexpectedly. + /// + public event EventHandler ProcessTerminated; + /// protected override void OnBindingContextChanged() { @@ -282,7 +287,7 @@ public IPlatformElementConfiguration On() where T : IConfigPlatfo return _platformConfigurationRegistry.Value.On(); } - static string EscapeJsString(string js) + private static string EscapeJsString(string js) { if (js == null) return null; @@ -361,5 +366,22 @@ void IWebView.Navigated(WebNavigationEvent evnt, string url, WebNavigationResult var args = new WebNavigatedEventArgs(evnt, new UrlWebViewSource { Url = url }, url, result); (this as IWebViewController)?.SendNavigated(args); } + + void IWebView.ProcessTerminated(WebProcessTerminatedEventArgs args) + { +#if ANDROID + var platformArgs = new PlatformWebViewProcessTerminatedEventArgs(args.Sender, args.RenderProcessGoneDetail); + var webViewProcessTerminatedEventArgs = new WebViewProcessTerminatedEventArgs(platformArgs); +#elif IOS || MACCATALYST + var platformArgs = new PlatformWebViewProcessTerminatedEventArgs(args.Sender); + var webViewProcessTerminatedEventArgs = new WebViewProcessTerminatedEventArgs(platformArgs); +#elif WINDOWS + var platformArgs = new PlatformWebViewProcessTerminatedEventArgs(args.Sender, args.CoreWebView2ProcessFailedEventArgs); + var webViewProcessTerminatedEventArgs = new WebViewProcessTerminatedEventArgs(platformArgs); +#else + var webViewProcessTerminatedEventArgs = new WebViewProcessTerminatedEventArgs(); +#endif + ProcessTerminated?.Invoke(this, webViewProcessTerminatedEventArgs); + } } } \ No newline at end of file diff --git a/src/Controls/src/Core/WebView/WebViewProcessTerminatedEventArgs.cs b/src/Controls/src/Core/WebView/WebViewProcessTerminatedEventArgs.cs new file mode 100644 index 000000000000..2de211f3392e --- /dev/null +++ b/src/Controls/src/Core/WebView/WebViewProcessTerminatedEventArgs.cs @@ -0,0 +1,25 @@ +#nullable disable +using System; + +namespace Microsoft.Maui.Controls +{ + public class WebViewProcessTerminatedEventArgs : EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public WebViewProcessTerminatedEventArgs() + { + } + + internal WebViewProcessTerminatedEventArgs(PlatformWebViewProcessTerminatedEventArgs args = null) + { + PlatformArgs = args; + } + + /// + /// Gets the platform-specific arguments associated with the . + /// + public PlatformWebViewProcessTerminatedEventArgs PlatformArgs { get; private set; } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/WebView/WebViewSource.cs b/src/Controls/src/Core/WebView/WebViewSource.cs index c6b8c5b6b708..4781089520fb 100644 --- a/src/Controls/src/Core/WebView/WebViewSource.cs +++ b/src/Controls/src/Core/WebView/WebViewSource.cs @@ -1,10 +1,12 @@ #nullable disable using System; using System.ComponentModel; +using System.Globalization; namespace Microsoft.Maui.Controls { /// + [TypeConverter(typeof(WebViewSourceTypeConverter))] public abstract class WebViewSource : BindableObject, IWebViewSource { public static implicit operator WebViewSource(Uri url) @@ -29,5 +31,22 @@ protected void OnSourceChanged() public abstract void Load(IWebViewDelegate renderer); internal event EventHandler SourceChanged; + + private sealed class WebViewSourceTypeConverter : TypeConverter + { + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => false; + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cultureInfo, object value, Type destinationType) => throw new NotSupportedException(); + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + => sourceType == typeof(string) || sourceType == typeof(Uri); + + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + => value switch + { + string str => (UrlWebViewSource)str, + Uri uri => (UrlWebViewSource)uri, + _ => throw new NotSupportedException(), + }; + } } } \ No newline at end of file diff --git a/src/Controls/src/Core/Window/Window.Mapper.cs b/src/Controls/src/Core/Window/Window.Mapper.cs index 6b7277d6363e..56b37abda81c 100644 --- a/src/Controls/src/Core/Window/Window.Mapper.cs +++ b/src/Controls/src/Core/Window/Window.Mapper.cs @@ -7,10 +7,6 @@ namespace Microsoft.Maui.Controls { public partial class Window { - [Obsolete("Use WindowHandler.Mapper instead.")] - public static IPropertyMapper ControlsWindowMapper = - new ControlsMapper(WindowHandler.Mapper); - internal static new void RemapForControls() { #if ANDROID diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index 2d99cd52ee3c..9e811170534f 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -1,15 +1,13 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using System.Xml.Schema; using Microsoft.Maui.ApplicationModel; using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Platform; using Microsoft.Maui.Graphics; -using Microsoft.Maui.Layouts; namespace Microsoft.Maui.Controls { @@ -62,6 +60,10 @@ public partial class Window : NavigableElement, IWindow, IToolbarElement, IMenuB public static readonly BindableProperty MinimumHeightProperty = BindableProperty.Create( nameof(MinimumHeight), typeof(double), typeof(Window), Primitives.Dimension.Minimum); + /// Bindable property for . + public static readonly BindableProperty TitleBarProperty = BindableProperty.Create( + nameof(TitleBar), typeof(TitleBar), typeof(Window), null, propertyChanged: TitleBarChanged); + HashSet _overlays = new HashSet(); List _visualChildren; Toolbar? _toolbar; @@ -163,6 +165,12 @@ public double MinimumHeight set => SetValue(MinimumHeightProperty, value); } + public ITitleBar? TitleBar + { + get => (ITitleBar?)GetValue(TitleBarProperty); + set => SetValue(TitleBarProperty, value); + } + double IWindow.X => GetPositionCoordinate(XProperty); double IWindow.Y => GetPositionCoordinate(YProperty); @@ -227,14 +235,14 @@ void IWindow.FrameChanged(Rect frame) } } - private protected override void UpdateHandlerValue(string property) + private protected override void UpdateHandlerValue(string property, bool valueChanged) { - if (_batchFrameUpdate > 0 && (property == nameof(X) || property == nameof(Y) || property == nameof(Width) || property == nameof(Height))) + if (valueChanged && _batchFrameUpdate > 0 && (property == nameof(X) || property == nameof(Y) || property == nameof(Width) || property == nameof(Height))) { return; } - base.UpdateHandlerValue(property); + base.UpdateHandlerValue(property, valueChanged); } public event EventHandler? ModalPopped; @@ -377,6 +385,23 @@ static void FlowDirectionChanged(BindableObject bindable, object oldValue, objec ((IVisualTreeElement)bindable).GetVisualChildren()); } + static void TitleBarChanged(BindableObject bindable, object oldValue, object newValue) + { + var self = (Window)bindable; + if (self != null) + { + if (oldValue is TitleBar prevTitleBar) + { + self.RemoveLogicalChild(prevTitleBar); + } + + if (newValue is TitleBar titleBar) + { + self.AddLogicalChild(titleBar); + } + } + } + bool IFlowDirectionController.ApplyEffectiveFlowDirectionToChildContainer => true; Window IWindowController.Window @@ -385,7 +410,7 @@ Window IWindowController.Window set => throw new InvalidOperationException("A window cannot set a window."); } - IView IWindow.Content => + IView? IWindow.Content => Page ?? throw new InvalidOperationException("No page was set on the window."); Application? Application => Parent as Application; @@ -614,7 +639,18 @@ void OnPageChanged(Page? oldPage, Page? newPage) } if (newPage is Shell newShell) + { newShell.PropertyChanged += ShellPropertyChanged; + } + + if (oldPage?.IsLoaded == true) + { + this.OnUnloaded(() => oldPage.DisconnectHandlers()); + } + else + { + oldPage?.DisconnectHandlers(); + } Handler?.UpdateValue(nameof(IWindow.FlowDirection)); } diff --git a/src/Controls/src/Core/WorkaroundXamlPreCompilePreviewFeatures.rsp b/src/Controls/src/Core/WorkaroundXamlPreCompilePreviewFeatures.rsp new file mode 100644 index 000000000000..e60a129bbc68 --- /dev/null +++ b/src/Controls/src/Core/WorkaroundXamlPreCompilePreviewFeatures.rsp @@ -0,0 +1 @@ +/features:"InterceptorsPreviewNamespaces=Microsoft.Maui.Controls.Generated" \ No newline at end of file diff --git a/src/Controls/src/Core/Xaml/Diagnostics/BindablePropertyDiagnostics.cs b/src/Controls/src/Core/Xaml/Diagnostics/BindablePropertyDiagnostics.cs index 937248592b3d..14dde1b018fd 100644 --- a/src/Controls/src/Core/Xaml/Diagnostics/BindablePropertyDiagnostics.cs +++ b/src/Controls/src/Core/Xaml/Diagnostics/BindablePropertyDiagnostics.cs @@ -31,17 +31,19 @@ public static ValueSource GetValueSource(BindableObject bindable, BindableProper if (specificity == SetterSpecificity.FromHandler) return new ValueSource(BaseValueSource.Unknown, isCurrent:true); - if (specificity.Vsm > 0) + if (specificity.IsVsm) return new ValueSource(BaseValueSource.Local); - if (specificity.Style > 0) + (ushort sStyle, byte sId, byte sClass, byte sType) = specificity.StyleInfo; + + if (sStyle > 0) return new ValueSource(BaseValueSource.Style); - if (specificity.Id > 0 || specificity.Class > 0 || specificity.Type > 0) + if (sId > 0 || sClass > 0 || sType > 0) return new ValueSource(BaseValueSource.Style); - if (specificity.Manual > 0) + if (specificity.IsManual) return new ValueSource(BaseValueSource.Local); - if (specificity.DynamicResource > 0) + if (specificity.IsDynamicResource) return new ValueSource(BaseValueSource.Unknown, isExpression:true); - if (specificity.Binding > 0) + if (specificity.IsBinding) return new ValueSource(BaseValueSource.Unknown, isExpression:true); return new ValueSource(BaseValueSource.Unknown); @@ -79,4 +81,4 @@ internal enum BaseValueSource ParentTemplateTrigger = 10, Local = 11, -} \ No newline at end of file +} diff --git a/src/Controls/src/Core/Xaml/DoesNotInheritDataTypeAttribute.cs b/src/Controls/src/Core/Xaml/DoesNotInheritDataTypeAttribute.cs new file mode 100644 index 000000000000..6c1f785c6f2d --- /dev/null +++ b/src/Controls/src/Core/Xaml/DoesNotInheritDataTypeAttribute.cs @@ -0,0 +1,9 @@ +#nullable disable +using System; + +namespace Microsoft.Maui.Controls.Xaml +{ + internal class DoesNotInheritDataTypeAttribute : Attribute + { + } +} diff --git a/src/Controls/src/Core/Xaml/IResourcesLoader.cs b/src/Controls/src/Core/Xaml/IResourcesLoader.cs deleted file mode 100644 index 84328bd81d14..000000000000 --- a/src/Controls/src/Core/Xaml/IResourcesLoader.cs +++ /dev/null @@ -1,14 +0,0 @@ -#nullable disable -using System; -using System.IO; -using System.Reflection; -using System.Xml; - -namespace Microsoft.Maui.Controls -{ - interface IResourcesLoader - { - T CreateFromResource(string resourcePath, Assembly assembly, IXmlLineInfo lineInfo) where T : new(); - string GetResource(string resourcePath, Assembly assembly, object target, IXmlLineInfo lineInfo); - } -} \ No newline at end of file diff --git a/src/Controls/src/Core/Xaml/TypeConversionExtensions.cs b/src/Controls/src/Core/Xaml/TypeConversionExtensions.cs index 8f0f226dec7f..87dbccc7b898 100644 --- a/src/Controls/src/Core/Xaml/TypeConversionExtensions.cs +++ b/src/Controls/src/Core/Xaml/TypeConversionExtensions.cs @@ -67,40 +67,39 @@ internal static object ConvertTo(this object value, Type toType, Func()?.GetConverterType() is Type converterType) - { - converter = (TypeConverter)Activator.CreateInstance(converterType); - } - - // cache the result, even if it is null - s_converterCache[memberInfo] = converter; - } - - if (converter is not null) + if (TryGetTypeConverter(memberInfo, out converter)) { return converter; } } - if (!s_converterCache.TryGetValue(toType, out converter)) + if (TryGetTypeConverter(toType, out converter)) { - if (toType.GetCustomAttribute()?.GetConverterType() is Type converterType) - { - converter = (TypeConverter)Activator.CreateInstance(converterType); - } - - // cache the result, even if it is null - s_converterCache[toType] = converter; + return converter; } - return converter; + return null; }; return ConvertTo(value, toType, getConverter, serviceProvider, out exception); } + internal static bool TryGetTypeConverter(this MemberInfo memberInfo, [NotNullWhen(true)] out TypeConverter converter) + { + if (!s_converterCache.TryGetValue(memberInfo, out converter)) + { + if (memberInfo.GetCustomAttribute()?.GetConverterType() is Type converterType) + { + converter = (TypeConverter)Activator.CreateInstance(converterType); + } + + // cache the result, even if it is null + s_converterCache[memberInfo] = converter; + } + + return converter is not null; + } + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] static Type GetConverterType(this TypeConverterAttribute attribute) => Type.GetType(attribute.ConverterTypeName); @@ -217,16 +216,11 @@ internal static object ConvertTo(this object value, Type toType, Func mis = null; - try - { - mis = new[] { onType.GetMethod("op_Implicit", bindingAttr, null, new[] { fromType }, null) }; - } - catch (AmbiguousMatchException) - { - mis = new List(); - foreach (var mi in onType.GetMethods(bindingAttr)) - { - if (mi.Name != "op_Implicit") - break; - var parameters = mi.GetParameters(); - if (parameters.Length == 0) - continue; - if (!parameters[0].ParameterType.IsAssignableFrom(fromType)) - continue; - ((List)mis).Add(mi); - } - } - - foreach (var mi in mis) - { - if (mi == null) - continue; - if (!mi.IsSpecialName) - continue; - if (!mi.IsPublic) - continue; - if (!mi.IsStatic) - continue; - if (!toType.IsAssignableFrom(mi.ReturnType)) - continue; - - return mi; - } - return null; - } } } \ No newline at end of file diff --git a/src/Controls/src/NuGet/Controls.NuGet.csproj b/src/Controls/src/NuGet/Controls.NuGet.csproj index 8492370d2ffe..41396d6d4af5 100644 --- a/src/Controls/src/NuGet/Controls.NuGet.csproj +++ b/src/Controls/src/NuGet/Controls.NuGet.csproj @@ -2,12 +2,19 @@ netstandard2.1;netstandard2.0;$(_MauiDotNetTfm);$(MauiPlatforms) + $(TargetFrameworks);$(_MauiPreviousDotNetTfm);$(MauiPreviousPlatforms) true false + + true + true + true + + true diff --git a/src/Controls/src/SourceGen/CodeBehindGenerator.cs b/src/Controls/src/SourceGen/CodeBehindGenerator.cs index d94a2415abd4..880c828a91d9 100644 --- a/src/Controls/src/SourceGen/CodeBehindGenerator.cs +++ b/src/Controls/src/SourceGen/CodeBehindGenerator.cs @@ -358,7 +358,9 @@ static void GenerateXamlCodeBehind(XamlProjectItem? xamlItem, Compilation compil sb.AppendLine("\t\tprivate void InitializeComponent()"); sb.AppendLine("\t\t{"); + sb.AppendLine("#pragma warning disable IL2026, IL3050 // The body of InitializeComponent will be replaced by XamlC so LoadFromXaml will never be called in production builds"); sb.AppendLine($"\t\t\tglobal::Microsoft.Maui.Controls.Xaml.Extensions.LoadFromXaml(this, typeof({rootType}));"); + if (namedFields != null) { foreach ((var fname, var ftype, var faccess) in namedFields) @@ -366,6 +368,7 @@ static void GenerateXamlCodeBehind(XamlProjectItem? xamlItem, Compilation compil sb.AppendLine($"\t\t\t{EscapeIdentifier(fname)} = global::Microsoft.Maui.Controls.NameScopeExtensions.FindByName<{ftype}>(this, \"{fname}\");"); } } + sb.AppendLine("#pragma warning restore IL2026, IL3050"); sb.AppendLine("\t\t}"); sb.AppendLine("\t}"); diff --git a/src/Controls/src/Xaml/ApplyPropertiesVisitor.cs b/src/Controls/src/Xaml/ApplyPropertiesVisitor.cs index a4151c29df8e..0b810b3879bd 100644 --- a/src/Controls/src/Xaml/ApplyPropertiesVisitor.cs +++ b/src/Controls/src/Xaml/ApplyPropertiesVisitor.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Xml; @@ -14,6 +15,10 @@ namespace Microsoft.Maui.Controls.Xaml { + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif class ApplyPropertiesVisitor : IXamlNodeVisitor { public static readonly IList Skips = new List { @@ -49,7 +54,7 @@ public void Visit(ValueNode node, INode parentNode) return; - if (TryGetPropertyName(node, parentNode, out XmlName propertyName)) + if (node.TryGetPropertyName(parentNode, out XmlName propertyName)) { if (TrySetRuntimeName(propertyName, source, value, node)) return; @@ -83,7 +88,7 @@ public void Visit(MarkupNode node, INode parentNode) public void Visit(ElementNode node, INode parentNode) { - if (TryGetPropertyName(node, parentNode, out XmlName propertyName) && propertyName == XmlName._CreateContent) + if (node.TryGetPropertyName(parentNode, out XmlName propertyName) && propertyName == XmlName._CreateContent) { var s0 = Values[parentNode]; if (s0 is ElementTemplate) @@ -107,7 +112,7 @@ public void Visit(ElementNode node, INode parentNode) if (!Values.TryGetValue(node, out var value) && Context.ExceptionHandler != null) return; - if (propertyName != XmlName.Empty || TryGetPropertyName(node, parentNode, out propertyName)) + if (propertyName != XmlName.Empty || node.TryGetPropertyName(parentNode, out propertyName)) { if (Skips.Contains(propertyName)) return; @@ -176,7 +181,7 @@ public void Visit(ElementNode node, INode parentNode) return; } - xpe = xpe ?? new XamlParseException($"Can not set the content of {((IElementNode)parentNode).XmlType.Name} as it doesn't have a ContentPropertyAttribute", node); + xpe = xpe ?? new XamlParseException($"Cannot set the content of {((IElementNode)parentNode).XmlType.Name} as it doesn't have a ContentPropertyAttribute", node); if (Context.ExceptionHandler != null) Context.ExceptionHandler(xpe); else @@ -229,22 +234,6 @@ public void Visit(ListNode node, INode parentNode) { } - public static bool TryGetPropertyName(INode node, INode parentNode, out XmlName name) - { - name = default(XmlName); - var parentElement = parentNode as IElementNode; - if (parentElement == null) - return false; - foreach (var kvp in parentElement.Properties) - { - if (kvp.Value != node) - continue; - name = kvp.Key; - return true; - } - return false; - } - internal static bool IsCollectionItem(INode node, INode parentNode) { var parentList = parentNode as IListNode; @@ -359,6 +348,13 @@ public static void SetPropertyValue(object xamlelement, XmlName propertyName, ob var serviceProvider = new XamlServiceProvider(node, context); var xKey = node is IElementNode eNode && eNode.Properties.ContainsKey(XmlName.xKey) ? ((ValueNode)eNode.Properties[XmlName.xKey]).Value as string : null; + // Special handling for ResourceDictionary.Source + if (xamlelement is ResourceDictionary rd && propertyName.LocalName == "Source" && propertyName.NamespaceURI == "") + { + ResourceDictionaryHelpers.LoadFromSource(rd, (string)value, rootElement.GetType(), lineInfo); + return; + } + if (TrySetPropertyValue(xamlelement, propertyName, xKey, value, rootElement, lineInfo, serviceProvider, out var xpe)) return; diff --git a/src/Controls/src/Xaml/Controls.Xaml.csproj b/src/Controls/src/Xaml/Controls.Xaml.csproj index 823b25feff13..b0b994403492 100644 --- a/src/Controls/src/Xaml/Controls.Xaml.csproj +++ b/src/Controls/src/Xaml/Controls.Xaml.csproj @@ -2,6 +2,7 @@ netstandard2.1;netstandard2.0;$(_MauiDotNetTfm);$(MauiPlatforms) + $(TargetFrameworks);$(_MauiPreviousDotNetTfm);$(MauiPreviousPlatforms) Microsoft.Maui.Controls.Xaml Microsoft.Maui.Controls.Xaml false @@ -22,6 +23,12 @@ .NET Multi-platform App UI (.NET MAUI) is a cross-platform framework for creating native mobile and desktop apps with C# and XAML. This package only contains the XAML tooling. Please install the Microsoft.Maui.Controls package to start using .NET MAUI. + + true + true + true + + @@ -35,7 +42,7 @@ - + $(TargetsForTfmSpecificBuildOutput); _MauiPackDesignAssemblies diff --git a/src/Controls/src/Xaml/CreateValuesVisitor.cs b/src/Controls/src/Xaml/CreateValuesVisitor.cs index 06f4ec560873..77f3cd75222e 100644 --- a/src/Controls/src/Xaml/CreateValuesVisitor.cs +++ b/src/Controls/src/Xaml/CreateValuesVisitor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; @@ -9,6 +10,10 @@ namespace Microsoft.Maui.Controls.Xaml { + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif class CreateValuesVisitor : IXamlNodeVisitor { public CreateValuesVisitor(HydrationContext context) @@ -56,9 +61,13 @@ public void Visit(ElementNode node, INode parentNode) } Context.Types[node] = type; if (IsXaml2009LanguagePrimitive(node)) + { value = CreateLanguagePrimitive(type, node); + } else if (node.Properties.ContainsKey(XmlName.xArguments) || node.Properties.ContainsKey(XmlName.xFactoryMethod)) + { value = CreateFromFactory(type, node); + } else if ( type.GetTypeInfo() .DeclaredConstructors.Any( @@ -66,7 +75,9 @@ public void Visit(ElementNode node, INode parentNode) ci.IsPublic && ci.GetParameters().Length != 0 && ci.GetParameters().All(pi => pi.CustomAttributes.Any(attr => attr.AttributeType == typeof(ParameterAttribute)))) && ValidateCtorArguments(type, node, out string ctorargname)) + { value = CreateFromParameterizedConstructor(type, node); + } else if (!type.GetTypeInfo().DeclaredConstructors.Any(ci => ci.IsPublic && ci.GetParameters().Length == 0) && !ValidateCtorArguments(type, node, out ctorargname)) { @@ -184,7 +195,7 @@ public void Visit(RootNode node, INode parentNode) public void Visit(ListNode node, INode parentNode) { //this is a gross hack to keep ListNode alive. ListNode must go in favor of Properties - if (ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out XmlName name)) + if (node.TryGetPropertyName(parentNode, out XmlName name)) node.XmlName = name; } @@ -253,12 +264,13 @@ bool isMatch(MethodInfo m) { if ((p[i].ParameterType.IsAssignableFrom(types[i]))) continue; - var op_impl = p[i].ParameterType.GetImplicitConversionOperator(fromType: types[i], toType: p[i].ParameterType) - ?? types[i].GetImplicitConversionOperator(fromType: types[i], toType: p[i].ParameterType); - if (op_impl == null) + if (!TypeConversionHelper.TryConvert(arguments[i], p[i].ParameterType, out var convertedValue)) + { return false; - arguments[i] = op_impl.Invoke(null, new[] { arguments[i] }); + } + + arguments[i] = convertedValue; } return true; } diff --git a/src/Controls/src/Xaml/Embedding/EmbeddingExtensions.cs b/src/Controls/src/Xaml/Embedding/EmbeddingExtensions.cs index 0e300cb7a96e..b5fe95846f2b 100644 --- a/src/Controls/src/Xaml/Embedding/EmbeddingExtensions.cs +++ b/src/Controls/src/Xaml/Embedding/EmbeddingExtensions.cs @@ -8,7 +8,7 @@ namespace Microsoft.Maui.Controls.Embedding; /// /// A set of extension methods that allow for embedding a MAUI view within a native application. /// -internal static class EmbeddingExtensions +public static class EmbeddingExtensions { /// /// Configures the to use the specified as the embedded application type. diff --git a/src/Controls/src/Xaml/ExpandMarkupsVisitor.cs b/src/Controls/src/Xaml/ExpandMarkupsVisitor.cs index 6e462f088891..b94858d40e96 100644 --- a/src/Controls/src/Xaml/ExpandMarkupsVisitor.cs +++ b/src/Controls/src/Xaml/ExpandMarkupsVisitor.cs @@ -1,10 +1,15 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Xml; using Microsoft.Maui.Controls.Xaml.Internals; namespace Microsoft.Maui.Controls.Xaml { + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif class ExpandMarkupsVisitor : IXamlNodeVisitor { public ExpandMarkupsVisitor(HydrationContext context) => Context = context; @@ -40,7 +45,7 @@ public void Visit(MarkupNode markupnode, INode parentNode) { var parentElement = parentNode as IElementNode; XmlName propertyName; - if (!ApplyPropertiesVisitor.TryGetPropertyName(markupnode, parentNode, out propertyName)) + if (!markupnode.TryGetPropertyName(parentNode, out propertyName)) return; if (Skips.Contains(propertyName)) return; @@ -106,6 +111,7 @@ INode ParseExpression(ref string expression, IXmlNamespaceResolver nsResolver, I return new MarkupExpansionParser { ExceptionHandler = Context.ExceptionHandler }.Parse(match, ref expression, serviceProvider); } + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] public class MarkupExpansionParser : MarkupExpressionParser, IExpressionParser { IElementNode _node; diff --git a/src/Controls/src/Xaml/FillResourceDictionariesVisitor.cs b/src/Controls/src/Xaml/FillResourceDictionariesVisitor.cs index ff2bf36d305c..68229b2cb48c 100644 --- a/src/Controls/src/Xaml/FillResourceDictionariesVisitor.cs +++ b/src/Controls/src/Xaml/FillResourceDictionariesVisitor.cs @@ -1,11 +1,16 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Xaml.Internals; namespace Microsoft.Maui.Controls.Xaml { + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif class FillResourceDictionariesVisitor : IXamlNodeVisitor { public FillResourceDictionariesVisitor(HydrationContext context) => Context = context; @@ -38,7 +43,7 @@ public void Visit(ElementNode node, INode parentNode) return; //Set RD to VE - if (typeof(ResourceDictionary).IsAssignableFrom(Context.Types[node]) && ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out XmlName propertyName)) + if (typeof(ResourceDictionary).IsAssignableFrom(Context.Types[node]) && node.TryGetPropertyName(parentNode, out XmlName propertyName)) { if ((propertyName.LocalName == "Resources" || propertyName.LocalName.EndsWith(".Resources", StringComparison.Ordinal)) && value is ResourceDictionary) diff --git a/src/Controls/src/Xaml/Hosting/AppHostBuilderExtensions.cs b/src/Controls/src/Xaml/Hosting/AppHostBuilderExtensions.cs index f06b547acd3d..37d545a56d7c 100644 --- a/src/Controls/src/Xaml/Hosting/AppHostBuilderExtensions.cs +++ b/src/Controls/src/Xaml/Hosting/AppHostBuilderExtensions.cs @@ -41,7 +41,6 @@ public static IMauiHandlersCollection AddMauiControlsHandlers(this IMauiHandlers static MauiAppBuilder SetupXamlDefaults(this MauiAppBuilder builder) { #if WINDOWS || ANDROID || IOS || MACCATALYST || TIZEN - DependencyService.Register(); DependencyService.Register(); #endif return builder; diff --git a/src/Controls/src/Xaml/MarkupExpressionParser.cs b/src/Controls/src/Xaml/MarkupExpressionParser.cs index cc5100f42146..6042dea75697 100644 --- a/src/Controls/src/Xaml/MarkupExpressionParser.cs +++ b/src/Controls/src/Xaml/MarkupExpressionParser.cs @@ -32,6 +32,7 @@ // using System; +using System.Diagnostics.CodeAnalysis; using System.Text; namespace Microsoft.Maui.Controls.Xaml @@ -46,6 +47,7 @@ protected struct Property public object value; } + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] public object ParseExpression(ref string expression, IServiceProvider serviceProvider) { if (serviceProvider == null) @@ -120,6 +122,7 @@ internal static bool MatchMarkup(out string match, string expression, out int en return true; } + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] protected Property ParseProperty(IServiceProvider serviceProvider, ref string remaining) { object value = null; @@ -148,6 +151,7 @@ protected Property ParseProperty(IServiceProvider serviceProvider, ref string re return new Property { last = next == '}', name = name, strValue = str_value, value = value }; } + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] Property ParsePropertyExpression(string prop, IServiceProvider serviceProvider, ref string remaining) { bool last; diff --git a/src/Controls/src/Xaml/MarkupExtensionParser.cs b/src/Controls/src/Xaml/MarkupExtensionParser.cs index 3d51baf75c63..e3b53e4f2e24 100644 --- a/src/Controls/src/Xaml/MarkupExtensionParser.cs +++ b/src/Controls/src/Xaml/MarkupExtensionParser.cs @@ -1,9 +1,14 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace Microsoft.Maui.Controls.Xaml { + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif internal sealed class MarkupExtensionParser : MarkupExpressionParser, IExpressionParser { IMarkupExtension markupExtension; diff --git a/src/Controls/src/Xaml/MarkupExtensions/AppThemeBindingExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/AppThemeBindingExtension.cs index 3a37e23a734f..41f78cab7cc4 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/AppThemeBindingExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/AppThemeBindingExtension.cs @@ -6,6 +6,11 @@ namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Default))] + [RequireService( + [typeof(IProvideValueTarget), + typeof(IValueConverterProvider), + typeof(IXmlLineInfoProvider), + typeof(IConverterOptions)])] public class AppThemeBindingExtension : IMarkupExtension { object _default; diff --git a/src/Controls/src/Xaml/MarkupExtensions/ArrayExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/ArrayExtension.cs index fe3a071736a0..00cfb14d3186 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/ArrayExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/ArrayExtension.cs @@ -1,11 +1,15 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Items))] [AcceptEmptyServiceProvider] +#if !NETSTANDARD + [RequiresDynamicCode("ArrayExtension is not AOT safe.")] +#endif public class ArrayExtension : IMarkupExtension { public ArrayExtension() diff --git a/src/Controls/src/Xaml/MarkupExtensions/BindingExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/BindingExtension.cs index 74eee25ba432..8800de4bf1ac 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/BindingExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/BindingExtension.cs @@ -1,11 +1,12 @@ using System; using System.ComponentModel; -using System.Linq.Expressions; +using System.Diagnostics.CodeAnalysis; using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Path))] + [RequireService([typeof(IXamlTypeResolver), typeof(IXamlDataTypeProvider)])] public sealed class BindingExtension : IMarkupExtension { public string Path { get; set; } = Binding.SelfPath; @@ -21,9 +22,29 @@ public sealed class BindingExtension : IMarkupExtension BindingBase IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) { - if (TypedBinding is null) { + if (TypedBinding is null) + { + return CreateBinding(); + } + + TypedBinding.Mode = Mode; + TypedBinding.Converter = Converter; + TypedBinding.ConverterParameter = ConverterParameter; + TypedBinding.StringFormat = StringFormat; + TypedBinding.Source = Source; + TypedBinding.UpdateSourceEventName = UpdateSourceEventName; + TypedBinding.FallbackValue = FallbackValue; + TypedBinding.TargetNullValue = TargetNullValue; + return TypedBinding; + + [UnconditionalSuppressMessage("TrimAnalysis", "IL2026", + Justification = "If this method is invoked, we have already produced warnings in XamlC " + + "when the compilation of this binding failed or was skipped.")] + BindingBase CreateBinding() + { Type bindingXDataType = null; - if ((serviceProvider.GetService(typeof(IXamlTypeResolver)) is IXamlTypeResolver typeResolver) + if (serviceProvider is not null && + (serviceProvider.GetService(typeof(IXamlTypeResolver)) is IXamlTypeResolver typeResolver) && (serviceProvider.GetService(typeof(IXamlDataTypeProvider)) is IXamlDataTypeProvider dataTypeProvider) && dataTypeProvider.BindingDataType != null) { @@ -35,18 +56,8 @@ BindingBase IMarkupExtension.ProvideValue(IServiceProvider serviceP FallbackValue = FallbackValue, TargetNullValue = TargetNullValue, DataType = bindingXDataType, - }; + }; } - - TypedBinding.Mode = Mode; - TypedBinding.Converter = Converter; - TypedBinding.ConverterParameter = ConverterParameter; - TypedBinding.StringFormat = StringFormat; - TypedBinding.Source = Source; - TypedBinding.UpdateSourceEventName = UpdateSourceEventName; - TypedBinding.FallbackValue = FallbackValue; - TypedBinding.TargetNullValue = TargetNullValue; - return TypedBinding; } object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) diff --git a/src/Controls/src/Xaml/MarkupExtensions/DataTemplateExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/DataTemplateExtension.cs index b3c63c4f21b5..ec78d9d1a80b 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/DataTemplateExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/DataTemplateExtension.cs @@ -1,9 +1,11 @@ using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(TypeName))] [ProvideCompiled("Microsoft.Maui.Controls.Build.Tasks.DataTemplateExtension")] + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] public sealed class DataTemplateExtension : IMarkupExtension { public string TypeName { get; set; } diff --git a/src/Controls/src/Xaml/MarkupExtensions/DynamicResourceExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/DynamicResourceExtension.cs index bd703c1c0813..aa73f39ab195 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/DynamicResourceExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/DynamicResourceExtension.cs @@ -4,6 +4,7 @@ namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Key))] + [RequireService([typeof(IXmlLineInfoProvider)])] public sealed class DynamicResourceExtension : IMarkupExtension { public string Key { get; set; } diff --git a/src/Controls/src/Xaml/MarkupExtensions/OnIdiomExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/OnIdiomExtension.cs index a70921a84e7d..c92eef52a5c7 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/OnIdiomExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/OnIdiomExtension.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; using System.Xml; @@ -8,6 +9,12 @@ namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Default))] + [RequireService( + [typeof(IProvideValueTarget), + typeof(IValueConverterProvider), + typeof(IXmlLineInfoProvider), + typeof(IConverterOptions)])] + [RequiresUnreferencedCode("The OnIdiomExtension is not trim safe. Use OnIdiom instead.")] public class OnIdiomExtension : IMarkupExtension { // See Device.Idiom diff --git a/src/Controls/src/Xaml/MarkupExtensions/OnPlatformExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/OnPlatformExtension.cs index 60fc8879245b..80cb64c8bbb4 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/OnPlatformExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/OnPlatformExtension.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; using Microsoft.Extensions.DependencyInjection; @@ -7,6 +8,12 @@ namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Default))] + [RequireService( + [typeof(IProvideValueTarget), + typeof(IValueConverterProvider), + typeof(IXmlLineInfoProvider), + typeof(IConverterOptions)])] + [RequiresUnreferencedCode("The OnPlatformExtension is not trim safe. Use OnPlatform instead.")] public class OnPlatformExtension : IMarkupExtension { static object s_notset = new object(); diff --git a/src/Controls/src/Xaml/MarkupExtensions/ReferenceExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/ReferenceExtension.cs index 4832a38f2213..ff6924ada165 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/ReferenceExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/ReferenceExtension.cs @@ -6,6 +6,7 @@ namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Name))] + [RequireService([typeof(IReferenceProvider), typeof(IProvideValueTarget)])] public class ReferenceExtension : IMarkupExtension { public string Name { get; set; } @@ -33,7 +34,7 @@ public object ProvideValue(IServiceProvider serviceProvider) return value; } - throw new XamlParseException($"Can not find the object referenced by `{Name}`", serviceProvider); + throw new XamlParseException($"Cannot find the object referenced by `{Name}`", serviceProvider); } } } diff --git a/src/Controls/src/Xaml/MarkupExtensions/StaticExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/StaticExtension.cs index ea1c7b8f6aa2..6f878f2e04bf 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/StaticExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/StaticExtension.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Xml; @@ -7,6 +8,7 @@ namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Member))] [ProvideCompiled("Microsoft.Maui.Controls.Build.Tasks.StaticExtension")] + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] public class StaticExtension : IMarkupExtension { public string Member { get; set; } diff --git a/src/Controls/src/Xaml/MarkupExtensions/StaticResourceExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/StaticResourceExtension.cs index a63031d995c6..99cd45f53938 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/StaticResourceExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/StaticResourceExtension.cs @@ -6,6 +6,7 @@ namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Key))] + [RequireService([typeof(IXmlLineInfoProvider), typeof(IProvideParentValues)])] [ProvideCompiled("Microsoft.Maui.Controls.Build.Tasks.StaticResourceExtension")] public sealed class StaticResourceExtension : IMarkupExtension { @@ -43,22 +44,11 @@ internal static object CastTo(object value, object targetProperty) if (propertyType is null || propertyType.IsAssignableFrom(valueType)) return value; - MethodInfo implicit_op; - - //OnPlatform might need double cast - if (valueType.IsGenericType && valueType.Name == "OnPlatform`1") + if (TypeConversionHelper.TryConvert(value, propertyType, out var convertedValue)) { - var onPlatType = valueType.GetGenericArguments()[0]; - implicit_op = valueType.GetImplicitConversionOperator(fromType: valueType, toType: onPlatType); - value = implicit_op.Invoke(value, new[] { value }); - valueType = value.GetType(); + return convertedValue; } - implicit_op = valueType.GetImplicitConversionOperator(fromType: valueType, toType: propertyType) - ?? propertyType.GetImplicitConversionOperator(fromType: valueType, toType: propertyType); - if (implicit_op != null) - return implicit_op.Invoke(value, new[] { value }); - return value; } diff --git a/src/Controls/src/Xaml/MarkupExtensions/StyleSheetExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/StyleSheetExtension.cs index 0c33b80ba3e0..8497accc921c 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/StyleSheetExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/StyleSheetExtension.cs @@ -8,6 +8,7 @@ namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Style))] [ProvideCompiled("Microsoft.Maui.Controls.XamlC.StyleSheetProvider")] + [RequireService([typeof(IXmlLineInfoProvider), typeof(IRootObjectProvider)])] public sealed class StyleSheetExtension : IValueProvider { public string Style { get; set; } @@ -20,7 +21,7 @@ object IValueProvider.ProvideValue(IServiceProvider serviceProvider) IXmlLineInfo lineInfo; if (!string.IsNullOrEmpty(Style) && Source != null) - throw new XamlParseException($"StyleSheet can not have both a Source and a content", serviceProvider); + throw new XamlParseException($"StyleSheet cannot have both a Source and a content", serviceProvider); if (Source != null) { diff --git a/src/Controls/src/Xaml/MarkupExtensions/TemplateBindingExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/TemplateBindingExtension.cs index 42a3582d4a74..22985b7c45cb 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/TemplateBindingExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/TemplateBindingExtension.cs @@ -1,9 +1,13 @@ using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(Path))] [AcceptEmptyServiceProvider] + [RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)] public sealed class TemplateBindingExtension : IMarkupExtension { public TemplateBindingExtension() @@ -22,17 +26,33 @@ public TemplateBindingExtension() public string StringFormat { get; set; } + [EditorBrowsable(EditorBrowsableState.Never)] public TypedBindingBase TypedBinding { get; set; } + BindingBase IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) { - return new Binding + if (TypedBinding is null) { - Source = RelativeBindingSource.TemplatedParent, - Path = Path, - Mode = Mode, - Converter = Converter, - ConverterParameter = ConverterParameter, - StringFormat = StringFormat - }; +#pragma warning disable IL2026 // Using member 'Microsoft.Maui.Controls.Binding.Binding(String, BindingMode, IValueConverter, Object, String, Object)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Using bindings with string paths is not trim safe. Use expression-based binding instead. + // This code is only reachable in XamlC compiled code when there is a missing x:DataType and the binding could not be compiled. + // In that case, we produce a warning that the binding could not be compiled. + return new Binding + { + Source = RelativeBindingSource.TemplatedParent, + Path = Path, + Mode = Mode, + Converter = Converter, + ConverterParameter = ConverterParameter, + StringFormat = StringFormat + }; +#pragma warning restore IL2026 + } + + TypedBinding.Mode = Mode; + TypedBinding.Converter = Converter; + TypedBinding.ConverterParameter = ConverterParameter; + TypedBinding.StringFormat = StringFormat; + TypedBinding.Source = RelativeBindingSource.TemplatedParent; + return TypedBinding; } object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) diff --git a/src/Controls/src/Xaml/MarkupExtensions/TypeExtension.cs b/src/Controls/src/Xaml/MarkupExtensions/TypeExtension.cs index 1bdde80cb3a2..16286a82a402 100644 --- a/src/Controls/src/Xaml/MarkupExtensions/TypeExtension.cs +++ b/src/Controls/src/Xaml/MarkupExtensions/TypeExtension.cs @@ -4,6 +4,7 @@ namespace Microsoft.Maui.Controls.Xaml { [ContentProperty(nameof(TypeName))] [ProvideCompiled("Microsoft.Maui.Controls.Build.Tasks.TypeExtension")] + [RequireService([typeof(IXamlTypeResolver), typeof(IXmlLineInfoProvider)])] public class TypeExtension : IMarkupExtension { public string TypeName { get; set; } diff --git a/src/Controls/src/Xaml/NodeExtensions.cs b/src/Controls/src/Xaml/NodeExtensions.cs new file mode 100644 index 000000000000..2fac8afcc859 --- /dev/null +++ b/src/Controls/src/Xaml/NodeExtensions.cs @@ -0,0 +1,27 @@ +namespace Microsoft.Maui.Controls.Xaml; + +internal static class NodeExtensions +{ + public static bool TryGetPropertyName(this INode node, INode parentNode, out XmlName name) + { + name = default; + + if (parentNode is not IElementNode parentElement) + { + return false; + } + + foreach (var kvp in parentElement.Properties) + { + if (kvp.Value != node) + { + continue; + } + + name = kvp.Key; + return true; + } + + return false; + } +} diff --git a/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt index 7dc5c58110bf..6b0a2988bd60 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt @@ -1 +1,10 @@ #nullable enable +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.get -> Microsoft.Maui.Controls.Internals.TypedBindingBase +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.set -> void +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder, System.Func implementationFactory) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers.LoadFromSource(Microsoft.Maui.Controls.ResourceDictionary rd, System.Uri source, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider.ValueTargetProvider(object! targetObject, object! targetProperty) -> void +Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers diff --git a/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt index 7dc5c58110bf..6b0a2988bd60 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt @@ -1 +1,10 @@ #nullable enable +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.get -> Microsoft.Maui.Controls.Internals.TypedBindingBase +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.set -> void +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder, System.Func implementationFactory) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers.LoadFromSource(Microsoft.Maui.Controls.ResourceDictionary rd, System.Uri source, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider.ValueTargetProvider(object! targetObject, object! targetProperty) -> void +Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers diff --git a/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt index 7dc5c58110bf..6b0a2988bd60 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt @@ -1 +1,10 @@ #nullable enable +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.get -> Microsoft.Maui.Controls.Internals.TypedBindingBase +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.set -> void +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder, System.Func implementationFactory) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers.LoadFromSource(Microsoft.Maui.Controls.ResourceDictionary rd, System.Uri source, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider.ValueTargetProvider(object! targetObject, object! targetProperty) -> void +Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers diff --git a/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt index 7dc5c58110bf..6b0a2988bd60 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt @@ -1 +1,10 @@ #nullable enable +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.get -> Microsoft.Maui.Controls.Internals.TypedBindingBase +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.set -> void +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder, System.Func implementationFactory) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers.LoadFromSource(Microsoft.Maui.Controls.ResourceDictionary rd, System.Uri source, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider.ValueTargetProvider(object! targetObject, object! targetProperty) -> void +Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers diff --git a/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt index 7dc5c58110bf..6b0a2988bd60 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -1 +1,10 @@ #nullable enable +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.get -> Microsoft.Maui.Controls.Internals.TypedBindingBase +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.set -> void +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder, System.Func implementationFactory) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers.LoadFromSource(Microsoft.Maui.Controls.ResourceDictionary rd, System.Uri source, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider.ValueTargetProvider(object! targetObject, object! targetProperty) -> void +Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers diff --git a/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt index 7dc5c58110bf..6b0a2988bd60 100644 --- a/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt @@ -1 +1,10 @@ #nullable enable +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.get -> Microsoft.Maui.Controls.Internals.TypedBindingBase +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.set -> void +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder, System.Func implementationFactory) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers.LoadFromSource(Microsoft.Maui.Controls.ResourceDictionary rd, System.Uri source, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider.ValueTargetProvider(object! targetObject, object! targetProperty) -> void +Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers diff --git a/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt index 7dc5c58110bf..6b0a2988bd60 100644 --- a/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt @@ -1 +1,10 @@ #nullable enable +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.get -> Microsoft.Maui.Controls.Internals.TypedBindingBase +~Microsoft.Maui.Controls.Xaml.TemplateBindingExtension.TypedBinding.set -> void +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder, System.Func implementationFactory) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Embedding.EmbeddingExtensions.UseMauiEmbeddedApp(this Microsoft.Maui.Hosting.MauiAppBuilder builder) -> Microsoft.Maui.Hosting.MauiAppBuilder +~static Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers.LoadFromSource(Microsoft.Maui.Controls.ResourceDictionary rd, System.Uri source, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void +Microsoft.Maui.Controls.Embedding.EmbeddingExtensions +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider +Microsoft.Maui.Controls.Xaml.Internals.ValueTargetProvider.ValueTargetProvider(object! targetObject, object! targetProperty) -> void +Microsoft.Maui.Controls.Xaml.ResourceDictionaryHelpers diff --git a/src/Controls/src/Xaml/ResourceDictionaryHelpers.cs b/src/Controls/src/Xaml/ResourceDictionaryHelpers.cs new file mode 100644 index 000000000000..7cbaf6a2c254 --- /dev/null +++ b/src/Controls/src/Xaml/ResourceDictionaryHelpers.cs @@ -0,0 +1,102 @@ +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Xml; + +namespace Microsoft.Maui.Controls.Xaml +{ + [EditorBrowsable(EditorBrowsableState.Never)] + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif + public static class ResourceDictionaryHelpers + { + // Called from XamlC generated code when the ResourceDictionary is not compiled + [EditorBrowsable(EditorBrowsableState.Never)] + public static void LoadFromSource(ResourceDictionary rd, Uri source, string resourcePath, Assembly assembly, IXmlLineInfo lineInfo) + { + var sourceInstance = CreateFromResource(resourcePath, assembly, lineInfo); + rd.SetSource(source, sourceInstance); + } + + // Called from XamlParser + internal static void LoadFromSource(ResourceDictionary rd, string value, Type rootType, IXmlLineInfo lineInfo) + { + (value, var assembly) = ResourceDictionary.RDSourceTypeConverter.SplitUriAndAssembly(value, rootType.Assembly); + + var rootTargetPath = XamlResourceIdAttribute.GetPathForType(rootType); + var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(new Uri(value, UriKind.Relative), rootTargetPath); + var sourceUri = ResourceDictionary.RDSourceTypeConverter.CombineUriAndAssembly(value, assembly); + + SetAndLoadSource(rd, sourceUri, resourcePath, assembly, lineInfo); + } + + // Called from Hot Reload + internal static void SetAndLoadSource(ResourceDictionary rd, Uri value, string resourcePath, Assembly assembly, IXmlLineInfo lineInfo) + { + var type = XamlResourceIdAttribute.GetTypeForPath(assembly, resourcePath); + var sourceInstance = type is not null + ? ResourceDictionary.GetOrCreateInstance(type) + : CreateFromResource(resourcePath, assembly, lineInfo); + + rd.SetSource(value, sourceInstance); + } + + static ResourceDictionary CreateFromResource(string resourcePath, Assembly assembly, IXmlLineInfo lineInfo) + { + var rd = new ResourceDictionary(); + + var resourceLoadingResponse = Maui.Controls.Internals.ResourceLoader.ResourceProvider2?.Invoke(new Maui.Controls.Internals.ResourceLoader.ResourceLoadingQuery + { + AssemblyName = assembly.GetName(), + ResourcePath = resourcePath, + Instance = rd, + }); + + var alternateResource = resourceLoadingResponse?.ResourceContent; + if (alternateResource != null) + { + XamlLoader.Load(rd, alternateResource, resourceLoadingResponse.UseDesignProperties); + return rd; + } + + var resourceId = XamlResourceIdAttribute.GetResourceIdForPath(assembly, resourcePath); + if (resourceId == null) + throw new XamlParseException($"Resource '{resourcePath}' not found.", lineInfo); + + using (var stream = assembly.GetManifestResourceStream(resourceId)) + { + if (stream == null) + throw new XamlParseException($"No resource found for '{resourceId}'.", lineInfo); + using (var reader = new StreamReader(stream)) + { + rd.LoadFromXaml(reader.ReadToEnd(), assembly); + return rd; + } + } + } + } + +#if !NETSTANDARD + internal static class ResourceDictionaryHotReloadHelper + { +#pragma warning disable CA2255 // The 'ModuleInitializer' attribute should not be used in libraries + [ModuleInitializer] +#pragma warning restore CA2255 + internal static void Init() + { + // This code will be trimmed in production builds + if (HotReload.MauiHotReloadHelper.IsSupported) + { +#pragma warning disable IL2026, IL3050 + ResourceDictionary.s_setAndLoadSource = ResourceDictionaryHelpers.SetAndLoadSource; +#pragma warning restore IL2026, IL3050 + } + } + } +#endif +} diff --git a/src/Controls/src/Xaml/ResourcesLoader.cs b/src/Controls/src/Xaml/ResourcesLoader.cs deleted file mode 100644 index 34b0c8d9efae..000000000000 --- a/src/Controls/src/Xaml/ResourcesLoader.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.IO; -using System.Reflection; -using System.Xml; -using Microsoft.Maui.Controls; - -[assembly: Dependency(typeof(Microsoft.Maui.Controls.Xaml.ResourcesLoader))] -namespace Microsoft.Maui.Controls.Xaml -{ - class ResourcesLoader : IResourcesLoader - { - public T CreateFromResource(string resourcePath, Assembly assembly, IXmlLineInfo lineInfo) where T : new() - { - var rd = new T(); - - var resourceLoadingResponse = Maui.Controls.Internals.ResourceLoader.ResourceProvider2?.Invoke(new Maui.Controls.Internals.ResourceLoader.ResourceLoadingQuery - { - AssemblyName = assembly.GetName(), - ResourcePath = resourcePath, - Instance = rd, - }); - - var alternateResource = resourceLoadingResponse?.ResourceContent; - if (alternateResource != null) - { - XamlLoader.Load(rd, alternateResource, resourceLoadingResponse.UseDesignProperties); - return rd; - } - - var resourceId = XamlResourceIdAttribute.GetResourceIdForPath(assembly, resourcePath); - if (resourceId == null) - throw new XamlParseException($"Resource '{resourcePath}' not found.", lineInfo); - - using (var stream = assembly.GetManifestResourceStream(resourceId)) - { - if (stream == null) - throw new XamlParseException($"No resource found for '{resourceId}'.", lineInfo); - using (var reader = new StreamReader(stream)) - { - rd.LoadFromXaml(reader.ReadToEnd(), assembly); - return rd; - } - } - } - - public string GetResource(string resourcePath, Assembly assembly, object target, IXmlLineInfo lineInfo) - { - var resourceLoadingResponse = Maui.Controls.Internals.ResourceLoader.ResourceProvider2?.Invoke(new Maui.Controls.Internals.ResourceLoader.ResourceLoadingQuery - { - AssemblyName = assembly.GetName(), - ResourcePath = resourcePath, - Instance = target - }); - - var alternateResource = resourceLoadingResponse?.ResourceContent; - if (alternateResource != null) - return alternateResource; - - var resourceId = XamlResourceIdAttribute.GetResourceIdForPath(assembly, resourcePath); - if (resourceId == null) - throw new XamlParseException($"Resource '{resourcePath}' not found.", lineInfo); - - using (var stream = assembly.GetManifestResourceStream(resourceId)) - { - if (stream == null) - throw new XamlParseException($"No resource found for '{resourceId}'.", lineInfo); - using (var reader = new StreamReader(stream)) - return reader.ReadToEnd(); - } - } - } -} \ No newline at end of file diff --git a/src/Controls/src/Xaml/SimplifyOnPlatformVisitor.cs b/src/Controls/src/Xaml/SimplifyOnPlatformVisitor.cs index 3ba35e8739b0..8a9a46c6a0f4 100644 --- a/src/Controls/src/Xaml/SimplifyOnPlatformVisitor.cs +++ b/src/Controls/src/Xaml/SimplifyOnPlatformVisitor.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; #nullable disable @@ -52,21 +52,21 @@ public void Visit(ElementNode node, INode parentNode) if (node.Properties.TryGetValue(new XmlName("", Target), out INode targetNode) || node.Properties.TryGetValue(new XmlName("", nameof(OnPlatformExtension.Default)), out targetNode)) { - if (!ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out XmlName name)) + if (!node.TryGetPropertyName(parentNode, out XmlName name)) return; if (parentNode is IElementNode parentEnode) parentEnode.Properties[name] = targetNode; } else if (node.CollectionItems.Count > 0) // syntax like {OnPlatform foo, iOS=bar} { - if (!ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out XmlName name)) + if (!node.TryGetPropertyName(parentNode, out XmlName name)) return; if (parentNode is IElementNode parentEnode) parentEnode.Properties[name] = node.CollectionItems[0]; } else //no prop for target and no Default set { - if (!ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out XmlName name)) + if (!node.TryGetPropertyName(parentNode, out XmlName name)) return; //if there's no value for the targetPlatform, ignore the node. //this is slightly different than what OnPlatform does (return default(T)) @@ -81,7 +81,7 @@ public void Visit(ElementNode node, INode parentNode) // var onNode = GetOnNode(node, Target) ?? GetDefault(node); // //Property node - // if (ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out XmlName name) + // if (node.TryGetPropertyName(parentNode, out XmlName name) // && parentNode is IElementNode parentEnode) // { // if (onNode != null) diff --git a/src/Controls/src/Xaml/SimplifyTypeExtensionVisitor.cs b/src/Controls/src/Xaml/SimplifyTypeExtensionVisitor.cs index 491b13c35074..22c1117bd8a9 100644 --- a/src/Controls/src/Xaml/SimplifyTypeExtensionVisitor.cs +++ b/src/Controls/src/Xaml/SimplifyTypeExtensionVisitor.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; #nullable disable @@ -36,7 +36,7 @@ public void Visit(ElementNode node, INode parentNode) } static bool IsValueOfXDataTypeOrTargetType(ElementNode node, INode parentNode, out XmlName propertyName) - => ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName) + => node.TryGetPropertyName(parentNode, out propertyName) && (IsXDataType(propertyName) || IsTargetTypePropertyOfMauiType(parentNode, propertyName)); static bool IsTargetTypePropertyOfMauiType(INode parentNode, XmlName propertyName) diff --git a/src/Controls/src/Xaml/ViewExtensions.cs b/src/Controls/src/Xaml/ViewExtensions.cs index d8d586c79b53..047c0058d595 100644 --- a/src/Controls/src/Xaml/ViewExtensions.cs +++ b/src/Controls/src/Xaml/ViewExtensions.cs @@ -26,10 +26,15 @@ // THE SOFTWARE. using System; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace Microsoft.Maui.Controls.Xaml { + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif public static class Extensions { public static TXaml LoadFromXaml(this TXaml view, Type callingType) diff --git a/src/Controls/src/Xaml/XamlLoader.cs b/src/Controls/src/Xaml/XamlLoader.cs index fea216d44218..b2e6103a5ba6 100644 --- a/src/Controls/src/Xaml/XamlLoader.cs +++ b/src/Controls/src/Xaml/XamlLoader.cs @@ -29,16 +29,20 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; -using System.Text.RegularExpressions; using System.Xml; using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Xaml.Diagnostics; namespace Microsoft.Maui.Controls.Xaml { + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif static partial class XamlLoader { public static void Load(object view, Type callingType) @@ -355,12 +359,85 @@ static string ReadResourceAsXaml(Type type, Assembly assembly, string likelyTarg var xaml = reader.ReadToEnd(); - var pattern = $"x:Class *= *\"{type.FullName}\""; - var regex = new Regex(pattern, RegexOptions.ECMAScript); - if (regex.IsMatch(xaml) || xaml.IndexOf($"x:Class=\"{type.FullName}\"") != -1) + if (ContainsXClass(xaml, type.FullName)) + { return xaml; + } } return null; + + // Equivalent to regex $"x:Class *= *\"{fullName}\"" + static bool ContainsXClass(string xaml, string fullName) + { + int index = 0; + while (index >= 0 && index < xaml.Length) + { + if (FindNextXClass() + && SkipWhitespaces() + && NextCharacter('=') + && SkipWhitespaces() + && NextCharacter('"') + && NextFullName() + && NextCharacter('"')) + { + return true; + } + } + + return false; + + bool FindNextXClass() + { + const string xClass = "x:Class"; + + index = xaml.IndexOf(xClass, startIndex: index); + if (index < 0) + { + return false; + } + + index += xClass.Length; + return true; + } + + bool SkipWhitespaces() + { + while (index < xaml.Length && xaml[index] == ' ') + { + index++; + } + + return true; + } + + bool NextCharacter(char character) + { + if (index < xaml.Length && xaml[index] != character) + { + return false; + } + + index++; + return true; + } + + bool NextFullName() + { + if (index >= xaml.Length - fullName.Length) + { + return false; + } + + var slice = xaml.AsSpan().Slice(index, fullName.Length); + if (!MemoryExtensions.Equals(slice, fullName.AsSpan(), StringComparison.Ordinal)) + { + return false; + } + + index += fullName.Length; + return true; + } + } } } } \ No newline at end of file diff --git a/src/Controls/src/Xaml/XamlParser.cs b/src/Controls/src/Xaml/XamlParser.cs index 6825cfcc99cb..fb00409662f6 100644 --- a/src/Controls/src/Xaml/XamlParser.cs +++ b/src/Controls/src/Xaml/XamlParser.cs @@ -28,6 +28,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; @@ -356,6 +357,10 @@ static void GatherXmlnsDefinitionAttributes() } } + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif public static Type GetElementType(XmlType xmlType, IXmlLineInfo xmlInfo, Assembly currentAssembly, out XamlParseException exception) { diff --git a/src/Controls/src/Xaml/XamlServiceProvider.cs b/src/Controls/src/Xaml/XamlServiceProvider.cs index dec1a464528d..5b2e3bbbd9e2 100644 --- a/src/Controls/src/Xaml/XamlServiceProvider.cs +++ b/src/Controls/src/Xaml/XamlServiceProvider.cs @@ -13,6 +13,12 @@ public class XamlServiceProvider : IServiceProvider { readonly Dictionary services = new Dictionary(); + static IValueConverterProvider defaultValueConverterProvider = new ValueConverterProvider(); + + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif internal XamlServiceProvider(INode node, HydrationContext context) { if (context != null && node != null && node.Parent != null && context.Values.TryGetValue(node.Parent, out object targetObject)) @@ -28,13 +34,13 @@ internal XamlServiceProvider(INode node, HydrationContext context) if (node is IXmlLineInfo xmlLineInfo) IXmlLineInfoProvider = new XmlLineInfoProvider(xmlLineInfo); - IValueConverterProvider = new ValueConverterProvider(); + IValueConverterProvider = defaultValueConverterProvider; if (node is IElementNode elementNode) Add(typeof(IXamlDataTypeProvider), new XamlDataTypeProvider(elementNode, context)); } - public XamlServiceProvider() => IValueConverterProvider = new ValueConverterProvider(); + public XamlServiceProvider() => IValueConverterProvider = defaultValueConverterProvider; internal IProvideValueTarget IProvideValueTarget { @@ -113,6 +119,22 @@ IEnumerable IProvideParentValues.ParentObjects } } +#nullable enable + public class ValueTargetProvider : IProvideValueTarget + { + private object targetObject; + private object targetProperty; + + public ValueTargetProvider(object targetObject, object targetProperty) + { + this.targetObject = targetObject; + this.targetProperty = targetProperty; + } + object IProvideValueTarget.TargetObject => targetObject; + object IProvideValueTarget.TargetProperty => targetProperty; + } +#nullable restore + public class SimpleValueTargetProvider : IProvideParentValues, IProvideValueTarget, IReferenceProvider { readonly object[] objectAndParents; @@ -168,6 +190,10 @@ public class XamlTypeResolver : IXamlTypeResolver readonly GetTypeFromXmlName getTypeFromXmlName; readonly IXmlNamespaceResolver namespaceResolver; + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#if !NETSTANDARD + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] +#endif public XamlTypeResolver(IXmlNamespaceResolver namespaceResolver, Assembly currentAssembly) : this(namespaceResolver, XamlParser.GetElementType, currentAssembly) { @@ -270,9 +296,9 @@ public string LookupNamespace(string prefix) class XamlDataTypeProvider : IXamlDataTypeProvider { - [RequiresUnreferencedCode("XamlDataTypeProvider is not trim and AOT-compatible.")] + [RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] #if !NETSTANDARD - [RequiresDynamicCode("XamlDataTypeProvider is not trim and AOT-compatible.")] + [RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)] #endif public XamlDataTypeProvider(IElementNode node, HydrationContext context) { @@ -291,24 +317,24 @@ static IElementNode GetParent(IElementNode node) static bool IsBindingContextBinding(IElementNode node) { - if ( ApplyPropertiesVisitor.TryGetPropertyName(node, node.Parent, out XmlName name) + if ( node.TryGetPropertyName(node.Parent, out XmlName name) && name.NamespaceURI == "" && name.LocalName == nameof(BindableObject.BindingContext)) return true; return false; } - static bool IsBindingBaseProperty(IElementNode node, HydrationContext context) + static bool DoesNotInheritDataType(IElementNode node, HydrationContext context) { - if ( ApplyPropertiesVisitor.TryGetPropertyName(node, node.Parent, out XmlName name) + if ( node.TryGetPropertyName(node.Parent, out XmlName name) && node.Parent is IElementNode parent && XamlParser.GetElementType(parent.XmlType, new XmlLineInfo(((IXmlLineInfo)node).LineNumber, ((IXmlLineInfo)node).LinePosition), context.RootElement.GetType().Assembly, out var xpe) is Type parentType && parentType.GetRuntimeProperties().FirstOrDefault(p => p.Name == name.LocalName) is PropertyInfo propertyInfo - && propertyInfo.PropertyType == typeof(BindingBase)) + && propertyInfo.CustomAttributes.Any(ca => ca.AttributeType == typeof(DoesNotInheritDataTypeAttribute))) { - return true; + return true; } return false; } @@ -334,7 +360,7 @@ static bool IsBindingBaseProperty(IElementNode node, HydrationContext context) { break; } - if (IsBindingBaseProperty(n, context)) + if (DoesNotInheritDataType(n, context)) { break; } diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/AccessExpressionBuilderTests.cs b/src/Controls/tests/BindingSourceGen.UnitTests/AccessExpressionBuilderTests.cs new file mode 100644 index 000000000000..78b4f5937389 --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/AccessExpressionBuilderTests.cs @@ -0,0 +1,80 @@ +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + +namespace BindingSourceGen.UnitTests; + +public class AccessExpressionBuilderTests +{ + [Fact] + public void CorrectlyFormatsSimpleCast() + { + var generatedCode = Build("source", + [ + new MemberAccess("A"), + new Cast(new TypeDescription("X", IsNullable: false, IsGenericParameter: false, IsValueType: false)), + new ConditionalAccess(new MemberAccess("B")), + ]); + + Assert.Equal("(source.A as X)?.B", generatedCode); + } + + [Fact] + public void CorrectlyFormatsSimpleCastOfNonNullableValueTypes() + { + var generatedCode = Build("source", + [ + new MemberAccess("A"), + new Cast(new TypeDescription("X", IsNullable: false, IsGenericParameter: false, IsValueType: true)), + new ConditionalAccess(new MemberAccess("B")), + ]); + + Assert.Equal("(source.A as X?)?.B", generatedCode); + } + + [Fact] + public void CorrectlyFormatsSimpleCastOfNullableValueTypes() + { + var generatedCode = Build("source", + [ + new MemberAccess("A"), + new Cast(new TypeDescription("X", IsNullable: true, IsGenericParameter: false, IsValueType: true)), + new ConditionalAccess(new MemberAccess("B")), + ]); + + Assert.Equal("(source.A as X?)?.B", generatedCode); + } + + [Fact] + public void CorrectlyFormatsInaccessibleFieldMemberAccess() + { + var generatedCode = Build("source", + [ + new InaccessibleMemberAccess(new TypeDescription("X"), new TypeDescription("Z"), AccessorKind.Field, "Y") + ]); + + Assert.Equal("GetUnsafeField0Y(source)", generatedCode); + } + + [Fact] + public void CorrectlyFormatsInaccessiblePropertyMemberAccess() + { + var generatedCode = Build("source", + [ + new InaccessibleMemberAccess(new TypeDescription("X"), new TypeDescription("Z"), AccessorKind.Property, "Y") + ]); + + Assert.Equal("GetUnsafeProperty0Y(source)", generatedCode); + } + + private static string Build(string initialExpression, IPathPart[] path) + { + string expression = initialExpression; + + foreach (var part in path) + { + expression = AccessExpressionBuilder.ExtendExpression(expression, part, bindingId: 0); + } + + return expression; + } +} diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/AssertExtensions.cs b/src/Controls/tests/BindingSourceGen.UnitTests/AssertExtensions.cs new file mode 100644 index 000000000000..0928bf1eaa07 --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/AssertExtensions.cs @@ -0,0 +1,54 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + +namespace BindingSourceGen.UnitTests; + +internal static class AssertExtensions +{ + internal static void CodeIsEqual(string expectedCode, string actualCode) + { + var expectedLines = SplitCode(expectedCode); + var actualLines = SplitCode(actualCode); + + foreach (var (expectedLine, actualLine) in expectedLines.Zip(actualLines)) + { + Assert.Equal(expectedLine, actualLine); + } + + Assert.Equal(expectedLines.Count(), actualLines.Count()); + } + + internal static void BindingsAreEqual(BindingInvocationDescription expectedBinding, CodeGeneratorResult codeGeneratorResult) + { + AssertNoDiagnostics(codeGeneratorResult); + Assert.NotNull(codeGeneratorResult.Binding); + + //TODO: Change arrays to custom collections implementing IEquatable + Assert.Equal(expectedBinding.Path, codeGeneratorResult.Binding.Path); + Assert.Equal(expectedBinding, codeGeneratorResult.Binding); + } + + private static IEnumerable SplitCode(string code) + => code.Split(Environment.NewLine) + .Select(static line => line.Trim()) + .Where(static line => !string.IsNullOrWhiteSpace(line)); + + internal static void AssertNoDiagnostics(CodeGeneratorResult codeGeneratorResult) + { + AssertNoDiagnostics(codeGeneratorResult.SourceCompilationDiagnostics, "Source compilation"); + AssertNoDiagnostics(codeGeneratorResult.SourceGeneratorDiagnostics, "Source generator"); + AssertNoDiagnostics(codeGeneratorResult.GeneratedCodeCompilationDiagnostics, "Generated code compilation"); + } + + internal static void AssertNoDiagnostics(ImmutableArray diagnostics, string name) + { + if (diagnostics.Any()) + { + var errorMessages = diagnostics.Select(error => error.ToString()); + throw new Exception($"\n{name} diagnostics: {string.Join(Environment.NewLine, errorMessages)}"); + } + } + +} diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/BindingCodeWriterTests.cs b/src/Controls/tests/BindingSourceGen.UnitTests/BindingCodeWriterTests.cs new file mode 100644 index 000000000000..d2e34b99570f --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/BindingCodeWriterTests.cs @@ -0,0 +1,524 @@ +using System.Linq; +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + +namespace BindingSourceGen.UnitTests; + +public class BindingCodeWriterTests +{ + [Fact] + public void BuildsCommonCode() + { + var code = BindingCodeWriter.GenerateCommonCode(); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace Microsoft.Maui.Controls.Generated + { + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + internal static partial class GeneratedBindingInterceptors + { + private static bool ShouldUseSetter(BindingMode mode, BindableProperty bindableProperty) + => mode == BindingMode.OneWayToSource + || mode == BindingMode.TwoWay + || (mode == BindingMode.Default + && (bindableProperty.DefaultBindingMode == BindingMode.OneWayToSource + || bindableProperty.DefaultBindingMode == BindingMode.TwoWay)); + + private static bool ShouldUseSetter(BindingMode mode) + => mode == BindingMode.OneWayToSource + || mode == BindingMode.TwoWay + || mode == BindingMode.Default; + } + } + """, + code); + } + + [Fact] + public void BuildsWholeBinding() + { + var code = BindingCodeWriter.GenerateBinding(new BindingInvocationDescription( + Location: new InterceptorLocation(FilePath: @"Path\To\Program.cs", Line: 20, Column: 30), + SourceType: new TypeDescription("global::MyNamespace.MySourceClass", IsValueType: false, IsNullable: false, IsGenericParameter: false), + PropertyType: new TypeDescription("global::MyNamespace.MyPropertyClass", IsValueType: false, IsNullable: false, IsGenericParameter: false), + Path: new EquatableArray([ + new MemberAccess("A"), + new ConditionalAccess(new MemberAccess("B")), + new ConditionalAccess(new MemberAccess("C")), + ]), + SetterOptions: new(IsWritable: true, AcceptsNullValue: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding), id: 1); + + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 20, 30)] + public static void SetBinding1( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (source.A is {} p0 + && p0.B is {} p1) + { + p1.C = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "A"), + new(static source => source.A, "B"), + new(static source => source.A?.B, "C"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + code); + } + + [Fact] + public void CorrectlyFormatsSimpleBinding() + { + var codeBuilder = new BindingCodeWriter.BindingInterceptorCodeBuilder(); + codeBuilder.AppendSetBindingInterceptor(id: 1, new BindingInvocationDescription( + Location: new InterceptorLocation(FilePath: @"Path\To\Program.cs", Line: 20, Column: 30), + SourceType: new TypeDescription("global::MyNamespace.MySourceClass", IsValueType: false, IsNullable: false, IsGenericParameter: false), + PropertyType: new TypeDescription("global::MyNamespace.MyPropertyClass", IsValueType: false, IsNullable: false, IsGenericParameter: false), + Path: new EquatableArray([ + new MemberAccess("A"), + new ConditionalAccess(new MemberAccess("B")), + new ConditionalAccess(new MemberAccess("C")), + ]), + SetterOptions: new(IsWritable: true, AcceptsNullValue: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding)); + + var code = codeBuilder.ToString(); + AssertExtensions.CodeIsEqual( + $$""" + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 20, 30)] + public static void SetBinding1( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (source.A is {} p0 + && p0.B is {} p1) + { + p1.C = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "A"), + new(static source => source.A, "B"), + new(static source => source.A?.B, "C"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + """, + code); + } + + [Fact] + public void CorrectlyFormatsBindingWithoutAnyNullablesInPath() + { + var codeBuilder = new BindingCodeWriter.BindingInterceptorCodeBuilder(); + codeBuilder.AppendSetBindingInterceptor(id: 1, new BindingInvocationDescription( + Location: new InterceptorLocation(FilePath: @"Path\To\Program.cs", Line: 20, Column: 30), + SourceType: new TypeDescription("global::MyNamespace.MySourceClass", IsValueType: false, IsNullable: false, IsGenericParameter: false), + PropertyType: new TypeDescription("global::MyNamespace.MyPropertyClass", IsValueType: false, IsNullable: false, IsGenericParameter: false), + Path: new EquatableArray([ + new MemberAccess("A"), + new MemberAccess("B"), + new MemberAccess("C"), + ]), + SetterOptions: new(IsWritable: true, AcceptsNullValue: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding)); + + var code = codeBuilder.ToString(); + AssertExtensions.CodeIsEqual( + $$""" + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 20, 30)] + public static void SetBinding1( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + source.A.B.C = value; + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "A"), + new(static source => source.A, "B"), + new(static source => source.A.B, "C"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + """, + code); + } + + [Fact] + public void CorrectlyFormatsBindingWithoutSetter() + { + var codeBuilder = new BindingCodeWriter.BindingInterceptorCodeBuilder(); + codeBuilder.AppendSetBindingInterceptor(id: 1, new BindingInvocationDescription( + Location: new InterceptorLocation(FilePath: @"Path\To\Program.cs", Line: 20, Column: 30), + SourceType: new TypeDescription("global::MyNamespace.MySourceClass", IsNullable: false, IsGenericParameter: false, IsValueType: false), + PropertyType: new TypeDescription("global::MyNamespace.MyPropertyClass", IsNullable: false, IsGenericParameter: false, IsValueType: false), + Path: new EquatableArray([ + new MemberAccess("A"), + new MemberAccess("B"), + new MemberAccess("C"), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding)); + + var code = codeBuilder.ToString(); + AssertExtensions.CodeIsEqual( + $$""" + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 20, 30)] + public static void SetBinding1( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + throw new InvalidOperationException("Cannot set value on the source object."); + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "A"), + new(static source => source.A, "B"), + new(static source => source.A.B, "C"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + """, + code); + } + + [Fact] + public void CorrectlyFormatsBindingWithIndexers() + { + var codeBuilder = new BindingCodeWriter.BindingInterceptorCodeBuilder(); + codeBuilder.AppendSetBindingInterceptor(id: 1, new BindingInvocationDescription( + Location: new InterceptorLocation(FilePath: @"Path\To\Program.cs", Line: 20, Column: 30), + SourceType: new TypeDescription("global::MyNamespace.MySourceClass", IsNullable: false, IsGenericParameter: false), + PropertyType: new TypeDescription("global::MyNamespace.MyPropertyClass", IsNullable: true, IsGenericParameter: false), + Path: new EquatableArray([ + new IndexAccess("Item", 12), + new ConditionalAccess(new IndexAccess("Indexer", "Abc")), + new IndexAccess("Item", 0), + ]), + SetterOptions: new(IsWritable: true, AcceptsNullValue: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding)); + + var code = codeBuilder.ToString(); + AssertExtensions.CodeIsEqual( + $$""" + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 20, 30)] + public static void SetBinding1( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (value is null) + { + return; + } + + if (source[12] is {} p0) + { + p0["Abc"][0] = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "Item"), + new(static source => source, "Item[12]"), + new(static source => source[12], "Indexer"), + new(static source => source[12], "Indexer[Abc]"), + new(static source => source[12]?["Abc"], "Item"), + new(static source => source[12]?["Abc"], "Item[0]"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + """, + code); + } + + [Fact] + public void CorrectlyFormatsBindingWithCasts() + { + var codeBuilder = new BindingCodeWriter.BindingInterceptorCodeBuilder(); + codeBuilder.AppendSetBindingInterceptor(id: 1, new BindingInvocationDescription( + Location: new InterceptorLocation(FilePath: @"Path\To\Program.cs", Line: 20, Column: 30), + SourceType: new TypeDescription("global::MyNamespace.MySourceClass", IsNullable: false, IsGenericParameter: false), + PropertyType: new TypeDescription("global::MyNamespace.MyPropertyClass", IsNullable: false, IsGenericParameter: false), + Path: new EquatableArray([ + new MemberAccess("A"), + new Cast(new TypeDescription("X", IsValueType: false, IsNullable: false, IsGenericParameter: false)), + new ConditionalAccess(new MemberAccess("B")), + new Cast(new TypeDescription("Y", IsValueType: false, IsNullable: false, IsGenericParameter: false)), + new ConditionalAccess(new MemberAccess("C")), + new Cast(new TypeDescription("Z", IsValueType: true, IsNullable: true, IsGenericParameter: false)), + new ConditionalAccess(new MemberAccess("D")), + ]), + SetterOptions: new(IsWritable: true, AcceptsNullValue: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding)); + + var code = codeBuilder.ToString(); + + AssertExtensions.CodeIsEqual( + $$""" + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 20, 30)] + public static void SetBinding1( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (source.A is X p0 + && p0.B is Y p1 + && p1.C is Z p2) + { + p2.D = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "A"), + new(static source => (source.A as X), "B"), + new(static source => ((source.A as X)?.B as Y), "C"), + new(static source => (((source.A as X)?.B as Y)?.C as Z?), "D"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + """, + code); + } +} diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/BindingRepresentationGenTests.cs b/src/Controls/tests/BindingSourceGen.UnitTests/BindingRepresentationGenTests.cs new file mode 100644 index 000000000000..4d4fb397e314 --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/BindingRepresentationGenTests.cs @@ -0,0 +1,1118 @@ +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + + +namespace BindingSourceGen.UnitTests; + + +public class BindingRepresentationGenTests +{ + [Fact] + public void GenerateSimpleBinding() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (string s) => s.Length); + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("string"), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new MemberAccess("Length", IsValueType: true), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWithNestedProperties() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Button b) => b.Text?.Length); + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Microsoft.Maui.Controls.Button"), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new MemberAccess("Text"), + new ConditionalAccess(new MemberAccess("Length", IsValueType: true)), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWithNullableReferenceElementInPathWhenNullableEnabled() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Button?.Text?.Length); + + class Foo + { + public Button? Button { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new MemberAccess("Button"), + new ConditionalAccess(new MemberAccess("Text")), + new ConditionalAccess(new MemberAccess("Length", IsValueType: true)), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + + } + + [Fact] + public void GenerateBindingWithNullableReferenceSourceWhenNullableEnabled() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Button? b) => b?.Text?.Length); + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Microsoft.Maui.Controls.Button", IsNullable: true), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new ConditionalAccess(new MemberAccess("Text")), + new ConditionalAccess(new MemberAccess("Length", IsValueType: true)), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWithNullableValueTypeWhenNullableEnabled() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Value); + + class Foo + { + public int? Value { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new MemberAccess("Value", IsValueType: true), + ]), + SetterOptions: new(IsWritable: true, AcceptsNullValue: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWithNullableSourceReferenceAndNullableReferenceElementInPathWhenNullableEnabled() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Button? b) => b?.Text?.Length); + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Microsoft.Maui.Controls.Button", IsNullable: true), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new ConditionalAccess(new MemberAccess("Text")), + new ConditionalAccess(new MemberAccess("Length", IsValueType: true)), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWithNullablePropertyReferenceWhenNullableEnabled() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Value); + + class Foo + { + public string? Value { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("string", IsNullable: true), + new EquatableArray([ + new MemberAccess("Value"), + ]), + SetterOptions: new(IsWritable: true, AcceptsNullValue: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWithNullableReferenceTypesWhenNullableDisabledAndConditionalAccessOperator() + { + var source = """ + using Microsoft.Maui.Controls; + #nullable disable + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f?.Bar?.Length); + + class Foo + { + public string Bar { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 4, 7), + new TypeDescription("global::Foo", IsNullable: true), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new ConditionalAccess(new MemberAccess("Bar")), + new ConditionalAccess(new MemberAccess("Length", IsValueType: true)), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: false, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenNullableDisabledAndPropertyNonNullableValueType() + { + var source = """ + using Microsoft.Maui.Controls; + #nullable disable + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Bar.Length); + + class Foo + { + public Bar Bar { get; set; } + } + + class Bar + { + public int Length { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 4, 7), + new TypeDescription("global::Foo", IsNullable: true), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new MemberAccess("Bar"), + new MemberAccess("Length", IsValueType: true), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: false, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenNullableDisabledAndPropertyNullableValueType() + { + var source = """ + using Microsoft.Maui.Controls; + #nullable disable + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Bar.Length); + + class Foo + { + public Bar Bar { get; set; } + } + + class Bar + { + public int? Length { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 4, 7), + new TypeDescription("global::Foo", IsNullable: true), + new TypeDescription("int", IsNullable: true, IsValueType: true), + new EquatableArray([ + new MemberAccess("Bar"), + new MemberAccess("Length", IsValueType: true), + ]), + SetterOptions: new(IsWritable: true, AcceptsNullValue: true), + NullableContextEnabled: false, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenNullableDisabledAndPropertyReferenceType() + { + var source = """ + using Microsoft.Maui.Controls; + #nullable disable + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Bar.Length); + + class Foo + { + public Bar Bar { get; set; } + } + + class Bar + { + public CustomLength Length { get; set; } + } + + class CustomLength + { + + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 4, 7), + new TypeDescription("global::Foo", IsNullable: true), + new TypeDescription("global::CustomLength", IsNullable: true), + new EquatableArray([ + new MemberAccess("Bar"), + new MemberAccess("Length"), + ]), + SetterOptions: new(IsWritable: true, AcceptsNullValue: true), + NullableContextEnabled: false, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenBindingContainsIntegerIndexing() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Items[0].Length); + + class Foo + { + public string[] Items { get; set; } = { "Item1" }; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new MemberAccess("Items"), + new IndexAccess("Item", 0), + new MemberAccess("Length", IsValueType: true), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsStringIndexing() + { + var source = """ + using Microsoft.Maui.Controls; + using System.Collections.Generic; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Items["key"].Length); + + class Foo + { + public Dictionary Items { get; set; } = new(); + } + """; + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 4, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new MemberAccess("Items"), + new IndexAccess("Item", "key"), + new MemberAccess("Length", IsValueType: true), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsCustomIndexerWithIndexerNameAttribute() + { + var source = """ + using Microsoft.Maui.Controls; + using System.Runtime.CompilerServices; + + var label = new Label(); + var foo = new Foo(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f["key"].Length); + + class Foo + { [IndexerName("CustomIndexer")] + public string this[string key] => key; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 6, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new IndexAccess("CustomIndexer", "key"), + new MemberAccess("Length", IsValueType: true), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsNullableIndexer() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f["key"]?.Length); + + class Foo + { + public string? this[string key] => key; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new IndexAccess("Item", "key"), + new ConditionalAccess(new MemberAccess("Length", IsValueType: true)), // TODO: Improve naming so this looks right + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsConditionallyAccessedIndexer() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.bar?["key"].Length); + + class Foo + { + public Bar? bar { get; set; } + } + + class Bar + { + public string this[string key] => key; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new MemberAccess("bar"), + new ConditionalAccess(new IndexAccess("Item", "key")), + new MemberAccess("Length", IsValueType: true), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsComplexCombinedIndexers() + { + var source = """ + using Microsoft.Maui.Controls; + using System.Runtime.CompilerServices; + using MyNamespace; + + var label = new Label(); + label.SetBinding(Label.TextProperty, static (MySourceClass s) => (s[12]?["Abc"][0])); + + namespace MyNamespace + { + public class MySourceClass + { + public B this[int index] => new B(); + } + + public class B + { + [IndexerName("Indexer")] + public MyPropertyClass[] this[string index] => []; + } + + public class MyPropertyClass + { + + } + + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 6, 7), + new TypeDescription("global::MyNamespace.MySourceClass"), + new TypeDescription("global::MyNamespace.MyPropertyClass", IsNullable: true), + new EquatableArray([ + new IndexAccess("Item", 12), + new ConditionalAccess(new IndexAccess("Indexer", "Abc")), + new IndexAccess("Item", 0), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsCustomIndexerWithDefaultMemberAttribute() + { + var source = """ + using Microsoft.Maui.Controls; + using System.Text; + + var label = new Label(); + var foo = new Foo(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.s[0]); + + class Foo + { + public StringBuilder s {get; set;} = new(); + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 6, 7), + new TypeDescription("global::Foo"), + new TypeDescription("char", IsValueType: true), + new EquatableArray([ + new MemberAccess("s"), + new IndexAccess("Chars", 0, IsValueType: true), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsCustomIndexerWithoutAttributes() + { + var source = """ + using Microsoft.Maui.Controls; + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f["key"].Length); + + class Foo + { + public string this[string key] => key; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 4, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new IndexAccess("Item", "key"), + new MemberAccess("Length", IsValueType: true), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsSimpleReferenceTypeCast() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Value as string); + + class Foo + { + public object Value { get; set; } = "Value"; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("string", IsNullable: true), + new EquatableArray([ + new MemberAccess("Value"), + new Cast(new TypeDescription("string")), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsSimpleReferenceTypeExplicitCast() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => (string)f.Value); + + class Foo + { + public object Value { get; set; } = "Value"; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("string"), + new EquatableArray([ + new MemberAccess("Value"), + new Cast(new TypeDescription("string")), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsMemberAccessOfCastReferenceType() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => (f.C as C)?.X); + + public class Foo + { + public object C { get; set; } = new C(); + } + + class C + { + public int X { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new MemberAccess("C"), + new Cast(new TypeDescription("global::C")), + new ConditionalAccess(new MemberAccess("X", IsValueType: true)), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsMemberAccessOfExplicitCastReferenceType() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => ((C)f.C).X); + + public class Foo + { + public object C { get; set; } = new C(); + } + + class C + { + public int X { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new MemberAccess("C"), + new Cast(new TypeDescription("global::C")), + new MemberAccess("X", IsValueType: true), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + + [Theory] + [InlineData("static (Foo f) => (f.C as C)?.X")] + [InlineData("static (Foo f) => ((C?)f.C)?.X")] + public void GenerateBindingWhenGetterContainsMemberAccessOfCastNullableReferenceType(string bindingLambda) + { + var source = $$""" + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, {{bindingLambda}}); + + public class Foo + { + public object? C { get; set; } + } + + class C + { + public int X { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsNullable: true, IsValueType: true), + new EquatableArray([ + new MemberAccess("C"), + new Cast(new TypeDescription("global::C")), + new ConditionalAccess(new MemberAccess("X", IsValueType: true)), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Theory] + [InlineData("static (Foo f) => f.Value as int?")] + [InlineData("static (Foo f) => (int?)f.Value")] + public void GenerateBindingWhenGetterContainsSimpleValueTypeCast(string bindingLambda) + { + var source = $$""" + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, {{bindingLambda}}); + + class Foo + { + public int Value { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsNullable: true, IsValueType: true), + new EquatableArray([ + new MemberAccess("Value", IsValueType: true), + new Cast(new TypeDescription("int", IsNullable: true, IsValueType: true)), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GenerateBindingWhenGetterContainsSimpleValueTypeExplicitCast() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => (int)f.Value); + + class Foo + { + public int Value { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new MemberAccess("Value", IsValueType: true), + new Cast(new TypeDescription("int", IsValueType: true)), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Theory] + [InlineData("static (Foo f) => (f.C as C?)?.X")] + [InlineData("static (Foo f) => ((C?)f.C)?.X")] + public void GenerateBindingWhenGetterContainsMemberAccessOfCastNullableValueType(string bindingLambda) + { + var source = $$""" + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, {{bindingLambda}}); + + public class Foo + { + public object? C { get; set; } + } + + struct C + { + public int X { get; set; } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsNullable: true, IsValueType: true), + new EquatableArray([ + new MemberAccess("C"), + new Cast(new TypeDescription("global::C", IsNullable: true, IsValueType: true)), + new ConditionalAccess(new MemberAccess("X", IsValueType: true)), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void SetsIsWritableFalseWhenPropertyComesFromImmutableCollection() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.S[0]); + + class Foo + { + public string S { get; set; } = "Value"; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("char", IsValueType: true), + new EquatableArray([ + new MemberAccess("S"), + new IndexAccess("Chars", 0, IsValueType: true), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void SetsIsWritableTrueWhenPropertyComesFromMutableCollection() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.S[0]); + + class Foo + { + public char[] S { get; set; } = { 'A' }; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("char", IsValueType: true), + new EquatableArray([ + new MemberAccess("S"), + new IndexAccess("Item", 0, IsValueType: true), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void SetsIsWritableFalseWhenCustomIndexerHasNoSetter() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f["key"]); + + class Foo + { + public string this[string key] => key; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("string"), + new EquatableArray([ + new IndexAccess("Item", "key"), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void SetsIsWritableTrueWhenCustomIndexerHasSetter() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f["key"]); + + class Foo + { + public string this[string key] { get => key; set {} } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo"), + new TypeDescription("string"), + new EquatableArray([ + new IndexAccess("Item", "key"), + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void SetsIsWritableWhenElementAccessIsConditional() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo? f) => f?[0]); + + class Foo + { + public int this[int key] => key; + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + new TypeDescription("global::Foo", IsNullable: true), + new TypeDescription("int", IsValueType: true, IsNullable: true), + new EquatableArray([ + new ConditionalAccess(new IndexAccess("Item", 0, IsValueType: true)), + ]), + SetterOptions: new(IsWritable: false), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GeneratesInaccessibleMemberAccessWhenUsingPrivateFields() + { + var source = """ + using Microsoft.Maui.Controls; + + var foo = new Foo(); + foo.Bar(); + + class Foo + { + private int _value = 0; + public void Bar() + { + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f._value); + } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 12, 15), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new InaccessibleMemberAccess( + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + AccessorKind.Field, + "_value", + IsValueType: true + ) + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } + + [Fact] + public void GeneratesInaccessibleMemberAccessWhenUsingPrivateProperties() + { + var source = """ + using Microsoft.Maui.Controls; + + var foo = new Foo(); + foo.Bar(); + + class Foo + { + private int Value { get; set; } = 0; + public void Bar() + { + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Foo f) => f.Value); + } + } + """; + + var codeGeneratorResult = SourceGenHelpers.Run(source); + var expectedBinding = new BindingInvocationDescription( + new InterceptorLocation(@"Path\To\Program.cs", 12, 15), + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + new EquatableArray([ + new InaccessibleMemberAccess( + new TypeDescription("global::Foo"), + new TypeDescription("int", IsValueType: true), + AccessorKind.Property, + "Value", + IsValueType: true + ) + ]), + SetterOptions: new(IsWritable: true), + NullableContextEnabled: true, + MethodType: InterceptedMethodType.SetBinding); + + AssertExtensions.BindingsAreEqual(expectedBinding, codeGeneratorResult); + } +} diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/BindingTransformerTests.cs b/src/Controls/tests/BindingSourceGen.UnitTests/BindingTransformerTests.cs new file mode 100644 index 000000000000..bc3512adc660 --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/BindingTransformerTests.cs @@ -0,0 +1,138 @@ +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + +namespace BindingSourceGen.UnitTests; + +public class BindingTransformerTests +{ + [Fact] + public void WrapMemberAccessInConditionalAccessWhenSourceTypeIsReferenceType() + { + var binding = new BindingInvocationDescription( + Location: new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + SourceType: new TypeDescription("MyType", IsValueType: false), + PropertyType: new TypeDescription("MyType2"), + Path: new EquatableArray([new MemberAccess("A")]), + SetterOptions: new SetterOptions(IsWritable: true), + NullableContextEnabled: false, + MethodType: InterceptedMethodType.SetBinding); + + var transformer = new ReferenceTypesConditionalAccessTransformer(); + var transformedBinding = transformer.Transform(binding); + + var transformedPath = new EquatableArray([new ConditionalAccess(new MemberAccess("A"))]); + Assert.Equal(transformedPath, transformedBinding.Path); + } + + [Fact] + public void WrapMemberAccessInConditionalAccessWhePreviousPartTypeIsReferenceType() + { + var binding = new BindingInvocationDescription( + Location: new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + SourceType: new TypeDescription("MyType", IsValueType: true), + PropertyType: new TypeDescription("MyType2"), + Path: new EquatableArray( + [ + new MemberAccess("A", IsValueType: false), + new MemberAccess("B"), + ]), + SetterOptions: new SetterOptions(IsWritable: true), + NullableContextEnabled: false, + MethodType: InterceptedMethodType.SetBinding); + + var transformer = new ReferenceTypesConditionalAccessTransformer(); + var transformedBinding = transformer.Transform(binding); + + var transformedPath = new EquatableArray( + [ + new MemberAccess("A"), + new ConditionalAccess(new MemberAccess("B")), + ]); + Assert.Equal(transformedPath, transformedBinding.Path); + } + + [Fact] + public void DoNotWrapMemberAccessInConditionalAccessWhePreviousPartTypeIsValueType() + { + var binding = new BindingInvocationDescription( + Location: new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + SourceType: new TypeDescription("MyType", IsValueType: false), + PropertyType: new TypeDescription("MyType2"), + Path: new EquatableArray( + [ + new MemberAccess("A", IsValueType: true), + new MemberAccess("B"), + ]), + SetterOptions: new SetterOptions(IsWritable: true), + NullableContextEnabled: false, + MethodType: InterceptedMethodType.SetBinding); + + var transformer = new ReferenceTypesConditionalAccessTransformer(); + var transformedBinding = transformer.Transform(binding); + + var transformedPath = new EquatableArray( + [ + new ConditionalAccess(new MemberAccess("A", IsValueType: true)), + new MemberAccess("B"), + ]); + Assert.Equal(transformedPath, transformedBinding.Path); + } + + [Fact] + public void WrapAccessInConditionalAccessWhenAllPartsAreReferenceTypes() + { + var binding = new BindingInvocationDescription( + Location: new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + SourceType: new TypeDescription("MyType"), + PropertyType: new TypeDescription("MyType2"), + Path: new EquatableArray( + [ + new MemberAccess("A"), + new IndexAccess("Item", 0), + new MemberAccess("B"), + ]), + SetterOptions: new SetterOptions(IsWritable: true), + NullableContextEnabled: false, + MethodType: InterceptedMethodType.SetBinding); + + var transformer = new ReferenceTypesConditionalAccessTransformer(); + var transformedBinding = transformer.Transform(binding); + + var transformedPath = new EquatableArray( + [ + new ConditionalAccess(new MemberAccess("A")), + new ConditionalAccess(new IndexAccess("Item", 0)), + new ConditionalAccess(new MemberAccess("B")), + ]); + Assert.Equal(transformedPath, transformedBinding.Path); + } + + [Fact] + public void DoNotWrapAccessInConditionalAccessWhenNoPartsAreReferenceTypes() + { + var binding = new BindingInvocationDescription( + Location: new InterceptorLocation(@"Path\To\Program.cs", 3, 7), + SourceType: new TypeDescription("MyType", IsValueType: true), + PropertyType: new TypeDescription("MyType2"), + Path: new EquatableArray( + [ + new MemberAccess("A", IsValueType: true), + new IndexAccess("Item", 0, IsValueType: true), + new MemberAccess("B", IsValueType: true), + ]), + SetterOptions: new SetterOptions(IsWritable: true), + NullableContextEnabled: false, + MethodType: InterceptedMethodType.SetBinding); + + var transformer = new ReferenceTypesConditionalAccessTransformer(); + var transformedBinding = transformer.Transform(binding); + + var transformedPath = new EquatableArray( + [ + new MemberAccess("A", IsValueType: true), + new IndexAccess("Item", 0, IsValueType: true), + new MemberAccess("B", IsValueType: true), + ]); + Assert.Equal(transformedPath, transformedBinding.Path); + } +} diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/Controls.BindingSourceGen.UnitTests.csproj b/src/Controls/tests/BindingSourceGen.UnitTests/Controls.BindingSourceGen.UnitTests.csproj new file mode 100644 index 000000000000..f353f69562f1 --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/Controls.BindingSourceGen.UnitTests.csproj @@ -0,0 +1,30 @@ + + + + $(_MauiDotNetTfm) + enable + enable + + false + true + + + + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + \ No newline at end of file diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/DiagnosticsTests.cs b/src/Controls/tests/BindingSourceGen.UnitTests/DiagnosticsTests.cs new file mode 100644 index 000000000000..2b37e68bdc5e --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/DiagnosticsTests.cs @@ -0,0 +1,318 @@ +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + +namespace BindingSourceGen.UnitTests; + +public class DiagnosticsTests +{ + [Fact] + public void ReportsErrorWhenGetterIsNotLambda() + { + var source = """ + using System; + using Microsoft.Maui.Controls; + var label = new Label(); + var getter = new Func(b => b.Text.Length); + label.SetBinding(Label.RotationProperty, getter); + """; + + var result = SourceGenHelpers.Run(source); + + var diagnostic = Assert.Single(result.SourceGeneratorDiagnostics); + Assert.Equal("BSG0002", diagnostic.Id); + } + + [Fact] + public void ReportsErrorWhenLambdaBodyIsNotExpression() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Button b) => { return b.Text.Length; }); + """; + + var result = SourceGenHelpers.Run(source); + + var diagnostic = Assert.Single(result.SourceGeneratorDiagnostics); + Assert.Equal("BSG0003", diagnostic.Id); + } + + [Fact] + public void DoesNotReportWarningWhenUsingOverloadWithBindingClassDeclaredInInvocation() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + var slider = new Slider(); + label.SetBinding(Label.ScaleProperty, new Binding("Value", source: slider)); + """; + + var result = SourceGenHelpers.Run(source); + Assert.Empty(result.SourceGeneratorDiagnostics); + } + + [Fact] + public void DoesNotReportWarningWhenUsingOverloadWithBindingClassPassedAsVariable() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + var slider = new Slider(); + var binding = new Binding("Value", source: slider); + label.SetBinding(Label.ScaleProperty, binding); + """; + + var result = SourceGenHelpers.Run(source); + Assert.Empty(result.SourceGeneratorDiagnostics); + } + + [Fact] + public void DoesNotReportWarningWhenUsingOverloadWithStringConstantPath() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + var slider = new Slider(); + + label.BindingContext = slider; + label.SetBinding(Label.ScaleProperty, "Value"); + """; + + var result = SourceGenHelpers.Run(source); + Assert.Empty(result.SourceGeneratorDiagnostics); + } + + [Fact] + public void DoesNotReportWarningWhenUsingOverloadWithStringVariablePath() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + var slider = new Slider(); + + label.BindingContext = slider; + var str = "Value"; + label.SetBinding(Label.ScaleProperty, str); + """; + + var result = SourceGenHelpers.Run(source); + Assert.Empty(result.SourceGeneratorDiagnostics); + } + + [Fact] + public void DoesNotReportWarningWhenUsingOverloadWithNameofInPath() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + var slider = new Slider(); + + label.BindingContext = slider; + label.SetBinding(Label.ScaleProperty, nameof(Slider.Value)); + """; + + var result = SourceGenHelpers.Run(source); + Assert.Empty(result.SourceGeneratorDiagnostics); + } + + [Fact] + public void DoesNotReportWarningWhenUsingOverloadWithMethodCallThatReturnsString() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + var slider = new Slider(); + + label.BindingContext = slider; + label.SetBinding(Label.ScaleProperty, GetPath()); + + static string GetPath() => "Value"; + """; + + var result = SourceGenHelpers.Run(source); + Assert.Empty(result.SourceGeneratorDiagnostics); + } + + [Fact] + public void ReportsUnableToResolvePathWhenUsingMethodCall() + { + var source = """ + using Microsoft.Maui.Controls; + + double GetRotation(Button b) => b.Rotation; + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Button b) => GetRotation(b)); + """; + + var result = SourceGenHelpers.Run(source); + + var diagnostic = Assert.Single(result.SourceGeneratorDiagnostics); + Assert.Equal("BSG0001", diagnostic.Id); + } + + [Fact] + public void ReportsUnableToResolvePathWhenUsingMultidimensionalArray() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + + label.SetBinding(Label.RotationProperty, static (Foo b) => b.array[0, 0]); + + class Foo + { + int[,] array = new int[1, 1]; + } + """; + + var result = SourceGenHelpers.Run(source); + + var diagnostic = Assert.Single(result.SourceGeneratorDiagnostics); + Assert.Equal("BSG0001", diagnostic.Id); + } + + [Fact] + // https://github.com/dotnet/maui/issues/23531 + public void ReportsWarningWhenLambdaParameterIsSourceGeneratedType() + { + var source = """ + using Microsoft.Maui.Controls; + using SomeNamespace; + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (ClassA a) => a.CounterBtn.Text.Length); + """; + + var result = SourceGenHelpers.Run(source, [new BindingSourceGenerator(), new IncrementalGeneratorA()]); + + var diagnostic = Assert.Single(result.SourceGeneratorDiagnostics); + Assert.Equal("BSG0005", diagnostic.Id); + AssertExtensions.AssertNoDiagnostics(result.GeneratedCodeCompilationDiagnostics, "Generated code compilation"); + } + + [Fact] + // https://github.com/dotnet/maui/issues/23531 + public void ReportsWarningWhenPathContainsSourceGeneratedMember() + { + var source = """ + using Microsoft.Maui.Controls; + + var a = new SomeNamespace.ClassA(); + a.Foo(); + + namespace SomeNamespace + { + public partial class ClassA + { + public void Foo() + { + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (ClassA a) => a.CounterBtn.Text.Length); + } + } + } + + """; + + var result = SourceGenHelpers.Run(source, [new BindingSourceGenerator(), new IncrementalGeneratorA()]); + + var diagnostic = Assert.Single(result.SourceGeneratorDiagnostics); + Assert.Equal("BSG0006", diagnostic.Id); + AssertExtensions.AssertNoDiagnostics(result.GeneratedCodeCompilationDiagnostics, "Generated code compilation"); + } + + [Theory] + [InlineData("private")] + [InlineData("protected")] + [InlineData("private protected")] + // https://github.com/dotnet/maui/issues/23534 + public void ReportsWarningWhenSourceTypeIsUnaccessible(string modifier) + { + var source = $$""" + using Microsoft.Maui.Controls; + + var foo = new Foo(); + foo.Bar(); + + public class Foo + { + public void Bar() + { + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (UnaccessibleClass a) => a.Value); + } + + {{modifier}} class UnaccessibleClass + { + public int Value { get; set; } + } + } + """; + + var result = SourceGenHelpers.Run(source); + + var diagnostic = Assert.Single(result.SourceGeneratorDiagnostics); + Assert.Equal("BSG0007", diagnostic.Id); + AssertExtensions.AssertNoDiagnostics(result.GeneratedCodeCompilationDiagnostics, "Generated code compilation"); + } + + [Fact] + public void ReportsWarningWhenLambdaIsNotStatic() + { + var source = """ + using Microsoft.Maui.Controls; + + var label = new Label(); + var text = "Hello"; + label.SetBinding(Label.RotationProperty, (Button b) => text.Length); + """; + + var result = SourceGenHelpers.Run(source); + + var diagnostic = Assert.Single(result.SourceGeneratorDiagnostics); + Assert.Equal("BSG0010", diagnostic.Id); + AssertExtensions.AssertNoDiagnostics(result.GeneratedCodeCompilationDiagnostics, "Generated code compilation"); + } + + [Fact] + public void ReportsWarningWhenLambdaHasNoParameters() + { + var source = """ + using Microsoft.Maui.Controls; + + label.SetBinding(Label.RotationProperty, static () => text.Length); + """; + + var result = SourceGenHelpers.Run(source); + + var diagnostic = Assert.Single(result.SourceGeneratorDiagnostics); + Assert.Equal("BSG0005", diagnostic.Id); + } +} + +internal class IncrementalGeneratorA : IIncrementalGenerator +{ + public void Initialize(IncrementalGeneratorInitializationContext context) + { + context.RegisterSourceOutput( + context.CompilationProvider, + (ctx, compilation) => + { + var source = """ + using Microsoft.Maui.Controls; + namespace SomeNamespace + { + public partial class ClassA + { + public Button CounterBtn; + } + } + """; + ctx.AddSource("SampleSourceGeneratorOutput.g.cs", SourceText.From(source, Encoding.UTF8)); + }); + } +} diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/IncrementalGenerationTests.cs b/src/Controls/tests/BindingSourceGen.UnitTests/IncrementalGenerationTests.cs new file mode 100644 index 000000000000..1b9b6560e167 --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/IncrementalGenerationTests.cs @@ -0,0 +1,249 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + +namespace BindingSourceGen.UnitTests; + + +public class IncrementalGenerationTests +{ + [Fact] + public void CompilingTheSameSourceResultsInEqualModels() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (string s) => s.Length); + """; + + var inputCompilation1 = SourceGenHelpers.CreateCompilation(source); + var driver1 = SourceGenHelpers.CreateDriver([new BindingSourceGenerator().AsSourceGenerator()]); + var result1 = driver1.RunGenerators(inputCompilation1).GetRunResult().Results.Single(); + + var inputCompilation2 = SourceGenHelpers.CreateCompilation(source); + var driver2 = SourceGenHelpers.CreateDriver([new BindingSourceGenerator().AsSourceGenerator()]); + var result2 = driver2.RunGenerators(inputCompilation2).GetRunResult().Results.Single(); + + Assert.Equal(result1.TrackedSteps.Count, result2.TrackedSteps.Count); + CompareGeneratorOutputs(result1, result2); + } + + [Fact] + public void DoesNotRegenerateCodeWhenNoChanges() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (string s) => s.Length); + """; + + var results = RunGeneratorOnMultipleSourcesAndReturnSteps( + new Dictionary { { nameof(source), source } }, + new Dictionary { { nameof(source), source } }); + + var outputs = results[nameof(source)].SelectMany(step => step.Outputs); + Assert.All(outputs, output => Assert.True(output.Reason == IncrementalStepRunReason.Unchanged || output.Reason == IncrementalStepRunReason.Cached)); + } + + [Fact] + public void DoesRegenerateCodeWhenSourceChanged() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (string s) => s.Length); + """; + + var newSource = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (string s) => s); + """; + + var results = RunGeneratorOnMultipleSourcesAndReturnSteps( + new Dictionary { { nameof(source), source } }, + new Dictionary { { nameof(source), newSource } }); + + AssertStepRunReasonEquals(IncrementalStepRunReason.Modified, results[nameof(source)], TrackingNames.BindingsWithDiagnostics); + AssertStepRunReasonEquals(IncrementalStepRunReason.Modified, results[nameof(source)], TrackingNames.Bindings); + AssertStepRunReasonEquals(IncrementalStepRunReason.Unchanged, results[nameof(source)], "SourceOutput"); + AssertStepRunReasonEquals(IncrementalStepRunReason.Modified, results[nameof(source)], "ImplementationSourceOutput"); + } + + [Fact] + public void DoesRegenerateCodeWhenNewCodeInsertedAbove() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (string s) => s.Length); + """; + + var newSource = """ + using Microsoft.Maui.Controls; + var label = new Label(); + var x = 42; + label.SetBinding(Label.RotationProperty, static (string s) => s.Length); + """; + + var results = RunGeneratorOnMultipleSourcesAndReturnSteps( + new Dictionary { { nameof(source), source } }, + new Dictionary { { nameof(source), newSource } }); + + AssertStepRunReasonEquals(IncrementalStepRunReason.Modified, results[nameof(source)], TrackingNames.BindingsWithDiagnostics); + AssertStepRunReasonEquals(IncrementalStepRunReason.Modified, results[nameof(source)], TrackingNames.Bindings); + AssertStepRunReasonEquals(IncrementalStepRunReason.Unchanged, results[nameof(source)], "SourceOutput"); + AssertStepRunReasonEquals(IncrementalStepRunReason.Modified, results[nameof(source)], "ImplementationSourceOutput"); + } + + private static void AssertStepRunReasonEquals(IncrementalStepRunReason expectedReason, IncrementalGeneratorRunStep[] steps, string stepName) + { + Assert.Equal(expectedReason, steps.Single(r => r.Name == stepName).Outputs.Single().Reason); + } + + [Fact] + public void DoesNotRegenerateCodeWhenNewCodeInsertedBelow() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (string s) => s.Length); + """; + + var newSource = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (string s) => s.Length); + + var x = 42; + """; + + var results = RunGeneratorOnMultipleSourcesAndReturnSteps( + new Dictionary { { nameof(source), source } }, + new Dictionary { { nameof(source), newSource } }); + + var outputs = results[nameof(source)].SelectMany(step => step.Outputs); + Assert.All(outputs, output => Assert.True(output.Reason == IncrementalStepRunReason.Unchanged || output.Reason == IncrementalStepRunReason.Cached)); + } + + [Fact] + public void DoesNotRegerateCodeWhenDifferentFileEdited() + { + var fileASource = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (Label l) => l.Text.Length); + """; + + var fileBSource = """ + using Microsoft.Maui.Controls; + var button = new Button(); + button.SetBinding(Button.RotationProperty, static (Button b) => b.Text.Length); + """; + + var fileBModified = """ + using Microsoft.Maui.Controls; + var button = new Button(); + button.SetBinding(Button.RotationProperty, static (Button b) => b.Text); + """; + + var results = RunGeneratorOnMultipleSourcesAndReturnSteps( + new Dictionary { { nameof(fileASource), fileASource }, { nameof(fileBSource), fileBSource } }, + new Dictionary { { nameof(fileASource), fileASource }, { nameof(fileBSource), fileBModified } }); + + AssertStepRunReasonEquals(IncrementalStepRunReason.Unchanged, results[nameof(fileASource)], TrackingNames.BindingsWithDiagnostics); + AssertStepRunReasonEquals(IncrementalStepRunReason.Cached, results[nameof(fileASource)], TrackingNames.Bindings); + AssertStepRunReasonEquals(IncrementalStepRunReason.Cached, results[nameof(fileASource)], "SourceOutput"); + AssertStepRunReasonEquals(IncrementalStepRunReason.Cached, results[nameof(fileASource)], "ImplementationSourceOutput"); + + AssertStepRunReasonEquals(IncrementalStepRunReason.Modified, results[nameof(fileBSource)], TrackingNames.BindingsWithDiagnostics); + AssertStepRunReasonEquals(IncrementalStepRunReason.Modified, results[nameof(fileBSource)], TrackingNames.Bindings); + AssertStepRunReasonEquals(IncrementalStepRunReason.Unchanged, results[nameof(fileBSource)], "SourceOutput"); + AssertStepRunReasonEquals(IncrementalStepRunReason.Modified, results[nameof(fileBSource)], "ImplementationSourceOutput"); + } + + private static Dictionary RunGeneratorOnMultipleSourcesAndReturnSteps( + Dictionary initialSources, + Dictionary modifiedSources) + { + var inputCompilation = SourceGenHelpers.CreateCompilation(initialSources); + var cloneCompilation = inputCompilation.Clone(); + var driver = SourceGenHelpers.CreateDriver([new BindingSourceGenerator().AsSourceGenerator()]); + + var driverWithCachedInfo = driver.RunGenerators(inputCompilation); + + var initialResult = driverWithCachedInfo.GetRunResult().Results.Single(); + var initialSteps = initialResult.TrackedSteps; + + var initialReasons = initialSteps.SelectMany(step => step.Value) + .SelectMany(runStep => runStep.Outputs) + .Select(output => output.Reason); + + var newCompilation = SourceGenHelpers.CreateCompilation(modifiedSources); + var newResult = driverWithCachedInfo.RunGenerators(newCompilation).GetRunResult().Results.Single(); + var newSteps = newResult.TrackedSteps; + + // Single step runs, e.g. SourceOutput-fileA, SourceOuput-fileB + var runs = newSteps.SelectMany(step => step.Value); + + // Pairs . Note that a single run can be associated with multiple bindings. + // In such cases generate pair for each binding. + var bindingRunPairs = runs + .Select(run => (GetBindingInvocationDescription(run), run)) + .SelectMany(bindingsRunPair => bindingsRunPair.Item1.Select(binding => (binding, bindingsRunPair.run))); + + + // Sometimes the binding has more than one run of the same step associated with it. + // In such cases keep the one with Modified reason for safety. + return bindingRunPairs + .GroupBy(bindingRunPair => bindingRunPair.binding.Location.FilePath) + .ToDictionary( + x => x.Key, + x => x + .GroupBy(y => y.run.Name) + .Select(g => g + .FirstOrDefault(y => y.run.Outputs[0].Reason == IncrementalStepRunReason.Modified).run ?? g.First().run) + .ToArray()); + } + + private static BindingInvocationDescription[] GetBindingInvocationDescription(IncrementalGeneratorRunStep step) + { + var bindingCandidate = step switch + { + { Name: TrackingNames.BindingsWithDiagnostics } => step.Outputs[0].Value, + { Name: TrackingNames.Bindings } => step.Outputs[0].Value, + { Name: "SourceOutput" } => step.Inputs[0].Source.Outputs[0].Value, + { Name: "ImplementationSourceOutput" } => step.Inputs[0].Source.Outputs[0].Value, + _ => null + }; + + return bindingCandidate switch + { + BindingInvocationDescription => [(BindingInvocationDescription)bindingCandidate], + Result => [((Result)bindingCandidate).Value], + ImmutableArray => ((ImmutableArray)bindingCandidate).ToArray(), + _ => [] + }; + } + + private static void CompareGeneratorOutputs(GeneratorRunResult result1, GeneratorRunResult result2) + { + var stepComparisons = from stepA in result1.TrackedSteps + join stepB in result2.TrackedSteps on stepA.Key equals stepB.Key + where SourceGenHelpers.StepsForComparison.Contains(stepA.Key) + select new { StepA = stepA, StepB = stepB }; + + foreach (var comparison in stepComparisons) + { + var outputsA = comparison.StepA.Value.SelectMany(run => run.Outputs); + var outputsB = comparison.StepB.Value.SelectMany(run => run.Outputs); + + foreach (var (outputA, outputB) in outputsA.Zip(outputsB)) + { + Assert.Equal(outputA.Reason, outputB.Reason); + Assert.Equal(outputA.Value, outputB.Value); + } + } + } +} diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/IntegrationTests.cs b/src/Controls/tests/BindingSourceGen.UnitTests/IntegrationTests.cs new file mode 100644 index 000000000000..e4a1b7944695 --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/IntegrationTests.cs @@ -0,0 +1,1943 @@ +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + +namespace BindingSourceGen.UnitTests; +public class IntegrationTests +{ + [Fact] + public void GenerateSimpleBinding() + { + var source = """ + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (string s) => s.Length); + """; + + var result = SourceGenHelpers.Run(source); + Assert.NotNull(result.Binding); + + var id = Math.Abs(result.Binding.Location.GetHashCode()); + + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 3, 7)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + throw new InvalidOperationException("Cannot set value on the source object."); + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "Length"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-3-7.g.cs"]); + } + + [Fact] + public void GenerateSimpleBindingCreate() + { + var source = """ + using Microsoft.Maui.Controls; + var bindingBase = Binding.Create(static (string s) => s.Length); + """; + + var result = SourceGenHelpers.Run(source); + AssertExtensions.AssertNoDiagnostics(result); + Assert.NotNull(result.Binding); + + var id = Math.Abs(result.Binding.Location.GetHashCode()); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 2, 27)] + public static BindingBase Create{{id}}( + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode)) + { + throw new InvalidOperationException("Cannot set value on the source object."); + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "Length"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + return binding; + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-2-27.g.cs"]); + } + + [Fact] + public void IgnoresOtherOtherCreateMethod() + { + var source = """ + using System; + using Microsoft.Maui.Controls.Internals; + using MyNamespace; + var bindingBase = MyBinding.Create(static (string s) => s.Length); + + namespace MyNamespace + { + public static class MyBinding + { + public static TypedBinding Create(Func getter) + { + throw new NotImplementedException(); + } + } + } + """; + + var result = SourceGenHelpers.Run(source); + + AssertExtensions.AssertNoDiagnostics(result); + Assert.Null(result.Binding); + } + + [Fact] + public void IgnoresOtherBindingCreateMethod() + { + var source = """ + using System; + using MyNamespace; + var bindingBase = Binding.Create(static (string s) => s.Length); + + namespace MyNamespace + { + public class Binding + { + public static Microsoft.Maui.Controls.BindingBase Create( + Func getter, + Microsoft.Maui.Controls.BindingMode mode = Microsoft.Maui.Controls.BindingMode.Default, + Microsoft.Maui.Controls.IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + throw new InvalidOperationException($"Call to Create<{typeof(TSource)}, {typeof(TProperty)}>() was not intercepted."); + } + } + } + """; + + var result = SourceGenHelpers.Run(source); + + AssertExtensions.AssertNoDiagnostics(result); + Assert.Null(result.Binding); + } + + [Fact] + public void GenerateSimpleBindingWhenNullableDisabledNonNullableValueType() + { + var source = """ + #nullable disable + using Microsoft.Maui.Controls; + using MyNamespace; + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (A a) => a.B.C); + + namespace MyNamespace + { + public class A + { + public B B { get; set; } + } + + public class B + { + public int C { get; set; } + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 6, 7)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (source is {} p0 + && p0.B is {} p1) + { + p1.C = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "B"), + new(static source => source?.B, "C"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-6-7.g.cs"]); + } + + [Fact] + public void GenerateSimpleBindingWhenNullableDisabledNonNullableValueTypeWithIndexers() + { + var source = """ + #nullable disable + using Microsoft.Maui.Controls; + using System.Collections.Generic; + using MyNamespace; + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (A a) => a.B[0].C); + + namespace MyNamespace + { + public class A + { + public List B { get; set; } + } + + public class B + { + public int C { get; set; } + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 7, 7)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (source is {} p0 + && p0.B is {} p1 + && p1[0] is {} p2) + { + p2.C = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "B"), + new(static source => source?.B, "Item"), + new(static source => source?.B, "Item[0]"), + new(static source => source?.B?[0], "C"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-7-7.g.cs"]); + } + + public static IEnumerable GenerateSimpleBindingWhenNullableDisabledAndPropertyNullableData => + new List + { + new object[] + { + """ + // Nullable value type + #nullable disable + using Microsoft.Maui.Controls; + using MyNamespace; + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (A a) => a.B.C); + + namespace MyNamespace + { + public class A + { + public B B { get; set; } + } + + public class B + { + public C? C { get; set; } + } + + public struct C + { + + } + } + """ + }, + new object[] + { + """ + // Reference Type + #nullable disable + using Microsoft.Maui.Controls; + using MyNamespace; + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (A a) => a.B.C); + + namespace MyNamespace + { + public class A + { + public B B { get; set; } + } + + public class B + { + public C C { get; set; } + } + + public class C + { + + } + } + """ + }, + new object[] + { + """ + // Conditional access operator + #nullable disable + using Microsoft.Maui.Controls; + using MyNamespace; + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (A a) => a?.B.C); + + namespace MyNamespace + { + public class A + { + public B B { get; set; } + } + + public class B + { + public C C { get; set; } + } + + public class C + { + + } + } + """ + }, + new object[] + { + """ + // Nullable value type on path + #nullable disable + using Microsoft.Maui.Controls; + using MyNamespace; + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (A a) => a.B?.C); + + namespace MyNamespace + { + public class A + { + public B? B { get; set; } + } + + public struct B + { + public C C { get; set; } + } + + public class C + { + + } + } + """ + }, + }; + + [Theory] + [MemberData(nameof(GenerateSimpleBindingWhenNullableDisabledAndPropertyNullableData))] + public void GenerateSimpleBindingWhenNullableDisabledAndPropertyNullable(string source) + { + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 7, 7)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (source is {} p0 + && p0.B is {} p1) + { + p1.C = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "B"), + new(static source => source?.B, "C"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-7-7.g.cs"]); + } + + [Fact] + public void GenerateSimpleBindingWhenNullableDisabledAndNonNullableValueTypeInPath() + { + var source = """ + #nullable disable + using Microsoft.Maui.Controls; + using MyNamespace; + + + var label = new Label(); + label.SetBinding(Label.RotationProperty, static (A a) => a.B.C.D); + + namespace MyNamespace + { + public class A + { + public B B; + } + + public struct B + { + public C C; + + public B() + { + C = null!; + } + } + + public class C + { + public D D { get; set;} + } + + public class D { + + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 7, 7)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (source is {} p0 + && p0.B.C is {} p1) + { + p1.D = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "B"), + new(static source => source?.B, "C"), + new(static source => source?.B.C, "D"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-7-7.g.cs"]); + } + + [Theory] + [InlineData("static (MySourceClass s) => (((s.A as X)?.B as Y)?.C as Z)?.D")] + [InlineData("static (MySourceClass s) => ((Z?)((Y?)((X?)s.A)?.B)?.C)?.D")] + public void GenerateBindingWithNullableReferenceTypesCasts(string bindingLambda) + { + var source = $$""" + using Microsoft.Maui.Controls; + using MyNamespace; + var label = new Label(); + label.SetBinding(Label.TextProperty, {{bindingLambda}}); + + namespace MyNamespace + { + public class MySourceClass + { + public object? A { get; set; } + } + + public class X + { + public object? B { get; set; } + } + + public class Y + { + public object C { get; set; } = null!; + } + + public class Z + { + public MyPropertyClass D { get; set; } = null!; + } + + public class MyPropertyClass + { + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 4, 7)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (value is null) + { + return; + } + if (source.A is global::MyNamespace.X p0 + && p0.B is global::MyNamespace.Y p1 + && p1.C is global::MyNamespace.Z p2) + { + p2.D = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "A"), + new(static source => (source.A as global::MyNamespace.X), "B"), + new(static source => ((source.A as global::MyNamespace.X)?.B as global::MyNamespace.Y), "C"), + new(static source => (((source.A as global::MyNamespace.X)?.B as global::MyNamespace.Y)?.C as global::MyNamespace.Z), "D"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-4-7.g.cs"]); + } + + [Fact] + public void GenerateBindingWithNonNullableReferenceTypesCasts() + { + var source = $$""" + using Microsoft.Maui.Controls; + using MyNamespace; + var label = new Label(); + label.SetBinding(Label.TextProperty, static (MySourceClass s) => ((Z)((Y)((X)s.A).B).C).D); + + namespace MyNamespace + { + public class MySourceClass + { + public object A { get; set; } = null!; + } + + public class X + { + public object B { get; set; } = null!; + } + + public class Y + { + public object C { get; set; } = null!; + } + + public class Z + { + public MyPropertyClass D { get; set; } = null!; + } + + public class MyPropertyClass + { + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 4, 7)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (source.A is global::MyNamespace.X p0 + && p0.B is global::MyNamespace.Y p1 + && p1.C is global::MyNamespace.Z p2) + { + p2.D = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "A"), + new(static source => (source.A as global::MyNamespace.X), "B"), + new(static source => ((source.A as global::MyNamespace.X)?.B as global::MyNamespace.Y), "C"), + new(static source => (((source.A as global::MyNamespace.X)?.B as global::MyNamespace.Y)?.C as global::MyNamespace.Z), "D"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-4-7.g.cs"]); + } + + [Fact] + public void GenerateBindingWithForcedConditionalAccessAfterCast() + { + var source = $$""" + using Microsoft.Maui.Controls; + var label = new Label(); + label.SetBinding(Label.TextProperty, static (MyNamespace.A n) => ((MyNamespace.Wrapper)n.X).Wrapped.Y.Value.Length); + + namespace MyNamespace + { + public struct A + { + public object X; + public B Y; + } + + public struct B + { + public string Value; + } + + public class Wrapper + { + public A Wrapped; + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 3, 7)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + throw new InvalidOperationException("Cannot set value on the source object."); + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "X"), + new(static source => (source.X as global::MyNamespace.Wrapper), "Wrapped"), + new(static source => (source.X as global::MyNamespace.Wrapper)?.Wrapped, "Y"), + new(static source => (source.X as global::MyNamespace.Wrapper)?.Wrapped.Y, "Value"), + new(static source => (source.X as global::MyNamespace.Wrapper)?.Wrapped.Y.Value, "Length"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-3-7.g.cs"]); + } + + [Fact] + public void GenerateBindingWithIndexers() + { + var source = """ + using Microsoft.Maui.Controls; + using System.Runtime.CompilerServices; + using MyNamespace; + + var label = new Label(); + label.SetBinding(Label.TextProperty, static (MySourceClass s) => (s[12]?["Abc"][0])); + + namespace MyNamespace + { + public class MySourceClass + { + public B this[int index] => new B(); + } + + public class B + { + [IndexerName("Indexer")] + public MyPropertyClass[] this[string index] => []; + } + + public class MyPropertyClass + { + + } + + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 6, 7)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + if (value is null) + { + return; + } + + if (source[12] is {} p0) + { + p0["Abc"][0] = value; + } + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "Item"), + new(static source => source, "Item[12]"), + new(static source => source[12], "Indexer"), + new(static source => source[12], "Indexer[Abc]"), + new(static source => source[12]?["Abc"], "Item"), + new(static source => source[12]?["Abc"], "Item[0]"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-6-7.g.cs"]); + } + + [Fact] + public void GenerateBindingReferencingPrivateField() + { + var source = """ + + using Microsoft.Maui.Controls; + using MyNamespace; + + var mySourceClass = new MySourceClass(); + mySourceClass.SetBinding(); + + namespace MyNamespace + { + public class MySourceClass + { + private Button _button = new Button(); + + public void SetBinding() + { + var entry = new Entry(); + entry.SetBinding(Entry.TextProperty, static (MySourceClass sc) => sc._button.Text); + } + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 17, 23)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + GetUnsafeField{{id}}_button(source).Text = value; + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "_button"), + new(static source => GetUnsafeField{{id}}_button(source), "Text"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + + [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_button")] + private static extern ref global::Microsoft.Maui.Controls.Button GetUnsafeField{{id}}_button(global::MyNamespace.MySourceClass source); + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-17-23.g.cs"]); + } + + [Fact] + public void GenerateBindingReferencingPrivateProperty() + { + var source = """ + + using Microsoft.Maui.Controls; + using MyNamespace; + + var mySourceClass = new MySourceClass(); + mySourceClass.SetBinding(); + + namespace MyNamespace + { + public class MySourceClass + { + private Button Button {get; set;} = new Button(); + + public void SetBinding() + { + var entry = new Entry(); + entry.SetBinding(Entry.TextProperty, static (MySourceClass sc) => sc.Button.Text); + } + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 17, 23)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + GetUnsafeProperty{{id}}Button(source).Text = value; + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "Button"), + new(static source => GetUnsafeProperty{{id}}Button(source), "Text"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_Button")] + private static extern global::Microsoft.Maui.Controls.Button GetUnsafeProperty{{id}}Button(global::MyNamespace.MySourceClass source); + + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "set_Button")] + private static extern void SetUnsafeProperty{{id}}Button(global::MyNamespace.MySourceClass source, global::Microsoft.Maui.Controls.Button value); + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-17-23.g.cs"]); + } + + [Fact] + public void GenerateBindingWithPrivatePropertySetter() + { + var source = """ + + using Microsoft.Maui.Controls; + using MyNamespace; + + var mySourceClass = new MySourceClass(); + mySourceClass.SetBinding(); + + namespace MyNamespace + { + public class MySourceClass + { + private string Text {get; set;} = "Hello"; + + public void SetBinding() + { + var entry = new Entry(); + entry.SetBinding(Entry.TextProperty, static (MySourceClass sc) => sc.Text); + } + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 17, 23)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + setter = static (source, value) => + { + SetUnsafeProperty{{id}}Text(source, value); + }; + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "Text"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_Text")] + private static extern string GetUnsafeProperty{{id}}Text(global::MyNamespace.MySourceClass source); + + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "set_Text")] + private static extern void SetUnsafeProperty{{id}}Text(global::MyNamespace.MySourceClass source, string value); + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-17-23.g.cs"]); + } + + [Fact] + public void GenerateBindingWithPrivateReadonlyProperty() + { + var source = """ + + using Microsoft.Maui.Controls; + using MyNamespace; + + var mySourceClass = new MySourceClass(); + mySourceClass.SetBinding(); + + namespace MyNamespace + { + public class MySourceClass + { + private string Text {get;} = "Hello"; + + public void SetBinding() + { + var entry = new Entry(); + entry.SetBinding(Entry.TextProperty, static (MySourceClass sc) => sc.Text); + } + } + } + """; + + var result = SourceGenHelpers.Run(source); + var id = Math.Abs(result.Binding!.Location.GetHashCode()); + AssertExtensions.AssertNoDiagnostics(result); + AssertExtensions.CodeIsEqual( + $$""" + //------------------------------------------------------------------------------ + // + // This code was generated by a .NET MAUI source generator. + // + // Changes to this file may cause incorrect behavior and will be lost if + // the code is regenerated. + // + //------------------------------------------------------------------------------ + #nullable enable + + namespace System.Runtime.CompilerServices + { + using System; + using System.CodeDom.Compiler; + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : Attribute + { + public InterceptsLocationAttribute(string filePath, int line, int column) + { + FilePath = filePath; + Line = line; + Column = column; + } + + public string FilePath { get; } + public int Line { get; } + public int Column { get; } + } + } + + namespace Microsoft.Maui.Controls.Generated + { + using System; + using System.CodeDom.Compiler; + using System.Runtime.CompilerServices; + using Microsoft.Maui.Controls.Internals; + + internal static partial class GeneratedBindingInterceptors + { + + {{BindingCodeWriter.GeneratedCodeAttribute}} + [InterceptsLocationAttribute(@"Path\To\Program.cs", 17, 23)] + public static void SetBinding{{id}}( + this BindableObject bindableObject, + BindableProperty bindableProperty, + Func getter, + BindingMode mode = BindingMode.Default, + IValueConverter? converter = null, + object? converterParameter = null, + string? stringFormat = null, + object? source = null, + object? fallbackValue = null, + object? targetNullValue = null) + { + Action? setter = null; + if (ShouldUseSetter(mode, bindableProperty)) + { + throw new InvalidOperationException("Cannot set value on the source object."); + } + + var binding = new TypedBinding( + getter: source => (getter(source), true), + setter, + handlers: new Tuple, string>[] + { + new(static source => source, "Text"), + }) + { + Mode = mode, + Converter = converter, + ConverterParameter = converterParameter, + StringFormat = stringFormat, + Source = source, + FallbackValue = fallbackValue, + TargetNullValue = targetNullValue + }; + + bindableObject.SetBinding(bindableProperty, binding); + } + + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_Text")] + private static extern string GetUnsafeProperty{{id}}Text(global::MyNamespace.MySourceClass source); + } + } + """, + result.GeneratedFiles["Path-To-Program.cs-GeneratedBindingInterceptors-17-23.g.cs"]); + } +} diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/SetterBuilderTests.cs b/src/Controls/tests/BindingSourceGen.UnitTests/SetterBuilderTests.cs new file mode 100644 index 000000000000..01762d9fbf27 --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/SetterBuilderTests.cs @@ -0,0 +1,145 @@ +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + +namespace BindingSourceGen.UnitTests; + +public class SetterBuilderTests +{ + [Fact] + public void GeneratesSetterWithoutAnyPatternMatchingForEmptyPath() + { + var setter = Setter.From([], bindingId: 0); + + Assert.Empty(setter.PatternMatchingExpressions); + Assert.Equal("source = value;", setter.AssignmentStatement); + } + + [Fact] + public void GeneratesSetterWithSourceNotNullPatternMatchingForSinglePathStepWhenSourceTypeIsNullableAndConditionalAccess() + { + var setter = Setter.From([new ConditionalAccess(new MemberAccess("A"))], bindingId: 0); + + Assert.Single(setter.PatternMatchingExpressions); + Assert.Equal("source is {} p0", setter.PatternMatchingExpressions[0]); + Assert.Equal("p0.A = value;", setter.AssignmentStatement); + } + + [Fact] + public void GeneratesSetterWithoutAnyPatternMatchingForSignlePathStepWhenSourceTypeIsNotNullable() + { + var setter = Setter.From([new MemberAccess("A")], bindingId: 0); + + Assert.Empty(setter.PatternMatchingExpressions); + Assert.Equal("source.A = value;", setter.AssignmentStatement); + } + + [Fact] + public void GeneratesSetterWithCorrectConditionalAccess() + { + var setter = Setter.From( + [ + new MemberAccess("A"), + new ConditionalAccess(new MemberAccess("B")), + new ConditionalAccess(new MemberAccess("C")), + ], bindingId: 0); + + Assert.Equal(2, setter.PatternMatchingExpressions.Length); + Assert.Equal("source.A is {} p0", setter.PatternMatchingExpressions[0]); + Assert.Equal("p0.B is {} p1", setter.PatternMatchingExpressions[1]); + Assert.Equal("p1.C = value;", setter.AssignmentStatement); + } + + [Fact] + public void GeneratesSetterWithPatternMatchingWithValueTypeCast1() + { + var setter = Setter.From( + [ + new MemberAccess("A"), + new Cast(new TypeDescription("X", IsValueType: false)), + new ConditionalAccess(new MemberAccess("B")), + new Cast(new TypeDescription("Y", IsValueType: true)), + new ConditionalAccess(new MemberAccess("C")), + new MemberAccess("D"), + ], bindingId: 0); + + Assert.Equal(2, setter.PatternMatchingExpressions.Length); + Assert.Equal("source.A is X p0", setter.PatternMatchingExpressions[0]); + Assert.Equal("p0.B is Y p1", setter.PatternMatchingExpressions[1]); + Assert.Equal("p1.C.D = value;", setter.AssignmentStatement); + } + + [Fact] + public void GeneratesSetterWithPatternMatchingWithValueTypeCast2() + { + var setter = Setter.From( + [ + new MemberAccess("A"), + new Cast(new TypeDescription("X", IsValueType: false)), + new ConditionalAccess(new MemberAccess("B")), + new Cast(new TypeDescription("Y", IsValueType: true)), + new ConditionalAccess(new MemberAccess("C")), + new ConditionalAccess(new MemberAccess("D")), + ], bindingId: 0); + + Assert.Equal(3, setter.PatternMatchingExpressions.Length); + Assert.Equal("source.A is X p0", setter.PatternMatchingExpressions[0]); + Assert.Equal("p0.B is Y p1", setter.PatternMatchingExpressions[1]); + Assert.Equal("p1.C is {} p2", setter.PatternMatchingExpressions[2]); + Assert.Equal("p2.D = value;", setter.AssignmentStatement); + } + + [Fact] + public void GeneratesSetterWithPatternMatchingWithCastsAndConditionalAccess() + { + var setter = Setter.From( + [ + new MemberAccess("A"), + new Cast(TargetType: new TypeDescription("X", IsValueType: false, IsNullable: false)), + new ConditionalAccess(new MemberAccess("B")), + new Cast(new TypeDescription("Y", IsValueType: false, IsNullable: false)), + new ConditionalAccess(new MemberAccess("C")), + new Cast(new TypeDescription("Z", IsValueType: true, IsNullable: true)), + new ConditionalAccess(new MemberAccess("D")), + ], bindingId: 0); + + Assert.Equal(3, setter.PatternMatchingExpressions.Length); + Assert.Equal("source.A is X p0", setter.PatternMatchingExpressions[0]); + Assert.Equal("p0.B is Y p1", setter.PatternMatchingExpressions[1]); + Assert.Equal("p1.C is Z p2", setter.PatternMatchingExpressions[2]); + Assert.Equal("p2.D = value;", setter.AssignmentStatement); + } + + [Fact] + public void GeneratesSetterWithInaccessibleFieldMemberAccess() + { + var setter = Setter.From( + [ + new InaccessibleMemberAccess(new TypeDescription("X"), new TypeDescription("Z"), AccessorKind.Field, "Y") + ], bindingId: 0); + Assert.Empty(setter.PatternMatchingExpressions); + Assert.Equal("GetUnsafeField0Y(source) = value;", setter.AssignmentStatement); + } + + [Fact] + public void GeneratesSetterThatSetsInaccessibleProperty() + { + var setter = Setter.From( + [ + new InaccessibleMemberAccess(new TypeDescription("X"), new TypeDescription("Z"), AccessorKind.Property, "Y") + ], bindingId: 0); + Assert.Empty(setter.PatternMatchingExpressions); + Assert.Equal("SetUnsafeProperty0Y(source, value);", setter.AssignmentStatement); + } + + [Fact] + public void GeneratesSetterWithInaccessiblePropertyMemberAccessInPath() + { + var setter = Setter.From( + [ + new InaccessibleMemberAccess(new TypeDescription("X"), new TypeDescription("Z"), AccessorKind.Property, "Y"), + new MemberAccess("A"), + ], bindingId: 0); + Assert.Empty(setter.PatternMatchingExpressions); + Assert.Equal("GetUnsafeProperty0Y(source).A = value;", setter.AssignmentStatement); + } +} diff --git a/src/Controls/tests/BindingSourceGen.UnitTests/SourceGenHelpers.cs b/src/Controls/tests/BindingSourceGen.UnitTests/SourceGenHelpers.cs new file mode 100644 index 000000000000..9e714287fd26 --- /dev/null +++ b/src/Controls/tests/BindingSourceGen.UnitTests/SourceGenHelpers.cs @@ -0,0 +1,84 @@ +using System.Collections.Immutable; +using System.Reflection; +using System.Runtime.Loader; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.Maui.Controls.BindingSourceGen; +using Xunit; + + +internal record CodeGeneratorResult( + Dictionary GeneratedFiles, + ImmutableArray SourceCompilationDiagnostics, + ImmutableArray SourceGeneratorDiagnostics, + ImmutableArray GeneratedCodeCompilationDiagnostics, + BindingInvocationDescription? Binding); + +internal static class SourceGenHelpers +{ + private static readonly CSharpParseOptions ParseOptions = new CSharpParseOptions(LanguageVersion.Preview).WithFeatures( + [new KeyValuePair("InterceptorsPreviewNamespaces", "Microsoft.Maui.Controls.Generated")]); + + internal static List StepsForComparison = [TrackingNames.Bindings, TrackingNames.BindingsWithDiagnostics]; + + internal static CSharpGeneratorDriver CreateDriver(IEnumerable generators) + { + return CSharpGeneratorDriver.Create( + generators: generators, + driverOptions: new GeneratorDriverOptions(disabledOutputs: IncrementalGeneratorOutputKind.None, trackIncrementalGeneratorSteps: true), + parseOptions: ParseOptions); + } + + internal static CodeGeneratorResult Run(string source) + { + return Run(source, new[] { new BindingSourceGenerator() }); + } + + internal static CodeGeneratorResult Run(string source, IEnumerable generators) + { + // Function assumes the first generator in a list is BindingSourceGenerator + Assert.NotEmpty(generators); + Assert.IsType(generators.First()); + + var inputCompilation = CreateCompilation(source); + var driver = CreateDriver(generators.Select(g => g.AsSourceGenerator())); + + var result = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out Compilation compilation, out _).GetRunResult().Results.FirstOrDefault(); + var generatedCode = result.GeneratedSources.FirstOrDefault().SourceText.ToString(); + + var trackedSteps = result.TrackedSteps; + var resultBinding = trackedSteps.TryGetValue("Bindings", out ImmutableArray value) + ? (BindingInvocationDescription)value[0].Outputs[0].Value + : null; + + return new CodeGeneratorResult( + GeneratedFiles: result.GeneratedSources.ToDictionary(source => source.HintName, source => source.SourceText.ToString()), + SourceCompilationDiagnostics: inputCompilation.GetDiagnostics(), + SourceGeneratorDiagnostics: result.Diagnostics, + GeneratedCodeCompilationDiagnostics: compilation.GetDiagnostics(), + Binding: resultBinding); + } + + private static Compilation CreateCompilationFromSyntaxTrees(List syntaxTrees) + => CSharpCompilation.Create("compilation", + syntaxTrees, + [ + MetadataReference.CreateFromFile(typeof(Microsoft.Maui.Controls.BindableObject).GetTypeInfo().Assembly.Location), + MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), + MetadataReference.CreateFromFile(AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("System.Runtime")).Location), + ], + new CSharpCompilationOptions(OutputKind.ConsoleApplication) + .WithNullableContextOptions(NullableContextOptions.Enable)); + + + internal static Compilation CreateCompilation(string source) + { + return CreateCompilationFromSyntaxTrees([CSharpSyntaxTree.ParseText(source, ParseOptions, path: @"Path\To\Program.cs")]); + } + + internal static Compilation CreateCompilation(Dictionary sources) + { + var syntaxTrees = sources.Select(s => CSharpSyntaxTree.ParseText(s.Value, ParseOptions, path: s.Key)).ToList(); + return CreateCompilationFromSyntaxTrees(syntaxTrees); + } +} diff --git a/src/Controls/tests/Core.UnitTests/AbsoluteLayoutTests.cs b/src/Controls/tests/Core.UnitTests/AbsoluteLayoutTests.cs index 669b24d58edf..1774bbb45142 100644 --- a/src/Controls/tests/Core.UnitTests/AbsoluteLayoutTests.cs +++ b/src/Controls/tests/Core.UnitTests/AbsoluteLayoutTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using Microsoft.Maui.Controls.Compatibility; using Microsoft.Maui.Devices; using Microsoft.Maui.Graphics; using Xunit; @@ -25,7 +24,7 @@ public void Constructor() Assert.Empty(abs.Children); - var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity); + var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None); Assert.Equal(Size.Zero, sizeReq.Request); Assert.Equal(Size.Zero, sizeReq.Minimum); } @@ -38,7 +37,7 @@ public void AbsolutePositionAndSizeUsingRectangle() IsPlatformEnabled = true }; - var child = new View { IsPlatformEnabled = true }; + var child = MockPlatformSizeService.Sub(); abs.Children.Add(child, new Rect(10, 20, 30, 40)); @@ -56,8 +55,7 @@ public void AbsolutePositionRelativeSize() IsPlatformEnabled = true }; - var child = new View { IsPlatformEnabled = true }; - + var child = MockPlatformSizeService.Sub(); abs.Children.Add(child, new Rect(10, 20, 0.4, 0.5), AbsoluteLayoutFlags.SizeProportional); @@ -81,7 +79,7 @@ public void RelativePositionAbsoluteSize(double width, double height, double rel IsPlatformEnabled = true }; - var child = new View { IsPlatformEnabled = true }; + var child = MockPlatformSizeService.Sub(); abs.Children.Add(child, new Rect(relX, relY, width, height), AbsoluteLayoutFlags.PositionProportional); @@ -109,10 +107,7 @@ public void RelativePositionRelativeSize(double relX, double relY, double relHei IsPlatformEnabled = true }; - var child = new View - { - IsPlatformEnabled = true - }; + var child = MockPlatformSizeService.Sub(); abs.Children.Add(child, new Rect(relX, relY, relWidth, relHeight), AbsoluteLayoutFlags.All); abs.Layout(new Rect(0, 0, 100, 100)); @@ -135,12 +130,12 @@ public void SizeRequestWithNormalChild() IsPlatformEnabled = true }; - var child = new View(); + var child = MockPlatformSizeService.Sub(); // ChildSizeReq == 100x20 abs.Children.Add(child, new Rect(10, 20, 30, 40)); - var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity); + var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None); Assert.Equal(new Size(40, 60), sizeReq.Request); Assert.Equal(new Size(40, 60), sizeReq.Minimum); @@ -154,12 +149,12 @@ public void SizeRequestWithRelativePositionChild() IsPlatformEnabled = true }; - var child = new View(); + var child = MockPlatformSizeService.Sub(); // ChildSizeReq == 100x20 abs.Children.Add(child, new Rect(0.5, 0.5, 30, 40), AbsoluteLayoutFlags.PositionProportional); - var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity); + var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None); Assert.Equal(new Size(30, 40), sizeReq.Request); Assert.Equal(new Size(30, 40), sizeReq.Minimum); @@ -173,15 +168,12 @@ public void SizeRequestWithRelativeChild() IsPlatformEnabled = true }; - var child = new View - { - IsPlatformEnabled = true - }; + var child = MockPlatformSizeService.Sub(); // ChildSizeReq == 100x20 abs.Children.Add(child, new Rect(0.5, 0.5, 0.5, 0.5), AbsoluteLayoutFlags.All); - var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity); + var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None); Assert.Equal(new Size(200, 40), sizeReq.Request); Assert.Equal(new Size(0, 0), sizeReq.Minimum); @@ -195,15 +187,12 @@ public void SizeRequestWithRelativeSizeChild() IsPlatformEnabled = true }; - var child = new View - { - IsPlatformEnabled = true - }; + var child = MockPlatformSizeService.Sub(); // ChildSizeReq == 100x20 abs.Children.Add(child, new Rect(10, 20, 0.5, 0.5), AbsoluteLayoutFlags.SizeProportional); - var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity); + var sizeReq = abs.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None); Assert.Equal(new Size(210, 60), sizeReq.Request); Assert.Equal(new Size(10, 20), sizeReq.Minimum); @@ -217,10 +206,7 @@ public void MeasureInvalidatedFiresWhenFlagsChanged() IsPlatformEnabled = true }; - var child = new View - { - IsPlatformEnabled = true - }; + var child = MockPlatformSizeService.Sub(); abs.Children.Add(child, new Rect(1, 1, 100, 100)); @@ -240,10 +226,7 @@ public void MeasureInvalidatedFiresWhenBoundsChanged() IsPlatformEnabled = true }; - var child = new View - { - IsPlatformEnabled = true - }; + var child = MockPlatformSizeService.Sub(); abs.Children.Add(child, new Rect(1, 1, 100, 100)); diff --git a/src/Controls/tests/Core.UnitTests/BaseTestFixture.cs b/src/Controls/tests/Core.UnitTests/BaseTestFixture.cs index 95367db7a3f3..6df23fa7410e 100644 --- a/src/Controls/tests/Core.UnitTests/BaseTestFixture.cs +++ b/src/Controls/tests/Core.UnitTests/BaseTestFixture.cs @@ -29,7 +29,6 @@ public BaseTestFixture() Microsoft.Maui.Controls.Hosting.CompatibilityCheck.UseCompatibility(); _defaultCulture = System.Threading.Thread.CurrentThread.CurrentCulture; _defaultUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; - MockPlatformSizeService.Current?.Reset(); DispatcherProvider.SetCurrent(new DispatcherProviderStub()); DeviceDisplay.SetCurrent(null); DeviceInfo.SetCurrent(null); @@ -53,7 +52,6 @@ protected virtual void Dispose(bool disposing) if (disposing) { - MockPlatformSizeService.Current?.Reset(); AppInfo.SetCurrent(null); DeviceDisplay.SetCurrent(null); DeviceInfo.SetCurrent(null); diff --git a/src/Controls/tests/Core.UnitTests/BindableObjectUnitTests.cs b/src/Controls/tests/Core.UnitTests/BindableObjectUnitTests.cs index 56b26cc65e73..f1f9316cf5e7 100644 --- a/src/Controls/tests/Core.UnitTests/BindableObjectUnitTests.cs +++ b/src/Controls/tests/Core.UnitTests/BindableObjectUnitTests.cs @@ -1407,6 +1407,7 @@ public void SetValueCoreImplicitelyCastBasicType() Assert.NotEqual(-42, bindable.GetValue(prop)); } + [TypeConverter(typeof(CastFromStringTypeConverter))] class CastFromString { public string Result { get; private set; } @@ -1416,6 +1417,22 @@ public static implicit operator CastFromString(string source) o.Result = source; return o; } + + private sealed class CastFromStringTypeConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + => sourceType == typeof(string); + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + => value switch + { + string s => (CastFromString)s, + _ => throw new NotSupportedException(), + }; + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => false; + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) => throw new NotSupportedException(); + } } [Fact] @@ -1430,6 +1447,7 @@ public void SetValueCoreInvokesOpImplicitOnPropertyType() Assert.Equal("foo", ((CastFromString)bindable.GetValue(prop)).Result); } + [TypeConverter(typeof(CastToStringTypeConverter))] class CastToString { string Result { get; set; } @@ -1448,6 +1466,21 @@ public override string ToString() { throw new InvalidOperationException(); } + + private sealed class CastToStringTypeConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) => false; + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) => throw new NotSupportedException(); + + public override bool CanConvertTo(ITypeDescriptorContext context, Type sourceType) + => sourceType == typeof(CastToString); + public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + => value switch + { + CastToString cts when destinationType == typeof(string) => (string)cts, + _ => throw new NotSupportedException(), + }; + } } [Fact] diff --git a/src/Controls/tests/Core.UnitTests/BindingExpressionTests.cs b/src/Controls/tests/Core.UnitTests/BindingExpressionTests.cs index e0d74726dd50..46eca59fbc36 100644 --- a/src/Controls/tests/Core.UnitTests/BindingExpressionTests.cs +++ b/src/Controls/tests/Core.UnitTests/BindingExpressionTests.cs @@ -139,7 +139,7 @@ public static IEnumerable TryConvertWithNumbersAndCulturesCasesData() public void TryConvertWithNumbersAndCultures(object inputString, CultureInfo culture, object expected) { CultureInfo.CurrentCulture = culture; - BindingExpression.TryConvert(ref inputString, Entry.TextProperty, expected.GetType(), false); + BindingExpressionHelper.TryConvert(ref inputString, Entry.TextProperty, expected.GetType(), false); Assert.Equal(expected, inputString); } diff --git a/src/Controls/tests/Core.UnitTests/BindingUnitTests.cs b/src/Controls/tests/Core.UnitTests/BindingUnitTests.cs index 5cef25f7bd35..836d95986827 100644 --- a/src/Controls/tests/Core.UnitTests/BindingUnitTests.cs +++ b/src/Controls/tests/Core.UnitTests/BindingUnitTests.cs @@ -1533,7 +1533,7 @@ public void MultiplePropertyUpdates() } [Fact, Category("[Binding] Complex paths")] - [Description("When part of a complex path can not be evaluated during an update, bindables should return to their default value.")] + [Description("When part of a complex path cannot be evaluated during an update, bindables should return to their default value.")] public void NullInPathUsesDefaultValue() { var vm = new ComplexMockViewModel @@ -1555,7 +1555,7 @@ public void NullInPathUsesDefaultValue() } [Fact, Category("[Binding] Complex paths")] - [Description("When part of a complex path can not be evaluated during an update, bindables should return to their default value.")] + [Description("When part of a complex path cannot be evaluated during an update, bindables should return to their default value.")] public void NullContextUsesDefaultValue() { var vm = new ComplexMockViewModel diff --git a/src/Controls/tests/Core.UnitTests/BoxViewUnitTests.cs b/src/Controls/tests/Core.UnitTests/BoxViewUnitTests.cs index f4909044bdea..6ae8b71e5053 100644 --- a/src/Controls/tests/Core.UnitTests/BoxViewUnitTests.cs +++ b/src/Controls/tests/Core.UnitTests/BoxViewUnitTests.cs @@ -21,7 +21,7 @@ public void TestConstructor() }; Assert.Equal(new Color(0.2f, 0.3f, 0.4f), box.Color); - var request = box.Measure(double.PositiveInfinity, double.PositiveInfinity).Request; + var request = box.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None).Request; Assert.Equal(20, request.Width); Assert.Equal(30, request.Height); } @@ -34,7 +34,7 @@ public void DefaultSize() IsPlatformEnabled = true, }; - var request = box.Measure(double.PositiveInfinity, double.PositiveInfinity).Request; + var request = box.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None).Request; Assert.Equal(40, request.Width); Assert.Equal(40, request.Height); } diff --git a/src/Controls/tests/Core.UnitTests/ContentViewUnitTest.cs b/src/Controls/tests/Core.UnitTests/ContentViewUnitTest.cs index b2fe9e869cdc..1a79a5bfacc6 100644 --- a/src/Controls/tests/Core.UnitTests/ContentViewUnitTest.cs +++ b/src/Controls/tests/Core.UnitTests/ContentViewUnitTest.cs @@ -86,7 +86,7 @@ public void TestFrameLayout() IsPlatformEnabled = true, }; - Assert.Equal(new Size(120, 220), contentView.Measure(double.PositiveInfinity, double.PositiveInfinity).Request); + Assert.Equal(new Size(120, 220), contentView.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None).Request); contentView.Layout(new Rect(0, 0, 300, 300)); @@ -111,7 +111,7 @@ public void WidthRequest() WidthRequest = 20 }; - Assert.Equal(new Size(40, 220), contentView.Measure(double.PositiveInfinity, double.PositiveInfinity).Request); + Assert.Equal(new Size(40, 220), contentView.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None).Request); } [Fact] @@ -132,7 +132,7 @@ public void HeightRequest() HeightRequest = 20 }; - Assert.Equal(new Size(120, 40), contentView.Measure(double.PositiveInfinity, double.PositiveInfinity).Request); + Assert.Equal(new Size(120, 40), contentView.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.None).Request); } [Fact] diff --git a/src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj b/src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj index dd8a433035e1..8c41c5ab5e37 100644 --- a/src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj +++ b/src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj @@ -5,11 +5,6 @@ Microsoft.Maui.Controls.Core.UnitTests false 0114;0672;0108;0067;0168;0169;0219;0612;0618;1998 - - 9.0 Microsoft.Maui.Controls.Core.UnitTests @@ -30,6 +25,16 @@ + + $(InterceptorsPreviewNamespaces);Microsoft.Maui.Controls.Generated + + + + + diff --git a/src/Controls/tests/Core.UnitTests/ControlsMapperTests.cs b/src/Controls/tests/Core.UnitTests/ControlsMapperTests.cs index 5486be36b81e..7258d7df4a26 100644 --- a/src/Controls/tests/Core.UnitTests/ControlsMapperTests.cs +++ b/src/Controls/tests/Core.UnitTests/ControlsMapperTests.cs @@ -41,8 +41,8 @@ public void Append() bool appendCalled = false; bool originalMapperCalled = false; - ButtonWithControlsMapper. - ControlsButtonWithControlsMapper + ButtonWithControlsMapperHandler. + Mapper .AppendToMapping("MapperTest", (_, _) => { Assert.True(originalMapperCalled); @@ -68,8 +68,8 @@ public void Prepend() bool newMapperMethodCalled = false; bool originalMapperCalled = false; - ButtonWithControlsMapper. - ControlsButtonWithControlsMapper + ButtonWithControlsMapperHandler. + Mapper .PrependToMapping("MapperTest", (_, _) => { Assert.False(originalMapperCalled); @@ -96,9 +96,7 @@ public void Replace() bool newMapperMethodCalled = false; bool originalMapperCalled = false; - ButtonWithControlsMapper. - ControlsButtonWithControlsMapper - .ModifyMapping("MapperTest", (handler, view, previous) => + ButtonWithControlsMapperHandler.Mapper.ModifyMapping("MapperTest", (handler, view, previous) => { Assert.False(originalMapperCalled); previous.Invoke(handler, view); @@ -121,10 +119,7 @@ void MapperCalled() class ButtonWithControlsMapper : Button { - public static IPropertyMapper ControlsButtonWithControlsMapper = - new ControlsMapper(ButtonWithControlsMapperHandler.Mapper); - - + public Action MapperCalled { get; private set; } public ButtonWithControlsMapper(Action mapperCalled) { diff --git a/src/Controls/tests/Core.UnitTests/DependencyResolutionTests.cs b/src/Controls/tests/Core.UnitTests/DependencyResolutionTests.cs index f80cc26c8170..33f080e2586f 100644 --- a/src/Controls/tests/Core.UnitTests/DependencyResolutionTests.cs +++ b/src/Controls/tests/Core.UnitTests/DependencyResolutionTests.cs @@ -125,7 +125,7 @@ public void GetHandlerFromContainer() public void GetEffectFromContainer() { string effectName = "anEffect"; - Internals.Registrar.Effects[effectName] = typeof(MockEffect); + Internals.Registrar.Effects[effectName] = new Registrar.EffectType(typeof(MockEffect)); var effect = new MockEffect(); _container.Register(typeof(MockEffect), effect); var result = Effect.Resolve(effectName); diff --git a/src/Controls/tests/Core.UnitTests/ElementTests.cs b/src/Controls/tests/Core.UnitTests/ElementTests.cs index aae1b53ba97c..c332e47819c6 100644 --- a/src/Controls/tests/Core.UnitTests/ElementTests.cs +++ b/src/Controls/tests/Core.UnitTests/ElementTests.cs @@ -1,6 +1,8 @@ +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.Runtime.CompilerServices; using Xunit; namespace Microsoft.Maui.Controls.Core.UnitTests @@ -8,6 +10,10 @@ namespace Microsoft.Maui.Controls.Core.UnitTests public class TestElement : Element { + /// Bindable property for . + public static readonly BindableProperty TrackPropertyChangedDelegateProperty = BindableProperty.Create(nameof(TestElement), typeof(int), typeof(Element), 0, propertyChanged: OnTrackPropertyChangedDelegate); + + public TestElement() { internalChildren.CollectionChanged += OnChildrenChanged; @@ -37,12 +43,88 @@ private protected override IList LogicalChildrenInternalBackingStore => internalChildren; readonly ObservableCollection internalChildren = new ObservableCollection(); - } + public int TrackPropertyChangedDelegate + { + get => (int)GetValue(TrackPropertyChangedDelegateProperty); + set => SetValue(TrackPropertyChangedDelegateProperty, value); + } + + public event EventHandler TrackPropertyChanged; + public int TrackPropertyChangedDelegateCount { get; private set; } + public int TrackPropertyChangedOnPropertyChangedCount { get; private set; } + public int TrackPropertyChangedUpdateHandlerValueCount { get; private set; } + + private static void OnTrackPropertyChangedDelegate(BindableObject bindable, object oldValue, object newValue) + { + ((TestElement)bindable).TrackPropertyChangedDelegateCount++; + ((TestElement)bindable).TrackPropertyChanged?.Invoke(bindable, EventArgs.Empty); + } + + protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + if (propertyName == TrackPropertyChangedDelegateProperty.PropertyName) + { + TrackPropertyChangedOnPropertyChangedCount++; + TrackPropertyChanged?.Invoke(this, EventArgs.Empty); + } + + base.OnPropertyChanged(propertyName); + } + + private protected override void UpdateHandlerValue(string propertyName, bool valueChanged) + { + if (propertyName == TrackPropertyChangedDelegateProperty.PropertyName) + { + TrackPropertyChangedUpdateHandlerValueCount++; + TrackPropertyChanged?.Invoke(this, EventArgs.Empty); + } + + base.UpdateHandlerValue(propertyName, valueChanged); + } + } + public class ElementTests : BaseTestFixture { + + [Fact] + public void ValidateHandleUpdatesHappenAfterPropertyChangedDelegate() + { + var element = new TestElement(); + + element.TrackPropertyChanged += (_, _) => + { + Assert.True(element.TrackPropertyChangedUpdateHandlerValueCount <= element.TrackPropertyChangedOnPropertyChangedCount); + Assert.True(element.TrackPropertyChangedUpdateHandlerValueCount <= element.TrackPropertyChangedDelegateCount); + }; + + element.TrackPropertyChangedDelegate = 1; + } + + [Fact] + public void ValidateChangingBindablePropertyDuringOnPropertyChangedStillPropagatesHandlerUpdateLater() + { + var element = new TestElement(); + + + element.PropertyChanged += (_, _) => + { + if (element.TrackPropertyChangedDelegate == 1) + element.TrackPropertyChangedDelegate = 2; + }; + + element.TrackPropertyChanged += (_, _) => + { + Assert.True(element.TrackPropertyChangedUpdateHandlerValueCount <= element.TrackPropertyChangedOnPropertyChangedCount); + Assert.True(element.TrackPropertyChangedUpdateHandlerValueCount <= element.TrackPropertyChangedDelegateCount); + }; + + element.TrackPropertyChangedDelegate = 1; + Assert.Equal(2, element.TrackPropertyChangedUpdateHandlerValueCount); + } + [Fact] public void DescendantAddedLevel1() { diff --git a/src/Controls/tests/Core.UnitTests/FlexLayoutMarginTests.cs b/src/Controls/tests/Core.UnitTests/FlexLayoutMarginTests.cs index a10644457b5c..7ad5f49b3621 100644 --- a/src/Controls/tests/Core.UnitTests/FlexLayoutMarginTests.cs +++ b/src/Controls/tests/Core.UnitTests/FlexLayoutMarginTests.cs @@ -16,7 +16,7 @@ public class FlexLayoutMarginTests : BaseTestFixture [Fact] public void TestMarginLeft() { - var view0 = new View { IsPlatformEnabled = true, WidthRequest = 10, Margin = new Thickness(10, 0, 0, 0), }; + var view0 = MockPlatformSizeService.Sub(width: 10, margin: new(10, 0, 0, 0)); var layout = new FlexLayout { IsPlatformEnabled = true, @@ -34,7 +34,7 @@ public void TestMarginLeft() [Fact] public void TestMarginTop() { - var view0 = new View { IsPlatformEnabled = true, HeightRequest = 10, Margin = new Thickness(0, 10, 0, 0), }; + var view0 = MockPlatformSizeService.Sub(height: 10, margin: new(0, 10, 0, 0)); var layout = new FlexLayout { IsPlatformEnabled = true, @@ -53,7 +53,7 @@ public void TestMarginTop() [Fact] public void TestMarginRight() { - var view0 = new View { IsPlatformEnabled = true, WidthRequest = 10, Margin = new Thickness(0, 0, 10, 0), }; + var view0 = MockPlatformSizeService.Sub(width: 10, margin: new(0, 0, 10, 0)); var layout = new FlexLayout { IsPlatformEnabled = true, @@ -73,7 +73,7 @@ public void TestMarginRight() [Fact] public void TestMarginBottom() { - var view0 = new View { IsPlatformEnabled = true, HeightRequest = 10, Margin = new Thickness(0, 0, 0, 10), }; + var view0 = MockPlatformSizeService.Sub(height: 10, margin: new(0, 0, 0, 10)); var layout = new FlexLayout { IsPlatformEnabled = true, @@ -93,7 +93,7 @@ public void TestMarginBottom() [Fact] public void TestMarginAndFlexRow() { - var view0 = new View { IsPlatformEnabled = true, Margin = new Thickness(10, 0, 10, 0), }; + var view0 = MockPlatformSizeService.Sub(margin: new(10, 0, 10, 0)); FlexLayout.SetGrow(view0, 1); var layout = new FlexLayout { @@ -112,7 +112,7 @@ public void TestMarginAndFlexRow() [Fact] public void TestMarginAndFlexColumn() { - var view0 = new View { IsPlatformEnabled = true, Margin = new Thickness(0, 10, 0, 10), }; + var view0 = MockPlatformSizeService.Sub(margin: new(0, 10, 0, 10)); FlexLayout.SetGrow(view0, 1); var layout = new FlexLayout { @@ -131,7 +131,7 @@ public void TestMarginAndFlexColumn() [Fact] public void TestMarginAndStretchRow() { - var view0 = new View { IsPlatformEnabled = true, Margin = new Thickness(0, 10, 0, 10), }; + var view0 = MockPlatformSizeService.Sub(margin: new(0, 10, 0, 10)); FlexLayout.SetGrow(view0, 1); var layout = new FlexLayout { @@ -151,8 +151,7 @@ public void TestMarginAndStretchRow() [Fact] public void TestMarginAndStretchColumn() { - - var view0 = new View { IsPlatformEnabled = true, Margin = new Thickness(10, 0, 10, 0) }; + var view0 = MockPlatformSizeService.Sub(margin: new(10, 0, 10, 0)); FlexLayout.SetGrow(view0, 1); var layout = new FlexLayout { @@ -171,11 +170,11 @@ public void TestMarginAndStretchColumn() [Fact] public void TestMarginWithSiblingRow() { - MockPlatformSizeService.Current.GetPlatformSizeFunc = (visual, width, height) => new SizeRequest(new Size(0, 0)); + static SizeRequest GetSize(VisualElement _, double w, double h) => new(new(0, 0)); - var view0 = new View { IsPlatformEnabled = true, Margin = new Thickness(0, 0, 10, 0) }; + var view0 = MockPlatformSizeService.Sub(GetSize, margin: new(0, 0, 10, 0)); FlexLayout.SetGrow(view0, 1); - var view1 = new View { IsPlatformEnabled = true }; + var view1 = MockPlatformSizeService.Sub(GetSize); FlexLayout.SetGrow(view1, 1); var layout = new FlexLayout { @@ -197,9 +196,9 @@ public void TestMarginWithSiblingRow() [Fact] public void TestMarginWithSiblingColumn() { - var view0 = new View { IsPlatformEnabled = true, Margin = new Thickness(0, 0, 0, 10) }; + var view0 = MockPlatformSizeService.Sub(margin: new(0, 0, 0, 10)); FlexLayout.SetGrow(view0, 1); - var view1 = new View { IsPlatformEnabled = true }; + var view1 = MockPlatformSizeService.Sub(); FlexLayout.SetGrow(view1, 1); var layout = new FlexLayout diff --git a/src/Controls/tests/Core.UnitTests/FlexOrderTests.cs b/src/Controls/tests/Core.UnitTests/FlexOrderTests.cs index 3e5d3765586f..3a087779144d 100644 --- a/src/Controls/tests/Core.UnitTests/FlexOrderTests.cs +++ b/src/Controls/tests/Core.UnitTests/FlexOrderTests.cs @@ -15,10 +15,10 @@ public class FlexOrderTests : BaseTestFixture [Fact] public void TestOrderingElements() { - var label0 = new Label { IsPlatformEnabled = true }; - var label1 = new Label { IsPlatformEnabled = true }; - var label2 = new Label { IsPlatformEnabled = true }; - var label3 = new Label { IsPlatformEnabled = true }; + var label0 = MockPlatformSizeService.Sub