diff --git a/build.sh b/build.sh index a287a8b7659..50bd9865604 100755 --- a/build.sh +++ b/build.sh @@ -10,14 +10,16 @@ set -e usage() { echo "Common settings:" -echo " --binaryLog Create MSBuild binary log (short: -bl)" + echo " --binaryLog Create MSBuild binary log (short: -bl)" echo " --configuration Build configuration: 'Debug' or 'Release' (short: -c)" echo " --rid, --target-rid Overrides the rid that is produced by the build. e.g. alpine.3.18-arm64, fedora.37-x64, freebsd.13-arm64, ubuntu.19.10-x64" echo " --os, --target-os Target operating system: e.g. linux, osx, freebsd. Note: this is the base OS name, not the distro" echo " --arch, --target-arch Target architecture: e.g. x64, x86, arm64, arm, riscv64" echo " --branding Specify versioning for shipping packages/assets. 'preview' will produce assets suffixed with '.final', 'rtm' will not contain a pre-release suffix. Default or unspecified will use VMR repo defaults." echo " --verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)" - echo " --with-system-libs Use system versions of these libraries. Combine with a plus. eg brotli+libunwind+rapidjson+zlib" + echo " --with-system-libs Use system versions of these libraries. Combine with a plus. 'all' will use all supported libraries. e.g. brotli+libunwind+rapidjson+zlib" + echo " --official-build-id Official build ID to use for the build. This is used to set the OfficialBuildId MSBuild property." + echo "" echo "Actions:" @@ -138,7 +140,21 @@ while [[ $# > 0 ]]; do shift ;; -with-system-libs) - properties+=( "/p:UseSystemLibs=$2" ) + value="$2" + if [[ "$value" != +* ]]; then + # Ensure the value is prepended with a '+' + value="+$value" + fi + properties+=( "/p:UseSystemLibs=$value" ) + shift + ;; + -official-build-id) + officialBuildId="$2" + if [[ ! "$officialBuildId" =~ ^[0-9]{8}\.[0-9]{1,3}$ ]]; then + echo "ERROR: Invalid official-build-id format. Expected format: YYYYYMMDD.X" + #exit 1 + fi + properties+=( "/p:OfficialBuildId=$officialBuildId" ) shift ;; -verbosity|-v) diff --git a/eng/build.ps1 b/eng/build.ps1 index ca7f968fcf5..3d4fcc1c056 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -9,6 +9,8 @@ Param( [string][Alias('v')]$verbosity = "minimal", [Parameter()][ValidateSet("preview", "rtm", "default")] [string]$branding = "default", + [Parameter()][ValidatePattern("^\d{8}\.\d{1,3}$")] + [string][Alias('obid')]$officialBuildId, # Actions [switch]$clean, @@ -31,13 +33,14 @@ Param( function Get-Usage() { Write-Host "Common settings:" - Write-Host " -binaryLog Output binary log (short: -bl)" - Write-Host " -configuration Build configuration: 'Debug' or 'Release' (short: -c). [Default: Release]" - Write-Host " -rid, -targetRid Overrides the rid that is produced by the build. e.g. win-arm64, win-x64" - Write-Host " -os, -targetOS Target operating system: e.g. windows." - Write-Host " -arch, -targetArch Target architecture: e.g. x64, x86, arm64, arm, riscv64" - Write-Host " -verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)" + Write-Host " -binaryLog Output binary log (short: -bl)" + Write-Host " -configuration Build configuration: 'Debug' or 'Release' (short: -c). [Default: Release]" + Write-Host " -rid, -targetRid Overrides the rid that is produced by the build. e.g. win-arm64, win-x64" + Write-Host " -os, -targetOS Target operating system: e.g. windows." + Write-Host " -arch, -targetArch Target architecture: e.g. x64, x86, arm64, arm, riscv64" + Write-Host " -verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)" Write-Host " -branding Specify versioning for shipping packages/assets. 'preview' will produce assets suffixed with '.final', 'rtm' will not contain a pre-release suffix. Default or unspecified will use VMR repo defaults." + Write-Host " -officialBuildId Official build ID to use for the build. This is used to set the OfficialBuildId MSBuild property." Write-Host "" Write-Host "Actions:" @@ -95,6 +98,7 @@ if ($branding) { "default" { $arguments += "" } } } +if ($officialBuildId) { $arguments += "/p:OfficialBuildId=$officialBuildId" } function Build { $toolsetBuildProj = InitializeToolset diff --git a/eng/pipelines/source-build-sdk-diff-tests.yml b/eng/pipelines/source-build-sdk-diff-tests.yml index 351cfefbfb6..38075f307ee 100644 --- a/eng/pipelines/source-build-sdk-diff-tests.yml +++ b/eng/pipelines/source-build-sdk-diff-tests.yml @@ -18,6 +18,11 @@ resources: include: - refs/heads/release/*.0.1xx-preview* - refs/heads/internal/release/*.0.1xx* + # Trigger on build stages vs successful pipeline completion for a higher run frequency when there are + # publish/validation failures. + stages: + - VMR_Vertical_Build + - VMR_SourceOnly_Build - pipeline: dotnet-source-build-pre10.0 source: dotnet-source-build-pre10.0 diff --git a/eng/pipelines/templates/jobs/vmr-build.yml b/eng/pipelines/templates/jobs/vmr-build.yml index fe6a2f9d153..196cbb01b7b 100644 --- a/eng/pipelines/templates/jobs/vmr-build.yml +++ b/eng/pipelines/templates/jobs/vmr-build.yml @@ -69,6 +69,11 @@ parameters: type: object default: '' +# Enables usage of the system libraries when building. +- name: useSystemLibraries + type: boolean + default: false + #### SOURCE-ONLY parameters #### # Instead of building the VMR directly, exports the sources into a tarball and builds from that @@ -227,8 +232,24 @@ jobs: - name: brandingArgument value: $(commandPrefix)branding $(brandingType) + - ${{ if and(eq(variables['System.TeamProject'], 'internal'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - name: officialBuildArgument + ${{ if eq(parameters.targetOS, 'windows') }}: + value: $(commandPrefix)officialBuildId $(Build.BuildNumber) + ${{ else }}: + value: $(commandPrefix)official-build-id $(Build.BuildNumber) + - ${{ else }}: + - name: officialBuildArgument + value: '' + + - name: useSystemLibrariesArgument + ${{ if eq(parameters.useSystemLibraries, 'true') }}: + value: $(commandPrefix)with-system-libs all + ${{ else }}: + value: '' + - name: baseArguments - value: $(commandPrefix)ci $(cleanArgument) $(commandPrefix)prepareMachine -c ${{ parameters.configuration }} $(brandingArgument) + value: $(commandPrefix)ci $(cleanArgument) $(commandPrefix)prepareMachine -c ${{ parameters.configuration }} $(brandingArgument) $(useSystemLibrariesArgument) $(officialBuildArgument) - name: baseProperties value: $(officialBuildProperties) /p:VerticalName=$(Agent.JobName) diff --git a/eng/pipelines/templates/stages/source-build-and-validate.yml b/eng/pipelines/templates/stages/source-build-and-validate.yml index 5e37a59fff9..1a7b2804d36 100644 --- a/eng/pipelines/templates/stages/source-build-and-validate.yml +++ b/eng/pipelines/templates/stages/source-build-and-validate.yml @@ -101,6 +101,7 @@ stages: buildFromArchive: ${{ leg.buildFromArchive }} runOnline: ${{ leg.runOnline }} useMonoRuntime: ${{ leg.useMonoRuntime }} + useSystemLibraries: ${{ leg.useSystemLibraries }} withPreviousSDK: ${{ leg.withPreviousSDK }} # We only want to publish SB artifacts for each distinct distro/version/arch combination diff --git a/eng/pipelines/templates/stages/source-build-stages.yml b/eng/pipelines/templates/stages/source-build-stages.yml index a2c059ab5c0..b359f462c42 100644 --- a/eng/pipelines/templates/stages/source-build-stages.yml +++ b/eng/pipelines/templates/stages/source-build-stages.yml @@ -63,6 +63,7 @@ stages: enablePoison: false # 🚫 runOnline: true # ✅ useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 - ${{ if containsValue(parameters.verifications, 'source-build-stage2') }}: @@ -74,6 +75,7 @@ stages: enablePoison: false # 🚫 runOnline: false # 🚫 useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 reuseBuildArtifactsFrom: '{0}_Online_MsftSdk_x64' @@ -88,6 +90,7 @@ stages: excludeOmniSharpTests: false # 🚫 runOnline: false # 🚫 useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 - buildNameFormat: '{0}_Offline_PreviousSourceBuiltSdk' @@ -97,6 +100,7 @@ stages: enablePoison: true # ✅ runOnline: false # 🚫 useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: true # ✅ - buildNameFormat: '{0}_Offline_MsftSdk' @@ -106,6 +110,7 @@ stages: enablePoison: false # 🚫 runOnline: false # 🚫 useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 - buildNameFormat: '{0}_Offline_MsftSdk' @@ -115,6 +120,7 @@ stages: enablePoison: false # 🚫 runOnline: false # 🚫 useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 - buildNameFormat: '{0}_Offline_MsftSdk' @@ -124,6 +130,7 @@ stages: enablePoison: false # 🚫 runOnline: false # 🚫 useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 - buildNameFormat: '{0}_Online_PreviousSourceBuiltSdk' @@ -133,6 +140,7 @@ stages: enablePoison: false # 🚫 runOnline: true # ✅ useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: true # ✅ - buildNameFormat: '{0}_Mono_Offline_MsftSdk' @@ -142,6 +150,7 @@ stages: enablePoison: false # 🚫 runOnline: false # 🚫 useMonoRuntime: true # ✅ + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 - buildNameFormat: '{0}_Offline_MsftSdk' @@ -151,6 +160,7 @@ stages: enablePoison: false # 🚫 runOnline: false # 🚫 useMonoRuntime: false # 🚫 + useSystemLibraries: true # ✅ withPreviousSDK: false # 🚫 - buildNameFormat: '{0}Arm64_Offline_MsftSdk' @@ -160,6 +170,7 @@ stages: enablePoison: false # 🚫 runOnline: false # 🚫 useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 - buildNameFormat: '{0}_Offline_CurrentSourceBuiltSdk' @@ -169,6 +180,7 @@ stages: enablePoison: false # 🚫 runOnline: false # 🚫 useMonoRuntime: false # 🚫 + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 reuseBuildArtifactsFrom: '{0}_Offline_MsftSdk_x64' @@ -179,5 +191,6 @@ stages: enablePoison: false # 🚫 runOnline: false # 🚫 useMonoRuntime: true # ✅ + useSystemLibraries: false # 🚫 withPreviousSDK: false # 🚫 reuseBuildArtifactsFrom: '{0}_Mono_Offline_MsftSdk_x64' diff --git a/eng/pipelines/templates/variables/vmr-build.yml b/eng/pipelines/templates/variables/vmr-build.yml index 9a5a2921f99..db723d07a2f 100644 --- a/eng/pipelines/templates/variables/vmr-build.yml +++ b/eng/pipelines/templates/variables/vmr-build.yml @@ -73,7 +73,7 @@ variables: - ${{ if eq(variables['isOfficialBuild'], true) }}: - name: officialBuildProperties - value: '/p:OfficialBuildId=$(Build.BuildNumber) $(officialBuilderProperty)' + value: '$(officialBuilderProperty)' - ${{ else }}: - name: officialBuildProperties value: '' diff --git a/repo-projects/runtime.proj b/repo-projects/runtime.proj index b313f64fb17..38c563e4322 100644 --- a/repo-projects/runtime.proj +++ b/repo-projects/runtime.proj @@ -46,13 +46,12 @@ $(BuildArgs) $(FlagParameterPrefix)pgoinstrument - +$(UseSystemLibs) - $(BuildArgs) --cmakeargs -DCLR_CMAKE_USE_SYSTEM_BROTLI=true - $(BuildArgs) --cmakeargs -DCLR_CMAKE_USE_SYSTEM_LIBUNWIND=true + $(BuildArgs) --cmakeargs -DCLR_CMAKE_USE_SYSTEM_BROTLI=true + $(BuildArgs) --cmakeargs -DCLR_CMAKE_USE_SYSTEM_LIBUNWIND=true - $(BuildArgs) --cmakeargs -DCLR_CMAKE_USE_SYSTEM_RAPIDJSON=true - $(BuildArgs) --cmakeargs -DCLR_CMAKE_USE_SYSTEM_ZLIB=true + $(BuildArgs) --cmakeargs -DCLR_CMAKE_USE_SYSTEM_RAPIDJSON=true + $(BuildArgs) --cmakeargs -DCLR_CMAKE_USE_SYSTEM_ZLIB=true $(BuildArgs) /p:FeatureXplatEventSource=false diff --git a/src/aspnetcore/eng/Version.Details.xml b/src/aspnetcore/eng/Version.Details.xml index ddf715d8e44..092da0082d3 100644 --- a/src/aspnetcore/eng/Version.Details.xml +++ b/src/aspnetcore/eng/Version.Details.xml @@ -420,25 +420,25 @@ https://github.com/nuget/nuget.client 8fef55f5a55a3b4f2c96cd1a9b5ddc51d4b927f8 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 86968b14b5c2ba5104d205665c76c22544c067f6 + 54bab2dbb7652269d9ae0758de122f933b254561 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 86968b14b5c2ba5104d205665c76c22544c067f6 + 54bab2dbb7652269d9ae0758de122f933b254561 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 86968b14b5c2ba5104d205665c76c22544c067f6 + 54bab2dbb7652269d9ae0758de122f933b254561 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 86968b14b5c2ba5104d205665c76c22544c067f6 + 54bab2dbb7652269d9ae0758de122f933b254561 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 86968b14b5c2ba5104d205665c76c22544c067f6 + 54bab2dbb7652269d9ae0758de122f933b254561 diff --git a/src/aspnetcore/eng/Versions.props b/src/aspnetcore/eng/Versions.props index d46e69b58fe..753929a5dd1 100644 --- a/src/aspnetcore/eng/Versions.props +++ b/src/aspnetcore/eng/Versions.props @@ -182,11 +182,11 @@ 3.2.0-preview.25358.102 - 1.0.0-prerelease.25324.1 - 1.0.0-prerelease.25324.1 - 1.0.0-prerelease.25324.1 - 1.0.0-prerelease.25324.1 - 1.0.0-prerelease.25324.1 + 1.0.0-prerelease.25363.1 + 1.0.0-prerelease.25363.1 + 1.0.0-prerelease.25363.1 + 1.0.0-prerelease.25363.1 + 1.0.0-prerelease.25363.1 6.0.322601 1.10.93 diff --git a/src/aspnetcore/src/Components/WebAssembly/JSInterop/src/WebAssemblyJSObjectReferenceJsonConverter.cs b/src/aspnetcore/src/Components/WebAssembly/JSInterop/src/WebAssemblyJSObjectReferenceJsonConverter.cs index ff294cef264..38ff95ea0c7 100644 --- a/src/aspnetcore/src/Components/WebAssembly/JSInterop/src/WebAssemblyJSObjectReferenceJsonConverter.cs +++ b/src/aspnetcore/src/Components/WebAssembly/JSInterop/src/WebAssemblyJSObjectReferenceJsonConverter.cs @@ -26,6 +26,12 @@ public override bool CanConvert(Type typeToConvert) public override IJSObjectReference? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var id = JSObjectReferenceJsonWorker.ReadJSObjectReferenceIdentifier(ref reader); + + if (id == -1) + { + return null; + } + return new WebAssemblyJSObjectReference(_jsRuntime, id); } diff --git a/src/aspnetcore/src/Components/WebAssembly/WebAssembly/test/JSObjectReferenceJsonConverterTest.cs b/src/aspnetcore/src/Components/WebAssembly/WebAssembly/test/JSObjectReferenceJsonConverterTest.cs index 65aeb2acf66..0467e1ac326 100644 --- a/src/aspnetcore/src/Components/WebAssembly/WebAssembly/test/JSObjectReferenceJsonConverterTest.cs +++ b/src/aspnetcore/src/Components/WebAssembly/WebAssembly/test/JSObjectReferenceJsonConverterTest.cs @@ -44,4 +44,17 @@ public void Read_ReadsJson_IJSInProcessObjectReference() // Assert Assert.Equal(expectedId, deserialized?.Id); } + + [Fact] + public void Read_ReturnsNull_WhenIdIsMinusOne() + { + // Arrange + var json = "{\"__jsObjectId\":-1}"; + + // Act + var deserialized = JsonSerializer.Deserialize(json, JsonSerializerOptions); + + // Assert + Assert.Null(deserialized); + } } diff --git a/src/aspnetcore/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs b/src/aspnetcore/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs index bbeb1ad4d9b..3de7fdc739b 100644 --- a/src/aspnetcore/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs +++ b/src/aspnetcore/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs @@ -83,18 +83,28 @@ public void NavigatesWithoutInteractivityByRequestRedirection(bool controlFlowBy [Theory] [InlineData(true)] [InlineData(false)] - public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(bool streaming) + public void ProgrammaticNavigationToNotExistingPath_ReExecutesTo404(bool streaming) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: true); string streamingPath = streaming ? "-streaming" : ""; Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}?navigate-programmatically=true"); AssertReExecutionPageRendered(); } + [Fact] + public void ProgrammaticNavigationToNotExistingPath_AfterAsyncOperation_ReExecutesTo404() + { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: true); + Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr?doAsync=true&navigate-programmatically=true"); + AssertReExecutionPageRendered(); + } + [Theory] [InlineData(true)] [InlineData(false)] - public void LinkNavigationToNotExistingPathReExecutesTo404(bool streaming) + public void LinkNavigationToNotExistingPath_ReExecutesTo404(bool streaming) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: true); string streamingPath = streaming ? "-streaming" : ""; Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}"); Browser.Click(By.Id("link-to-not-existing-page")); @@ -104,8 +114,9 @@ public void LinkNavigationToNotExistingPathReExecutesTo404(bool streaming) [Theory] [InlineData(true)] [InlineData(false)] - public void BrowserNavigationToNotExistingPathReExecutesTo404(bool streaming) + public void BrowserNavigationToNotExistingPath_ReExecutesTo404(bool streaming) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: true); // non-existing path has to have re-execution middleware set up // so it has to have "reexecution" prefix. Otherwise middleware mapping // will not be activated, see configuration in Startup diff --git a/src/aspnetcore/src/Components/test/E2ETest/ServerRenderingTests/RedirectionTest.cs b/src/aspnetcore/src/Components/test/E2ETest/ServerRenderingTests/RedirectionTest.cs index e7830517b3e..0f9b419fb84 100644 --- a/src/aspnetcore/src/Components/test/E2ETest/ServerRenderingTests/RedirectionTest.cs +++ b/src/aspnetcore/src/Components/test/E2ETest/ServerRenderingTests/RedirectionTest.cs @@ -32,9 +32,13 @@ public override async Task InitializeAsync() Browser.Equal("Redirections", () => _originalH1Element.Text); } - [Fact] - public void RedirectStreamingGetToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingGetToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.LinkText("Streaming GET with internal redirection")).Click(); AssertElementRemoved(_originalH1Element); Browser.Equal("Scroll to hash", () => Browser.Exists(By.TagName("h1")).Text); @@ -47,16 +51,23 @@ public void RedirectStreamingGetToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectStreamingGetToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingGetToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); Browser.Exists(By.LinkText("Streaming GET with external redirection")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectStreamingPostToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingPostToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.CssSelector("#form-streaming-internal button")).Click(); AssertElementRemoved(_originalH1Element); Browser.Equal("Scroll to hash", () => Browser.Exists(By.TagName("h1")).Text); @@ -69,16 +80,23 @@ public void RedirectStreamingPostToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectStreamingPostToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingPostToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); Browser.Exists(By.CssSelector("#form-streaming-external button")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectEnhancedGetToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedGetToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // Note that for enhanced nav we can't preserve the hash part of the URL, as it // gets discarded when the browser follows a 'fetch' redirection. This is not solvable // unless we are willing to make the server return extra information so that the @@ -95,16 +113,23 @@ public void RedirectEnhancedGetToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectEnhancedGetToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedGetToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); Browser.Exists(By.LinkText("Enhanced GET with external redirection")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectEnhancedPostToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedPostToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.CssSelector("#form-enhanced-internal button")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -116,16 +141,23 @@ public void RedirectEnhancedPostToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectEnhancedPostToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedPostToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); Browser.Exists(By.CssSelector("#form-enhanced-external button")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectStreamingEnhancedGetToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingEnhancedGetToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.LinkText("Streaming enhanced GET with internal redirection")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -137,16 +169,25 @@ public void RedirectStreamingEnhancedGetToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectStreamingEnhancedGetToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingEnhancedGetToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.LinkText("Streaming enhanced GET with external redirection")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } + - [Fact] - public void RedirectStreamingEnhancedPostToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingEnhancedPostToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.CssSelector("#form-streaming-enhanced-internal button")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -158,16 +199,24 @@ public void RedirectStreamingEnhancedPostToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectStreamingEnhancedPostToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingEnhancedPostToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.CssSelector("#form-streaming-enhanced-external button")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectEnhancedNonBlazorGetToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedNonBlazorGetToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.LinkText("Enhanced GET to non-Blazor endpoint with internal redirection")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -179,16 +228,24 @@ public void RedirectEnhancedNonBlazorGetToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectEnhancedNonBlazorGetToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedNonBlazorGetToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.LinkText("Enhanced GET to non-Blazor endpoint with external redirection")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectEnhancedNonBlazorPostToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedNonBlazorPostToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.CssSelector("#form-nonblazor-enhanced-internal button")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -205,9 +262,13 @@ public void RedirectEnhancedNonBlazorPostToInternal() // response to something like a 200 that the 'fetch' is allowed to read (embedding the // destination URL). - [Fact] - public void RedirectEnhancedGetToInternalWithErrorBoundary() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedGetToInternalWithErrorBoundary(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // This test verifies that redirection works even if an ErrorBoundary wraps // a component throwing a NavigationException. diff --git a/src/aspnetcore/src/Components/test/E2ETest/Tests/InteropTest.cs b/src/aspnetcore/src/Components/test/E2ETest/Tests/InteropTest.cs index ef7d9fe1896..07d54f0fa3d 100644 --- a/src/aspnetcore/src/Components/test/E2ETest/Tests/InteropTest.cs +++ b/src/aspnetcore/src/Components/test/E2ETest/Tests/InteropTest.cs @@ -89,8 +89,6 @@ public void CanInvokeInteropMethods() ["invokeVoidAsyncReturnsWithoutSerializing"] = "Success", ["invokeVoidAsyncReturnsWithoutSerializingInJSObjectReference"] = "Success", ["invokeAsyncThrowsSerializingCircularStructure"] = "Success", - ["invokeAsyncThrowsUndefinedJSObjectReference"] = "Success", - ["invokeAsyncThrowsNullJSObjectReference"] = "Success", ["disposeJSObjectReferenceAsync"] = "Success", // GetValue tests ["getValueFromDataPropertyAsync"] = "10", @@ -108,7 +106,12 @@ public void CanInvokeInteropMethods() ["invokeConstructorWithClassConstructorAsync.function"] = "6", ["invokeConstructorWithNonConstructorAsync"] = "Success", // Function reference tests - ["changeFunctionViaObjectReferenceAsync"] = "42" + ["changeFunctionViaObjectReferenceAsync"] = "42", + // JS Object Nullable reference tests + ["invokeAsyncUndefinedJSObjectReference"] = "Success", + ["invokeAsyncNullJSObjectReference"] = "Success", + ["invokeAsyncNullFromVariableJSObjectReference"] = "Success", + ["invokeAsyncNonExistentJSObjectReference"] = "Success", }; var expectedSyncValues = new Dictionary @@ -148,8 +151,6 @@ public void CanInvokeInteropMethods() ["invokeVoidReturnsWithoutSerializingIJSInProcessRuntime"] = "Success", ["invokeVoidReturnsWithoutSerializingInIJSInProcessObjectReference"] = "Success", ["invokeThrowsSerializingCircularStructure"] = "Success", - ["invokeThrowsUndefinedJSObjectReference"] = "Success", - ["invokeThrowsNullJSObjectReference"] = "Success", ["stringValueUpperSync"] = "MY STRING", ["testDtoNonSerializedValueSync"] = "99999", ["testDtoSync"] = "Same", @@ -174,7 +175,12 @@ public void CanInvokeInteropMethods() ["invokeConstructorWithClassConstructor.function"] = "6", ["invokeConstructorWithNonConstructor"] = "Success", // Function reference tests - ["changeFunctionViaObjectReference"] = "42" + ["changeFunctionViaObjectReference"] = "42", + // JS Object Nullable reference tests + ["invokeUndefinedJSObjectReference"] = "Success", + ["invokeNullJSObjectReference"] = "Success", + ["invokeNullFromVariableJSObjectReference"] = "Success", + ["invokeNonExistentJSObjectReference"] = "Success", }; // Include the sync assertions only when running under WebAssembly diff --git a/src/aspnetcore/src/Components/test/testassets/BasicTestApp/InteropComponent.razor b/src/aspnetcore/src/Components/test/testassets/BasicTestApp/InteropComponent.razor index eb7839539d5..3cafad7b577 100644 --- a/src/aspnetcore/src/Components/test/testassets/BasicTestApp/InteropComponent.razor +++ b/src/aspnetcore/src/Components/test/testassets/BasicTestApp/InteropComponent.razor @@ -167,33 +167,6 @@ ReturnValues["invokeAsyncThrowsSerializingCircularStructure"] = $"Failure: {ex.Message}"; } - try - { - var undefinedJsObjectReference = await JSRuntime.InvokeAsync("returnUndefined"); - ReturnValues["invokeAsyncThrowsUndefinedJSObjectReference"] = undefinedJsObjectReference is null ? "Failure: null" : "Failure: not null"; - } - catch (JSException) - { - ReturnValues["invokeAsyncThrowsUndefinedJSObjectReference"] = "Success"; - } - catch (Exception ex) - { - ReturnValues["invokeAsyncThrowsUndefinedJSObjectReference"] = $"Failure: {ex.Message}"; - } - - try - { - var nullJsObjectReference = await JSRuntime.InvokeAsync("returnNull"); - ReturnValues["invokeAsyncThrowsNullJSObjectReference"] = nullJsObjectReference is null ? "Failure: null" : "Failure: not null"; - } - catch (JSException) - { - ReturnValues["invokeAsyncThrowsNullJSObjectReference"] = "Success"; - } - catch (Exception ex) - { - ReturnValues["invokeAsyncThrowsNullJSObjectReference"] = $"Failure: {ex.Message}"; - } var jsObjectReference = await JSRuntime.InvokeAsync("returnJSObjectReference"); ReturnValues["jsObjectReference.identity"] = await jsObjectReference.InvokeAsync("identity", "Invoked from JSObjectReference"); @@ -308,6 +281,13 @@ FunctionReferenceTests(); } + await JSObjectReferenceAsyncTests(); + + if (shouldSupportSyncInterop) + { + JSObjectReferenceTests(); + } + Invocations = invocations; DoneWithInterop = true; } @@ -394,34 +374,6 @@ ReturnValues["invokeThrowsSerializingCircularStructure"] = $"Failure: {ex.Message}"; } - try - { - var undefinedJsObjectReference = inProcRuntime.Invoke("returnUndefined"); - ReturnValues["invokeThrowsUndefinedJSObjectReference"] = undefinedJsObjectReference is null ? "Failure: null" : "Failure: not null"; - } - catch (JSException) - { - ReturnValues["invokeThrowsUndefinedJSObjectReference"] = "Success"; - } - catch (Exception ex) - { - ReturnValues["invokeThrowsUndefinedJSObjectReference"] = $"Failure: {ex.Message}"; - } - - try - { - var nullJsObjectReference = inProcRuntime.Invoke("returnNull"); - ReturnValues["invokeThrowsNullJSObjectReference"] = nullJsObjectReference is null ? "Failure: null" : "Failure: not null"; - } - catch (JSException) - { - ReturnValues["invokeThrowsNullJSObjectReference"] = "Success"; - } - catch (Exception ex) - { - ReturnValues["invokeThrowsNullJSObjectReference"] = $"Failure: {ex.Message}"; - } - var jsInProcObjectReference = inProcRuntime.Invoke("returnJSObjectReference"); ReturnValues["jsInProcessObjectReference.identity"] = jsInProcObjectReference.Invoke("identity", "Invoked from JSInProcessObjectReference"); @@ -626,6 +578,124 @@ ReturnValues["changeFunctionViaObjectReference"] = testClassRef.Invoke("getTextLength").ToString(); } + private async Task JSObjectReferenceAsyncTests() + { + try + { + var undefinedJsObjectReference = await JSRuntime.InvokeAsync("jsInteropTests.returnUndefined"); + ReturnValues["invokeAsyncUndefinedJSObjectReference"] = undefinedJsObjectReference is null ? "Success" : $"Failure: not null (type: {undefinedJsObjectReference.GetType().FullName})"; + } + catch (JSException ex) + { + ReturnValues["invokeAsyncUndefinedJSObjectReference"] = $"Failure: {ex.Message}"; + } + catch (Exception ex) + { + ReturnValues["invokeAsyncUndefinedJSObjectReference"] = $"Failure: {ex.Message}"; + } + + try + { + var nullJsObjectReference = await JSRuntime.InvokeAsync("jsInteropTests.returnNull"); + ReturnValues["invokeAsyncNullJSObjectReference"] = nullJsObjectReference is null ? "Success" : $"Failure: not null (type: {nullJsObjectReference.GetType().FullName})"; + } + catch (JSException ex) + { + ReturnValues["invokeAsyncNullJSObjectReference"] = $"Failure: {ex.Message}"; + } + catch (Exception ex) + { + ReturnValues["invokeAsyncNullJSObjectReference"] = $"Failure: {ex.Message}"; + } + + try + { + var nullVariableJsObjectReference = await JSRuntime.GetValueAsync("jsInteropTests.testObject.nullProperty"); + ReturnValues["invokeAsyncNullFromVariableJSObjectReference"] = nullVariableJsObjectReference is null ? "Success" : $"Failure: not null (type: {nullVariableJsObjectReference.GetType().FullName})"; + } + catch (JSException ex) + { + ReturnValues["invokeAsyncNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}"; + } + catch (Exception ex) + { + ReturnValues["invokeAsyncNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}"; + } + + try + { + await JSRuntime.GetValueAsync("nonexistend"); + } + catch (JSException) + { + ReturnValues["invokeAsyncNonExistentJSObjectReference"] = "Success"; + } + catch (Exception ex) + { + ReturnValues["invokeAsyncNonExistentJSObjectReference"] = $"Failure: {ex.Message}"; + } + } + + private void JSObjectReferenceTests() + { + var inProcRuntime = ((IJSInProcessRuntime)JSRuntime); + + try + { + var undefinedJsObjectReference = inProcRuntime.Invoke("returnUndefined"); + ReturnValues["invokeUndefinedJSObjectReference"] = undefinedJsObjectReference is null ? "Success" : $"Failure: not null (type: {undefinedJsObjectReference.GetType().FullName})"; + } + catch (JSException ex) + { + ReturnValues["invokeUndefinedJSObjectReference"] = $"Failure: {ex.Message}"; + } + catch (Exception ex) + { + ReturnValues["invokeUndefinedJSObjectReference"] = $"Failure: {ex.Message}"; + } + + try + { + var nullJsObjectReference = inProcRuntime.Invoke("returnNull"); + ReturnValues["invokeNullJSObjectReference"] = nullJsObjectReference is null ? "Success" : $"Failure: not null (type: {nullJsObjectReference.GetType().FullName})"; + } + catch (JSException ex) + { + ReturnValues["invokeNullJSObjectReference"] = $"Failure: {ex.Message}"; + } + catch (Exception ex) + { + ReturnValues["invokeNullJSObjectReference"] = $"Failure: {ex.Message}"; + } + + try + { + var nullVariableJsObjectReference = inProcRuntime.GetValue("jsInteropTests.testObject.nullProperty"); + ReturnValues["invokeNullFromVariableJSObjectReference"] = nullVariableJsObjectReference is null ? "Success" : $"Failure: not null (type: {nullVariableJsObjectReference.GetType().FullName})"; + } + catch (JSException ex) + { + ReturnValues["invokeNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}"; + } + catch (Exception ex) + { + ReturnValues["invokeNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}"; + } + + try + { + inProcRuntime.GetValue("nonexistend"); + } + catch (JSException) + { + ReturnValues["invokeNonExistentJSObjectReference"] = "Success"; + } + catch (Exception ex) + { + ReturnValues["invokeNonExistentJSObjectReference"] = $"Failure: {ex.Message}"; + } + } + public class PassDotNetObjectByRefArgs { public string StringValue { get; set; } diff --git a/src/aspnetcore/src/Components/test/testassets/BasicTestApp/wwwroot/js/jsinteroptests.js b/src/aspnetcore/src/Components/test/testassets/BasicTestApp/wwwroot/js/jsinteroptests.js index 2a22736a58e..3faee4235ec 100644 --- a/src/aspnetcore/src/Components/test/testassets/BasicTestApp/wwwroot/js/jsinteroptests.js +++ b/src/aspnetcore/src/Components/test/testassets/BasicTestApp/wwwroot/js/jsinteroptests.js @@ -234,7 +234,8 @@ const testObject = { }, set setOnlyProperty(value) { this.num = value; - } + }, + nullProperty: null } window.jsInteropTests = { diff --git a/src/aspnetcore/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor b/src/aspnetcore/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor index 74374799ce0..f9d0b9da9b5 100644 --- a/src/aspnetcore/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor +++ b/src/aspnetcore/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor @@ -2,4 +2,4 @@ @page "/reexecution/redirection-not-found-ssr-streaming" @attribute [StreamRendering(true)] - + diff --git a/src/aspnetcore/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor b/src/aspnetcore/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor index 80a579a2e45..d64425d233d 100644 --- a/src/aspnetcore/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor +++ b/src/aspnetcore/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor @@ -2,4 +2,9 @@ @page "/reexecution/redirection-not-found-ssr" @attribute [StreamRendering(false)] - \ No newline at end of file + + +@code{ + [SupplyParameterFromQuery(Name = "doAsync")] + public bool DoAsync { get; set; } = false; +} diff --git a/src/aspnetcore/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor b/src/aspnetcore/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor index 68df9c6e0c8..46d8496af1c 100644 --- a/src/aspnetcore/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor +++ b/src/aspnetcore/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor @@ -16,7 +16,7 @@ public bool? NavigateProgrammatically { get; set; } [Parameter] - public bool StartStreaming { get; set; } = false; + public bool DoAsyncOperationBeforeRedirection { get; set; } = false; [Parameter] public bool WaitForInteractivity { get; set; } = false; @@ -25,7 +25,7 @@ protected override async Task OnInitializedAsync() { - if (StartStreaming) + if (DoAsyncOperationBeforeRedirection) { await Task.Yield(); } diff --git a/src/aspnetcore/src/Framework/AspNetCoreAnalyzers/src/SourceGenerators/PublicTopLevelProgramGenerator.cs b/src/aspnetcore/src/Framework/AspNetCoreAnalyzers/src/SourceGenerators/PublicTopLevelProgramGenerator.cs index 7e3f3eacd95..77b95a4b507 100644 --- a/src/aspnetcore/src/Framework/AspNetCoreAnalyzers/src/SourceGenerators/PublicTopLevelProgramGenerator.cs +++ b/src/aspnetcore/src/Framework/AspNetCoreAnalyzers/src/SourceGenerators/PublicTopLevelProgramGenerator.cs @@ -12,9 +12,10 @@ public class PublicProgramSourceGenerator : IIncrementalGenerator { private const string PublicPartialProgramClassSource = """ // -#pragma warning disable CS1591 +/// +/// Auto-generated public partial Program class for top-level statement apps. +/// public partial class Program { } -#pragma warning restore CS1591 """; public void Initialize(IncrementalGeneratorInitializationContext context) diff --git a/src/aspnetcore/src/Framework/AspNetCoreAnalyzers/test/SourceGenerators/PublicTopLevelProgramGeneratorTests.cs b/src/aspnetcore/src/Framework/AspNetCoreAnalyzers/test/SourceGenerators/PublicTopLevelProgramGeneratorTests.cs index 173dfa7469f..a75a34057fd 100644 --- a/src/aspnetcore/src/Framework/AspNetCoreAnalyzers/test/SourceGenerators/PublicTopLevelProgramGeneratorTests.cs +++ b/src/aspnetcore/src/Framework/AspNetCoreAnalyzers/test/SourceGenerators/PublicTopLevelProgramGeneratorTests.cs @@ -9,9 +9,10 @@ public class PublicTopLevelProgramGeneratorTests { private const string ExpectedGeneratedSource = """ // -#pragma warning disable CS1591 +/// +/// Auto-generated public partial Program class for top-level statement apps. +/// public partial class Program { } -#pragma warning restore CS1591 """; [Fact] diff --git a/src/aspnetcore/src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts b/src/aspnetcore/src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts index c7c10cacfef..8c0a3d9c699 100644 --- a/src/aspnetcore/src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts +++ b/src/aspnetcore/src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts @@ -155,6 +155,12 @@ export module DotNet { * @throws Error if the given value is not an Object. */ export function createJSObjectReference(jsObject: any): any { + if (jsObject === null || jsObject === undefined) { + return { + [jsObjectIdKey]: -1 + }; + } + if (jsObject && (typeof jsObject === "object" || jsObject instanceof Function)) { cachedJSObjectsById[nextJsObjectId] = new JSObject(jsObject); @@ -220,7 +226,7 @@ export module DotNet { export function disposeJSObjectReference(jsObjectReference: any): void { const id = jsObjectReference && jsObjectReference[jsObjectIdKey]; - if (typeof id === "number") { + if (typeof id === "number" && id !== -1) { disposeJSObjectReferenceById(id); } } diff --git a/src/aspnetcore/src/JSInterop/Microsoft.JSInterop.JS/src/test/CallDispatcher.test.ts b/src/aspnetcore/src/JSInterop/Microsoft.JSInterop.JS/src/test/CallDispatcher.test.ts index e5b250e4166..fbf2b23261b 100644 --- a/src/aspnetcore/src/JSInterop/Microsoft.JSInterop.JS/src/test/CallDispatcher.test.ts +++ b/src/aspnetcore/src/JSInterop/Microsoft.JSInterop.JS/src/test/CallDispatcher.test.ts @@ -395,4 +395,55 @@ describe("CallDispatcher", () => { expect(result2).toBe("30"); }); + + test("createJSObjectReference: Handles null values without throwing", () => { + const nullRef = DotNet.createJSObjectReference(null); + expect(nullRef).toEqual({ [jsObjectId]: -1 }); + }); + + test("createJSObjectReference: Handles undefined values without throwing", () => { + const undefinedRef = DotNet.createJSObjectReference(undefined); + expect(undefinedRef).toEqual({ [jsObjectId]: -1 }); + }); + + test("disposeJSObjectReference: Safely handles null reference disposal", () => { + const nullRef = DotNet.createJSObjectReference(null); + expect(() => DotNet.disposeJSObjectReference(nullRef)).not.toThrow(); + }); + + test("createJSObjectReference: Still throws for invalid types", () => { + expect(() => DotNet.createJSObjectReference("string")).toThrow(); + expect(() => DotNet.createJSObjectReference(123)).toThrow(); + expect(() => DotNet.createJSObjectReference(true)).toThrow(); + }); + + test("GetValue: Returns JSObjectReference with sentinel value for null property", () => { + const testObject = { nullProp: null }; + const objectId = getObjectReferenceId(testObject); + + const result = dispatcher.invokeJSFromDotNet( + "nullProp", + "[]", + DotNet.JSCallResultType.JSObjectReference, + objectId, + DotNet.JSCallType.GetValue + ); + + expect(result).toBe('{"__jsObjectId":-1}'); + }); + + test("GetValue: Returns JSObjectReference with sentinel value for undefined property", () => { + const testObject = { undefinedProp: undefined }; + const objectId = getObjectReferenceId(testObject); + + const result = dispatcher.invokeJSFromDotNet( + "undefinedProp", + "[]", + DotNet.JSCallResultType.JSObjectReference, + objectId, + DotNet.JSCallType.GetValue + ); + + expect(result).toBe('{"__jsObjectId":-1}'); + }); }); diff --git a/src/aspnetcore/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/JSObjectReferenceJsonConverter.cs b/src/aspnetcore/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/JSObjectReferenceJsonConverter.cs index 563291822a4..e4bf9db0c40 100644 --- a/src/aspnetcore/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/JSObjectReferenceJsonConverter.cs +++ b/src/aspnetcore/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/JSObjectReferenceJsonConverter.cs @@ -22,6 +22,12 @@ public override bool CanConvert(Type typeToConvert) public override IJSObjectReference? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var id = JSObjectReferenceJsonWorker.ReadJSObjectReferenceIdentifier(ref reader); + + if (id == -1) + { + return null; + } + return new JSObjectReference(_jsRuntime, id); } diff --git a/src/aspnetcore/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/JSObjectReferenceJsonConverterTest.cs b/src/aspnetcore/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/JSObjectReferenceJsonConverterTest.cs index 63b5a889782..383c0681931 100644 --- a/src/aspnetcore/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/JSObjectReferenceJsonConverterTest.cs +++ b/src/aspnetcore/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/JSObjectReferenceJsonConverterTest.cs @@ -87,4 +87,17 @@ public void Write_WritesValidJson() // Assert Assert.Equal($"{{\"__jsObjectId\":{jsObjectRef.Id}}}", json); } + + [Fact] + public void Read_ReturnsNull_WhenJSObjectIdIsMinusOne() + { + // Arrange + var json = "{\"__jsObjectId\":-1}"; + + // Act + var deserialized = JsonSerializer.Deserialize(json, JsonSerializerOptions); + + // Assert + Assert.Null(deserialized); + } } diff --git a/src/aspnetcore/src/Mvc/Mvc.ApiExplorer/src/EndpointMetadataApiDescriptionProvider.cs b/src/aspnetcore/src/Mvc/Mvc.ApiExplorer/src/EndpointMetadataApiDescriptionProvider.cs index c920ea01d8a..89d45efc5e1 100644 --- a/src/aspnetcore/src/Mvc/Mvc.ApiExplorer/src/EndpointMetadataApiDescriptionProvider.cs +++ b/src/aspnetcore/src/Mvc/Mvc.ApiExplorer/src/EndpointMetadataApiDescriptionProvider.cs @@ -405,7 +405,7 @@ private static void AddSupportedResponseTypes( foreach (var metadata in responseMetadataTypes) { if (metadata.StatusCode == apiResponseType.StatusCode && - metadata.Type == apiResponseType.Type && + TypesAreCompatible(apiResponseType.Type, metadata.Type) && metadata.Description is not null) { matchingDescription = metadata.Description; @@ -413,6 +413,20 @@ private static void AddSupportedResponseTypes( } return matchingDescription; } + + static bool TypesAreCompatible(Type? apiResponseType, Type? metadataType) + { + // We need to a special check for cases where the inferred type is different than the one specified in attributes. + // For example, an endpoint that defines [ProducesResponseType>], + // but the endpoint returns weatherForecasts.ToList(). Because List<> is a different type than IEnumerable<>, it would incorrectly set OpenAPI metadata incorrectly. + // We use a conservative unidirectional check where the attribute type must be assignable from the inferred type. + // This handles inheritance (BaseClass ← DerivedClass) and interface implementation (IEnumerable ← List). + // This should be sufficient, as it's more common to specify an interface or base class type in the attribute and a concrete type in the endpoint implementation, + // compared to doing the opposite. + // For more information, check the related bug: https://github.com/dotnet/aspnetcore/issues/60518 + return apiResponseType == metadataType || + metadataType?.IsAssignableFrom(apiResponseType) == true; + } } private static ApiResponseType CreateDefaultApiResponseType(Type responseType) diff --git a/src/aspnetcore/src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs b/src/aspnetcore/src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs index 9a5233a709a..7de4d5eb5b8 100644 --- a/src/aspnetcore/src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs +++ b/src/aspnetcore/src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs @@ -331,6 +331,108 @@ public void AddsResponseDescription() Assert.Equal(expectedBadRequestDescription, badRequestResponseType.Description); } + [Fact] + public void AddsResponseDescription_WorksWithGenerics() + { + const string expectedOkDescription = "The weather forecast for the next 5 days."; + + var apiDescription = GetApiDescription([ProducesResponseType>(StatusCodes.Status200OK, Description = expectedOkDescription)] + () => new GenericClass { Value = new TimeSpan() }); + + var okResponseType = Assert.Single(apiDescription.SupportedResponseTypes); + + Assert.Equal(200, okResponseType.StatusCode); + Assert.Equal(typeof(GenericClass), okResponseType.Type); + Assert.Equal(typeof(GenericClass), okResponseType.ModelMetadata?.ModelType); + Assert.Equal(expectedOkDescription, okResponseType.Description); + + var createdOkFormat = Assert.Single(okResponseType.ApiResponseFormats); + Assert.Equal("application/json", createdOkFormat.MediaType); + } + + [Fact] + public void AddsResponseDescription_WorksWithGenericsAndTypedResults() + { + const string expectedOkDescription = "The weather forecast for the next 5 days."; + + var apiDescription = GetApiDescription([ProducesResponseType>(StatusCodes.Status200OK, Description = expectedOkDescription)] + () => TypedResults.Ok(new GenericClass { Value = new TimeSpan() })); + + var okResponseType = Assert.Single(apiDescription.SupportedResponseTypes); + + Assert.Equal(200, okResponseType.StatusCode); + Assert.Equal(typeof(GenericClass), okResponseType.Type); + Assert.Equal(typeof(GenericClass), okResponseType.ModelMetadata?.ModelType); + Assert.Equal(expectedOkDescription, okResponseType.Description); + + var createdOkFormat = Assert.Single(okResponseType.ApiResponseFormats); + Assert.Equal("application/json", createdOkFormat.MediaType); + } + + [Fact] + public void AddsResponseDescription_WorksWithCollections() + { + const string expectedOkDescription = "The weather forecast for the next 5 days."; + + var apiDescription = GetApiDescription([ProducesResponseType>(StatusCodes.Status200OK, Description = expectedOkDescription)] + () => new List { new() }); + + var okResponseType = Assert.Single(apiDescription.SupportedResponseTypes); + + Assert.Equal(200, okResponseType.StatusCode); + Assert.Equal(typeof(List), okResponseType.Type); // We use List as the inferred type has higher priority than those set by metadata (attributes) + Assert.Equal(typeof(List), okResponseType.ModelMetadata?.ModelType); + Assert.Equal(expectedOkDescription, okResponseType.Description); + + var createdOkFormat = Assert.Single(okResponseType.ApiResponseFormats); + Assert.Equal("application/json", createdOkFormat.MediaType); + } + + [Fact] + public void AddsResponseDescription_WorksWithCollectionsAndTypedResults() + { + const string expectedOkDescription = "The weather forecast for the next 5 days."; + + var apiDescription = GetApiDescription([ProducesResponseType>(StatusCodes.Status200OK, Description = expectedOkDescription)] + () => TypedResults.Ok(new List { new() })); + + var okResponseType = Assert.Single(apiDescription.SupportedResponseTypes); + + Assert.Equal(200, okResponseType.StatusCode); + Assert.Equal(typeof(List), okResponseType.Type); // We use List as the inferred type has higher priority than those set by metadata (attributes) + Assert.Equal(typeof(List), okResponseType.ModelMetadata?.ModelType); + Assert.Equal(expectedOkDescription, okResponseType.Description); + + var createdOkFormat = Assert.Single(okResponseType.ApiResponseFormats); + Assert.Equal("application/json", createdOkFormat.MediaType); + } + + /// + /// EndpointMetadataApiDescriptionProvider performs a one way type check for discovering response types to match the description that's set in [ProducesResponseType] + /// The reason we do a one-way check instead of a bidirectional check is to prevent too many positive matches. + /// + /// + /// Example: If we did a bidirectional check, we would match something scenarios like this, which can cause confusion: + /// [ProducesResponseType(StatusCodes.Status200OK, Description = "Returned with a string")] -> TypedResults.Ok(new object()) + /// This would match because object is assignable to string, + /// but it doesn't make sense to add the Description to the object type because the attribute says we should return a string. + /// + /// This test documents this desired behavior and will fail if the behavior changes, so the developer can double check if their change is intentional. + /// + [Fact] + public void AddsResponseDescription_ShouldFailWhenInferredTypeIsNotDirectlyAssignableToAttributeType() + { + var apiDescription = GetApiDescription([ProducesResponseType(StatusCodes.Status200OK, Description = "Only returned with a string")] + () => TypedResults.Ok(new object())); + + var okResponseType = Assert.Single(apiDescription.SupportedResponseTypes); + + Assert.Equal(200, okResponseType.StatusCode); + Assert.Equal(typeof(object), okResponseType.Type); + Assert.Equal(typeof(object), okResponseType.ModelMetadata?.ModelType); + Assert.Null(okResponseType.Description); + } + [Fact] public void WithEmptyMethodBody_AddsResponseDescription() { @@ -1814,4 +1916,6 @@ private class TestServiceProvider : IServiceProvider return null; } } + + private class GenericClass { public required TType Value { get; set; } } } diff --git a/src/aspnetcore/src/OpenApi/gen/XmlCommentGenerator.Emitter.cs b/src/aspnetcore/src/OpenApi/gen/XmlCommentGenerator.Emitter.cs index 7e27ffb79b9..cf8bb5e875e 100644 --- a/src/aspnetcore/src/OpenApi/gen/XmlCommentGenerator.Emitter.cs +++ b/src/aspnetcore/src/OpenApi/gen/XmlCommentGenerator.Emitter.cs @@ -93,6 +93,7 @@ private static Dictionary GenerateCacheEntries() } } + {{GeneratedCodeAttribute}} file static class DocumentationCommentIdHelper { /// @@ -302,6 +303,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool // For non-generic types, use FullName (if available) and replace nested type separators. return (type.FullName ?? type.Name).Replace('+', '.'); } + + /// + /// Normalizes a documentation comment ID to match the compiler-style format. + /// Strips the return type suffix for ordinary methods but retains it for conversion operators. + /// + /// The documentation comment ID to normalize. + /// The normalized documentation comment ID. + public static string NormalizeDocId(string docId) + { + // Find the tilde character that indicates the return type suffix + var tildeIndex = docId.IndexOf('~'); + if (tildeIndex == -1) + { + // No return type suffix, return as-is + return docId; + } + + // Check if this is a conversion operator (op_Implicit or op_Explicit) + // For these operators, we need to keep the return type suffix + if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit")) + { + return docId; + } + + // For ordinary methods, strip the return type suffix + return docId.Substring(0, tildeIndex); + } } {{GeneratedCodeAttribute}} @@ -317,7 +345,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform { return Task.CompletedTask; } - if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment)) { if (methodComment.Summary is { } summary) { @@ -423,7 +451,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext { if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo }) { - if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment)) { schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary; if (propertyComment.Examples?.FirstOrDefault() is { } jsonString) @@ -432,7 +460,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } } - if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment)) { schema.Description = typeComment.Summary; if (typeComment.Examples?.FirstOrDefault() is { } jsonString) @@ -444,6 +472,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } + {{GeneratedCodeAttribute}} file static class JsonNodeExtensions { public static JsonNode? Parse(this string? json) diff --git a/src/aspnetcore/src/OpenApi/gen/XmlCommentGenerator.Parser.cs b/src/aspnetcore/src/OpenApi/gen/XmlCommentGenerator.Parser.cs index 0463486167d..ba8248194d2 100644 --- a/src/aspnetcore/src/OpenApi/gen/XmlCommentGenerator.Parser.cs +++ b/src/aspnetcore/src/OpenApi/gen/XmlCommentGenerator.Parser.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections.Generic; using System.Globalization; using System.Threading; @@ -14,6 +15,32 @@ namespace Microsoft.AspNetCore.OpenApi.SourceGenerators; public sealed partial class XmlCommentGenerator { + /// + /// Normalizes a documentation comment ID to match the compiler-style format. + /// Strips the return type suffix for ordinary methods but retains it for conversion operators. + /// + /// The documentation comment ID to normalize. + /// The normalized documentation comment ID. + internal static string NormalizeDocId(string docId) + { + // Find the tilde character that indicates the return type suffix + var tildeIndex = docId.IndexOf('~'); + if (tildeIndex == -1) + { + // No return type suffix, return as-is + return docId; + } + + // Check if this is a conversion operator (op_Implicit or op_Explicit) + // For these operators, we need to keep the return type suffix + if (docId.Contains("op_Implicit", StringComparison.Ordinal) || docId.Contains("op_Explicit", StringComparison.Ordinal)) + { + return docId; + } + + // For ordinary methods, strip the return type suffix + return docId.Substring(0, tildeIndex); + } internal static List<(string, string)> ParseXmlFile(AdditionalText additionalText, CancellationToken cancellationToken) { var text = additionalText.GetText(cancellationToken); @@ -37,7 +64,7 @@ public sealed partial class XmlCommentGenerator var name = member.Attribute(DocumentationCommentXmlNames.NameAttributeName)?.Value; if (name is not null) { - comments.Add((name, member.ToString())); + comments.Add((NormalizeDocId(name), member.ToString())); } } return comments; @@ -54,7 +81,7 @@ public sealed partial class XmlCommentGenerator if (DocumentationCommentId.CreateDeclarationId(type) is string name && type.GetDocumentationCommentXml(CultureInfo.InvariantCulture, expandIncludes: true, cancellationToken: cancellationToken) is string xml) { - comments.Add((name, xml)); + comments.Add((NormalizeDocId(name), xml)); } } var properties = visitor.GetPublicProperties(); @@ -63,7 +90,7 @@ public sealed partial class XmlCommentGenerator if (DocumentationCommentId.CreateDeclarationId(property) is string name && property.GetDocumentationCommentXml(CultureInfo.InvariantCulture, expandIncludes: true, cancellationToken: cancellationToken) is string xml) { - comments.Add((name, xml)); + comments.Add((NormalizeDocId(name), xml)); } } var methods = visitor.GetPublicMethods(); @@ -77,7 +104,7 @@ public sealed partial class XmlCommentGenerator if (DocumentationCommentId.CreateDeclarationId(method) is string name && method.GetDocumentationCommentXml(CultureInfo.InvariantCulture, expandIncludes: true, cancellationToken: cancellationToken) is string xml) { - comments.Add((name, xml)); + comments.Add((NormalizeDocId(name), xml)); } } return comments; diff --git a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/XmlCommentDocumentationIdTests.cs b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/XmlCommentDocumentationIdTests.cs new file mode 100644 index 00000000000..fbf42c1e509 --- /dev/null +++ b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/XmlCommentDocumentationIdTests.cs @@ -0,0 +1,90 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Net.Http; +using System.Text.Json.Nodes; + +namespace Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests; + +[UsesVerify] +public class XmlCommentDocumentationIdTests +{ + [Fact] + public async Task CanMergeXmlCommentsWithDifferentDocumentationIdFormats() + { + // This test verifies that XML comments from referenced assemblies (without return type suffix) + // are properly merged with in-memory symbols (with return type suffix) + var source = """ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using ReferencedLibrary; + +var builder = WebApplication.CreateBuilder(); + +builder.Services.AddOpenApi(); + +var app = builder.Build(); + +app.MapPost("/test-method", ReferencedLibrary.TestApi.TestMethod); + +app.Run(); +"""; + + var referencedLibrarySource = """ +using System; +using System.Threading.Tasks; + +namespace ReferencedLibrary; + +public static class TestApi +{ + /// + /// This method should have its XML comment merged properly. + /// + /// The identifier for the test. + /// A task representing the asynchronous operation. + public static Task TestMethod(int id) + { + return Task.CompletedTask; + } +} +"""; + + var references = new Dictionary> + { + { "ReferencedLibrary", [referencedLibrarySource] } + }; + + var generator = new XmlCommentGenerator(); + await SnapshotTestHelper.Verify(source, generator, references, out var compilation, out var additionalAssemblies); + await SnapshotTestHelper.VerifyOpenApi(compilation, additionalAssemblies, document => + { + var path = document.Paths["/test-method"].Operations[HttpMethod.Post]; + + // Verify that the XML comment from the referenced library was properly merged + // This would fail before the fix because the documentation IDs didn't match + Assert.NotNull(path.Summary); + Assert.Equal("This method should have its XML comment merged properly.", path.Summary); + + // Verify the parameter comment is also available + Assert.NotNull(path.Parameters); + Assert.Single(path.Parameters); + Assert.Equal("The identifier for the test.", path.Parameters[0].Description); + }); + } + + [Theory] + [InlineData("M:Sample.MyMethod(System.Int32)~System.Threading.Tasks.Task", "M:Sample.MyMethod(System.Int32)")] + [InlineData("M:Sample.MyMethod(System.Int32)", "M:Sample.MyMethod(System.Int32)")] + [InlineData("M:Sample.op_Implicit(System.Int32)~Sample.MyClass", "M:Sample.op_Implicit(System.Int32)~Sample.MyClass")] + [InlineData("M:Sample.op_Explicit(System.Int32)~Sample.MyClass", "M:Sample.op_Explicit(System.Int32)~Sample.MyClass")] + [InlineData("T:Sample.MyClass", "T:Sample.MyClass")] + [InlineData("P:Sample.MyClass.MyProperty", "P:Sample.MyClass.MyProperty")] + public void NormalizeDocId_ReturnsExpectedResult(string input, string expected) + { + var result = XmlCommentGenerator.NormalizeDocId(input); + Assert.Equal(expected, result); + } +} \ No newline at end of file diff --git a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AddOpenApiTests.CanInterceptAddOpenApi#OpenApiXmlCommentSupport.generated.verified.cs b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AddOpenApiTests.CanInterceptAddOpenApi#OpenApiXmlCommentSupport.generated.verified.cs index 0f7dc96817c..dea5968bdf6 100644 --- a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AddOpenApiTests.CanInterceptAddOpenApi#OpenApiXmlCommentSupport.generated.verified.cs +++ b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AddOpenApiTests.CanInterceptAddOpenApi#OpenApiXmlCommentSupport.generated.verified.cs @@ -75,6 +75,7 @@ private static Dictionary GenerateCacheEntries() } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class DocumentationCommentIdHelper { /// @@ -284,6 +285,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool // For non-generic types, use FullName (if available) and replace nested type separators. return (type.FullName ?? type.Name).Replace('+', '.'); } + + /// + /// Normalizes a documentation comment ID to match the compiler-style format. + /// Strips the return type suffix for ordinary methods but retains it for conversion operators. + /// + /// The documentation comment ID to normalize. + /// The normalized documentation comment ID. + public static string NormalizeDocId(string docId) + { + // Find the tilde character that indicates the return type suffix + var tildeIndex = docId.IndexOf('~'); + if (tildeIndex == -1) + { + // No return type suffix, return as-is + return docId; + } + + // Check if this is a conversion operator (op_Implicit or op_Explicit) + // For these operators, we need to keep the return type suffix + if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit")) + { + return docId; + } + + // For ordinary methods, strip the return type suffix + return docId.Substring(0, tildeIndex); + } } [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] @@ -299,7 +327,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform { return Task.CompletedTask; } - if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment)) { if (methodComment.Summary is { } summary) { @@ -405,7 +433,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext { if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo }) { - if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment)) { schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary; if (propertyComment.Examples?.FirstOrDefault() is { } jsonString) @@ -414,7 +442,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } } - if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment)) { schema.Description = typeComment.Summary; if (typeComment.Examples?.FirstOrDefault() is { } jsonString) @@ -426,6 +454,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class JsonNodeExtensions { public static JsonNode? Parse(this string? json) @@ -500,4 +529,4 @@ public static IServiceCollection AddOpenApi(this IServiceCollection services, st } } -} \ No newline at end of file +} diff --git a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AdditionalTextsTests.CanHandleXmlForSchemasInAdditionalTexts#OpenApiXmlCommentSupport.generated.verified.cs b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AdditionalTextsTests.CanHandleXmlForSchemasInAdditionalTexts#OpenApiXmlCommentSupport.generated.verified.cs index 10b09abc3d0..fe18f3d0de2 100644 --- a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AdditionalTextsTests.CanHandleXmlForSchemasInAdditionalTexts#OpenApiXmlCommentSupport.generated.verified.cs +++ b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AdditionalTextsTests.CanHandleXmlForSchemasInAdditionalTexts#OpenApiXmlCommentSupport.generated.verified.cs @@ -104,6 +104,7 @@ private static Dictionary GenerateCacheEntries() } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class DocumentationCommentIdHelper { /// @@ -313,6 +314,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool // For non-generic types, use FullName (if available) and replace nested type separators. return (type.FullName ?? type.Name).Replace('+', '.'); } + + /// + /// Normalizes a documentation comment ID to match the compiler-style format. + /// Strips the return type suffix for ordinary methods but retains it for conversion operators. + /// + /// The documentation comment ID to normalize. + /// The normalized documentation comment ID. + public static string NormalizeDocId(string docId) + { + // Find the tilde character that indicates the return type suffix + var tildeIndex = docId.IndexOf('~'); + if (tildeIndex == -1) + { + // No return type suffix, return as-is + return docId; + } + + // Check if this is a conversion operator (op_Implicit or op_Explicit) + // For these operators, we need to keep the return type suffix + if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit")) + { + return docId; + } + + // For ordinary methods, strip the return type suffix + return docId.Substring(0, tildeIndex); + } } [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] @@ -328,7 +356,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform { return Task.CompletedTask; } - if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment)) { if (methodComment.Summary is { } summary) { @@ -434,7 +462,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext { if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo }) { - if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment)) { schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary; if (propertyComment.Examples?.FirstOrDefault() is { } jsonString) @@ -443,7 +471,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } } - if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment)) { schema.Description = typeComment.Summary; if (typeComment.Examples?.FirstOrDefault() is { } jsonString) @@ -455,6 +483,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class JsonNodeExtensions { public static JsonNode? Parse(this string? json) @@ -497,4 +526,4 @@ public static IServiceCollection AddOpenApi(this IServiceCollection services) } } -} \ No newline at end of file +} diff --git a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs index 4e6a566bb89..69e1bbcab4b 100644 --- a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs +++ b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs @@ -159,34 +159,34 @@ Note that there isn't a way to provide a ""cref"" to cache.Add(@"P:GenericParent.TaskOfTupleProp", new XmlComment(@"This property is a generic type containing a tuple.", null, null, null, null, false, null, null, null)); cache.Add(@"P:GenericParent.TupleWithGenericProp", new XmlComment(@"This property is a tuple with a generic type inside.", null, null, null, null, false, null, null, null)); cache.Add(@"P:GenericParent.TupleWithNestedGenericProp", new XmlComment(@"This property is a tuple with a nested generic type inside.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:ExampleClass.Add(System.Int32,System.Int32)~System.Int32", new XmlComment(@"Adds two integers and returns the result.", null, null, @"The sum of two integers.", null, false, [@" ```int c = Math.Add(4, 5); + cache.Add(@"M:ExampleClass.Add(System.Int32,System.Int32)", new XmlComment(@"Adds two integers and returns the result.", null, null, @"The sum of two integers.", null, false, [@" ```int c = Math.Add(4, 5); if (c > 10) { Console.WriteLine(c); }```"], [new XmlParameterComment(@"left", @"The left operand of the addition.", null, false), new XmlParameterComment(@"right", @"The right operand of the addition.", null, false)], null)); - cache.Add(@"M:ExampleClass.AddAsync(System.Int32,System.Int32)~System.Threading.Tasks.Task{System.Int32}", new XmlComment(@"This method is an example of a method that + cache.Add(@"M:ExampleClass.AddAsync(System.Int32,System.Int32)", new XmlComment(@"This method is an example of a method that returns an awaitable item.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:ExampleClass.DoNothingAsync~System.Threading.Tasks.Task", new XmlComment(@"This method is an example of a method that + cache.Add(@"M:ExampleClass.DoNothingAsync", new XmlComment(@"This method is an example of a method that returns a Task which should map to a void return type.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:ExampleClass.AddNumbers(System.Int32[])~System.Int32", new XmlComment(@"This method is an example of a method that consumes + cache.Add(@"M:ExampleClass.AddNumbers(System.Int32[])", new XmlComment(@"This method is an example of a method that consumes an params array.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:ITestInterface.Method(System.Int32)~System.Int32", new XmlComment(@"This method is part of the test interface.", null, @"This content would be inherited by classes + cache.Add(@"M:ITestInterface.Method(System.Int32)", new XmlComment(@"This method is part of the test interface.", null, @"This content would be inherited by classes that implement this interface when the implementing class uses ""inheritdoc""", @"The value of arg", null, false, null, [new XmlParameterComment(@"arg", @"The argument to the method", null, false)], null)); - cache.Add(@"M:InheritOnlyReturns.MyParentMethod(System.Boolean)~System.Boolean", new XmlComment(@"In this example, this summary is only visible for this method.", null, null, @"A boolean", null, false, null, null, null)); - cache.Add(@"M:InheritOnlyReturns.MyChildMethod~System.Boolean", new XmlComment(null, null, null, @"A boolean", null, false, null, null, null)); - cache.Add(@"M:InheritAllButRemarks.MyParentMethod(System.Boolean)~System.Boolean", new XmlComment(@"In this example, this summary is visible on all the methods.", null, @"The remarks can be inherited by other methods + cache.Add(@"M:InheritOnlyReturns.MyParentMethod(System.Boolean)", new XmlComment(@"In this example, this summary is only visible for this method.", null, null, @"A boolean", null, false, null, null, null)); + cache.Add(@"M:InheritOnlyReturns.MyChildMethod", new XmlComment(null, null, null, @"A boolean", null, false, null, null, null)); + cache.Add(@"M:InheritAllButRemarks.MyParentMethod(System.Boolean)", new XmlComment(@"In this example, this summary is visible on all the methods.", null, @"The remarks can be inherited by other methods using the xpath expression.", @"A boolean", null, false, null, null, null)); - cache.Add(@"M:InheritAllButRemarks.MyChildMethod~System.Boolean", new XmlComment(@"In this example, this summary is visible on all the methods.", null, null, @"A boolean", null, false, null, null, null)); - cache.Add(@"M:GenericParent.GetTaskOfTuple~System.Threading.Tasks.Task{System.ValueTuple{System.Int32,System.String}}", new XmlComment(@"This method returns a generic type containing a tuple.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:GenericParent.GetTupleOfTask~System.ValueTuple{System.Int32,System.Collections.Generic.Dictionary{System.Int32,System.String}}", new XmlComment(@"This method returns a tuple with a generic type inside.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:GenericParent.GetTupleOfTask1``1~System.ValueTuple{System.Int32,System.Collections.Generic.Dictionary{System.Int32,``0}}", new XmlComment(@"This method return a tuple with a generic type containing a + cache.Add(@"M:InheritAllButRemarks.MyChildMethod", new XmlComment(@"In this example, this summary is visible on all the methods.", null, null, @"A boolean", null, false, null, null, null)); + cache.Add(@"M:GenericParent.GetTaskOfTuple", new XmlComment(@"This method returns a generic type containing a tuple.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:GenericParent.GetTupleOfTask", new XmlComment(@"This method returns a tuple with a generic type inside.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:GenericParent.GetTupleOfTask1``1", new XmlComment(@"This method return a tuple with a generic type containing a type parameter inside.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:GenericParent.GetTupleOfTask2``1~System.ValueTuple{``0,System.Collections.Generic.Dictionary{System.Int32,System.String}}", new XmlComment(@"This method return a tuple with a generic type containing a + cache.Add(@"M:GenericParent.GetTupleOfTask2``1", new XmlComment(@"This method return a tuple with a generic type containing a type parameter inside.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:GenericParent.GetNestedGeneric~System.Collections.Generic.Dictionary{System.Int32,System.Collections.Generic.Dictionary{System.Int32,System.String}}", new XmlComment(@"This method returns a nested generic with all types resolved.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:GenericParent.GetNestedGeneric1``1~System.Collections.Generic.Dictionary{System.Int32,System.Collections.Generic.Dictionary{System.Int32,``0}}", new XmlComment(@"This method returns a nested generic with a type parameter.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:ParamsAndParamRefs.GetGenericValue``1(``0)~``0", new XmlComment(@"The GetGenericValue method.", null, @"This sample shows how to specify the T ParamsAndParamRefs.GetGenericValue<T>(T para) + cache.Add(@"M:GenericParent.GetNestedGeneric", new XmlComment(@"This method returns a nested generic with all types resolved.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:GenericParent.GetNestedGeneric1``1", new XmlComment(@"This method returns a nested generic with a type parameter.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:ParamsAndParamRefs.GetGenericValue``1(``0)", new XmlComment(@"The GetGenericValue method.", null, @"This sample shows how to specify the T ParamsAndParamRefs.GetGenericValue<T>(T para) method as a cref attribute. The parameter and return value are both of an arbitrary type, T", null, null, false, null, null, null)); @@ -196,6 +196,7 @@ method as a cref attribute. } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class DocumentationCommentIdHelper { /// @@ -405,6 +406,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool // For non-generic types, use FullName (if available) and replace nested type separators. return (type.FullName ?? type.Name).Replace('+', '.'); } + + /// + /// Normalizes a documentation comment ID to match the compiler-style format. + /// Strips the return type suffix for ordinary methods but retains it for conversion operators. + /// + /// The documentation comment ID to normalize. + /// The normalized documentation comment ID. + public static string NormalizeDocId(string docId) + { + // Find the tilde character that indicates the return type suffix + var tildeIndex = docId.IndexOf('~'); + if (tildeIndex == -1) + { + // No return type suffix, return as-is + return docId; + } + + // Check if this is a conversion operator (op_Implicit or op_Explicit) + // For these operators, we need to keep the return type suffix + if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit")) + { + return docId; + } + + // For ordinary methods, strip the return type suffix + return docId.Substring(0, tildeIndex); + } } [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] @@ -420,7 +448,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform { return Task.CompletedTask; } - if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment)) { if (methodComment.Summary is { } summary) { @@ -526,7 +554,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext { if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo }) { - if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment)) { schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary; if (propertyComment.Examples?.FirstOrDefault() is { } jsonString) @@ -535,7 +563,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } } - if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment)) { schema.Description = typeComment.Summary; if (typeComment.Examples?.FirstOrDefault() is { } jsonString) @@ -547,6 +575,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class JsonNodeExtensions { public static JsonNode? Parse(this string? json) @@ -589,4 +618,4 @@ public static IServiceCollection AddOpenApi(this IServiceCollection services) } } -} \ No newline at end of file +} diff --git a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromControllers#OpenApiXmlCommentSupport.generated.verified.cs b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromControllers#OpenApiXmlCommentSupport.generated.verified.cs index 76e202554e4..4baa534fd17 100644 --- a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromControllers#OpenApiXmlCommentSupport.generated.verified.cs +++ b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromControllers#OpenApiXmlCommentSupport.generated.verified.cs @@ -70,15 +70,16 @@ private static Dictionary GenerateCacheEntries() { var cache = new Dictionary(); - cache.Add(@"M:TestController.Get~System.String", new XmlComment(@"A summary of the action.", @"A description of the action.", null, null, null, false, null, null, null)); - cache.Add(@"M:Test2Controller.Get(System.String)~System.String", new XmlComment(null, null, null, null, null, false, null, [new XmlParameterComment(@"name", @"The name of the person.", null, false)], [new XmlResponseComment(@"200", @"Returns the greeting.", @"")])); - cache.Add(@"M:Test2Controller.Get(System.Int32)~System.String", new XmlComment(null, null, null, null, null, false, null, [new XmlParameterComment(@"id", @"The id associated with the request.", null, false)], null)); - cache.Add(@"M:Test2Controller.Post(Todo)~System.String", new XmlComment(null, null, null, null, null, false, null, [new XmlParameterComment(@"todo", @"The todo to insert into the database.", null, false)], null)); + cache.Add(@"M:TestController.Get", new XmlComment(@"A summary of the action.", @"A description of the action.", null, null, null, false, null, null, null)); + cache.Add(@"M:Test2Controller.Get(System.String)", new XmlComment(null, null, null, null, null, false, null, [new XmlParameterComment(@"name", @"The name of the person.", null, false)], [new XmlResponseComment(@"200", @"Returns the greeting.", @"")])); + cache.Add(@"M:Test2Controller.Get(System.Int32)", new XmlComment(null, null, null, null, null, false, null, [new XmlParameterComment(@"id", @"The id associated with the request.", null, false)], null)); + cache.Add(@"M:Test2Controller.Post(Todo)", new XmlComment(null, null, null, null, null, false, null, [new XmlParameterComment(@"todo", @"The todo to insert into the database.", null, false)], null)); return cache; } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class DocumentationCommentIdHelper { /// @@ -288,6 +289,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool // For non-generic types, use FullName (if available) and replace nested type separators. return (type.FullName ?? type.Name).Replace('+', '.'); } + + /// + /// Normalizes a documentation comment ID to match the compiler-style format. + /// Strips the return type suffix for ordinary methods but retains it for conversion operators. + /// + /// The documentation comment ID to normalize. + /// The normalized documentation comment ID. + public static string NormalizeDocId(string docId) + { + // Find the tilde character that indicates the return type suffix + var tildeIndex = docId.IndexOf('~'); + if (tildeIndex == -1) + { + // No return type suffix, return as-is + return docId; + } + + // Check if this is a conversion operator (op_Implicit or op_Explicit) + // For these operators, we need to keep the return type suffix + if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit")) + { + return docId; + } + + // For ordinary methods, strip the return type suffix + return docId.Substring(0, tildeIndex); + } } [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] @@ -303,7 +331,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform { return Task.CompletedTask; } - if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment)) { if (methodComment.Summary is { } summary) { @@ -409,7 +437,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext { if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo }) { - if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment)) { schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary; if (propertyComment.Examples?.FirstOrDefault() is { } jsonString) @@ -418,7 +446,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } } - if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment)) { schema.Description = typeComment.Summary; if (typeComment.Examples?.FirstOrDefault() is { } jsonString) @@ -430,6 +458,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class JsonNodeExtensions { public static JsonNode? Parse(this string? json) @@ -472,4 +501,4 @@ public static IServiceCollection AddOpenApi(this IServiceCollection services) } } -} \ No newline at end of file +} diff --git a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromMinimalApis#OpenApiXmlCommentSupport.generated.verified.cs b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromMinimalApis#OpenApiXmlCommentSupport.generated.verified.cs index dbce7f0223b..fc1fbec8ab3 100644 --- a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromMinimalApis#OpenApiXmlCommentSupport.generated.verified.cs +++ b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromMinimalApis#OpenApiXmlCommentSupport.generated.verified.cs @@ -70,33 +70,34 @@ private static Dictionary GenerateCacheEntries() { var cache = new Dictionary(); - cache.Add(@"M:RouteHandlerExtensionMethods.Get~System.String", new XmlComment(@"A summary of the action.", @"A description of the action.", null, @"Returns the greeting.", null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get2(System.String)~System.String", new XmlComment(null, null, null, null, null, false, null, [new XmlParameterComment(@"name", @"The name of the person.", null, false)], [new XmlResponseComment(@"200", @"Returns the greeting.", @"")])); - cache.Add(@"M:RouteHandlerExtensionMethods.Get3(System.String)~System.String", new XmlComment(null, null, null, @"Returns the greeting.", null, false, null, [new XmlParameterComment(@"name", @"The name of the person.", @"Testy McTester", false)], null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get4~Microsoft.AspNetCore.Http.HttpResults.NotFound{System.String}", new XmlComment(null, null, null, @"Indicates that the value was not found.", null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get5~Microsoft.AspNetCore.Http.HttpResults.Results{Microsoft.AspNetCore.Http.HttpResults.NotFound{System.String},Microsoft.AspNetCore.Http.HttpResults.Ok{System.String},Microsoft.AspNetCore.Http.HttpResults.Created}", new XmlComment(null, null, null, @"This gets ignored.", null, false, null, null, [new XmlResponseComment(@"200", @"Indicates that the value is even.", @""), new XmlResponseComment(@"201", @"Indicates that the value is less than 50.", @""), new XmlResponseComment(@"404", @"Indicates that the value was not found.", @"")])); - cache.Add(@"M:RouteHandlerExtensionMethods.Post6(User)~Microsoft.AspNetCore.Http.IResult", new XmlComment(@"Creates a new user.", null, @"Sample request: + cache.Add(@"M:RouteHandlerExtensionMethods.Get", new XmlComment(@"A summary of the action.", @"A description of the action.", null, @"Returns the greeting.", null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get2(System.String)", new XmlComment(null, null, null, null, null, false, null, [new XmlParameterComment(@"name", @"The name of the person.", null, false)], [new XmlResponseComment(@"200", @"Returns the greeting.", @"")])); + cache.Add(@"M:RouteHandlerExtensionMethods.Get3(System.String)", new XmlComment(null, null, null, @"Returns the greeting.", null, false, null, [new XmlParameterComment(@"name", @"The name of the person.", @"Testy McTester", false)], null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get4", new XmlComment(null, null, null, @"Indicates that the value was not found.", null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get5", new XmlComment(null, null, null, @"This gets ignored.", null, false, null, null, [new XmlResponseComment(@"200", @"Indicates that the value is even.", @""), new XmlResponseComment(@"201", @"Indicates that the value is less than 50.", @""), new XmlResponseComment(@"404", @"Indicates that the value was not found.", @"")])); + cache.Add(@"M:RouteHandlerExtensionMethods.Post6(User)", new XmlComment(@"Creates a new user.", null, @"Sample request: POST /6 { ""username"": ""johndoe"", ""email"": ""john@example.com"" }", null, null, false, null, [new XmlParameterComment(@"user", @"The user information.", @"{""username"": ""johndoe"", ""email"": ""john@example.com""}", false)], [new XmlResponseComment(@"201", @"Successfully created the user.", @""), new XmlResponseComment(@"400", @"If the user data is invalid.", @"")])); - cache.Add(@"M:RouteHandlerExtensionMethods.Put7(System.Nullable{System.Int32},System.String)~Microsoft.AspNetCore.Http.IResult", new XmlComment(@"Updates an existing record.", null, null, null, null, false, null, [new XmlParameterComment(@"id", @"Legacy ID parameter - use uuid instead.", null, true), new XmlParameterComment(@"uuid", @"Unique identifier for the record.", null, false)], [new XmlResponseComment(@"204", @"Update successful.", @""), new XmlResponseComment(@"404", @"Legacy response - will be removed.", @"")])); - cache.Add(@"M:RouteHandlerExtensionMethods.Get8~System.Threading.Tasks.Task", new XmlComment(@"A summary of Get8.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get9~System.Threading.Tasks.ValueTask", new XmlComment(@"A summary of Get9.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get10~System.Threading.Tasks.Task", new XmlComment(@"A summary of Get10.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get11~System.Threading.Tasks.ValueTask", new XmlComment(@"A summary of Get11.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get12~System.Threading.Tasks.Task{System.String}", new XmlComment(@"A summary of Get12.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get13~System.Threading.Tasks.ValueTask{System.String}", new XmlComment(@"A summary of Get13.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get14~System.Threading.Tasks.Task{Holder{System.String}}", new XmlComment(@"A summary of Get14.", null, null, @"Returns the greeting.", null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get15~System.Threading.Tasks.Task{Holder{System.String}}", new XmlComment(@"A summary of Get15.", null, null, null, null, false, null, null, [new XmlResponseComment(@"200", @"Returns the greeting.", @"")])); + cache.Add(@"M:RouteHandlerExtensionMethods.Put7(System.Nullable{System.Int32},System.String)", new XmlComment(@"Updates an existing record.", null, null, null, null, false, null, [new XmlParameterComment(@"id", @"Legacy ID parameter - use uuid instead.", null, true), new XmlParameterComment(@"uuid", @"Unique identifier for the record.", null, false)], [new XmlResponseComment(@"204", @"Update successful.", @""), new XmlResponseComment(@"404", @"Legacy response - will be removed.", @"")])); + cache.Add(@"M:RouteHandlerExtensionMethods.Get8", new XmlComment(@"A summary of Get8.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get9", new XmlComment(@"A summary of Get9.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get10", new XmlComment(@"A summary of Get10.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get11", new XmlComment(@"A summary of Get11.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get12", new XmlComment(@"A summary of Get12.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get13", new XmlComment(@"A summary of Get13.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get14", new XmlComment(@"A summary of Get14.", null, null, @"Returns the greeting.", null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get15", new XmlComment(@"A summary of Get15.", null, null, null, null, false, null, null, [new XmlResponseComment(@"200", @"Returns the greeting.", @"")])); cache.Add(@"M:RouteHandlerExtensionMethods.Post16(Example)", new XmlComment(@"A summary of Post16.", null, null, null, null, false, null, null, null)); - cache.Add(@"M:RouteHandlerExtensionMethods.Get17(System.Int32[])~System.Int32[][]", new XmlComment(@"A summary of Get17.", null, null, null, null, false, null, null, null)); + cache.Add(@"M:RouteHandlerExtensionMethods.Get17(System.Int32[])", new XmlComment(@"A summary of Get17.", null, null, null, null, false, null, null, null)); return cache; } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class DocumentationCommentIdHelper { /// @@ -306,6 +307,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool // For non-generic types, use FullName (if available) and replace nested type separators. return (type.FullName ?? type.Name).Replace('+', '.'); } + + /// + /// Normalizes a documentation comment ID to match the compiler-style format. + /// Strips the return type suffix for ordinary methods but retains it for conversion operators. + /// + /// The documentation comment ID to normalize. + /// The normalized documentation comment ID. + public static string NormalizeDocId(string docId) + { + // Find the tilde character that indicates the return type suffix + var tildeIndex = docId.IndexOf('~'); + if (tildeIndex == -1) + { + // No return type suffix, return as-is + return docId; + } + + // Check if this is a conversion operator (op_Implicit or op_Explicit) + // For these operators, we need to keep the return type suffix + if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit")) + { + return docId; + } + + // For ordinary methods, strip the return type suffix + return docId.Substring(0, tildeIndex); + } } [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] @@ -321,7 +349,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform { return Task.CompletedTask; } - if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment)) { if (methodComment.Summary is { } summary) { @@ -427,7 +455,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext { if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo }) { - if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment)) { schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary; if (propertyComment.Examples?.FirstOrDefault() is { } jsonString) @@ -436,7 +464,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } } - if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment)) { schema.Description = typeComment.Summary; if (typeComment.Examples?.FirstOrDefault() is { } jsonString) @@ -448,6 +476,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class JsonNodeExtensions { public static JsonNode? Parse(this string? json) @@ -490,4 +519,4 @@ public static IServiceCollection AddOpenApi(this IServiceCollection services) } } -} \ No newline at end of file +} diff --git a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.SupportsXmlCommentsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.SupportsXmlCommentsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs index 915b30278e7..33e3e561e95 100644 --- a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.SupportsXmlCommentsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs +++ b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.SupportsXmlCommentsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs @@ -105,6 +105,7 @@ private static Dictionary GenerateCacheEntries() } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class DocumentationCommentIdHelper { /// @@ -314,6 +315,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool // For non-generic types, use FullName (if available) and replace nested type separators. return (type.FullName ?? type.Name).Replace('+', '.'); } + + /// + /// Normalizes a documentation comment ID to match the compiler-style format. + /// Strips the return type suffix for ordinary methods but retains it for conversion operators. + /// + /// The documentation comment ID to normalize. + /// The normalized documentation comment ID. + public static string NormalizeDocId(string docId) + { + // Find the tilde character that indicates the return type suffix + var tildeIndex = docId.IndexOf('~'); + if (tildeIndex == -1) + { + // No return type suffix, return as-is + return docId; + } + + // Check if this is a conversion operator (op_Implicit or op_Explicit) + // For these operators, we need to keep the return type suffix + if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit")) + { + return docId; + } + + // For ordinary methods, strip the return type suffix + return docId.Substring(0, tildeIndex); + } } [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] @@ -329,7 +357,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform { return Task.CompletedTask; } - if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment)) { if (methodComment.Summary is { } summary) { @@ -435,7 +463,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext { if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo }) { - if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment)) { schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary; if (propertyComment.Examples?.FirstOrDefault() is { } jsonString) @@ -444,7 +472,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } } - if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment)) + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment)) { schema.Description = typeComment.Summary; if (typeComment.Examples?.FirstOrDefault() is { } jsonString) @@ -456,6 +484,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext } } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] file static class JsonNodeExtensions { public static JsonNode? Parse(this string? json) @@ -498,4 +527,4 @@ public static IServiceCollection AddOpenApi(this IServiceCollection services) } } -} \ No newline at end of file +} diff --git a/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/XmlCommentDocumentationIdTests.CanMergeXmlCommentsWithDifferentDocumentationIdFormats#OpenApiXmlCommentSupport.generated.verified.cs b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/XmlCommentDocumentationIdTests.CanMergeXmlCommentsWithDifferentDocumentationIdFormats#OpenApiXmlCommentSupport.generated.verified.cs new file mode 100644 index 00000000000..fb09682caf3 --- /dev/null +++ b/src/aspnetcore/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/XmlCommentDocumentationIdTests.CanMergeXmlCommentsWithDifferentDocumentationIdFormats#OpenApiXmlCommentSupport.generated.verified.cs @@ -0,0 +1,501 @@ +//HintName: OpenApiXmlCommentSupport.generated.cs +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +#nullable enable +// Suppress warnings about obsolete types and members +// in generated code +#pragma warning disable CS0612, CS0618 + +namespace System.Runtime.CompilerServices +{ + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : System.Attribute + { + public InterceptsLocationAttribute(int version, string data) + { + } + } +} + +namespace Microsoft.AspNetCore.OpenApi.Generated +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.Linq; + using System.Reflection; + using System.Text; + using System.Text.Json; + using System.Text.Json.Nodes; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.AspNetCore.OpenApi; + using Microsoft.AspNetCore.Mvc.Controllers; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.OpenApi; + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + file record XmlComment( + string? Summary, + string? Description, + string? Remarks, + string? Returns, + string? Value, + bool Deprecated, + List? Examples, + List? Parameters, + List? Responses); + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + file record XmlParameterComment(string? Name, string? Description, string? Example, bool Deprecated); + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + file record XmlResponseComment(string Code, string? Description, string? Example); + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + file static class XmlCommentCache + { + private static Dictionary? _cache; + public static Dictionary Cache => _cache ??= GenerateCacheEntries(); + + private static Dictionary GenerateCacheEntries() + { + var cache = new Dictionary(); + cache.Add(@"M:ReferencedLibrary.TestApi.TestMethod(System.Int32)", new XmlComment(@"This method should have its XML comment merged properly.", null, null, @"A task representing the asynchronous operation.", null, false, null, [new XmlParameterComment(@"id", @"The identifier for the test.", null, false)], null)); + + + return cache; + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + file static class DocumentationCommentIdHelper + { + /// + /// Generates a documentation comment ID for a type. + /// Example: T:Namespace.Outer+Inner`1 becomes T:Namespace.Outer.Inner`1 + /// + public static string CreateDocumentationId(this Type type) + { + if (type == null) + { + throw new ArgumentNullException(nameof(type)); + } + + return "T:" + GetTypeDocId(type, includeGenericArguments: false, omitGenericArity: false); + } + + /// + /// Generates a documentation comment ID for a property. + /// Example: P:Namespace.ContainingType.PropertyName or for an indexer P:Namespace.ContainingType.Item(System.Int32) + /// + public static string CreateDocumentationId(this PropertyInfo property) + { + if (property == null) + { + throw new ArgumentNullException(nameof(property)); + } + + var sb = new StringBuilder(); + sb.Append("P:"); + + if (property.DeclaringType != null) + { + sb.Append(GetTypeDocId(property.DeclaringType, includeGenericArguments: false, omitGenericArity: false)); + } + + sb.Append('.'); + sb.Append(property.Name); + + // For indexers, include the parameter list. + var indexParams = property.GetIndexParameters(); + if (indexParams.Length > 0) + { + sb.Append('('); + for (int i = 0; i < indexParams.Length; i++) + { + if (i > 0) + { + sb.Append(','); + } + + sb.Append(GetTypeDocId(indexParams[i].ParameterType, includeGenericArguments: true, omitGenericArity: false)); + } + sb.Append(')'); + } + + return sb.ToString(); + } + + /// + /// Generates a documentation comment ID for a method (or constructor). + /// For example: + /// M:Namespace.ContainingType.MethodName(ParamType1,ParamType2)~ReturnType + /// M:Namespace.ContainingType.#ctor(ParamType) + /// + public static string CreateDocumentationId(this MethodInfo method) + { + if (method == null) + { + throw new ArgumentNullException(nameof(method)); + } + + var sb = new StringBuilder(); + sb.Append("M:"); + + // Append the fully qualified name of the declaring type. + if (method.DeclaringType != null) + { + sb.Append(GetTypeDocId(method.DeclaringType, includeGenericArguments: false, omitGenericArity: false)); + } + + sb.Append('.'); + + // Append the method name, handling constructors specially. + if (method.IsConstructor) + { + sb.Append(method.IsStatic ? "#cctor" : "#ctor"); + } + else + { + sb.Append(method.Name); + if (method.IsGenericMethod) + { + sb.Append("``"); + sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", method.GetGenericArguments().Length); + } + } + + // Append the parameter list, if any. + var parameters = method.GetParameters(); + if (parameters.Length > 0) + { + sb.Append('('); + for (int i = 0; i < parameters.Length; i++) + { + if (i > 0) + { + sb.Append(','); + } + + // Omit the generic arity for the parameter type. + sb.Append(GetTypeDocId(parameters[i].ParameterType, includeGenericArguments: true, omitGenericArity: true)); + } + sb.Append(')'); + } + + // Append the return type after a '~' (if the method returns a value). + if (method.ReturnType != typeof(void)) + { + sb.Append('~'); + // Omit the generic arity for the return type. + sb.Append(GetTypeDocId(method.ReturnType, includeGenericArguments: true, omitGenericArity: true)); + } + + return sb.ToString(); + } + + /// + /// Generates a documentation ID string for a type. + /// This method handles nested types (replacing '+' with '.'), + /// generic types, arrays, pointers, by-ref types, and generic parameters. + /// The flag controls whether + /// constructed generic type arguments are emitted, while + /// controls whether the generic arity marker (e.g. "`1") is appended. + /// + private static string GetTypeDocId(Type type, bool includeGenericArguments, bool omitGenericArity) + { + if (type.IsGenericParameter) + { + // Use `` for method-level generic parameters and ` for type-level. + if (type.DeclaringMethod != null) + { + return "``" + type.GenericParameterPosition; + } + else if (type.DeclaringType != null) + { + return "`" + type.GenericParameterPosition; + } + else + { + return type.Name; + } + } + + if (type.IsGenericType) + { + Type genericDef = type.GetGenericTypeDefinition(); + string fullName = genericDef.FullName ?? genericDef.Name; + + var sb = new StringBuilder(fullName.Length); + + // Replace '+' with '.' for nested types + for (var i = 0; i < fullName.Length; i++) + { + char c = fullName[i]; + if (c == '+') + { + sb.Append('.'); + } + else if (c == '`') + { + break; + } + else + { + sb.Append(c); + } + } + + if (!omitGenericArity) + { + int arity = genericDef.GetGenericArguments().Length; + sb.Append('`'); + sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", arity); + } + + if (includeGenericArguments && !type.IsGenericTypeDefinition) + { + var typeArgs = type.GetGenericArguments(); + sb.Append('{'); + + for (int i = 0; i < typeArgs.Length; i++) + { + if (i > 0) + { + sb.Append(','); + } + + sb.Append(GetTypeDocId(typeArgs[i], includeGenericArguments, omitGenericArity)); + } + + sb.Append('}'); + } + + return sb.ToString(); + } + + // For non-generic types, use FullName (if available) and replace nested type separators. + return (type.FullName ?? type.Name).Replace('+', '.'); + } + + /// + /// Normalizes a documentation comment ID to match the compiler-style format. + /// Strips the return type suffix for ordinary methods but retains it for conversion operators. + /// + /// The documentation comment ID to normalize. + /// The normalized documentation comment ID. + public static string NormalizeDocId(string docId) + { + // Find the tilde character that indicates the return type suffix + var tildeIndex = docId.IndexOf('~'); + if (tildeIndex == -1) + { + // No return type suffix, return as-is + return docId; + } + + // Check if this is a conversion operator (op_Implicit or op_Explicit) + // For these operators, we need to keep the return type suffix + if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit")) + { + return docId; + } + + // For ordinary methods, strip the return type suffix + return docId.Substring(0, tildeIndex); + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + file class XmlCommentOperationTransformer : IOpenApiOperationTransformer + { + public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransformerContext context, CancellationToken cancellationToken) + { + var methodInfo = context.Description.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor + ? controllerActionDescriptor.MethodInfo + : context.Description.ActionDescriptor.EndpointMetadata.OfType().SingleOrDefault(); + + if (methodInfo is null) + { + return Task.CompletedTask; + } + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment)) + { + if (methodComment.Summary is { } summary) + { + operation.Summary = summary; + } + if (methodComment.Description is { } description) + { + operation.Description = description; + } + if (methodComment.Remarks is { } remarks) + { + operation.Description = remarks; + } + if (methodComment.Parameters is { Count: > 0}) + { + foreach (var parameterComment in methodComment.Parameters) + { + var parameterInfo = methodInfo.GetParameters().SingleOrDefault(info => info.Name == parameterComment.Name); + var operationParameter = operation.Parameters?.SingleOrDefault(parameter => parameter.Name == parameterComment.Name); + if (operationParameter is not null) + { + var targetOperationParameter = UnwrapOpenApiParameter(operationParameter); + targetOperationParameter.Description = parameterComment.Description; + if (parameterComment.Example is { } jsonString) + { + targetOperationParameter.Example = jsonString.Parse(); + } + targetOperationParameter.Deprecated = parameterComment.Deprecated; + } + else + { + var requestBody = operation.RequestBody; + if (requestBody is not null) + { + requestBody.Description = parameterComment.Description; + if (parameterComment.Example is { } jsonString) + { + var content = requestBody?.Content?.Values; + if (content is null) + { + continue; + } + foreach (var mediaType in content) + { + mediaType.Example = jsonString.Parse(); + } + } + } + } + } + } + // Applies `` on XML comments for operation with single response value. + if (methodComment.Returns is { } returns && operation.Responses is { Count: 1 }) + { + var response = operation.Responses.First(); + response.Value.Description = returns; + } + // Applies `` on XML comments for operation with multiple response values. + if (methodComment.Responses is { Count: > 0} && operation.Responses is { Count: > 0 }) + { + foreach (var response in operation.Responses) + { + var responseComment = methodComment.Responses.SingleOrDefault(xmlResponse => xmlResponse.Code == response.Key); + if (responseComment is not null) + { + response.Value.Description = responseComment.Description; + } + } + } + } + + return Task.CompletedTask; + } + + private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceParameter) + { + if (sourceParameter is OpenApiParameterReference parameterReference) + { + if (parameterReference.Target is OpenApiParameter target) + { + return target; + } + else + { + throw new InvalidOperationException($"The input schema must be an {nameof(OpenApiParameter)} or {nameof(OpenApiParameterReference)}."); + } + } + else if (sourceParameter is OpenApiParameter directParameter) + { + return directParameter; + } + else + { + throw new InvalidOperationException($"The input schema must be an {nameof(OpenApiParameter)} or {nameof(OpenApiParameterReference)}."); + } + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + file class XmlCommentSchemaTransformer : IOpenApiSchemaTransformer + { + public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext context, CancellationToken cancellationToken) + { + if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo }) + { + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment)) + { + schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary; + if (propertyComment.Examples?.FirstOrDefault() is { } jsonString) + { + schema.Example = jsonString.Parse(); + } + } + } + if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment)) + { + schema.Description = typeComment.Summary; + if (typeComment.Examples?.FirstOrDefault() is { } jsonString) + { + schema.Example = jsonString.Parse(); + } + } + return Task.CompletedTask; + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + file static class JsonNodeExtensions + { + public static JsonNode? Parse(this string? json) + { + if (json is null) + { + return null; + } + + try + { + return JsonNode.Parse(json); + } + catch (JsonException) + { + try + { + // If parsing fails, try wrapping in quotes to make it a valid JSON string + return JsonNode.Parse($"\"{json.Replace("\"", "\\\"")}\""); + } + catch (JsonException) + { + return null; + } + } + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")] + file static class GeneratedServiceCollectionExtensions + { + [InterceptsLocation] + public static IServiceCollection AddOpenApi(this IServiceCollection services) + { + return services.AddOpenApi("v1", options => + { + options.AddSchemaTransformer(new XmlCommentSchemaTransformer()); + options.AddOperationTransformer(new XmlCommentOperationTransformer()); + }); + } + + } +} \ No newline at end of file diff --git a/src/command-line-api/src/System.CommandLine.Tests/VersionOptionTests.cs b/src/command-line-api/src/System.CommandLine.Tests/VersionOptionTests.cs index 5e7f528ab2c..135f0a8b143 100644 --- a/src/command-line-api/src/System.CommandLine.Tests/VersionOptionTests.cs +++ b/src/command-line-api/src/System.CommandLine.Tests/VersionOptionTests.cs @@ -37,7 +37,7 @@ public async Task When_the_version_option_is_specified_then_invocation_is_short_ { var wasCalled = false; var rootCommand = new RootCommand(); - rootCommand.SetAction((_) => wasCalled = true); + rootCommand.SetAction(_ => wasCalled = true); var output = new StringWriter(); @@ -46,6 +46,21 @@ public async Task When_the_version_option_is_specified_then_invocation_is_short_ wasCalled.Should().BeFalse(); } + [Fact] // https://github.com/dotnet/command-line-api/issues/2628 + public void When_the_version_option_is_specified_then_there_are_no_parse_errors_due_to_unspecified_subcommand() + { + Command subcommand = new("subcommand"); + RootCommand root = new() + { + subcommand + }; + subcommand.SetAction(_ => 0); + + var parseResult = root.Parse("--version"); + + parseResult.Errors.Should().BeEmpty(); + } + [Fact] public async Task Version_option_appears_in_help() { diff --git a/src/command-line-api/src/System.CommandLine/ParserConfiguration.cs b/src/command-line-api/src/System.CommandLine/ParserConfiguration.cs index f239c3c4b4c..c3a8b061458 100644 --- a/src/command-line-api/src/System.CommandLine/ParserConfiguration.cs +++ b/src/command-line-api/src/System.CommandLine/ParserConfiguration.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.CommandLine.Parsing; -using System.Linq; namespace System.CommandLine { diff --git a/src/command-line-api/src/System.CommandLine/Parsing/CommandResult.cs b/src/command-line-api/src/System.CommandLine/Parsing/CommandResult.cs index 6561f5a3869..ae4bd2922f2 100644 --- a/src/command-line-api/src/System.CommandLine/Parsing/CommandResult.cs +++ b/src/command-line-api/src/System.CommandLine/Parsing/CommandResult.cs @@ -43,17 +43,10 @@ internal CommandResult( internal override bool UseDefaultValueFor(ArgumentResult argumentResult) => argumentResult.Argument.HasDefaultValue && argumentResult.Tokens.Count == 0; - /// Only the inner most command goes through complete validation. - internal void Validate(bool completeValidation) + internal void Validate(bool isInnermostCommand) { - if (completeValidation) + if (isInnermostCommand) { - if (Command.Action is null && Command.HasSubcommands) - { - SymbolResultTree.InsertFirstError( - new ParseError(LocalizationResources.RequiredCommandWasNotProvided(), this)); - } - if (Command.HasValidators) { int errorCountBefore = SymbolResultTree.ErrorCount; @@ -71,12 +64,12 @@ internal void Validate(bool completeValidation) if (Command.HasOptions) { - ValidateOptionsAndAddDefaultResults(completeValidation); + ValidateOptionsAndAddDefaultResults(isInnermostCommand); } if (Command.HasArguments) { - ValidateArgumentsAndAddDefaultResults(completeValidation); + ValidateArgumentsAndAddDefaultResults(isInnermostCommand); } } diff --git a/src/command-line-api/src/System.CommandLine/Parsing/ParseOperation.cs b/src/command-line-api/src/System.CommandLine/Parsing/ParseOperation.cs index 8ac410566ce..c5c7b9fdf84 100644 --- a/src/command-line-api/src/System.CommandLine/Parsing/ParseOperation.cs +++ b/src/command-line-api/src/System.CommandLine/Parsing/ParseOperation.cs @@ -63,6 +63,7 @@ internal ParseResult Parse() ValidateAndAddDefaultResults(); + if (_isHelpRequested) { _symbolResultTree.Errors?.Clear(); @@ -373,17 +374,24 @@ private void AddCurrentTokenToUnmatched() private void ValidateAndAddDefaultResults() { - // Only the inner most command goes through complete validation, + // Only the innermost command goes through complete validation, // for other commands only a subset of options is checked. - _innermostCommandResult.Validate(completeValidation: true); + _innermostCommandResult.Validate(isInnermostCommand: true); CommandResult? currentResult = _innermostCommandResult.Parent as CommandResult; while (currentResult is not null) { - currentResult.Validate(completeValidation: false); + currentResult.Validate(isInnermostCommand: false); currentResult = currentResult.Parent as CommandResult; } + + if (_primaryAction is null && + _innermostCommandResult is { Command: { Action: null, HasSubcommands: true } }) + { + _symbolResultTree.InsertFirstError( + new ParseError(LocalizationResources.RequiredCommandWasNotProvided(), _innermostCommandResult)); + } } } } \ No newline at end of file diff --git a/src/diagnostics/eng/InstallRuntimes.proj b/src/diagnostics/eng/InstallRuntimes.proj index 9dbfd87967d..7b137bd2d3d 100644 --- a/src/diagnostics/eng/InstallRuntimes.proj +++ b/src/diagnostics/eng/InstallRuntimes.proj @@ -113,7 +113,7 @@ 6.0.0 4.0.0-beta.25359.1 17.10.0-beta1.24272.1 - 3.1.21 + 3.1.23 6.0.0 6.0.4 6.0.0 diff --git a/src/diagnostics/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClientExceptions.cs b/src/diagnostics/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClientExceptions.cs index e9c2f15c426..c49984572e2 100644 --- a/src/diagnostics/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClientExceptions.cs +++ b/src/diagnostics/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClientExceptions.cs @@ -21,6 +21,7 @@ public UnsupportedProtocolException(string msg) : base(msg) { } public class ServerNotAvailableException : DiagnosticsClientException { public ServerNotAvailableException(string msg) : base(msg) { } + public ServerNotAvailableException(string msg, Exception exception) : base(msg, exception) { } } // When the runtime responded with an error diff --git a/src/diagnostics/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcTransport.cs b/src/diagnostics/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcTransport.cs index 7d4fb0a909a..de15869988a 100644 --- a/src/diagnostics/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcTransport.cs +++ b/src/diagnostics/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcTransport.cs @@ -6,6 +6,7 @@ using System.IO; using System.IO.Pipes; using System.Linq; +using System.Net.Sockets; using System.Runtime.InteropServices; using System.Security.Principal; using System.Threading; @@ -20,6 +21,7 @@ internal abstract class IpcEndpoint /// /// The amount of time to block attempting to connect /// A stream used for writing and reading data to and from the target .NET process + /// ServerNotAvailableException public abstract Stream Connect(TimeSpan timeout); /// @@ -29,6 +31,7 @@ internal abstract class IpcEndpoint /// /// A task that completes with a stream used for writing and reading data to and from the target .NET process. /// + /// ServerNotAvailableException public abstract Task ConnectAsync(CancellationToken token); /// @@ -51,66 +54,81 @@ internal static class IpcEndpointHelper { public static Stream Connect(IpcEndpointConfig config, TimeSpan timeout) { - if (config.Transport == IpcEndpointConfig.TransportType.NamedPipe) - { - NamedPipeClientStream namedPipe = new( - ".", - config.Address, - PipeDirection.InOut, - PipeOptions.None, - TokenImpersonationLevel.Impersonation); - namedPipe.Connect((int)timeout.TotalMilliseconds); - return namedPipe; - } - else if (config.Transport == IpcEndpointConfig.TransportType.UnixDomainSocket) + try { - IpcUnixDomainSocket socket = new(); - socket.Connect(new IpcUnixDomainSocketEndPoint(config.Address), timeout); - return new ExposedSocketNetworkStream(socket, ownsSocket: true); - } + if (config.Transport == IpcEndpointConfig.TransportType.NamedPipe) + { + NamedPipeClientStream namedPipe = new( + ".", + config.Address, + PipeDirection.InOut, + PipeOptions.None, + TokenImpersonationLevel.Impersonation); + namedPipe.Connect((int)timeout.TotalMilliseconds); + return namedPipe; + } + else if (config.Transport == IpcEndpointConfig.TransportType.UnixDomainSocket) + { + IpcUnixDomainSocket socket = new(); + socket.Connect(new IpcUnixDomainSocketEndPoint(config.Address), timeout); + return new ExposedSocketNetworkStream(socket, ownsSocket: true); + } #if DIAGNOSTICS_RUNTIME - else if (config.Transport == IpcEndpointConfig.TransportType.TcpSocket) - { - var tcpClient = new TcpClient (); - var endPoint = new IpcTcpSocketEndPoint(config.Address); - tcpClient.Connect(endPoint.EndPoint); - return tcpClient.GetStream(); - } + else if (config.Transport == IpcEndpointConfig.TransportType.TcpSocket) + { + var tcpClient = new TcpClient (); + var endPoint = new IpcTcpSocketEndPoint(config.Address); + tcpClient.Connect(endPoint.EndPoint); + return tcpClient.GetStream(); + } #endif - else + else + { + throw new ArgumentException($"Unsupported IpcEndpointConfig transport type {config.Transport}"); + } + + } + catch (SocketException ex) { - throw new ArgumentException($"Unsupported IpcEndpointConfig transport type {config.Transport}"); + throw new ServerNotAvailableException($"Unable to connect to the server. {ex.Message}", ex); } } public static async Task ConnectAsync(IpcEndpointConfig config, CancellationToken token) { - if (config.Transport == IpcEndpointConfig.TransportType.NamedPipe) - { - NamedPipeClientStream namedPipe = new( - ".", - config.Address, - PipeDirection.InOut, - PipeOptions.Asynchronous, - TokenImpersonationLevel.Impersonation); - - // Pass non-infinite timeout in order to cause internal connection algorithm - // to check the CancellationToken periodically. Otherwise, if the named pipe - // is waited using WaitNamedPipe with an infinite timeout, then the - // CancellationToken cannot be observed. - await namedPipe.ConnectAsync(int.MaxValue, token).ConfigureAwait(false); - - return namedPipe; - } - else if (config.Transport == IpcEndpointConfig.TransportType.UnixDomainSocket) + try { - IpcUnixDomainSocket socket = new(); - await socket.ConnectAsync(new IpcUnixDomainSocketEndPoint(config.Address), token).ConfigureAwait(false); - return new ExposedSocketNetworkStream(socket, ownsSocket: true); + if (config.Transport == IpcEndpointConfig.TransportType.NamedPipe) + { + NamedPipeClientStream namedPipe = new( + ".", + config.Address, + PipeDirection.InOut, + PipeOptions.Asynchronous, + TokenImpersonationLevel.Impersonation); + + // Pass non-infinite timeout in order to cause internal connection algorithm + // to check the CancellationToken periodically. Otherwise, if the named pipe + // is waited using WaitNamedPipe with an infinite timeout, then the + // CancellationToken cannot be observed. + await namedPipe.ConnectAsync(int.MaxValue, token).ConfigureAwait(false); + + return namedPipe; + } + else if (config.Transport == IpcEndpointConfig.TransportType.UnixDomainSocket) + { + IpcUnixDomainSocket socket = new(); + await socket.ConnectAsync(new IpcUnixDomainSocketEndPoint(config.Address), token).ConfigureAwait(false); + return new ExposedSocketNetworkStream(socket, ownsSocket: true); + } + else + { + throw new ArgumentException($"Unsupported IpcEndpointConfig transport type {config.Transport}"); + } } - else + catch (SocketException ex) { - throw new ArgumentException($"Unsupported IpcEndpointConfig transport type {config.Transport}"); + throw new ServerNotAvailableException($"Unable to connect to the server. {ex.Message}", ex); } } } @@ -221,10 +239,13 @@ internal class PidIpcEndpoint : IpcEndpoint { public static string IpcRootPath { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? @"\\.\pipe\" : Path.GetTempPath(); public static string DiagnosticsPortPattern { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? @"^dotnet-diagnostic-(\d+)$" : @"^dotnet-diagnostic-(\d+)-(\d+)-socket$"; - + // Format strings as private const members + private const string _defaultAddressFormatWindows = "dotnet-diagnostic-{0}"; + private const string _dsrouterAddressFormatWindows = "dotnet-diagnostic-dsrouter-{0}"; + private const string _defaultAddressFormatNonWindows = "dotnet-diagnostic-{0}-{1}-socket"; + private const string _dsrouterAddressFormatNonWindows = "dotnet-diagnostic-dsrouter-{0}-{1}-socket"; private int _pid; private IpcEndpointConfig _config; - /// /// Creates a reference to a .NET process's IPC Transport /// using the default rules for a given pid @@ -271,11 +292,11 @@ private static bool TryGetDefaultAddress(int pid, out string defaultAddress) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - defaultAddress = $"dotnet-diagnostic-{pid}"; + defaultAddress = string.Format(_defaultAddressFormatWindows, pid); try { - string dsrouterAddress = Directory.GetFiles(IpcRootPath, $"dotnet-diagnostic-dsrouter-{pid}").FirstOrDefault(); + string dsrouterAddress = Directory.GetFiles(IpcRootPath, string.Format(_dsrouterAddressFormatWindows, pid)).FirstOrDefault(); if (!string.IsNullOrEmpty(dsrouterAddress)) { defaultAddress = dsrouterAddress; @@ -287,11 +308,11 @@ private static bool TryGetDefaultAddress(int pid, out string defaultAddress) { try { - defaultAddress = Directory.GetFiles(IpcRootPath, $"dotnet-diagnostic-{pid}-*-socket") // Try best match. + defaultAddress = Directory.GetFiles(IpcRootPath, string.Format(_defaultAddressFormatNonWindows, pid, "*")) // Try best match. .OrderByDescending(f => new FileInfo(f).LastWriteTime) .FirstOrDefault(); - string dsrouterAddress = Directory.GetFiles(IpcRootPath, $"dotnet-diagnostic-dsrouter-{pid}-*-socket") // Try best match. + string dsrouterAddress = Directory.GetFiles(IpcRootPath, string.Format(_dsrouterAddressFormatNonWindows, pid, "*")) // Try best match. .OrderByDescending(f => new FileInfo(f).LastWriteTime) .FirstOrDefault(); @@ -332,8 +353,15 @@ public static string GetDefaultAddress(int pid) string msg = $"Unable to connect to Process {pid}."; if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + int total_length = IpcRootPath.Length + string.Format(_defaultAddressFormatNonWindows, pid, "##########").Length; + if (total_length > 108) // This isn't perfect as we don't know the disambiguation key length. However it should catch most cases. + { + msg += "The total length of the diagnostic socket path may exceed 108 characters. " + + "Try setting the TMPDIR environment variable to a shorter path"; + } msg += $" Please verify that {IpcRootPath} is writable by the current user. " + "If the target process has environment variable TMPDIR set, please set TMPDIR to the same directory. " + + "Please also ensure that the target process has {TMPDIR}/dotnet-diagnostic-{pid}-{disambiguation_key}-socket shorter than 108 characters. " + "Please see https://aka.ms/dotnet-diagnostics-port for more information"; } throw new ServerNotAvailableException(msg); @@ -349,7 +377,7 @@ public static bool IsDefaultAddressDSRouter(int pid, string address) address = address.Substring(IpcRootPath.Length); } - string dsrouterAddress = $"dotnet-diagnostic-dsrouter-{pid}"; + string dsrouterAddress = string.Format(_dsrouterAddressFormatWindows, pid); return address.StartsWith(dsrouterAddress, StringComparison.OrdinalIgnoreCase); } diff --git a/src/diagnostics/src/Microsoft.Diagnostics.TestHelpers/SdkPrebuiltDebuggeeCompiler.cs b/src/diagnostics/src/Microsoft.Diagnostics.TestHelpers/SdkPrebuiltDebuggeeCompiler.cs index d397dd809e4..ebc4105d435 100644 --- a/src/diagnostics/src/Microsoft.Diagnostics.TestHelpers/SdkPrebuiltDebuggeeCompiler.cs +++ b/src/diagnostics/src/Microsoft.Diagnostics.TestHelpers/SdkPrebuiltDebuggeeCompiler.cs @@ -15,6 +15,15 @@ public class SdkPrebuiltDebuggeeCompiler : IDebuggeeCompiler public SdkPrebuiltDebuggeeCompiler(TestConfiguration config, string debuggeeName) { + if (string.IsNullOrEmpty(config.TargetConfiguration)) + { + throw new System.ArgumentException("TargetConfiguration must be set in the TestConfiguration"); + } + if (string.IsNullOrEmpty(config.BuildProjectFramework)) + { + throw new System.ArgumentException("BuildProjectFramework must be set in the TestConfiguration"); + } + // The layout is how the current .NET Core SDK layouts the binaries out: // Source Path: //[] // Binary Path: /bin/// diff --git a/src/diagnostics/src/tests/CommonTestRunner/TestRunner.cs b/src/diagnostics/src/tests/CommonTestRunner/TestRunner.cs index 730dac25d1e..47497f6826d 100644 --- a/src/diagnostics/src/tests/CommonTestRunner/TestRunner.cs +++ b/src/diagnostics/src/tests/CommonTestRunner/TestRunner.cs @@ -49,6 +49,10 @@ public static async Task Create(TestConfiguration config, ITestOutpu // Get the full debuggee launch command line (includes the host if required) string exePath = debuggeeConfig.BinaryExePath; + if (!File.Exists(exePath)) + { + throw new FileNotFoundException($"Expected to find target executable at {exePath} but it didn't exist. Perhaps the path was improperly configured or a build/deployment error caused the file to be missing?"); + } string pipeName = null; StringBuilder arguments = new(); diff --git a/src/diagnostics/src/tests/Microsoft.Diagnostics.Monitoring.EventPipe/EventCounterPipelineUnitTests.cs b/src/diagnostics/src/tests/Microsoft.Diagnostics.Monitoring.EventPipe/EventCounterPipelineUnitTests.cs index 973e2d5a8cd..2fb091ea9bf 100644 --- a/src/diagnostics/src/tests/Microsoft.Diagnostics.Monitoring.EventPipe/EventCounterPipelineUnitTests.cs +++ b/src/diagnostics/src/tests/Microsoft.Diagnostics.Monitoring.EventPipe/EventCounterPipelineUnitTests.cs @@ -59,8 +59,9 @@ private sealed class TestMetricsLogger : ICountersLogger private readonly List _expectedCounters = new(); private Dictionary _metrics = new(); private readonly TaskCompletionSource _foundExpectedCountersSource; + private readonly ITestOutputHelper _output; - public TestMetricsLogger(IEnumerable expectedCounters, TaskCompletionSource foundExpectedCountersSource) + public TestMetricsLogger(IEnumerable expectedCounters, TaskCompletionSource foundExpectedCountersSource, ITestOutputHelper output) { _foundExpectedCountersSource = foundExpectedCountersSource; _expectedCounters = new(expectedCounters); @@ -68,6 +69,7 @@ public TestMetricsLogger(IEnumerable expectedCounters, TaskComp { foundExpectedCountersSource.SetResult(null); } + _output = output; } public IEnumerable Metrics => _metrics.Values; @@ -90,17 +92,29 @@ public void Log(ICounterPayload payload) ExpectedCounter expectedCounter = _expectedCounters.Find(c => c.MatchesCounterMetadata(payload.CounterMetadata)); if(expectedCounter != null) { + _expectedCounters.Remove(expectedCounter); _metrics.Add(expectedCounter, payload); + + _output.WriteLine($"Found expected counter: {expectedCounter.ProviderName}/{expectedCounter.CounterName}. Counters remaining={_expectedCounters.Count}"); // Complete the task source if the last expected key was removed. if (_expectedCounters.Count == 0) { + _output.WriteLine($"All expected counters have been received. Signaling pipeline can exit."); _foundExpectedCountersSource.TrySetResult(null); } } + else + { + _output.WriteLine($"Received additional counter event: {payload.CounterMetadata.ProviderName}/{payload.CounterMetadata.CounterName}"); + } } - public Task PipelineStarted(CancellationToken token) => Task.CompletedTask; + public Task PipelineStarted(CancellationToken token) + { + _output.WriteLine("Counters pipeline is running. Waiting to receive expected counters from tracee."); + return Task.CompletedTask; + } public Task PipelineStopped(CancellationToken token) => Task.CompletedTask; } @@ -113,7 +127,7 @@ public async Task TestCounterEventPipeline(TestConfiguration config) TaskCompletionSource foundExpectedCountersSource = new(TaskCreationOptions.RunContinuationsAsynchronously); - TestMetricsLogger logger = new(expectedCounters.Select(name => new ExpectedCounter(expectedProvider, name)), foundExpectedCountersSource); + TestMetricsLogger logger = new(expectedCounters.Select(name => new ExpectedCounter(expectedProvider, name)), foundExpectedCountersSource, _output); await using (TestRunner testRunner = await PipelineTestUtilities.StartProcess(config, "CounterRemoteTest", _output)) { @@ -169,7 +183,7 @@ public async Task TestDuplicateNameMetrics(TestConfiguration config) new ExpectedCounter(providerName, counterName, "MeterTag=two","InstrumentTag=B"), ]; TaskCompletionSource foundExpectedCountersSource = new(TaskCreationOptions.RunContinuationsAsynchronously); - TestMetricsLogger logger = new(expectedCounters, foundExpectedCountersSource); + TestMetricsLogger logger = new(expectedCounters, foundExpectedCountersSource, _output); await using (TestRunner testRunner = await PipelineTestUtilities.StartProcess(config, "DuplicateNameMetrics", _output, testProcessTimeout: 3_000)) { diff --git a/src/diagnostics/src/tests/Microsoft.Diagnostics.NETCore.Client/GetProcessInfoTests.cs b/src/diagnostics/src/tests/Microsoft.Diagnostics.NETCore.Client/GetProcessInfoTests.cs index 961ee8123e2..7f7181bc478 100644 --- a/src/diagnostics/src/tests/Microsoft.Diagnostics.NETCore.Client/GetProcessInfoTests.cs +++ b/src/diagnostics/src/tests/Microsoft.Diagnostics.NETCore.Client/GetProcessInfoTests.cs @@ -74,7 +74,22 @@ private async Task BasicProcessInfoTestCore(TestConfiguration config, bool useAs ProcessInfo processInfoBeforeResume = null; if (suspend) { - processInfoBeforeResume = await clientShim.GetProcessInfo(); + // when the process is just starting up, the IPC channel may not be ready yet. We need to be prepared for the connection attempt to fail. + // If 100 retries over 10 seconds fail then we'll go ahead and fail the test. + const int retryCount = 100; + for (int i = 0; i < retryCount; i++) + { + try + { + processInfoBeforeResume = await clientShim.GetProcessInfo(); + break; + } + catch (ServerNotAvailableException) when (i < retryCount-1) + { + _output.WriteLine($"Failed to connect to the IPC channel as the process is starting up. Attempt {i+1} of {retryCount}. Waiting 0.1 seconds, then retrying."); + await Task.Delay(100); + } + } ValidateProcessInfo(runner.Pid, processInfoBeforeResume); Assert.True((config.RuntimeFrameworkVersionMajor < 8) == string.IsNullOrEmpty(processInfoBeforeResume.ManagedEntrypointAssemblyName)); diff --git a/src/efcore/eng/Version.Details.xml b/src/efcore/eng/Version.Details.xml index 748a4119e16..a88e269d18e 100644 --- a/src/efcore/eng/Version.Details.xml +++ b/src/efcore/eng/Version.Details.xml @@ -1,80 +1,80 @@ - + - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 diff --git a/src/efcore/eng/Versions.props b/src/efcore/eng/Versions.props index e0dd2995e1c..e2a9f7d63f0 100644 --- a/src/efcore/eng/Versions.props +++ b/src/efcore/eng/Versions.props @@ -16,24 +16,24 @@ False - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 - 10.0.0-beta.25360.101 + 10.0.0-beta.25364.102 17.14.8 diff --git a/src/efcore/global.json b/src/efcore/global.json index 81b3c4ca1fa..7cb1bad5cb7 100644 --- a/src/efcore/global.json +++ b/src/efcore/global.json @@ -18,7 +18,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25360.101", - "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25360.101" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25364.102", + "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25364.102" } } diff --git a/src/efcore/src/EFCore.Relational/Query/Internal/GroupBySingleQueryingEnumerable.cs b/src/efcore/src/EFCore.Relational/Query/Internal/GroupBySingleQueryingEnumerable.cs index af0eb423bff..24f47e554a4 100644 --- a/src/efcore/src/EFCore.Relational/Query/Internal/GroupBySingleQueryingEnumerable.cs +++ b/src/efcore/src/EFCore.Relational/Query/Internal/GroupBySingleQueryingEnumerable.cs @@ -145,7 +145,7 @@ public virtual DbCommand CreateDbCommand() _relationalQueryContext.Connection, _relationalQueryContext.Parameters, null, - null, + _relationalQueryContext.Context, null, CommandSource.LinqQuery), Guid.Empty, (DbCommandMethod)(-1)); diff --git a/src/efcore/src/EFCore.Relational/Query/Internal/GroupBySplitQueryingEnumerable.cs b/src/efcore/src/EFCore.Relational/Query/Internal/GroupBySplitQueryingEnumerable.cs index e8b67872908..1696922220b 100644 --- a/src/efcore/src/EFCore.Relational/Query/Internal/GroupBySplitQueryingEnumerable.cs +++ b/src/efcore/src/EFCore.Relational/Query/Internal/GroupBySplitQueryingEnumerable.cs @@ -155,7 +155,7 @@ public virtual DbCommand CreateDbCommand() _relationalQueryContext.Connection, _relationalQueryContext.Parameters, null, - null, + _relationalQueryContext.Context, null, CommandSource.LinqQuery), Guid.Empty, (DbCommandMethod)(-1)); diff --git a/src/efcore/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs b/src/efcore/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs index 5a79eb34b9e..85b999e82a0 100644 --- a/src/efcore/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs +++ b/src/efcore/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs @@ -129,7 +129,7 @@ public virtual DbCommand CreateDbCommand() _relationalQueryContext.Connection, _relationalQueryContext.Parameters, null, - null, + _relationalQueryContext.Context, null, CommandSource.LinqQuery), Guid.Empty, (DbCommandMethod)(-1)); diff --git a/src/efcore/src/EFCore.Sqlite.Core/Storage/Internal/SqliteDatabaseCreator.cs b/src/efcore/src/EFCore.Sqlite.Core/Storage/Internal/SqliteDatabaseCreator.cs index 681a08b37b7..311abf79b3d 100644 --- a/src/efcore/src/EFCore.Sqlite.Core/Storage/Internal/SqliteDatabaseCreator.cs +++ b/src/efcore/src/EFCore.Sqlite.Core/Storage/Internal/SqliteDatabaseCreator.cs @@ -52,7 +52,7 @@ public override void Create() Dependencies.Connection, null, null, - null, + Dependencies.CurrentContext.Context, Dependencies.CommandLogger, CommandSource.Migrations)); Dependencies.Connection.Close(); @@ -101,7 +101,7 @@ public override bool HasTables() Dependencies.Connection, null, null, - null, + Dependencies.CurrentContext.Context, Dependencies.CommandLogger, CommandSource.Migrations))!; return count != 0; diff --git a/src/razor/eng/Versions.props b/src/razor/eng/Versions.props index c5567b25ea5..b363b6efa43 100644 --- a/src/razor/eng/Versions.props +++ b/src/razor/eng/Versions.props @@ -30,7 +30,7 @@ imported. This OK because we want to just have an obvious salt for a local build. --> - 17.15.1 + 17.15.2 17.15 $(AddinMajorVersion) $(AddinVersion).$(OfficialBuildId) diff --git a/src/razor/eng/config/PublishData.json b/src/razor/eng/config/PublishData.json index f43f477c561..f7242854cd7 100644 --- a/src/razor/eng/config/PublishData.json +++ b/src/razor/eng/config/PublishData.json @@ -28,8 +28,8 @@ "NonShipping" ], "vsBranch": "main", - "insertionCreateDraftPR": false, - "insertionTitlePrefix": "[d17.15 P1]" + "insertionCreateDraftPR": true, + "insertionTitlePrefix": "[dNext.1]" }, "release/dev17.6": { "nugetKind": [ @@ -107,6 +107,15 @@ "vsBranch": "rel/d17.14", "insertionCreateDraftPR": false, "insertionTitlePrefix": "[d17.14 P3]" + }, + "release/dev-next": { + "nugetKind": [ + "Shipping", + "NonShipping" + ], + "vsBranch": "main", + "insertionCreateDraftPR": false, + "insertionTitlePrefix": "[dNext]" } } } diff --git a/src/roslyn/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer.cs b/src/roslyn/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer.cs index d1c1f8c4445..544731492af 100644 --- a/src/roslyn/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer.cs +++ b/src/roslyn/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer.cs @@ -19,26 +19,19 @@ namespace Microsoft.CodeAnalysis.RemoveUnnecessaryNullableDirective; [DiagnosticAnalyzer(LanguageNames.CSharp)] -internal sealed class CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer - : AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer +internal sealed class CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer() + : AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer(IDEDiagnosticIds.RemoveUnnecessaryNullableDirectiveDiagnosticId, + EnforceOnBuildValues.RemoveUnnecessaryNullableDirective, + option: null, + fadingOption: null, + new LocalizableResourceString(nameof(CSharpAnalyzersResources.Remove_unnecessary_nullable_directive), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + new LocalizableResourceString(nameof(CSharpAnalyzersResources.Nullable_directive_is_unnecessary), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources))) { - public CSharpRemoveUnnecessaryNullableDirectiveDiagnosticAnalyzer() - : base(IDEDiagnosticIds.RemoveUnnecessaryNullableDirectiveDiagnosticId, - EnforceOnBuildValues.RemoveUnnecessaryNullableDirective, - option: null, - fadingOption: null, - new LocalizableResourceString(nameof(CSharpAnalyzersResources.Remove_unnecessary_nullable_directive), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - new LocalizableResourceString(nameof(CSharpAnalyzersResources.Nullable_directive_is_unnecessary), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources))) - { - } - public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticDocumentAnalysis; protected override void InitializeWorker(AnalysisContext context) - { - context.RegisterCompilationStartAction(AnalyzeCompilation); - } + => context.RegisterCompilationStartAction(AnalyzeCompilation); private void AnalyzeCompilation(CompilationStartAnalysisContext context) { diff --git a/src/roslyn/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/NullableImpactingSpanWalker.cs b/src/roslyn/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/NullableImpactingSpanWalker.cs index 38622e35bf7..372636faed9 100644 --- a/src/roslyn/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/NullableImpactingSpanWalker.cs +++ b/src/roslyn/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryNullableDirective/NullableImpactingSpanWalker.cs @@ -97,6 +97,10 @@ private static bool IsLanguageRestrictedToNonNullForm(TypeSyntax node) return true; } + // An attribute name cannot itself be nullable. `[CLSCompliant?]` is not a thing. + if (node.IsParentKind(SyntaxKind.Attribute)) + return true; + return false; // If this is Y in X.Y, walk up to X.Y diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/AddObsoleteAttribute/AddObsoleteAttributeTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/AddObsoleteAttribute/AddObsoleteAttributeTests.cs index 8d60be340f0..a940ac5dcca 100644 --- a/src/roslyn/src/Analyzers/CSharp/Tests/AddObsoleteAttribute/AddObsoleteAttributeTests.cs +++ b/src/roslyn/src/Analyzers/CSharp/Tests/AddObsoleteAttribute/AddObsoleteAttributeTests.cs @@ -3,14 +3,18 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.AddObsoleteAttribute; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< - Microsoft.CodeAnalysis.Testing.EmptyDiagnosticAnalyzer, - Microsoft.CodeAnalysis.CSharp.AddObsoleteAttribute.CSharpAddObsoleteAttributeCodeFixProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddObsoleteAttribute; +using VerifyCS = CSharpCodeFixVerifier< + EmptyDiagnosticAnalyzer, + CSharpAddObsoleteAttributeCodeFixProvider>; + [Trait(Traits.Feature, Traits.Features.CodeActionsAddObsoleteAttribute)] public sealed class AddObsoleteAttributeTests { diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/FileHeaders/FileHeaderTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/FileHeaders/FileHeaderTests.cs index 4a8b37d756b..2bc54c7c094 100644 --- a/src/roslyn/src/Analyzers/CSharp/Tests/FileHeaders/FileHeaderTests.cs +++ b/src/roslyn/src/Analyzers/CSharp/Tests/FileHeaders/FileHeaderTests.cs @@ -3,16 +3,19 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.FileHeaders; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Testing; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.FileHeaders.CSharpFileHeaderDiagnosticAnalyzer, - Microsoft.CodeAnalysis.CSharp.FileHeaders.CSharpFileHeaderCodeFixProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.FileHeaders; +using VerifyCS = CSharpCodeFixVerifier< + CSharpFileHeaderDiagnosticAnalyzer, + CSharpFileHeaderCodeFixProvider>; + public sealed class FileHeaderTests { private const string TestSettings = """ diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs index 05cb84877df..9047d5010c8 100644 --- a/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs +++ b/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs @@ -13484,4 +13484,28 @@ uint M(bool condition) CodeFixTestBehaviors = CodeFixTestBehaviors.FixOne | CodeFixTestBehaviors.SkipFixAllCheck, DiagnosticSelector = d => d[1], }.RunAsync(); + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/60720")] + public Task TestNullableWithinGeneric() + => new VerifyCS.Test + { + TestCode = """ + #nullable enable + + using System; + using System.Threading.Tasks; + + Task M(string s, Func> func) + { + return string.IsNullOrWhiteSpace(s) + ? Task.FromResult(null) + : (Task)func(s)!; + } + """, + LanguageVersion = LanguageVersion.CSharp13, + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + }, + }.RunAsync(); } diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveTests.cs index f4ffe53ba2e..b9656bbb560 100644 --- a/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveTests.cs +++ b/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessaryNullableDirective/CSharpRemoveUnnecessaryNullableDirectiveTests.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.RemoveUnnecessaryNullableDirective; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.Analyzers.UnitTests.RemoveUnnecessaryNullableDirective; @@ -62,6 +63,32 @@ enum EnumName } """); + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/65401")] + public Task TestUnnecessaryDisableEnumDeclaration_WithAttribute() + => VerifyCodeFixAsync( + NullableContextOptions.Enable, + """ + [|#nullable disable|] + using System; + + [CLSCompliant(false)] + enum EnumName + { + First, + Second, + } + """, + """ + using System; + + [CLSCompliant(false)] + enum EnumName + { + First, + Second, + } + """); + [Fact] public Task TestUnnecessaryDisableEnumDeclarationWithFileHeader() => VerifyCodeFixAsync( diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessarySuppressions/RemoveUnnecessaryAttributeSuppressionsTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessarySuppressions/RemoveUnnecessaryAttributeSuppressionsTests.cs index 47866bc70ca..409cfd9bbe7 100644 --- a/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessarySuppressions/RemoveUnnecessaryAttributeSuppressionsTests.cs +++ b/src/roslyn/src/Analyzers/CSharp/Tests/RemoveUnnecessarySuppressions/RemoveUnnecessaryAttributeSuppressionsTests.cs @@ -3,17 +3,19 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions.CSharpRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer, - Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions.RemoveUnnecessaryAttributeSuppressionsCodeFixProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnnecessarySuppressions; +using VerifyCS = CSharpCodeFixVerifier< + CSharpRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer, + RemoveUnnecessaryAttributeSuppressionsCodeFixProvider>; + [Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessarySuppressions)] [WorkItem("https://github.com/dotnet/roslyn/issues/44176")] public sealed class RemoveUnnecessaryAttributeSuppressionsTests diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs index f52eaa57550..a28518bbe36 100644 --- a/src/roslyn/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs +++ b/src/roslyn/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs @@ -3,17 +3,20 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.UpdateLegacySuppressions; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions.CSharpRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer, - Microsoft.CodeAnalysis.UpdateLegacySuppressions.UpdateLegacySuppressionsCodeFixProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UpdateLegacySuppressions; +using VerifyCS = CSharpCodeFixVerifier< + CSharpRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer, + UpdateLegacySuppressionsCodeFixProvider>; + [Trait(Traits.Feature, Traits.Features.CodeActionsUpdateLegacySuppressions)] [WorkItem("https://github.com/dotnet/roslyn/issues/44362")] public sealed class UpdateLegacySuppressionsTests diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs index 818f0e09cd6..75db660d4d9 100644 --- a/src/roslyn/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs +++ b/src/roslyn/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs @@ -2097,9 +2097,11 @@ static void M() } """, new TestParameters(options: ImplicitTypeEverywhere())); - [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")] - public Task DoNotSuggestVarOnStackAllocExpressions_SpanType_NestedConditional() - => TestMissingInRegularAndScriptAsync(""" + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/22768")] + [WorkItem("https://github.com/dotnet/roslyn/issues/79337")] + public Task DoSuggestVarOnStackAllocExpressions_SpanType_NestedConditional() + => TestInRegularAndScript1Async(""" using System; namespace System { @@ -2115,11 +2117,29 @@ static void M(bool choice) [|Span|] x = choice ? stackalloc int [10] : stackalloc int [100]; } } + """, """ + using System; + namespace System + { + public readonly ref struct Span + { + unsafe public Span(void* pointer, int length) { } + } + } + class C + { + static void M(bool choice) + { + var x = choice ? stackalloc int [10] : stackalloc int [100]; + } + } """, new TestParameters(options: ImplicitTypeEverywhere())); - [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")] - public Task DoNotSuggestVarOnStackAllocExpressions_SpanType_NestedCast() - => TestMissingInRegularAndScriptAsync(""" + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/22768")] + [WorkItem("https://github.com/dotnet/roslyn/issues/79337")] + public Task DoSuggestVarOnStackAllocExpressions_SpanType_NestedCast() + => TestInRegularAndScript1Async(""" using System; namespace System { @@ -2135,6 +2155,22 @@ static void M() [|Span|] x = (Span)stackalloc int [100]; } } + """, """ + using System; + namespace System + { + public readonly ref struct Span + { + unsafe public Span(void* pointer, int length) { } + } + } + class C + { + static void M() + { + var x = (Span)stackalloc int [100]; + } + } """, new TestParameters(options: ImplicitTypeEverywhere())); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")] diff --git a/src/roslyn/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryParenthesesTests.vb b/src/roslyn/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryParenthesesTests.vb index 9d66369c48b..5b7e600d503 100644 --- a/src/roslyn/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryParenthesesTests.vb +++ b/src/roslyn/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryParenthesesTests.vb @@ -15,7 +15,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.RemoveUnnecessaryP ''' whose current option is set to something other than 'Ignore'. ''' - Partial Public Class RemoveUnnecessaryParenthesesTests + Partial Public NotInheritable Class RemoveUnnecessaryParenthesesTests Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest_NoEditor Private Shared ReadOnly CheckOverflow As CompilationOptions = New VisualBasicCompilationOptions(OutputKind.ConsoleApplication, checkOverflow:=True) @@ -651,7 +651,16 @@ end class" Assert.Equal("[1,2]", diagnostic.Properties.Item(WellKnownDiagnosticTags.Unnecessary)) End Using + End Function + + Public Async Function TestWithNullMemberAccess() As Task + Await TestMissingAsync( +"class C + sub M() + RoundTime($$(d.EndDate - d.StartDate)?.TotalMinutes / 60) + end sub +end class", New TestParameters(options:=RequireArithmeticBinaryParenthesesForClarity)) End Function End Class End Namespace diff --git a/src/roslyn/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs b/src/roslyn/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs index 335d55a65f3..93ceaedbf57 100644 --- a/src/roslyn/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs +++ b/src/roslyn/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs @@ -2,13 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.AddMissingImports; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; @@ -26,6 +27,12 @@ public sealed class CSharpAddMissingImportsRefactoringProviderTests : AbstractCS protected override CodeRefactoringProvider CreateCodeRefactoringProvider(EditorTestWorkspace workspace, TestParameters parameters) => new CSharpAddMissingImportsRefactoringProvider(); + private static readonly CodeStyleOption2 InsideNamespaceOption = + new(AddImportPlacement.InsideNamespace, NotificationOption2.Error); + + private static readonly CodeStyleOption2 OutsideNamespaceOption = + new(AddImportPlacement.InsideNamespace, NotificationOption2.Error); + protected override void InitializeWorkspace(EditorTestWorkspace workspace, TestParameters parameters) { // Treat the span being tested as the pasted span @@ -46,13 +53,16 @@ protected override void InitializeWorkspace(EditorTestWorkspace workspace, TestP private Task TestInRegularAndScriptAsync( [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup, [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string expectedMarkup, - bool placeSystemNamespaceFirst, bool separateImportDirectiveGroups) + bool placeSystemNamespaceFirst, + bool separateImportDirectiveGroups, + bool placeInsideNamespace = false) { var options = new OptionsCollection(GetLanguage()) { { GenerationOptions.PlaceSystemNamespaceFirst, placeSystemNamespaceFirst }, { GenerationOptions.SeparateImportDirectiveGroups, separateImportDirectiveGroups }, + { CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, placeInsideNamespace ? InsideNamespaceOption : OutsideNamespaceOption }, }; return TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: options); } @@ -353,4 +363,29 @@ class C List list; } """, placeSystemNamespaceFirst: true, separateImportDirectiveGroups: true); + + [WpfTheory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/54842")] + public Task TestWithNamespace(bool placeInsideNamespace) + => TestInRegularAndScriptAsync(""" + namespace N + { + using System; + + class C + { + [|List list;|] + } + } + """, """ + namespace N + { + using System; + using System.Collections.Generic; + + class C + { + List list; + } + } + """, placeSystemNamespaceFirst: true, separateImportDirectiveGroups: true, placeInsideNamespace); } diff --git a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AbstractAddUsingTests.cs b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AbstractAddUsingTests.cs index d739fecb85c..d6cb4ae26b9 100644 --- a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AbstractAddUsingTests.cs +++ b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AbstractAddUsingTests.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; @@ -18,14 +16,10 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddUsing; -public abstract class AbstractAddUsingTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest +public abstract class AbstractAddUsingTests(ITestOutputHelper? logger = null) + : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest(logger) { - protected AbstractAddUsingTests(ITestOutputHelper logger = null) - : base(logger) - { - } - - internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) + internal override (DiagnosticAnalyzer?, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) => (null, new CSharpAddImportCodeFixProvider()); private protected OptionsCollection SeparateGroups => Option(GenerationOptions.SeparateImportDirectiveGroups, true); @@ -36,7 +30,7 @@ internal Task TestAsync( TestHost testHost, int index = 0, CodeActionPriority? priority = null, - OptionsCollection options = null) + OptionsCollection? options = null) => TestInRegularAndScript1Async( initialMarkup, expectedMarkup, diff --git a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AddUsingTests.cs b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AddUsingTests.cs index c9ce5e2cdac..a9f79963b3c 100644 --- a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AddUsingTests.cs +++ b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AddUsingTests.cs @@ -6633,4 +6633,17 @@ class Program """, index: 0, parameters: new TestParameters(testHost: testHost)); + + [Theory, CombinatorialData] + [WorkItem("https://github.com/dotnet/roslyn/issues/72022")] + public Task TestAssemblyLevelAttribute(TestHost testHost) + => TestAsync( + """ + [assembly: [|NeutralResourcesLanguage|]("en")] + """, + """ + using System.Resources; + + [assembly: NeutralResourcesLanguage("en")] + """, testHost); } diff --git a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs index cdb2f66eb19..d9bd2d2acc4 100644 --- a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs +++ b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs @@ -20,11 +20,12 @@ using Microsoft.CodeAnalysis.Testing; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier< - Microsoft.CodeAnalysis.GenerateEqualsAndGetHashCodeFromMembers.GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.GenerateEqualsAndGetHashCodeFromMembers; +using VerifyCS = CSharpCodeRefactoringVerifier< + GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider>; + [UseExportProvider] [Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)] public sealed class GenerateEqualsAndGetHashCodeFromMembersTests @@ -69,10 +70,7 @@ private static OptionsCollection PreferExplicitTypeWithInfo() internal static void EnableOption(ImmutableArray options, string id) { var option = options.FirstOrDefault(o => o.Id == id); - if (option != null) - { - option.Value = true; - } + option?.Value = true; } [Fact] diff --git a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs index ade0311f695..d42de6fa6e5 100644 --- a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs +++ b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs @@ -5901,4 +5901,26 @@ internal class Test public int B { get; set; } } """, index: 1); + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/49649")] + public Task TestInTopLevelProgram() + => TestInRegularAndScriptAsync( + """ + var student = new [|Student|]("Youssef"); + Console.WriteLine(student.Name); + """, + """ + var student = new Student("Youssef"); + Console.WriteLine(student.Name); + + internal class Student + { + private string v; + + public Student(string v) + { + this.v = v; + } + } + """, index: 1); } diff --git a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs index 1dd09cc7e77..8f3cab891e6 100644 --- a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs +++ b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs @@ -1349,6 +1349,50 @@ public partial class Goo """); + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/76565")] + public Task TestCouldInitializeThrowingProperty_ButGeneratePropertyInstead() + => TestInRegularAndScript1Async( + """ + using System; + + class C([||]string s) + { + private string S => throw new NotImplementedException(); + } + """, + """ + using System; + + class C(string s) + { + public string S1 { get; } = s; + + private string S => throw new NotImplementedException(); + } + """, index: 1); + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/76565")] + public Task TestCouldInitializeThrowingProperty_ButGenerateFieldInstead() + => TestInRegularAndScript1Async( + """ + using System; + + class C([||]string s) + { + private string S => throw new NotImplementedException(); + } + """, + """ + using System; + + class C(string s) + { + private readonly string s = s; + + private string S => throw new NotImplementedException(); + } + """, index: 2); + [Fact] public Task TestUpdateCodeToReferenceExistingField1() => TestInRegularAndScript1Async( diff --git a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/MoveStaticMembers/CSharpMoveStaticMembersTests.cs b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/MoveStaticMembers/CSharpMoveStaticMembersTests.cs index 10c97ce96b0..d943b9e2b3c 100644 --- a/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/MoveStaticMembers/CSharpMoveStaticMembersTests.cs +++ b/src/roslyn/src/EditorFeatures/CSharpTest/CodeActions/MoveStaticMembers/CSharpMoveStaticMembersTests.cs @@ -4,16 +4,19 @@ using System.Collections.Immutable; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.MoveStaticMembers; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.MoveStaticMembers; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities.MoveStaticMembers; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier< - Microsoft.CodeAnalysis.CSharp.CodeRefactorings.MoveStaticMembers.CSharpMoveStaticMembersRefactoringProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.MoveStaticMembers; +using VerifyCS = CSharpCodeRefactoringVerifier< + CSharpMoveStaticMembersRefactoringProvider>; + [UseExportProvider] [Trait(Traits.Feature, Traits.Features.CodeActionsMoveStaticMembers)] public sealed class CSharpMoveStaticMembersTests diff --git a/src/roslyn/src/EditorFeatures/CSharpTest/Diagnostics/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs b/src/roslyn/src/EditorFeatures/CSharpTest/Diagnostics/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs index de315e1a800..9ea1e21c7bf 100644 --- a/src/roslyn/src/EditorFeatures/CSharpTest/Diagnostics/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs +++ b/src/roslyn/src/EditorFeatures/CSharpTest/Diagnostics/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs @@ -2,21 +2,29 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable +#if CODE_STYLE +extern alias CODESTYLE_UTILITIES; +#endif +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Remote.Testing; using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; -public abstract partial class AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest : AbstractDiagnosticProviderBasedUserDiagnosticTest -{ - protected AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest(ITestOutputHelper logger) - : base(logger) - { - } +#if CODE_STYLE +using OptionsCollectionAlias = CODESTYLE_UTILITIES::Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.OptionsCollection; +#else +using OptionsCollectionAlias = OptionsCollection; +#endif +public abstract partial class AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest(ITestOutputHelper? logger) + : AbstractDiagnosticProviderBasedUserDiagnosticTest(logger) +{ protected override ParseOptions GetScriptOptions() => Options.Script; protected internal override string GetLanguage() => LanguageNames.CSharp; @@ -151,4 +159,29 @@ public interface IAsyncEnumerator : IAsyncDisposable internal OptionsCollection IgnoreAllParentheses => ParenthesesOptionsProvider.IgnoreAllParentheses; internal OptionsCollection RemoveAllUnnecessaryParentheses => ParenthesesOptionsProvider.RemoveAllUnnecessaryParentheses; internal OptionsCollection RequireAllParenthesesForClarity => ParenthesesOptionsProvider.RequireAllParenthesesForClarity; + + internal new Task TestInRegularAndScript1Async( + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup, + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string expectedMarkup, + int index = 0, + TestParameters? parameters = null) + { + return base.TestInRegularAndScript1Async(initialMarkup, expectedMarkup, index, parameters); + } + + internal new Task TestInRegularAndScriptAsync( + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup, + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string expectedMarkup, + int index = 0, + CodeActionPriority? priority = null, + CompilationOptions? compilationOptions = null, + OptionsCollectionAlias? options = null, + object? fixProviderData = null, + ParseOptions? parseOptions = null, + string? title = null, + TestHost testHost = TestHost.OutOfProcess) + { + return base.TestInRegularAndScriptAsync( + initialMarkup, expectedMarkup, index, priority, compilationOptions, options, fixProviderData, parseOptions, title, testHost); + } } diff --git a/src/roslyn/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs b/src/roslyn/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs index c9afd36b6d8..ff3450ab70d 100644 --- a/src/roslyn/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs +++ b/src/roslyn/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs @@ -753,12 +753,9 @@ public async Task CommitAsync(bool previewChanges, IUIThreadOperationContext edi previewChanges = previewChanges || PreviewChanges; - if (editorOperationContext is not null) - { - // Prevent Editor's typing responsiveness auto canceling the rename operation. - // InlineRenameSession will call IUIThreadOperationExecutor to sets up our own IUIThreadOperationContext - editorOperationContext.TakeOwnership(); - } + // Prevent Editor's typing responsiveness auto canceling the rename operation. + // InlineRenameSession will call IUIThreadOperationExecutor to sets up our own IUIThreadOperationContext + editorOperationContext?.TakeOwnership(); try { diff --git a/src/roslyn/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs b/src/roslyn/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs index 367eeb23440..e5d4ed313e5 100644 --- a/src/roslyn/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs +++ b/src/roslyn/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs @@ -333,10 +333,7 @@ protected virtual void Dispose(bool disposing) Session.ReplacementsComputed -= OnReplacementsComputed; Session.CommitStateChange -= CommitStateChange; - if (SmartRenameViewModel is not null) - { - SmartRenameViewModel.Dispose(); - } + SmartRenameViewModel?.Dispose(); UnregisterOleComponent(); } diff --git a/src/roslyn/src/EditorFeatures/Core/Shared/Utilities/CaretPreservingEditTransaction.cs b/src/roslyn/src/EditorFeatures/Core/Shared/Utilities/CaretPreservingEditTransaction.cs index 5bcb2e0203b..7dfdafeb9d9 100644 --- a/src/roslyn/src/EditorFeatures/Core/Shared/Utilities/CaretPreservingEditTransaction.cs +++ b/src/roslyn/src/EditorFeatures/Core/Shared/Utilities/CaretPreservingEditTransaction.cs @@ -93,10 +93,7 @@ public IMergeTextUndoTransactionPolicy? MergePolicy set { - if (_transaction != null) - { - _transaction.MergePolicy = value; - } + _transaction?.MergePolicy = value; } } diff --git a/src/roslyn/src/EditorFeatures/Core/SignatureHelp/Presentation/SignatureHelpPresenter.SignatureHelpPresenterSession.cs b/src/roslyn/src/EditorFeatures/Core/SignatureHelp/Presentation/SignatureHelpPresenter.SignatureHelpPresenterSession.cs index 7dc0a0b51f3..4bdd65c1574 100644 --- a/src/roslyn/src/EditorFeatures/Core/SignatureHelp/Presentation/SignatureHelpPresenter.SignatureHelpPresenterSession.cs +++ b/src/roslyn/src/EditorFeatures/Core/SignatureHelp/Presentation/SignatureHelpPresenter.SignatureHelpPresenterSession.cs @@ -98,10 +98,7 @@ public void PresentItems( Contract.ThrowIfNull(_signatureMap); var defaultValue = _signatureMap.GetValueOrDefault(_selectedItem); - if (_editorSessionOpt != null) - { - _editorSessionOpt.SelectedSignature = defaultValue; - } + _editorSessionOpt?.SelectedSignature = defaultValue; } finally { diff --git a/src/roslyn/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs b/src/roslyn/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs index aa5f7030fb9..7090b5e0b51 100644 --- a/src/roslyn/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs +++ b/src/roslyn/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs @@ -166,10 +166,7 @@ internal static void EnableOptions( internal static void EnableOption(ImmutableArray options, string id) { var option = options.FirstOrDefault(o => o.Id == id); - if (option != null) - { - option.Value = true; - } + option?.Value = true; } internal Task TestWithPickMembersDialogAsync( diff --git a/src/roslyn/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb b/src/roslyn/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb index c6d15c0d97a..97c02854545 100644 --- a/src/roslyn/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb +++ b/src/roslyn/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb @@ -254,6 +254,66 @@ class var { } Await TestAPIAndFeature(input, kind, host) End Function + + + Public Async Function TestNamedType_TypeOfOperator_Name(kind As TestKind, host As TestHost) As Task + Dim input = + + + + class {|Definition:Celsius|} + { + public {|Definition:Celsius|}() + { + System.Type t = typeof({|ValueUsageInfo.Name:[|$$Celsius|]|}); + } + } + + + + Await TestAPIAndFeature(input, kind, host) + End Function + + + + Public Async Function TestNamedType_SizeOfOperator_Name(kind As TestKind, host As TestHost) As Task + Dim input = + + + + class {|Definition:Celsius|} + { + public {|Definition:Celsius|}() + { + int t = sizeof({|ValueUsageInfo.Name:[|$$Celsius|]|}); + } + } + + + + Await TestAPIAndFeature(input, kind, host) + End Function + + + + Public Async Function TestNamedType_NameOfOperator_Name(kind As TestKind, host As TestHost) As Task + Dim input = + + + + class {|Definition:Celsius|} + { + public {|Definition:Celsius|}() + { + string t = nameof({|ValueUsageInfo.Name:[|$$Celsius|]|}); + } + } + + + + Await TestAPIAndFeature(input, kind, host) + End Function + Public Async Function TestNamedType_InaccessibleType(kind As TestKind, host As TestHost) As Task diff --git a/src/roslyn/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs b/src/roslyn/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs index c6a60c70f02..4e02d3fe208 100644 --- a/src/roslyn/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs +++ b/src/roslyn/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs @@ -20,7 +20,6 @@ using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.InitializeParameter; -using Microsoft.CodeAnalysis.Shared.Collections; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Naming; using Roslyn.Utilities; @@ -73,11 +72,18 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false); var fieldOrProperty = TryFindMatchingUninitializedFieldOrPropertySymbol(); - var refactorings = fieldOrProperty == null - ? HandleNoExistingFieldOrProperty() - : HandleExistingFieldOrProperty(); + using var refactorings = TemporaryArray.Empty; + if (fieldOrProperty != null) + { + // Found a field/property that this parameter should be assigned to. Just offer the simple assignment to it. + refactorings.Add(CreateCodeAction( + string.Format(fieldOrProperty.Kind == SymbolKind.Field ? FeaturesResources.Initialize_field_0 : FeaturesResources.Initialize_property_0, fieldOrProperty.Name), + cancellationToken => AddAssignmentForPrimaryConstructorAsync(document, parameter, fieldOrProperty, cancellationToken))); + } + + AddCreateFieldOrPropertyCodeActions(); - context.RegisterRefactorings(refactorings.ToImmutableArray(), context.Span); + context.RegisterRefactorings(refactorings.ToImmutableAndClear(), context.Span); return; ISymbol? TryFindMatchingUninitializedFieldOrPropertySymbol() @@ -133,15 +139,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte static CodeAction CreateCodeAction(string title, Func> createSolution) => CodeAction.Create(title, createSolution, title); - IEnumerable HandleExistingFieldOrProperty() - { - // Found a field/property that this parameter should be assigned to. Just offer the simple assignment to it. - yield return CreateCodeAction( - string.Format(fieldOrProperty.Kind == SymbolKind.Field ? FeaturesResources.Initialize_field_0 : FeaturesResources.Initialize_property_0, fieldOrProperty.Name), - cancellationToken => AddAssignmentForPrimaryConstructorAsync(document, parameter, fieldOrProperty, cancellationToken)); - } - - IEnumerable HandleNoExistingFieldOrProperty() + void AddCreateFieldOrPropertyCodeActions() { // Didn't find a field/prop that this parameter could be assigned to. Offer to create new one and assign to that. @@ -159,8 +157,8 @@ IEnumerable HandleNoExistingFieldOrProperty() string.Format(FeaturesResources.Create_and_assign_property_0, property.Name), cancellationToken => AddMultipleMembersAsync(document, typeDeclaration, [parameter], [property], cancellationToken)); - yield return siblingFieldOrProperty is IFieldSymbol ? fieldAction : propertyAction; - yield return siblingFieldOrProperty is IFieldSymbol ? propertyAction : fieldAction; + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? fieldAction : propertyAction); + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? propertyAction : fieldAction); var parameters = GetParametersWithoutAssociatedMembers(); if (parameters.Length >= 2) @@ -172,8 +170,8 @@ IEnumerable HandleNoExistingFieldOrProperty() FeaturesResources.Create_and_assign_remaining_as_properties, cancellationToken => AddMultipleMembersAsync(document, typeDeclaration, parameters, parameters.SelectAsArray(CreateProperty), cancellationToken)); - yield return siblingFieldOrProperty is IFieldSymbol ? allFieldsAction : allPropertiesAction; - yield return siblingFieldOrProperty is IFieldSymbol ? allPropertiesAction : allFieldsAction; + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? allFieldsAction : allPropertiesAction); + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? allPropertiesAction : allFieldsAction); } } diff --git a/src/roslyn/src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs b/src/roslyn/src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs index 37992126de4..3263b9dcd50 100644 --- a/src/roslyn/src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs +++ b/src/roslyn/src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs @@ -7,14 +7,16 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; +using Microsoft.CodeAnalysis.GenerateComparisonOperators; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier< - Microsoft.CodeAnalysis.GenerateComparisonOperators.GenerateComparisonOperatorsCodeRefactoringProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.GenerateComparisonOperators; +using VerifyCS = CSharpCodeRefactoringVerifier< + GenerateComparisonOperatorsCodeRefactoringProvider>; + [UseExportProvider] [Trait(Traits.Feature, Traits.Features.CodeActionsGenerateComparisonOperators)] public sealed class GenerateComparisonOperatorsTests diff --git a/src/roslyn/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs b/src/roslyn/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs index bd8c52909be..049fbf52bbe 100644 --- a/src/roslyn/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs +++ b/src/roslyn/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs @@ -102,10 +102,7 @@ private sealed class ChangeOptionValueOperation(bool selectedAll) : CodeActionOp public override void Apply(Workspace workspace, CancellationToken cancellationToken) { var service = workspace.Services.GetService(); - if (service != null) - { - service.GenerateOverrides = _selectedAll; - } + service?.GenerateOverrides = _selectedAll; } } } diff --git a/src/roslyn/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs b/src/roslyn/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs index 0ebac83ad0f..2309c81eb50 100644 --- a/src/roslyn/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs +++ b/src/roslyn/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.PooledObjects; @@ -100,7 +101,7 @@ private ImmutableArray GetActions( State state, CancellationToken cancellationToken) { - using var _ = ArrayBuilder.GetInstance(out var result); + using var result = TemporaryArray.Empty; var generateNewTypeInDialog = false; if (state.NamespaceToGenerateInOpt != null) diff --git a/src/roslyn/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs b/src/roslyn/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs index bdce9d78b0c..a2a2490d683 100644 --- a/src/roslyn/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs +++ b/src/roslyn/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs @@ -77,10 +77,7 @@ public static async Task CreateQuickInfoItemAsync( if (groups.TryGetValue(SymbolDescriptionGroups.Documentation, out var docParts) && !docParts.IsDefaultOrEmpty) { AddSection(QuickInfoSectionKinds.DocumentationComments, docParts); - if (onTheFlyDocsInfo != null) - { - onTheFlyDocsInfo.HasComments = true; - } + onTheFlyDocsInfo?.HasComments = true; } if (options.QuickInfoOptions.ShowRemarksInQuickInfo && diff --git a/src/roslyn/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs b/src/roslyn/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs index ccd8de06085..53ef252db13 100644 --- a/src/roslyn/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs +++ b/src/roslyn/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs @@ -263,13 +263,10 @@ private async Task ReplaceReferencesAsync( editor.ReplaceNode(parent, parent.WithAdditionalAnnotations( ConflictAnnotation.Create(FeaturesResources.Property_referenced_implicitly))); } - else if (syntaxFacts.IsMemberInitializerNamedAssignmentIdentifier(parent)) - { - editor.ReplaceNode(parent, parent.WithAdditionalAnnotations( - ConflictAnnotation.Create(FeaturesResources.Property_reference_cannot_be_updated))); - } - else if (syntaxFacts.IsNameOfSubpattern(parent)) + else if (IsInNonUpdatableLocation(syntaxFacts, parent)) { + // If the property is in a location where it cannot be updated, then just + // replace it with a warning. editor.ReplaceNode(parent, parent.WithAdditionalAnnotations( ConflictAnnotation.Create(FeaturesResources.Property_reference_cannot_be_updated))); } @@ -284,6 +281,13 @@ await service.ReplaceReferenceAsync( } } } + + static bool IsInNonUpdatableLocation(ISyntaxFacts syntaxFacts, SyntaxNode parent) + { + return syntaxFacts.IsMemberInitializerNamedAssignmentIdentifier(parent) || + syntaxFacts.IsNameOfSubpattern(parent) || + syntaxFacts.IsInNamespaceOrTypeContext(parent); + } } private static async Task ReplaceDefinitionsWithMethodsAsync( diff --git a/src/roslyn/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionTest_NoEditor.cs b/src/roslyn/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionTest_NoEditor.cs index 887450a6e6f..12d8bd9c7eb 100644 --- a/src/roslyn/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionTest_NoEditor.cs +++ b/src/roslyn/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionTest_NoEditor.cs @@ -174,10 +174,7 @@ internal static void EnableOptions( internal static void EnableOption(ImmutableArray options, string id) { var option = options.FirstOrDefault(o => o.Id == id); - if (option != null) - { - option.Value = true; - } + option?.Value = true; } internal Task TestWithPickMembersDialogAsync( diff --git a/src/roslyn/src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb b/src/roslyn/src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb index ba62265f778..fe7c9d8b76e 100644 --- a/src/roslyn/src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb +++ b/src/roslyn/src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb @@ -8,7 +8,7 @@ Imports Microsoft.CodeAnalysis.ReplacePropertyWithMethods Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeActions.ReplacePropertyWithMethods - Public Class ReplacePropertyWithMethodsTests + Public NotInheritable Class ReplacePropertyWithMethodsTests Inherits AbstractVisualBasicCodeActionTest_NoEditor Protected Overrides Function CreateCodeRefactoringProvider(workspace As TestWorkspace, parameters As TestParameters) As CodeRefactoringProvider @@ -698,5 +698,24 @@ Class C End Sub End Class") End Function + + + Public Async Function TestPropertyNameReferencedInAsClause() As Task + Await TestInRegularAndScriptAsync( +"class C + property [||]Goo as Goo +end class", +"class C + Private _Goo As Goo + + Public Function GetGoo() As Goo + Return _Goo + End Function + + Public Sub SetGoo(AutoPropertyValue As Goo) + _Goo = AutoPropertyValue + End Sub +end class") + End Function End Class End Namespace diff --git a/src/roslyn/src/RoslynAnalyzers/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/ResxGeneratorTests.cs b/src/roslyn/src/RoslynAnalyzers/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/ResxGeneratorTests.cs index 7f723ad532d..55bea2fa656 100644 --- a/src/roslyn/src/RoslynAnalyzers/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/ResxGeneratorTests.cs +++ b/src/roslyn/src/RoslynAnalyzers/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/ResxGeneratorTests.cs @@ -5,860 +5,860 @@ using System.Threading.Tasks; using Xunit; using CSharpLanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion; -using VerifyCS = Microsoft.CodeAnalysis.ResxSourceGenerator.Test.CSharpSourceGeneratorVerifier; -using VerifyVB = Microsoft.CodeAnalysis.ResxSourceGenerator.Test.VisualBasicSourceGeneratorVerifier; -namespace Microsoft.CodeAnalysis.ResxSourceGenerator.Test +namespace Microsoft.CodeAnalysis.ResxSourceGenerator.Test; + +using VerifyCS = CSharpSourceGeneratorVerifier; +using VerifyVB = VisualBasicSourceGeneratorVerifier; + +public sealed class ResxGeneratorTests { - public class ResxGeneratorTests + private const string ResxHeader = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + """; + private const string ResxFooter = """ + + """; + + [Theory] + [InlineData(CSharpLanguageVersion.CSharp5, Skip = "Expression-bodied members are not supported in C# 5")] + [InlineData(CSharpLanguageVersion.CSharp6)] + [InlineData(CSharpLanguageVersion.CSharp7)] + [InlineData(CSharpLanguageVersion.CSharp8)] + [InlineData(CSharpLanguageVersion.CSharp9)] + public async Task SingleString_DefaultCSharpAsync(CSharpLanguageVersion languageVersion) { - private const string ResxHeader = """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - """; - private const string ResxFooter = """ - - """; - - [Theory] - [InlineData(CSharpLanguageVersion.CSharp5, Skip = "Expression-bodied members are not supported in C# 5")] - [InlineData(CSharpLanguageVersion.CSharp6)] - [InlineData(CSharpLanguageVersion.CSharp7)] - [InlineData(CSharpLanguageVersion.CSharp8)] - [InlineData(CSharpLanguageVersion.CSharp9)] - public async Task SingleString_DefaultCSharpAsync(CSharpLanguageVersion languageVersion) + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: languageVersion.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: languageVersion.ToString()) + LanguageVersion = languageVersion, + TestState = { - LanguageVersion = languageVersion, - TestState = - { - Sources = { "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - }, - }.AddGeneratedSources().RunAsync(); - } + Sources = { "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + }, + }.AddGeneratedSources().RunAsync(); + } - [Fact] - public async Task TwoResourcesSameName_DefaultCSharpAsync() + [Fact] + public async Task TwoResourcesSameName_DefaultCSharpAsync() + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test() { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test() + TestState = { - TestState = + Sources = { "" }, + AdditionalFiles = { - Sources = { "" }, - AdditionalFiles = - { - ("/0/First/Resources.resx", code), - ("/0/Second/Resources.resx", code), - }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - build_property.RootNamespace = TestProject - - [/0/First/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = First/ - - [/0/Second/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = Second/ - """), - }, + ("/0/First/Resources.resx", code), + ("/0/Second/Resources.resx", code), }, - }.AddGeneratedSources().RunAsync(); - } + AnalyzerConfigFiles = + { + ("/.globalconfig", $""" + is_global = true - [Fact] - public async Task TwoResourcesSameName_DefaultVisualBasicAsync() + build_property.RootNamespace = TestProject + + [/0/First/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = First/ + + [/0/Second/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = Second/ + """), + }, + }, + }.AddGeneratedSources().RunAsync(); + } + + [Fact] + public async Task TwoResourcesSameName_DefaultVisualBasicAsync() + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test() { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test() + TestState = { - TestState = + Sources = { "" }, + AdditionalFiles = { - Sources = { "" }, - AdditionalFiles = - { - ("/0/First/Resources.resx", code), - ("/0/Second/Resources.resx", code), - }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - build_property.RootNamespace = TestProject - - [/0/First/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = First/ - - [/0/Second/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = Second/ - """), - }, + ("/0/First/Resources.resx", code), + ("/0/Second/Resources.resx", code), + }, + AnalyzerConfigFiles = + { + ("/.globalconfig", $""" + is_global = true + + build_property.RootNamespace = TestProject + + [/0/First/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = First/ + + [/0/Second/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = Second/ + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Fact] - public async Task SingleString_DefaultVisualBasicAsync() + [Fact] + public async Task SingleString_DefaultVisualBasicAsync() + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test + TestState = { - TestState = - { - AdditionalFiles = { ("/0/Resources.resx", code) }, - }, - }.AddGeneratedSources().RunAsync(); - } + AdditionalFiles = { ("/0/Resources.resx", code) }, + }, + }.AddGeneratedSources().RunAsync(); + } - [Fact] - public async Task SingleString_DisableCodeGenAsync() + [Fact] + public async Task SingleString_DisableCodeGenAsync() + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test + TestState = { - TestState = + Sources = { "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - Sources = { "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", """ - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.GenerateSource = false - """), - }, + ("/.globalconfig", """ + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.GenerateSource = false + """), }, - }.RunAsync(); + }, + }.RunAsync(); - await new VerifyVB.Test + await new VerifyVB.Test + { + TestState = { - TestState = + Sources = { "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - Sources = { "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", """ - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.GenerateSource = false - """), - }, + ("/.globalconfig", """ + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.GenerateSource = false + """), }, - }.RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_RootNamespaceCSharpAsync(string rootNamespace) + }, + }.RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_RootNamespaceCSharpAsync(string rootNamespace) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: rootNamespace) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: rootNamespace) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - build_property.RootNamespace = {rootNamespace} - """), - }, + ("/.globalconfig", $""" + is_global = true + + build_property.RootNamespace = {rootNamespace} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_RootNamespaceVisualBasicAsync(string rootNamespace) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_RootNamespaceVisualBasicAsync(string rootNamespace) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: rootNamespace) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: rootNamespace) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - build_property.RootNamespace = {rootNamespace} - """), - }, + ("/.globalconfig", $""" + is_global = true + + build_property.RootNamespace = {rootNamespace} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_RelativeDirCSharpAsync(string relativeDir) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_RelativeDirCSharpAsync(string relativeDir) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: relativeDir) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: relativeDir) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = {relativeDir} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = {relativeDir} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_RelativeDirVisualBasicAsync(string relativeDir) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_RelativeDirVisualBasicAsync(string relativeDir) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: relativeDir) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: relativeDir) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.RelativeDir = {relativeDir} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.RelativeDir = {relativeDir} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_ClassNameCSharpAsync(string className) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_ClassNameCSharpAsync(string className) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: className) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: className) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.ClassName = {className} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.ClassName = {className} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("NS")] - [InlineData("NS1.NS2")] - public async Task SingleString_ClassNameVisualBasicAsync(string className) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("NS")] + [InlineData("NS1.NS2")] + public async Task SingleString_ClassNameVisualBasicAsync(string className) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: className) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: className) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.ClassName = {className} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.ClassName = {className} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_OmitGetResourceStringCSharpAsync(bool omitGetResourceString) - { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - var customGetResourceString = """ - #nullable enable - - namespace TestProject + [Theory] + [CombinatorialData] + public async Task SingleString_OmitGetResourceStringCSharpAsync(bool omitGetResourceString) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + var customGetResourceString = """ + #nullable enable + + namespace TestProject + { + internal static partial class Resources { - internal static partial class Resources - { - internal static string? GetResourceString(string resourceKey, string? defaultValue = null) => throw null!; - } + internal static string? GetResourceString(string resourceKey, string? defaultValue = null) => throw null!; } - """; + } + """; - await new VerifyCS.Test(identifier: omitGetResourceString.ToString()) + await new VerifyCS.Test(identifier: omitGetResourceString.ToString()) + { + TestState = { - TestState = + Sources = { omitGetResourceString ? customGetResourceString : "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - Sources = { omitGetResourceString ? customGetResourceString : "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.OmitGetResourceString = {(omitGetResourceString ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.OmitGetResourceString = {(omitGetResourceString ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_OmitGetResourceStringVisualBasicAsync(bool omitGetResourceString) + [Theory] + [CombinatorialData] + public async Task SingleString_OmitGetResourceStringVisualBasicAsync(bool omitGetResourceString) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + var customGetResourceString = """ + Namespace Global.TestProject + Friend Partial Class Resources + Friend Shared Function GetResourceString(resourceKey As String, Optional defaultValue As String = Nothing) + Return "" + End Function + End Class + End Namespace + """; + + await new VerifyVB.Test(identifier: omitGetResourceString.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - var customGetResourceString = """ - Namespace Global.TestProject - Friend Partial Class Resources - Friend Shared Function GetResourceString(resourceKey As String, Optional defaultValue As String = Nothing) - Return "" - End Function - End Class - End Namespace - """; - - await new VerifyVB.Test(identifier: omitGetResourceString.ToString()) + TestState = { - TestState = + Sources = { omitGetResourceString ? customGetResourceString : "" }, + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - Sources = { omitGetResourceString ? customGetResourceString : "" }, - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.OmitGetResourceString = {(omitGetResourceString ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.OmitGetResourceString = {(omitGetResourceString ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_AsConstantsCSharpAsync(bool asConstants) + [Theory] + [CombinatorialData] + public async Task SingleString_AsConstantsCSharpAsync(bool asConstants) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: asConstants.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: asConstants.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.AsConstants = {(asConstants ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.AsConstants = {(asConstants ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_AsConstantsVisualBasicAsync(bool asConstants) + [Theory] + [CombinatorialData] + public async Task SingleString_AsConstantsVisualBasicAsync(bool asConstants) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: asConstants.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: asConstants.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.AsConstants = {(asConstants ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.AsConstants = {(asConstants ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_IncludeDefaultValuesCSharpAsync(bool includeDefaultValues) + [Theory] + [CombinatorialData] + public async Task SingleString_IncludeDefaultValuesCSharpAsync(bool includeDefaultValues) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: includeDefaultValues.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: includeDefaultValues.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.IncludeDefaultValues = {(includeDefaultValues ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.IncludeDefaultValues = {(includeDefaultValues ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_IncludeDefaultValuesVisualBasicAsync(bool includeDefaultValues) + [Theory] + [CombinatorialData] + public async Task SingleString_IncludeDefaultValuesVisualBasicAsync(bool includeDefaultValues) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: includeDefaultValues.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: includeDefaultValues.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.IncludeDefaultValues = {(includeDefaultValues ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.IncludeDefaultValues = {(includeDefaultValues ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [CombinatorialData] - public async Task SingleString_EmitFormatMethodsCSharpAsync( - [CombinatorialValues("0", "x", "replacement")] string placeholder, - bool emitFormatMethods) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [CombinatorialData] + public async Task SingleString_EmitFormatMethodsCSharpAsync( + [CombinatorialValues("0", "x", "replacement")] string placeholder, + bool emitFormatMethods) + { + var code = ResxHeader + + $$""" + + value {{{placeholder}}} + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: $"{placeholder}_{emitFormatMethods}") { - var code = ResxHeader - + $$""" - - value {{{placeholder}}} - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: $"{placeholder}_{emitFormatMethods}") + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.EmitFormatMethods = {(emitFormatMethods ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.EmitFormatMethods = {(emitFormatMethods ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [InlineData(true, Skip = "Not yet supported")] - [InlineData(false)] - public async Task SingleString_EmitFormatMethodsVisualBasicAsync(bool emitFormatMethods) + [Theory] + [InlineData(true, Skip = "Not yet supported")] + [InlineData(false)] + public async Task SingleString_EmitFormatMethodsVisualBasicAsync(bool emitFormatMethods) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: emitFormatMethods.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: emitFormatMethods.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.EmitFormatMethods = {(emitFormatMethods ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.EmitFormatMethods = {(emitFormatMethods ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_PublicCSharpAsync(bool publicResource) + [Theory] + [CombinatorialData] + public async Task SingleString_PublicCSharpAsync(bool publicResource) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyCS.Test(identifier: publicResource.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyCS.Test(identifier: publicResource.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.Public = {(publicResource ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.Public = {(publicResource ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); + } - [Theory] - [CombinatorialData] - public async Task SingleString_PublicVisualBasicAsync(bool publicResource) + [Theory] + [CombinatorialData] + public async Task SingleString_PublicVisualBasicAsync(bool publicResource) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + await new VerifyVB.Test(identifier: publicResource.ToString()) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - await new VerifyVB.Test(identifier: publicResource.ToString()) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.Public = {(publicResource ? "true" : "false")} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.Public = {(publicResource ? "true" : "false")} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("CS1591")] - [InlineData("CS1591, IDE0010")] - [InlineData(" , CS1591, IDE0010 ")] - public async Task SingleString_NoWarnsCSharpAsync(string noWarn) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("CS1591")] + [InlineData("CS1591, IDE0010")] + [InlineData(" , CS1591, IDE0010 ")] + public async Task SingleString_NoWarnsCSharpAsync(string noWarn) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + var id = string.Join("_", noWarn.Replace(" ", "").Split(",", System.StringSplitOptions.TrimEntries | System.StringSplitOptions.RemoveEmptyEntries)); + + await new VerifyCS.Test(identifier: id) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - var id = string.Join("_", noWarn.Replace(" ", "").Split(",", System.StringSplitOptions.TrimEntries | System.StringSplitOptions.RemoveEmptyEntries)); - - await new VerifyCS.Test(identifier: id) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.NoWarn = {noWarn} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.NoWarn = {noWarn} + """), }, - }.AddGeneratedSources().RunAsync(); - } - - [Theory] - [InlineData("")] - [InlineData("CS1591")] - [InlineData("CS1591, IDE0010")] - [InlineData(" , CS1591, IDE0010 ")] - public async Task SingleString_NoWarnsVisualBasicAsync(string noWarn) + }, + }.AddGeneratedSources().RunAsync(); + } + + [Theory] + [InlineData("")] + [InlineData("CS1591")] + [InlineData("CS1591, IDE0010")] + [InlineData(" , CS1591, IDE0010 ")] + public async Task SingleString_NoWarnsVisualBasicAsync(string noWarn) + { + var code = ResxHeader + + """ + + value + comment + + """ + + ResxFooter; + + var id = string.Join("_", noWarn.Replace(" ", "").Split(",", System.StringSplitOptions.TrimEntries | System.StringSplitOptions.RemoveEmptyEntries)); + + await new VerifyVB.Test(identifier: id) { - var code = ResxHeader - + """ - - value - comment - - """ - + ResxFooter; - - var id = string.Join("_", noWarn.Replace(" ", "").Split(",", System.StringSplitOptions.TrimEntries | System.StringSplitOptions.RemoveEmptyEntries)); - - await new VerifyVB.Test(identifier: id) + TestState = { - TestState = + AdditionalFiles = { ("/0/Resources.resx", code) }, + AnalyzerConfigFiles = { - AdditionalFiles = { ("/0/Resources.resx", code) }, - AnalyzerConfigFiles = - { - ("/.globalconfig", $""" - is_global = true - - [/0/Resources.resx] - build_metadata.AdditionalFiles.NoWarn = {noWarn} - """), - }, + ("/.globalconfig", $""" + is_global = true + + [/0/Resources.resx] + build_metadata.AdditionalFiles.NoWarn = {noWarn} + """), }, - }.AddGeneratedSources().RunAsync(); - } + }, + }.AddGeneratedSources().RunAsync(); } } diff --git a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/AvoidAllocationWithArrayEmptyCodeFixTests.cs b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/AvoidAllocationWithArrayEmptyCodeFixTests.cs index 59a0985f90b..8554fb46947 100644 --- a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/AvoidAllocationWithArrayEmptyCodeFixTests.cs +++ b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/AvoidAllocationWithArrayEmptyCodeFixTests.cs @@ -3,513 +3,515 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.CodeFixes; using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.ExplicitAllocationAnalyzer, - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.CodeFixes.AvoidAllocationWithArrayEmptyCodeFix>; -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + ExplicitAllocationAnalyzer, + AvoidAllocationWithArrayEmptyCodeFix>; + +public class AvoidAllocationWithArrayEmptyCodeFixTests { - public class AvoidAllocationWithArrayEmptyCodeFixTests - { - [Theory] - [InlineData("IEnumerable")] - [InlineData("IReadOnlyList")] - [InlineData("IReadOnlyCollection")] - public Task ShouldReplaceEmptyListCreationWithArrayEmptyWithReturnTypeAsync(string type) - => VerifyCS.VerifyCodeFixAsync($$""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + [Theory] + [InlineData("IEnumerable")] + [InlineData("IReadOnlyList")] + [InlineData("IReadOnlyCollection")] + public Task ShouldReplaceEmptyListCreationWithArrayEmptyWithReturnTypeAsync(string type) + => VerifyCS.VerifyCodeFixAsync($$""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public {{type}} DoSomething() { - [PerformanceSensitive("uri")] - public {{type}} DoSomething() - { - return new List(); - } + return new List(); } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 35), $$""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 35), $$""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public {{type}} DoSomething() { - [PerformanceSensitive("uri")] - public {{type}} DoSomething() - { - return Array.Empty(); - } + return Array.Empty(); } } - """); - - [Fact] - public Task ShouldReplaceEmptyListCreationWithArrayEmptyWhenReturnFromMethodArrayAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + + [Fact] + public Task ShouldReplaceEmptyListCreationWithArrayEmptyWhenReturnFromMethodArrayAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public int[] DoSomething() { - [PerformanceSensitive("uri")] - public int[] DoSomething() - { - return new int[0]; - } + return new int[0]; } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 30), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 30), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public int[] DoSomething() { - [PerformanceSensitive("uri")] - public int[] DoSomething() - { - return Array.Empty(); - } + return Array.Empty(); } } - """); - - [Fact] - public Task ShouldReplaceEmptyLisCreationWithArrayEmptyForArrowExpressionAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + + [Fact] + public Task ShouldReplaceEmptyLisCreationWithArrayEmptyForArrowExpressionAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass - { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething => new List(); - } + [PerformanceSensitive("uri")] + public IEnumerable DoSomething => new List(); } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(10, 48, 10, 63), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(10, 48, 10, 63), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass - { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething => Array.Empty(); - } + [PerformanceSensitive("uri")] + public IEnumerable DoSomething => Array.Empty(); } - """); - [Fact] - public Task ShouldReplaceEmptyListCreationWithArrayEmptyForReadonlyPropertyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceEmptyListCreationWithArrayEmptyForReadonlyPropertyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething { get {return new List();}} + } + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(10, 59, 10, 74), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass + { + [PerformanceSensitive("uri")] + public IEnumerable DoSomething { get {return Array.Empty();}} + } + } + """); + [Fact] + public Task ShouldReplaceEmptyListWithCreationWithPredefinedSizeWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass + { + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething { get {return new List();}} + return new List(10); } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(10, 59, 10, 74), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 37), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething { get {return Array.Empty();}} + return Array.Empty(); } } - """); - [Fact] - public Task ShouldReplaceEmptyListWithCreationWithPredefinedSizeWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public async Task ShouldNotProposeCodeFixWhenNonEmptyListCreatedAsync() + { + var code = """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new List(10); - } + return new List(){1, 2}; } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 37), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; + } + """; - namespace SampleNamespace + await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 41), code); + } + [Fact] + public async Task ShouldNotProposeCodeFixWhenReturnTypeInheritFormEnumerableAsync() + { + var code = """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public List DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return Array.Empty(); - } + return new List(); } } - """); - [Fact] - public async Task ShouldNotProposeCodeFixWhenNonEmptyListCreatedAsync() - { - var code = """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 35), code); + } + [Fact] + public async Task ShouldNotProposeCodeFixWhenForCollectionCreationUsingCopyConstructorAsync() + { + var code = """ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new List(){1, 2}; - } + var innerList = new List(){1, 2}; + return new ReadOnlyCollection(innerList); } } - """; - - await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 41), code); - } - [Fact] - public async Task ShouldNotProposeCodeFixWhenReturnTypeInheritFormEnumerableAsync() - { - var code = """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, + [ + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(13, 29, 13, 50), + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(14, 20, 14, 58), + ], code); + } + [Fact] + public Task ShouldReplacEmptyCollectionCreationWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public List DoSomething() - { - return new List(); - } + return new Collection(); } } - """; - - await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 20, 12, 35), code); - } - [Fact] - public async Task ShouldNotProposeCodeFixWhenForCollectionCreationUsingCopyConstructorAsync() - { - var code = """ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(13, 20, 13, 41), """ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - var innerList = new List(){1, 2}; - return new ReadOnlyCollection(innerList); - } + return Array.Empty(); } } - """; - - await VerifyCS.VerifyCodeFixAsync(code, - [ - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(13, 29, 13, 50), - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(14, 20, 14, 58), - ], code); - } - [Fact] - public Task ShouldReplacEmptyCollectionCreationWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceEmptyArrayCreationWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new Collection(); - } + return new int[0]; } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(13, 20, 13, 41), """ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 30), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return Array.Empty(); - } + return Array.Empty(); } } - """); - [Fact] - public Task ShouldReplaceEmptyArrayCreationWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public async Task ShouldNotProposeCodeFixWhenNonEmptyArrayCreationAsync() + { + var code = """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new int[0]; - } + return new int[]{1, 2}; } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 30), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; + } + """; - namespace SampleNamespace + await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 35), code); + } + [Fact] + public Task ShouldReplaceEmptyArrayCreationWithInitBlockWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return Array.Empty(); - } + return new int[] { }; } } - """); - [Fact] - public async Task ShouldNotProposeCodeFixWhenNonEmptyArrayCreationAsync() - { - var code = """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 33), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public IEnumerable DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new int[]{1, 2}; - } + return Array.Empty(); } } - """; - - await VerifyCS.VerifyCodeFixAsync(code, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 35), code); - } - [Fact] - public Task ShouldReplaceEmptyArrayCreationWithInitBlockWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceListCreationAsMethodInvocationParameterWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething() { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return new int[] { }; - } + Do(new List()); } - } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 20, 12, 33), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - namespace SampleNamespace - { - class SampleClass + private void Do(IEnumerable a) { - [PerformanceSensitive("uri")] - public IEnumerable DoSomething() - { - return Array.Empty(); - } + } } - """); - [Fact] - public Task ShouldReplaceListCreationAsMethodInvocationParameterWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 16, 12, 31), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething() { - [PerformanceSensitive("uri")] - public void DoSomething() - { - Do(new List()); - } - - private void Do(IEnumerable a) - { - - } + Do(Array.Empty()); } - } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithSpan(12, 16, 12, 31), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - namespace SampleNamespace - { - class SampleClass + private void Do(IEnumerable a) { - [PerformanceSensitive("uri")] - public void DoSomething() - { - Do(Array.Empty()); - } - private void Do(IEnumerable a) - { - - } } } - """); - [Fact] - public Task ShouldReplaceArrayCreationAsMethodInvocationParameterWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceArrayCreationAsMethodInvocationParameterWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething() { - [PerformanceSensitive("uri")] - public void DoSomething() - { - Do(new int[0]); - } + Do(new int[0]); + } - private void Do(IEnumerable a) - { + private void Do(IEnumerable a) + { - } } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 16, 12, 26), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 16, 12, 26), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething() { - [PerformanceSensitive("uri")] - public void DoSomething() - { - Do(Array.Empty()); - } + Do(Array.Empty()); + } - private void Do(IEnumerable a) - { + private void Do(IEnumerable a) + { - } } } - """); - [Fact] - public Task ShouldReplaceArrayCreationAsDelegateInvocationParameterWithArrayEmptyAsync() - => VerifyCS.VerifyCodeFixAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """); + [Fact] + public Task ShouldReplaceArrayCreationAsDelegateInvocationParameterWithArrayEmptyAsync() + => VerifyCS.VerifyCodeFixAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething(Action> doSth) { - [PerformanceSensitive("uri")] - public void DoSomething(Action> doSth) - { - doSth(new int[0]); - } + doSth(new int[0]); } } - """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 19, 12, 29), """ - using System; - using System.Collections.Generic; - using Roslyn.Utilities; - - namespace SampleNamespace + } + """, VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithSpan(12, 19, 12, 29), """ + using System; + using System.Collections.Generic; + using Roslyn.Utilities; + + namespace SampleNamespace + { + class SampleClass { - class SampleClass + [PerformanceSensitive("uri")] + public void DoSomething(Action> doSth) { - [PerformanceSensitive("uri")] - public void DoSomething(Action> doSth) - { - doSth(Array.Empty()); - } + doSth(Array.Empty()); } } - """); - } + } + """); } diff --git a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/CallSiteImplicitAllocationAnalyzerTests.cs b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/CallSiteImplicitAllocationAnalyzerTests.cs index bf22e1b99b7..5ed95490694 100644 --- a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/CallSiteImplicitAllocationAnalyzerTests.cs +++ b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/CallSiteImplicitAllocationAnalyzerTests.cs @@ -4,203 +4,204 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.CallSiteImplicitAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysisPerformanceSensitiveAnalyzers.UnitTests +namespace Microsoft.CodeAnalysisPerformanceSensitiveAnalyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + CallSiteImplicitAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class CallSiteImplicitAllocationAnalyzerTests { - public class CallSiteImplicitAllocationAnalyzerTests - { - [Fact] - public Task CallSiteImplicitAllocation_ParamAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + [Fact] + public Task CallSiteImplicitAllocation_ParamAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Params(); //no allocation, because compiler will implicitly substitute Array.Empty() - Params(1, 2); - Params(new [] { 1, 2}); // explicit, so no warning - ParamsWithObjects(new [] { 1, 2}); // explicit, but converted to objects, so stil la warning?! + Params(); //no allocation, because compiler will implicitly substitute Array.Empty() + Params(1, 2); + Params(new [] { 1, 2}); // explicit, so no warning + ParamsWithObjects(new [] { 1, 2}); // explicit, but converted to objects, so stil la warning?! - // Only 4 args and above use the params overload of String.Format - var test = String.Format("Testing {0}, {1}, {2}, {3}", 1, "blah", 2.0m, 'c'); - } + // Only 4 args and above use the params overload of String.Format + var test = String.Format("Testing {0}, {1}, {2}, {3}", 1, "blah", 2.0m, 'c'); + } - public void Params(params int[] args) - { - } + public void Params(params int[] args) + { + } - public void ParamsWithObjects(params object[] args) - { - } + public void ParamsWithObjects(params object[] args) + { } - """, - // Test0.cs(11,9): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation + } + """, + // Test0.cs(11,9): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(11, 9), + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(11, 9), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(13,9): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation + // Test0.cs(13,9): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(13, 9), + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(13, 9), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(16,20): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation + // Test0.cs(16,20): warning HAA0101: This call site is calling into a function with a 'params' parameter. This results in an array allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(16, 20)); - - [Fact, WorkItem(3272, "https://github.com/dotnet/roslyn-analyzers/issues/3272")] - public Task EmptyParamsWithNetFramework45Async() - => new VerifyCS.Test + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(16, 20)); + + [Fact, WorkItem(3272, "https://github.com/dotnet/roslyn-analyzers/issues/3272")] + public Task EmptyParamsWithNetFramework45Async() + => new VerifyCS.Test + { + ReferenceAssemblies = ReferenceAssemblies.NetFramework.Net45.Default, + TestState = { - ReferenceAssemblies = ReferenceAssemblies.NetFramework.Net45.Default, - TestState = + Sources = { - Sources = + """ + using System; + using Roslyn.Utilities; + + public class MyClass { - """ - using System; - using Roslyn.Utilities; + [PerformanceSensitive("uri")] + public void Testing() + { + Params(); // allocation + } - public class MyClass + public void Params(params int[] args) { - [PerformanceSensitive("uri")] - public void Testing() - { - Params(); // allocation - } - - public void Params(params int[] args) - { - } } - """, - ("PerformanceSensitiveAttribute.cs", VerifyCS.PerformanceSensitiveAttributeSource) - }, - ExpectedDiagnostics = - { + } + """, + ("PerformanceSensitiveAttribute.cs", VerifyCS.PerformanceSensitiveAttributeSource) + }, + ExpectedDiagnostics = + { #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(9, 9), + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(9, 9), #pragma warning restore RS0030 // Do not use banned APIs - }, }, - }.RunAsync(); + }, + }.RunAsync(); - [Fact] - public Task CallSiteImplicitAllocation_NonOverridenMethodOnStructAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task CallSiteImplicitAllocation_NonOverridenMethodOnStructAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var normal = new Normal().GetHashCode(); - var overridden = new OverrideToHashCode().GetHashCode(); - } + var normal = new Normal().GetHashCode(); + var overridden = new OverrideToHashCode().GetHashCode(); } + } - public struct Normal - { - } + public struct Normal + { + } - public struct OverrideToHashCode + public struct OverrideToHashCode + { + public override int GetHashCode() { - public override int GetHashCode() - { - return -1; - } + return -1; } - """, - // Test0.cs(10,22): warning HAA0102: Non-overridden virtual method call on a value type adds a boxing or constrained instruction + } + """, + // Test0.cs(10,22): warning HAA0102: Non-overridden virtual method call on a value type adds a boxing or constrained instruction #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ValueTypeNonOverridenCallRule).WithLocation(9, 22)); + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ValueTypeNonOverridenCallRule).WithLocation(9, 22)); - [Fact] - public Task CallSiteImplicitAllocation_DoNotReportNonOverriddenMethodCallForStaticCallsAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task CallSiteImplicitAllocation_DoNotReportNonOverriddenMethodCallForStaticCallsAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var t = System.Enum.GetUnderlyingType(typeof(System.StringComparison)); - } + var t = System.Enum.GetUnderlyingType(typeof(System.StringComparison)); } - """); + } + """); - [Fact] - public Task CallSiteImplicitAllocation_DoNotReportNonOverriddenMethodCallForNonVirtualCallsAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.IO; - using Roslyn.Utilities; + [Fact] + public Task CallSiteImplicitAllocation_DoNotReportNonOverriddenMethodCallForNonVirtualCallsAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.IO; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - FileAttributes attr = FileAttributes.System; - attr.HasFlag (FileAttributes.Directory); - } + FileAttributes attr = FileAttributes.System; + attr.HasFlag (FileAttributes.Directory); } - """); + } + """); - [Fact] - public Task ParamsIsPrecededByOptionalParametersAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.IO; - using Roslyn.Utilities; + [Fact] + public Task ParamsIsPrecededByOptionalParametersAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.IO; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + void Fun1() { - [PerformanceSensitive("uri")] - void Fun1() - { - Fun2(); - {|#0:Fun2(args: "", i: 5)|}; - } + Fun2(); + {|#0:Fun2(args: "", i: 5)|}; + } - void Fun2(int i = 0, params object[] args) - { - } + void Fun2(int i = 0, params object[] args) + { } - """, - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(0)); + } + """, + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ParamsParameterRule).WithLocation(0)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Calling_non_overridden_virtual_methods_on_value_typesAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Calling_non_overridden_virtual_methods_on_value_typesAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - enum E { A } + enum E { A } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - E.A.GetHashCode(); - } + E.A.GetHashCode(); } - """, - // Test0.cs(12,9): warning HAA0102: Non-overridden virtual method call on a value type adds a boxing or constrained instruction + } + """, + // Test0.cs(12,9): warning HAA0102: Non-overridden virtual method call on a value type adds a boxing or constrained instruction #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ValueTypeNonOverridenCallRule).WithLocation(11, 9)); - } + VerifyCS.Diagnostic(CallSiteImplicitAllocationAnalyzer.ValueTypeNonOverridenCallRule).WithLocation(11, 9)); } diff --git a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ConcatenationAllocationAnalyzerTests.cs b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ConcatenationAllocationAnalyzerTests.cs index 98e7c045bd1..680e1420ebb 100644 --- a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ConcatenationAllocationAnalyzerTests.cs +++ b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ConcatenationAllocationAnalyzerTests.cs @@ -4,110 +4,111 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.ConcatenationAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + ConcatenationAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class ConcatenationAllocationAnalyzerTests { - public class ConcatenationAllocationAnalyzerTests - { - [Fact] - public Task ConcatenationAllocation_Basic1Async() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task ConcatenationAllocation_Basic1Async() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - string s0 = "hello" + 0.ToString() + "world" + 1.ToString(); - } + string s0 = "hello" + 0.ToString() + "world" + 1.ToString(); } - """); + } + """); - [Fact] - public Task ConcatenationAllocation_Basic2Async() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task ConcatenationAllocation_Basic2Async() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - string s2 = "ohell" + 2.ToString() + "world" + 3.ToString() + 4.ToString(); - } + string s2 = "ohell" + 2.ToString() + "world" + 3.ToString() + 4.ToString(); } - """, - // Test0.cs(9,21): warning HAA0201: Considering using StringBuilder + } + """, + // Test0.cs(9,21): warning HAA0201: Considering using StringBuilder #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ConcatenationAllocationAnalyzer.StringConcatenationAllocationRule).WithLocation(9, 21)); + VerifyCS.Diagnostic(ConcatenationAllocationAnalyzer.StringConcatenationAllocationRule).WithLocation(9, 21)); - [Theory] - [InlineData("string s0 = nameof(System.String) + '-';")] - [InlineData("string s0 = nameof(System.String) + true;")] - [InlineData("string s0 = nameof(System.String) + new System.IntPtr();")] - [InlineData("string s0 = nameof(System.String) + new System.UIntPtr();")] - public Task ConcatenationAllocation_DoNotWarnForOptimizedValueTypesAsync(string statement) - => VerifyCS.VerifyAnalyzerAsync($$""" - using System; - using Roslyn.Utilities; + [Theory] + [InlineData("string s0 = nameof(System.String) + '-';")] + [InlineData("string s0 = nameof(System.String) + true;")] + [InlineData("string s0 = nameof(System.String) + new System.IntPtr();")] + [InlineData("string s0 = nameof(System.String) + new System.UIntPtr();")] + public Task ConcatenationAllocation_DoNotWarnForOptimizedValueTypesAsync(string statement) + => VerifyCS.VerifyAnalyzerAsync($$""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - {{statement}} - } + {{statement}} } - """); + } + """); - [Theory] - [InlineData(@"const string s0 = nameof(System.String) + ""."" + nameof(System.String);")] - [InlineData(@"const string s0 = nameof(System.String) + ""."";")] - [InlineData(@"string s0 = nameof(System.String) + ""."" + nameof(System.String);")] - [InlineData(@"string s0 = nameof(System.String) + ""."";")] - public Task ConcatenationAllocation_DoNotWarnForConstAsync(string statement) - => VerifyCS.VerifyAnalyzerAsync($$""" - using System; - using Roslyn.Utilities; + [Theory] + [InlineData(@"const string s0 = nameof(System.String) + ""."" + nameof(System.String);")] + [InlineData(@"const string s0 = nameof(System.String) + ""."";")] + [InlineData(@"string s0 = nameof(System.String) + ""."" + nameof(System.String);")] + [InlineData(@"string s0 = nameof(System.String) + ""."";")] + public Task ConcatenationAllocation_DoNotWarnForConstAsync(string statement) + => VerifyCS.VerifyAnalyzerAsync($$""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - {{statement}} - } + {{statement}} } - """); + } + """); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Non_constant_value_types_in_CSharp_string_concatenationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Non_constant_value_types_in_CSharp_string_concatenationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - System.DateTime c = System.DateTime.Now; - string s1 = "char value will box" + c; - } + System.DateTime c = System.DateTime.Now; + string s1 = "char value will box" + c; } - """, - // Test0.cs(11,45): warning HAA0202: Value type (System.DateTime) is being boxed to a reference type for a string concatenation. + } + """, + // Test0.cs(11,45): warning HAA0202: Value type (System.DateTime) is being boxed to a reference type for a string concatenation. #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ConcatenationAllocationAnalyzer.ValueTypeToReferenceTypeInAStringConcatenationRule).WithLocation(10, 45).WithArguments("System.DateTime")); - } + VerifyCS.Diagnostic(ConcatenationAllocationAnalyzer.ValueTypeToReferenceTypeInAStringConcatenationRule).WithLocation(10, 45).WithArguments("System.DateTime")); } diff --git a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/DisplayClassAllocationAnalyzerTests.cs b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/DisplayClassAllocationAnalyzerTests.cs index 62f1fae06db..8c0f431e85a 100644 --- a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/DisplayClassAllocationAnalyzerTests.cs +++ b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/DisplayClassAllocationAnalyzerTests.cs @@ -4,164 +4,166 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; +using Microsoft.CodeAnalysis.Testing; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.DisplayClassAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + DisplayClassAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class DisplayClassAllocationAnalyzerTests { - public class DisplayClassAllocationAnalyzerTests - { - [Fact] - public Task DisplayClassAllocation_AnonymousMethodExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - class Test + [Fact] + public Task DisplayClassAllocation_AnonymousMethodExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + class Test + { + static void Main() { - static void Main() - { - Action action = CreateAction(5); - } + Action action = CreateAction(5); + } - [PerformanceSensitive("uri")] - static Action CreateAction(T item) + [PerformanceSensitive("uri")] + static Action CreateAction(T item) + { + T test = default(T); + int counter = 0; + return delegate { - T test = default(T); - int counter = 0; - return delegate - { - counter++; - Console.WriteLine("counter={0}", counter); - }; - } + counter++; + Console.WriteLine("counter={0}", counter); + }; } - """, - // Test0.cs(15,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure + } + """, + // Test0.cs(15,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(15, 13), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(15, 13), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(16,16): warning HAA0303: Considering moving this out of the generic method + // Test0.cs(16,16): warning HAA0303: Considering moving this out of the generic method #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.LambaOrAnonymousMethodInGenericMethodRule).WithLocation(16, 16), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.LambaOrAnonymousMethodInGenericMethodRule).WithLocation(16, 16), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(16,16): warning HAA0301: Heap allocation of closure Captures: counter + // Test0.cs(16,16): warning HAA0301: Heap allocation of closure Captures: counter #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(16, 16).WithArguments("counter")); + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(16, 16).WithArguments("counter")); - [Fact] - public Task DisplayClassAllocation_SimpleLambdaExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System; - using System.Linq; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_SimpleLambdaExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System; + using System.Linq; + using Roslyn.Utilities; - public class Testing + public class Testing + { + [PerformanceSensitive("uri")] + public Testing() { - [PerformanceSensitive("uri")] - public Testing() - { - int[] intData = new[] { 123, 32, 4 }; - int min = 31; - var results = intData.Where(i => i > min).ToList(); - } + int[] intData = new[] { 123, 32, 4 }; + int min = 31; + var results = intData.Where(i => i > min).ToList(); } - """, - // Test0.cs(12,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure + } + """, + // Test0.cs(12,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(12, 13), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(12, 13), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(13,39): warning HAA0301: Heap allocation of closure Captures: min + // Test0.cs(13,39): warning HAA0301: Heap allocation of closure Captures: min #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(13, 39).WithArguments("min")); + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(13, 39).WithArguments("min")); - [Fact] - public Task DisplayClassAllocation_ParenthesizedLambdaExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System; - using System.Linq; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_ParenthesizedLambdaExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System; + using System.Linq; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + var words = new[] { "aaaa", "bbbb", "cccc", "ddd" }; + var actions = new List(); + foreach (string word in words) // <-- captured closure { - var words = new[] { "aaaa", "bbbb", "cccc", "ddd" }; - var actions = new List(); - foreach (string word in words) // <-- captured closure - { - actions.Add(() => Console.WriteLine(word)); // <-- reason for closure capture - } + actions.Add(() => Console.WriteLine(word)); // <-- reason for closure capture } } - """, - // Test0.cs(13,25): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure + } + """, + // Test0.cs(13,25): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(13, 25), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(13, 25), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(15,28): warning HAA0301: Heap allocation of closure Captures: word + // Test0.cs(15,28): warning HAA0301: Heap allocation of closure Captures: word #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(15, 28).WithArguments("word")); + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(15, 28).WithArguments("word")); - [Fact] - public Task DisplayClassAllocation_DoNotReportForNonCapturingAnonymousMethodAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_DoNotReportForNonCapturingAnonymousMethodAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Sorter(int[] arr) { - [PerformanceSensitive("uri")] - public void Sorter(int[] arr) - { - System.Array.Sort(arr, delegate(int x, int y) { return x - y; }); - } + System.Array.Sort(arr, delegate(int x, int y) { return x - y; }); } - """); + } + """); - [Fact] - public Task DisplayClassAllocation_DoNotReportForNonCapturingLambdaAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_DoNotReportForNonCapturingLambdaAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Sorter(int[] arr) { - [PerformanceSensitive("uri")] - public void Sorter(int[] arr) - { - System.Array.Sort(arr, (x, y) => x - y); - } + System.Array.Sort(arr, (x, y) => x - y); } - """); + } + """); - [Fact] - public Task DisplayClassAllocation_ReportForCapturingAnonymousMethodAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task DisplayClassAllocation_ReportForCapturingAnonymousMethodAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Sorter(int[] arr) { - [PerformanceSensitive("uri")] - public void Sorter(int[] arr) - { - int z = 2; - System.Array.Sort(arr, delegate(int x, int y) { return x - z; }); - } + int z = 2; + System.Array.Sort(arr, delegate(int x, int y) { return x - z; }); } - """, - // Test0.cs(9,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure + } + """, + // Test0.cs(9,13): warning HAA0302: The compiler will emit a class that will hold this as a field to allow capturing of this closure #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(9, 13), + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureCaptureRule).WithLocation(9, 13), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(10,32): warning HAA0301: Heap allocation of closure Captures: z + // Test0.cs(10,32): warning HAA0301: Heap allocation of closure Captures: z #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(10, 32).WithArguments("z")); - } + VerifyCS.Diagnostic(DisplayClassAllocationAnalyzer.ClosureDriverRule).WithLocation(10, 32).WithArguments("z")); } diff --git a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/EnumeratorAllocationAnalyzerTests.cs b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/EnumeratorAllocationAnalyzerTests.cs index c79909c8862..eb8a5092ffa 100644 --- a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/EnumeratorAllocationAnalyzerTests.cs +++ b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/EnumeratorAllocationAnalyzerTests.cs @@ -3,152 +3,155 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; +using Microsoft.CodeAnalysis.Testing; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.EnumeratorAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + EnumeratorAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class EnumeratorAllocationAnalyzerTests { - public class EnumeratorAllocationAnalyzerTests - { - [Fact] - public Task EnumeratorAllocation_BasicAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System; - using System.Linq; - using Roslyn.Utilities; - - public class MyClass + [Fact] + public Task EnumeratorAllocation_BasicAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System; + using System.Linq; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + int[] intData = new[] { 123, 32, 4 }; + IList iListData = new[] { 123, 32, 4 }; + List listData = new[] { 123, 32, 4 }.ToList(); + + foreach (var i in intData) { - int[] intData = new[] { 123, 32, 4 }; - IList iListData = new[] { 123, 32, 4 }; - List listData = new[] { 123, 32, 4 }.ToList(); - - foreach (var i in intData) - { - Console.WriteLine(i); - } - - foreach (var i in listData) - { - Console.WriteLine(i); - } - - foreach (var i in iListData) // Allocations (line 19) - { - Console.WriteLine(i); - } - - foreach (var i in (IEnumerable)intData) // Allocations (line 24) - { - Console.WriteLine(i); - } + Console.WriteLine(i); + } + + foreach (var i in listData) + { + Console.WriteLine(i); } - } - """, - // Test0.cs(25,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation -#pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic().WithLocation(25, 24), -#pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(30,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation -#pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic().WithLocation(30, 24)); - [Fact] - public Task EnumeratorAllocation_AdvancedAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System; - using Roslyn.Utilities; + foreach (var i in iListData) // Allocations (line 19) + { + Console.WriteLine(i); + } - public class MyClass - { - [PerformanceSensitive("uri")] - public void SomeMethod() + foreach (var i in (IEnumerable)intData) // Allocations (line 24) { - // These next 3 are from the YouTube video - foreach (object a in new[] { 1, 2, 3}) // Allocations 'new [] { 1. 2, 3}' - { - Console.WriteLine(a.ToString()); - } - - IEnumerable fx1 = default(IEnumerable); - foreach (var f in fx1) // Allocations 'in' - { - } - - List fx2 = default(List); - foreach (var f in fx2) // NO Allocations - { - } + Console.WriteLine(i); } } - """, - // Test0.cs(17,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation + } + """, + // Test0.cs(25,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic().WithLocation(17, 24)); - - [Fact] - public Task EnumeratorAllocation_Via_InvocationExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System.Collections; - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyCS.Diagnostic().WithLocation(25, 24), +#pragma warning restore RS0030 // Do not use banned APIs + // Test0.cs(30,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation +#pragma warning disable RS0030 // Do not use banned APIs + VerifyCS.Diagnostic().WithLocation(30, 24)); + + [Fact] + public Task EnumeratorAllocation_AdvancedAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + // These next 3 are from the YouTube video + foreach (object a in new[] { 1, 2, 3}) // Allocations 'new [] { 1. 2, 3}' { - var enumeratorRaw = GetIEnumerableRaw(); - while (enumeratorRaw.MoveNext()) - { - Console.WriteLine(enumeratorRaw.Current.ToString()); - } - - var enumeratorRawViaIEnumerable = GetIEnumeratorViaIEnumerable(); - while (enumeratorRawViaIEnumerable.MoveNext()) - { - Console.WriteLine(enumeratorRawViaIEnumerable.Current.ToString()); - } + Console.WriteLine(a.ToString()); } - private IEnumerator GetIEnumerableRaw() + IEnumerable fx1 = default(IEnumerable); + foreach (var f in fx1) // Allocations 'in' { - return new[] { 123, 32, 4 }.GetEnumerator(); } - private IEnumerator GetIEnumeratorViaIEnumerable() + List fx2 = default(List); + foreach (var f in fx2) // NO Allocations { - int[] intData = new[] { 123, 32, 4 }; - return (IEnumerator)intData.GetEnumerator(); } } - """, - // Test0.cs(17,43): warning HAA0401: Non-ValueType enumerator may result in a heap allocation + } + """, + // Test0.cs(17,24): warning HAA0401: Non-ValueType enumerator may result in a heap allocation #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic().WithLocation(17, 43)); - - [Fact] - public Task EnumeratorAllocation_IterateOverString_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyCS.Diagnostic().WithLocation(17, 24)); + + [Fact] + public Task EnumeratorAllocation_Via_InvocationExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System.Collections; + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + var enumeratorRaw = GetIEnumerableRaw(); + while (enumeratorRaw.MoveNext()) + { + Console.WriteLine(enumeratorRaw.Current.ToString()); + } + + var enumeratorRawViaIEnumerable = GetIEnumeratorViaIEnumerable(); + while (enumeratorRawViaIEnumerable.MoveNext()) { - foreach (char c in "aaa") { }; + Console.WriteLine(enumeratorRawViaIEnumerable.Current.ToString()); } } - """); - } + + private IEnumerator GetIEnumerableRaw() + { + return new[] { 123, 32, 4 }.GetEnumerator(); + } + + private IEnumerator GetIEnumeratorViaIEnumerable() + { + int[] intData = new[] { 123, 32, 4 }; + return (IEnumerator)intData.GetEnumerator(); + } + } + """, + // Test0.cs(17,43): warning HAA0401: Non-ValueType enumerator may result in a heap allocation +#pragma warning disable RS0030 // Do not use banned APIs + VerifyCS.Diagnostic().WithLocation(17, 43)); + + [Fact] + public Task EnumeratorAllocation_IterateOverString_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() + { + foreach (char c in "aaa") { }; + } + } + """); } diff --git a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ExplicitAllocationAnalyzerTests.cs b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ExplicitAllocationAnalyzerTests.cs index 18798598180..208e5874c6f 100644 --- a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ExplicitAllocationAnalyzerTests.cs +++ b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/ExplicitAllocationAnalyzerTests.cs @@ -4,755 +4,757 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.ExplicitAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -using VerifyVB = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.VisualBasicPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.ExplicitAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; - -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests -{ - public class ExplicitAllocationAnalyzerTests - { - [Fact] - public Task ExplicitAllocation_ObjectInitializerAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass - { - [PerformanceSensitive("uri")] - public void Testing() - { - var @class = new TestClass { Name = "Bob" }; - } - } - public class TestClass - { - public string Name { get; set; } - } - """, -#pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 22)); - - [Fact] - public Task ExplicitAllocation_ObjectInitializer_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync( - """ - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim instance = New TestClass With {.Name = "Bob"} - End Sub - End Class - - Public Class TestClass - Public Property Name As String - End Class - """, -#pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 24)); +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; - [Fact] - public Task ExplicitAllocation_ObjectInitializerStruct_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; +using VerifyCS = CSharpPerformanceCodeFixVerifier< + ExplicitAllocationAnalyzer, + EmptyCodeFixProvider>; +using VerifyVB = VisualBasicPerformanceCodeFixVerifier< + ExplicitAllocationAnalyzer, + EmptyCodeFixProvider>; - public class MyClass +public sealed class ExplicitAllocationAnalyzerTests +{ + [Fact] + public Task ExplicitAllocation_ObjectInitializerAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var @struct = new TestStruct { Name = "Bob" }; - } + var @class = new TestClass { Name = "Bob" }; } + } - public struct TestStruct + public class TestClass + { + public string Name { get; set; } + } + """, +#pragma warning disable RS0030 // Do not use banned APIs + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 22)); + + [Fact] + public Task ExplicitAllocation_ObjectInitializer_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync( + """ + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim instance = New TestClass With {.Name = "Bob"} + End Sub + End Class + + Public Class TestClass + Public Property Name As String + End Class + """, +#pragma warning disable RS0030 // Do not use banned APIs + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 24)); + + [Fact] + public Task ExplicitAllocation_ObjectInitializerStruct_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - public string Name { get; set; } + var @struct = new TestStruct { Name = "Bob" }; } - """); - - [Fact] - public Task ExplicitAllocation_ObjectInitializerStruct_NoWarning_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim instance = New TestClass With {.Name = "Bob"} - End Sub - End Class - - Public Structure TestClass - Public Property Name As String - End Structure - """); - - [Fact] - public Task ExplicitAllocation_ImplicitArrayCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using Roslyn.Utilities; - - public class MyClass + } + + public struct TestStruct + { + public string Name { get; set; } + } + """); + + [Fact] + public Task ExplicitAllocation_ObjectInitializerStruct_NoWarning_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim instance = New TestClass With {.Name = "Bob"} + End Sub + End Class + + Public Structure TestClass + Public Property Name As String + End Structure + """); + + [Fact] + public Task ExplicitAllocation_ImplicitArrayCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - int[] intData = new[] { 123, 32, 4 }; - } + int[] intData = new[] { 123, 32, 4 }; } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(9, 25)); - - [Fact] - public Task ExplicitAllocation_ImplicitArrayCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim intData() As Integer = {123, 32, 4} - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(9, 25)); + + [Fact] + public Task ExplicitAllocation_ImplicitArrayCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim intData() As Integer = {123, 32, 4} + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(7, 36)); - - [Fact] - public Task ExplicitAllocation_AnonymousObjectCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(7, 36)); + + [Fact] + public Task ExplicitAllocation_AnonymousObjectCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var temp = new { A = 123, Name = "Test", }; - } + var temp = new { A = 123, Name = "Test", }; } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.AnonymousObjectCreationRule).WithLocation(9, 20)); - - [Fact] - public Task ExplicitAllocation_AnonymousObjectCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim temp = New With {Key .B = 123, .Name = "Test"} - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.AnonymousObjectCreationRule).WithLocation(9, 20)); + + [Fact] + public Task ExplicitAllocation_AnonymousObjectCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim temp = New With {Key .B = 123, .Name = "Test"} + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.AnonymousObjectCreationRule).WithLocation(7, 20)); - - [Fact] - public Task ExplicitAllocation_ArrayCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.AnonymousObjectCreationRule).WithLocation(7, 20)); + + [Fact] + public Task ExplicitAllocation_ArrayCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - int[] intData = new int[] { 123, 32, 4 }; - } + int[] intData = new int[] { 123, 32, 4 }; } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(9, 25)); - - [Fact] - public Task ExplicitAllocation_ArrayCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim intData = New Integer() {123, 32, 4} - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(9, 25)); + + [Fact] + public Task ExplicitAllocation_ArrayCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim intData = New Integer() {123, 32, 4} + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(7, 23)); - - [Fact] - public Task ExplicitAllocation_ObjectCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(7, 23)); + + [Fact] + public Task ExplicitAllocation_ObjectCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var allocation = new String('a', 10); - } + var allocation = new String('a', 10); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 26)); - - [Fact] - public Task ExplicitAllocation_ObjectCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim allocation = New String("a"c, 10) - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 26)); + + [Fact] + public Task ExplicitAllocation_ObjectCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim allocation = New String("a"c, 10) + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 26)); - - [Fact] - public Task ExplicitAllocation_LetClauseAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using System.Linq; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 26)); + + [Fact] + public Task ExplicitAllocation_LetClauseAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System.Linq; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - int[] intData = new[] { 123, 32, 4 }; - var result = (from a in intData - let b = a * 3 - select b).ToList(); - } + int[] intData = new[] { 123, 32, 4 }; + var result = (from a in intData + let b = a * 3 + select b).ToList(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(10, 25), + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(10, 25), #pragma warning restore RS0030 // Do not use banned APIs #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.LetCauseRule).WithLocation(12, 23)); - - [Fact] - public Task ExplicitAllocation_LetClause_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports System.Linq - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim intData() As Integer = {123, 32, 4} - Dim result = (From x In intData - Let b = x * 3 - Select b).ToList() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.LetCauseRule).WithLocation(12, 23)); + + [Fact] + public Task ExplicitAllocation_LetClause_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports System.Linq + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim intData() As Integer = {123, 32, 4} + Dim result = (From x In intData + Let b = x * 3 + Select b).ToList() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(8, 36), + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ArrayCreationRule).WithLocation(8, 36), #pragma warning restore RS0030 // Do not use banned APIs #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.LetCauseRule).WithLocation(10, 27)); + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.LetCauseRule).WithLocation(10, 27)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_to_System_Object_typeAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_to_System_Object_typeAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using Roslyn.Utilities; - public struct S { } + public struct S { } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - object box = new S(); - } + object box = new S(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 22)); - - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_to_System_Object_type_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports Roslyn.Utilities - - Public Structure S - End Structure - - Public Class A - - Public Sub SomeMethod() - Dim box As Object = new S() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 22)); + + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_to_System_Object_type_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports Roslyn.Utilities + + Public Structure S + End Structure + + Public Class A + + Public Sub SomeMethod() + Dim box As Object = new S() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 29)); + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 29)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_to_System_ValueType_typeAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_to_System_ValueType_typeAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using Roslyn.Utilities; - public struct S { } + public struct S { } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - System.ValueType box = new S(); - } + System.ValueType box = new S(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 32)); - - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_to_System_ValueType_type_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports Roslyn.Utilities - - Public Structure S - End Structure - - Public Class A - - Public Sub SomeMethod() - Dim box As System.ValueType = new S() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 32)); + + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_to_System_ValueType_type_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports Roslyn.Utilities + + Public Structure S + End Structure + + Public Class A + + Public Sub SomeMethod() + Dim box As System.ValueType = new S() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 39)); + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 39)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_into_interface_referenceAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_into_interface_referenceAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using Roslyn.Utilities; - interface I { } + interface I { } - public struct S : I { } + public struct S : I { } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - I box = new S(); - } + I box = new S(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(12, 17)); - - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_value_type_into_interface_reference_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports Roslyn.Utilities - - Interface I - End Interface - - Public Structure S - Implements I - End Structure - - Public Class A - - Public Sub SomeMethod() - Dim box As I = new S() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(12, 17)); + + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_value_type_into_interface_reference_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports Roslyn.Utilities + + Interface I + End Interface + + Public Structure S + Implements I + End Structure + + Public Class A + + Public Sub SomeMethod() + Dim box As I = new S() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(13, 24)); + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(13, 24)); - [Fact] - public Task ExplicitAllocation_StructCreation_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task ExplicitAllocation_StructCreation_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public struct S { } + public struct S { } - public class MyClass - { + public class MyClass + { - [PerformanceSensitive("uri")] - public void Testing() - { - var noBox1 = new DateTime(); - S noBox2 = new S(); - } - } - """); - - [Fact] - public Task ExplicitAllocation_StructCreation_NoWarning_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Structure S - End Structure - - Public Class A - - Public Sub Testing() - Dim noBox1 = new DateTime() - Dim noBox2 As S = new S() - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_PrimitiveTypeConversion_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - double x = new int(); - } + var noBox1 = new DateTime(); + S noBox2 = new S(); } - """); - - [Fact] - public Task ExplicitAllocation_PrimitiveTypeConversion_NoWarning_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim x As Double = New Integer() - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_ImplicitValueTypeConversion_NoWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - struct A + } + """); + + [Fact] + public Task ExplicitAllocation_StructCreation_NoWarning_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Structure S + End Structure + + Public Class A + + Public Sub Testing() + Dim noBox1 = new DateTime() + Dim noBox2 As S = new S() + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_PrimitiveTypeConversion_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - public static implicit operator A(B other) - { - return new A(); - } + double x = new int(); } - - struct B + } + """); + + [Fact] + public Task ExplicitAllocation_PrimitiveTypeConversion_NoWarning_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim x As Double = New Integer() + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_ImplicitValueTypeConversion_NoWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + struct A + { + public static implicit operator A(B other) { + return new A(); } + } - public class MyClass + struct B + { + } + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - A a = new B(); - } + A a = new B(); } - """); - - [Fact] - public Task ExplicitAllocation_ImplicitValueTypeConversion_NoWarning_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Structure A - Public Shared Widening Operator CType(other As B) As A - Return New A() - End Operator - End Structure - - Structure B - End Structure - - Public Class C - - Public Sub Testing() - Dim a As A = New B() - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_NoParamsArrayCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using Roslyn.Utilities; - - public class MyClass + } + """); + + [Fact] + public Task ExplicitAllocation_ImplicitValueTypeConversion_NoWarning_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Structure A + Public Shared Widening Operator CType(other As B) As A + Return New A() + End Operator + End Structure + + Structure B + End Structure + + Public Class C + + Public Sub Testing() + Dim a As A = New B() + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_NoParamsArrayCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing(params int[] values) { - [PerformanceSensitive("uri")] - public void Testing(params int[] values) - { - Testing(); - } + Testing(); } - """); - - [Fact] - public Task ExplicitAllocation_NoParamsArrayCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(ParamArray values() As Integer) - Testing() - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_ExplicitDelegateCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + } + """); + + [Fact] + public Task ExplicitAllocation_NoParamsArrayCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(ParamArray values() As Integer) + Testing() + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_ExplicitDelegateCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing(object sender, EventArgs e) { - [PerformanceSensitive("uri")] - public void Testing(object sender, EventArgs e) - { - var handler = new EventHandler(Testing); - } + var handler = new EventHandler(Testing); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 23)); - - [Fact] - public Task ExplicitAllocation_ExplicitDelegateCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(sender As Object, e As EventArgs) - Dim handler = new EventHandler(AddressOf Testing) - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 23)); + + [Fact] + public Task ExplicitAllocation_ExplicitDelegateCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(sender As Object, e As EventArgs) + Dim handler = new EventHandler(AddressOf Testing) + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 23)); - - [Fact] - public Task ExplicitAllocation_ImplicitDelegateCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 23)); + + [Fact] + public Task ExplicitAllocation_ImplicitDelegateCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing(object sender, EventArgs e) { - [PerformanceSensitive("uri")] - public void Testing(object sender, EventArgs e) - { - EventHandler handler = Testing; - } + EventHandler handler = Testing; } - """); - - [Fact] - public Task ExplicitAllocation_ImplicitDelegateCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(sender As Object, e As EventArgs) - Dim handler As EventHandler = AddressOf Testing - End Sub - End Class - """); - - [Fact] - public Task ExplicitAllocation_ListInitializerCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System.Collections.Generic; - using Roslyn.Utilities; - - public class MyClass + } + """); + + [Fact] + public Task ExplicitAllocation_ImplicitDelegateCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(sender As Object, e As EventArgs) + Dim handler As EventHandler = AddressOf Testing + End Sub + End Class + """); + + [Fact] + public Task ExplicitAllocation_ListInitializerCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var intData = new List { 3, 4 }; - } + var intData = new List { 3, 4 }; } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 23)); - - [Fact] - public Task ExplicitAllocation_ListInitializerCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System.Collections.Generic - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing() - Dim intData = New List(Of Integer) From {3, 4} - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(9, 23)); + + [Fact] + public Task ExplicitAllocation_ListInitializerCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System.Collections.Generic + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing() + Dim intData = New List(Of Integer) From {3, 4} + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 23)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreationAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 23)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreationAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() + where T : class, new() { - [PerformanceSensitive("uri")] - public void Testing() - where T : class, new() - { - var allocation = new T(); - } + var allocation = new T(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 26)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(Of T As {Class, New})() - Dim allocation = New T() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 26)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(Of T As {Class, New})() + Dim allocation = New T() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 26)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation2Async() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 26)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation2Async() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() + where T : struct { - [PerformanceSensitive("uri")] - public void Testing() - where T : struct - { - object allocation = new T(); - } + object allocation = new T(); } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 29)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation2_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(Of T As Structure)() - Dim allocation As Object = New T() - End Sub - End Class - """, + VerifyCS.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(10, 29)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation2_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(Of T As Structure)() + Dim allocation As Object = New T() + End Sub + End Class + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 36)); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation3Async() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + VerifyVB.Diagnostic(ExplicitAllocationAnalyzer.ObjectCreationRule).WithLocation(7, 36)); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation3Async() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() + where T : struct { - [PerformanceSensitive("uri")] - public void Testing() - where T : struct - { - T value = new T(); - } + T value = new T(); } - """); - - [Fact] - public Task ExplicitAllocation_GenericObjectCreation3_VisualBasicAsync() - => VerifyVB.VerifyAnalyzerAsync(""" - Imports System - Imports Roslyn.Utilities - - Public Class A - - Public Sub Testing(Of T As Structure)() - Dim value As T = new T() - End Sub - End Class - """); - } + } + """); + + [Fact] + public Task ExplicitAllocation_GenericObjectCreation3_VisualBasicAsync() + => VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports Roslyn.Utilities + + Public Class A + + Public Sub Testing(Of T As Structure)() + Dim value As T = new T() + End Sub + End Class + """); } diff --git a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/TypeConversionAllocationAnalyzerTests.cs b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/TypeConversionAllocationAnalyzerTests.cs index 331dceb9828..39c7bd51887 100644 --- a/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/TypeConversionAllocationAnalyzerTests.cs +++ b/src/roslyn/src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/UnitTests/TypeConversionAllocationAnalyzerTests.cs @@ -4,810 +4,812 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers; +using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; -using VerifyCS = Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.CSharpPerformanceCodeFixVerifier< - Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.TypeConversionAllocationAnalyzer, - Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; -namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests +namespace Microsoft.CodeAnalysis.PerformanceSensitive.Analyzers.UnitTests; + +using VerifyCS = CSharpPerformanceCodeFixVerifier< + TypeConversionAllocationAnalyzer, + EmptyCodeFixProvider>; + +public sealed class TypeConversionAllocationAnalyzerTests { - public class TypeConversionAllocationAnalyzerTests - { - [Fact] - public Task TypeConversionAllocation_ArgumentSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_ArgumentSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyObject + public class MyObject + { + public MyObject(object obj) { - public MyObject(object obj) - { - } + } - private void ObjCall(object obj) - { - } + private void ObjCall(object obj) + { + } - [PerformanceSensitive("uri")] - public void SomeMethod() - { - ObjCall(10); // Allocation - _ = new MyObject(10); // Allocation - } + [PerformanceSensitive("uri")] + public void SomeMethod() + { + ObjCall(10); // Allocation + _ = new MyObject(10); // Allocation } - """, + } + """, #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(17, 17), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(17, 17), #pragma warning restore RS0030 // Do not use banned APIs #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(18, 26) + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(18, 26) #pragma warning restore RS0030 // Do not use banned APIs - ); + ); - [Fact] - public Task TypeConversionAllocation_ArgumentSyntax_WithDelegatesAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_ArgumentSyntax_WithDelegatesAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var @class = new MyClass(); - @class.ProcessFunc(someObjCall); // implicit, so Allocation - @class.ProcessFunc(new Func(someObjCall)); // Explicit, so NO Allocation - } + var @class = new MyClass(); + @class.ProcessFunc(someObjCall); // implicit, so Allocation + @class.ProcessFunc(new Func(someObjCall)); // Explicit, so NO Allocation + } - public void ProcessFunc(Func func) - { - } + public void ProcessFunc(Func func) + { + } - private string someObjCall(object obj) => null; + private string someObjCall(object obj) => null; + } + + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() + { + var @struct = new MyStruct(); + @struct.ProcessFunc(someObjCall); // implicit allocation + boxing + @struct.ProcessFunc(new Func(someObjCall)); // Explicit allocation + boxing } - public struct MyStruct + public void ProcessFunc(Func func) { - [PerformanceSensitive("uri")] - public void Testing() - { - var @struct = new MyStruct(); - @struct.ProcessFunc(someObjCall); // implicit allocation + boxing - @struct.ProcessFunc(new Func(someObjCall)); // Explicit allocation + boxing - } + } - public void ProcessFunc(Func func) - { - } + private string someObjCall(object obj) => null; + } + """, + // Test0.cs(10,28): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(10, 28, 10, 39), + // Test0.cs(27,29): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(27, 29, 27, 40), + // Test0.cs(27,29): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(27, 29, 27, 40), + // Test0.cs(28,54): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(28, 54, 28, 65)); - private string someObjCall(object obj) => null; - } - """, - // Test0.cs(10,28): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(10, 28, 10, 39), - // Test0.cs(27,29): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(27, 29, 27, 40), - // Test0.cs(27,29): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(27, 29, 27, 40), - // Test0.cs(28,54): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(28, 54, 28, 65)); - - [Fact] - public Task TypeConversionAllocation_ReturnStatementSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyObject - { - public Object Obj1 - { - [PerformanceSensitive("uri")] - get { return 0; } - } + [Fact] + public Task TypeConversionAllocation_ReturnStatementSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + public class MyObject + { + public Object Obj1 + { [PerformanceSensitive("uri")] - public Object Obj2 - { - get { return 0; } - } + get { return 0; } + } + + [PerformanceSensitive("uri")] + public Object Obj2 + { + get { return 0; } } - """, - // Test0.cs(9,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(9,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 22), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 22), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(15,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + // Test0.cs(15,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(15, 22)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(15, 22)); - [Fact] - public Task TypeConversionAllocation_ReturnStatementSyntax_NoAllocAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_ReturnStatementSyntax_NoAllocAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyObject + public class MyObject + { + [PerformanceSensitive("uri")] + public Object ObjNoAllocation1 { get { return 0.ToString(); } } + + public Object ObjNoAllocation2 { [PerformanceSensitive("uri")] - public Object ObjNoAllocation1 { get { return 0.ToString(); } } - - public Object ObjNoAllocation2 - { - [PerformanceSensitive("uri")] - get { return 0.ToString(); } - } + get { return 0.ToString(); } } - """); + } + """); - [Fact] - public Task TypeConversionAllocation_YieldStatementSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using System.Collections.Generic; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_YieldStatementSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using System.Collections.Generic; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + public void SomeMethod() { - public void SomeMethod() + foreach (var item in GetItems()) { - foreach (var item in GetItems()) - { - } - - foreach (var item in GetItemsNoAllocation()) - { - } } - [PerformanceSensitive("uri")] - public IEnumerable GetItems() + foreach (var item in GetItemsNoAllocation()) { - yield return 0; // Allocation - yield break; } + } - [PerformanceSensitive("uri")] - public IEnumerable GetItemsNoAllocation() - { - yield return 0; // NO Allocation (IEnumerable) - yield break; - } + [PerformanceSensitive("uri")] + public IEnumerable GetItems() + { + yield return 0; // Allocation + yield break; + } + + [PerformanceSensitive("uri")] + public IEnumerable GetItemsNoAllocation() + { + yield return 0; // NO Allocation (IEnumerable) + yield break; } - """, - // Test0.cs(21,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(21,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(21, 22)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(21, 22)); - [Fact] - public Task TypeConversionAllocation_BinaryExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_BinaryExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - object x = "blah"; - object a1 = x ?? 0; // Allocation - object a2 = x ?? 0.ToString(); // No Allocation + object x = "blah"; + object a1 = x ?? 0; // Allocation + object a2 = x ?? 0.ToString(); // No Allocation - var b1 = 10 as object; // Allocation - var b2 = 10.ToString() as object; // No Allocation - } + var b1 = 10 as object; // Allocation + var b2 = 10.ToString() as object; // No Allocation } - """, - // Test0.cs(10,26): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(10,26): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 26), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 26), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(13,18): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + // Test0.cs(13,18): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(13, 18)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(13, 18)); - [Fact] - public Task TypeConversionAllocation_BinaryExpressionSyntax_WithDelegatesAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_BinaryExpressionSyntax_WithDelegatesAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Func temp = null; - var result1 = temp ?? someObjCall; // implicit, so Allocation - var result2 = temp ?? new Func(someObjCall); // Explicit, so NO Allocation - } + Func temp = null; + var result1 = temp ?? someObjCall; // implicit, so Allocation + var result2 = temp ?? new Func(someObjCall); // Explicit, so NO Allocation + } - private string someObjCall(object obj) - { - return obj.ToString(); - } + private string someObjCall(object obj) + { + return obj.ToString(); } + } - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Func temp = null; - var result1 = temp ?? someObjCall; // implicit allocation + boxing - var result2 = temp ?? new Func(someObjCall); // Explicit allocation + boxing - } + Func temp = null; + var result1 = temp ?? someObjCall; // implicit allocation + boxing + var result2 = temp ?? new Func(someObjCall); // Explicit allocation + boxing + } - private string someObjCall(object obj) - { - return obj.ToString(); - } + private string someObjCall(object obj) + { + return obj.ToString(); } - """, - // Test0.cs(10,31): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(10, 31, 10, 42), - // Test0.cs(26,31): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(26, 31, 26, 42), - // Test0.cs(26,31): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(26, 31, 26, 42), - // Test0.cs(27,56): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(27, 56, 27, 67)); + } + """, + // Test0.cs(10,31): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(10, 31, 10, 42), + // Test0.cs(26,31): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(26, 31, 26, 42), + // Test0.cs(26,31): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(26, 31, 26, 42), + // Test0.cs(27,56): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(27, 56, 27, 67)); - [Fact] - public Task TypeConversionAllocation_EqualsValueClauseSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_EqualsValueClauseSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() + for (object i = 0;;) // Allocation { - for (object i = 0;;) // Allocation - { - } + } - for (int i = 0;;) // NO Allocation - { - } + for (int i = 0;;) // NO Allocation + { } } - """, - // Test0.cs(9,25): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(9,25): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 25)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 25)); - [Fact] - public Task TypeConversionAllocation_EqualsValueClauseSyntax_WithDelegatesAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_EqualsValueClauseSyntax_WithDelegatesAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Func func2 = someObjCall; // implicit, so Allocation - Func func1 = new Func(someObjCall); // Explicit, so NO Allocation - } + Func func2 = someObjCall; // implicit, so Allocation + Func func1 = new Func(someObjCall); // Explicit, so NO Allocation + } - private string someObjCall(object obj) - { - return obj.ToString(); - } + private string someObjCall(object obj) + { + return obj.ToString(); } + } - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Func func2 = someObjCall; // implicit allocation + boxing - Func func1 = new Func(someObjCall); // Explicit allocation + boxing - } + Func func2 = someObjCall; // implicit allocation + boxing + Func func1 = new Func(someObjCall); // Explicit allocation + boxing + } - private string someObjCall(object obj) - { - return obj.ToString(); - } + private string someObjCall(object obj) + { + return obj.ToString(); } - """, - // Test0.cs(9,38): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(9, 38, 9, 49), - // Test0.cs(24,38): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(24, 38, 24, 49), - // Test0.cs(24,38): warning HAA0603: This will allocate a delegate instance - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(24, 38, 24, 49), - // Test0.cs(25,63): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(25, 63, 25, 74)); - - [Fact] - [WorkItem(2, "https://github.com/mjsabby/RoslynClrHeapAllocationAnalyzer/issues/2")] - public Task TypeConversionAllocation_EqualsValueClause_ExplicitMethodGroupAllocation_BugAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass + } + """, + // Test0.cs(9,38): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(9, 38, 9, 49), + // Test0.cs(24,38): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(24, 38, 24, 49), + // Test0.cs(24,38): warning HAA0603: This will allocate a delegate instance + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithSpan(24, 38, 24, 49), + // Test0.cs(25,63): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(25, 63, 25, 74)); + + [Fact] + [WorkItem(2, "https://github.com/mjsabby/RoslynClrHeapAllocationAnalyzer/issues/2")] + public Task TypeConversionAllocation_EqualsValueClause_ExplicitMethodGroupAllocation_BugAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Action methodGroup = this.Method; - } + Action methodGroup = this.Method; + } - private void Method() - { - } + private void Method() + { } + } - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - Action methodGroup = this.Method; - } + Action methodGroup = this.Method; + } - private void Method() - { - } + private void Method() + { } - """, - // Test0.cs(9,30): warning HAA0603: This will allocate a delegate instance + } + """, + // Test0.cs(9,30): warning HAA0603: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(9, 30), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(9, 30), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(22,30): warning HAA0603: This will allocate a delegate instance + // Test0.cs(22,30): warning HAA0603: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(22, 30), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(22, 30), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(22,30): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + // Test0.cs(22,30): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithLocation(22, 30)); - - [Fact] - public Task TypeConversionAllocation_ConditionalExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; - - public class MyClass - { - [PerformanceSensitive("uri")] - public void Testing() - { - object obj = "test"; - object test1 = true ? 0 : obj; // Allocation - object test2 = true ? 0.ToString() : obj; // NO Allocation - } - } - """, - // Test0.cs(10,31): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithLocation(22, 30)); + + [Fact] + public Task TypeConversionAllocation_ConditionalExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; + + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() + { + object obj = "test"; + object test1 = true ? 0 : obj; // Allocation + object test2 = true ? 0.ToString() : obj; // NO Allocation + } + } + """, + // Test0.cs(10,31): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 31)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 31)); - [Fact] - public Task TypeConversionAllocation_CastExpressionSyntaxAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_CastExpressionSyntaxAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var f1 = (object)5; // Allocation - var f2 = (object)"5"; // NO Allocation - } + var f1 = (object)5; // Allocation + var f2 = (object)"5"; // NO Allocation } - """, - // Test0.cs(9,26): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(9,26): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 26)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 26)); - [Fact] - public async Task TypeConversionAllocation_ArgumentWithImplicitStringCastOperatorAsync() - { - const string programWithoutImplicitCastOperator = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_ArgumentWithImplicitStringCastOperatorAsync() + { + const string programWithoutImplicitCastOperator = """ + using System; + using Roslyn.Utilities; - public struct AStruct + public struct AStruct + { + [PerformanceSensitive("uri")] + public static void Dump(AStruct astruct) { - [PerformanceSensitive("uri")] - public static void Dump(AStruct astruct) - { - System.Console.WriteLine(astruct); - } + System.Console.WriteLine(astruct); } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(programWithoutImplicitCastOperator, - // Test0.cs(10,34): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + await VerifyCS.VerifyAnalyzerAsync(programWithoutImplicitCastOperator, + // Test0.cs(10,34): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 34)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 34)); #pragma warning restore RS0030 // Do not use banned APIs - const string programWithImplicitCastOperator = """ - using System; - using Roslyn.Utilities; + const string programWithImplicitCastOperator = """ + using System; + using Roslyn.Utilities; - public struct AStruct - { - public readonly string WrappedString; + public struct AStruct + { + public readonly string WrappedString; - public AStruct(string s) - { - WrappedString = s ?? ""; - } + public AStruct(string s) + { + WrappedString = s ?? ""; + } - [PerformanceSensitive("uri")] - public static void Dump(AStruct astruct) - { - System.Console.WriteLine(astruct); - } + [PerformanceSensitive("uri")] + public static void Dump(AStruct astruct) + { + System.Console.WriteLine(astruct); + } - [PerformanceSensitive("uri")] - public static implicit operator string(AStruct astruct) - { - return astruct.WrappedString; - } + [PerformanceSensitive("uri")] + public static implicit operator string(AStruct astruct) + { + return astruct.WrappedString; } - """; - await VerifyCS.VerifyAnalyzerAsync(programWithImplicitCastOperator); - } + } + """; + await VerifyCS.VerifyAnalyzerAsync(programWithImplicitCastOperator); + } - [Fact] - public async Task TypeConversionAllocation_YieldReturnImplicitStringCastOperatorAsync() - { - const string programWithoutImplicitCastOperator = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_YieldReturnImplicitStringCastOperatorAsync() + { + const string programWithoutImplicitCastOperator = """ + using System; + using Roslyn.Utilities; - public struct AStruct + public struct AStruct + { + [PerformanceSensitive("uri")] + public System.Collections.Generic.IEnumerator GetEnumerator() { - [PerformanceSensitive("uri")] - public System.Collections.Generic.IEnumerator GetEnumerator() - { - yield return this; - } + yield return this; } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(programWithoutImplicitCastOperator, - // Test0.cs(10,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + await VerifyCS.VerifyAnalyzerAsync(programWithoutImplicitCastOperator, + // Test0.cs(10,22): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 22)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 22)); #pragma warning restore RS0030 // Do not use banned APIs - const string programWithImplicitCastOperator = """ - using System; - using Roslyn.Utilities; + const string programWithImplicitCastOperator = """ + using System; + using Roslyn.Utilities; - public struct AStruct + public struct AStruct + { + [PerformanceSensitive("uri")] + public System.Collections.Generic.IEnumerator GetEnumerator() { - [PerformanceSensitive("uri")] - public System.Collections.Generic.IEnumerator GetEnumerator() - { - yield return this; - } + yield return this; + } - public static implicit operator string(AStruct astruct) - { - return ""; - } + public static implicit operator string(AStruct astruct) + { + return ""; } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(programWithImplicitCastOperator); - } + await VerifyCS.VerifyAnalyzerAsync(programWithImplicitCastOperator); + } - [Fact] - public Task TypeConversionAllocation_InterpolatedStringWithInt_BoxingWarningAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + public Task TypeConversionAllocation_InterpolatedStringWithInt_BoxingWarningAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - class Program + class Program + { + [PerformanceSensitive("uri")] + void SomeMethod() { - [PerformanceSensitive("uri")] - void SomeMethod() - { - string s = $"{1}"; - } + string s = $"{1}"; } - """, - // Test0.cs(10,23): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(10,23): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 23)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(9, 23)); #if false - [Fact] - public void TypeConversionAllocation_InterpolatedStringWithString_NoWarning() - { - var sampleProgram = @"string s = $""{1.ToString()}"";"; + [Fact] + public void TypeConversionAllocation_InterpolatedStringWithString_NoWarning() + { + var sampleProgram = @"string s = $""{1.ToString()}"";"; - var analyser = new TypeConversionAllocationAnalyzer(); - var info = ProcessCode(analyser, sampleProgram, ImmutableArray.Create(SyntaxKind.Interpolation)); + var analyser = new TypeConversionAllocationAnalyzer(); + var info = ProcessCode(analyser, sampleProgram, ImmutableArray.Create(SyntaxKind.Interpolation)); - Assert.Empty(info.Allocations); - } + Assert.Empty(info.Allocations); + } #endif - [Theory] - [InlineData(@"private readonly System.Func fileExists = System.IO.File.Exists;")] - [InlineData(@"private System.Func fileExists { get; } = System.IO.File.Exists;")] - [InlineData(@"private static System.Func fileExists { get; } = System.IO.File.Exists;")] - [InlineData(@"private static readonly System.Func fileExists = System.IO.File.Exists;")] - public Task TypeConversionAllocation_DelegateAssignmentToReadonly_DoNotWarnAsync(string snippet) - => VerifyCS.VerifyAnalyzerAsync($$""" - using System; - using Roslyn.Utilities; - - class Program - { - [PerformanceSensitive("uri")] - {{snippet}} - } - """, - // Test0.cs(8,68): info HeapAnalyzerReadonlyMethodGroupAllocationRule: This will allocate a delegate instance + [Theory] + [InlineData(@"private readonly System.Func fileExists = System.IO.File.Exists;")] + [InlineData(@"private System.Func fileExists { get; } = System.IO.File.Exists;")] + [InlineData(@"private static System.Func fileExists { get; } = System.IO.File.Exists;")] + [InlineData(@"private static readonly System.Func fileExists = System.IO.File.Exists;")] + public Task TypeConversionAllocation_DelegateAssignmentToReadonly_DoNotWarnAsync(string snippet) + => VerifyCS.VerifyAnalyzerAsync($$""" + using System; + using Roslyn.Utilities; + + class Program + { + [PerformanceSensitive("uri")] + {{snippet}} + } + """, + // Test0.cs(8,68): info HeapAnalyzerReadonlyMethodGroupAllocationRule: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ReadonlyMethodGroupAllocationRule).WithLocation(7, 68)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ReadonlyMethodGroupAllocationRule).WithLocation(7, 68)); - [Fact] - public async Task TypeConversionAllocation_ExpressionBodiedPropertyBoxing_WithBoxingAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; - - class Program - { - [PerformanceSensitive("uri")] - object Obj => 1; - } - """; - - await VerifyCS.VerifyAnalyzerAsync(snippet, - // Test0.cs(8,19): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + [Fact] + public async Task TypeConversionAllocation_ExpressionBodiedPropertyBoxing_WithBoxingAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; + + class Program + { + [PerformanceSensitive("uri")] + object Obj => 1; + } + """; + + await VerifyCS.VerifyAnalyzerAsync(snippet, + // Test0.cs(8,19): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(7, 19)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(7, 19)); #pragma warning restore RS0030 // Do not use banned APIs - } - - [Fact] - public async Task TypeConversionAllocation_ExpressionBodiedPropertyBoxing_WithoutBoxingAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; - - class Program - { - [PerformanceSensitive("uri")] - object Obj => 1.ToString(); - } - """; + } - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + [Fact] + public async Task TypeConversionAllocation_ExpressionBodiedPropertyBoxing_WithoutBoxingAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; + + class Program + { + [PerformanceSensitive("uri")] + object Obj => 1.ToString(); + } + """; + + await VerifyCS.VerifyAnalyzerAsync(snippet); + } - [Fact] - public async Task TypeConversionAllocation_ExpressionBodiedPropertyDelegateAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_ExpressionBodiedPropertyDelegateAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - class Program - { - void Function(int i) { } + class Program + { + void Function(int i) { } - [PerformanceSensitive("uri")] - Action Obj => Function; - } - """; + [PerformanceSensitive("uri")] + Action Obj => Function; + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet, - // Test0.cs(10,24): warning HAA0603: This will allocate a delegate instance + await VerifyCS.VerifyAnalyzerAsync(snippet, + // Test0.cs(10,24): warning HAA0603: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(9, 24)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(9, 24)); #pragma warning restore RS0030 // Do not use banned APIs - } + } - [Fact] - public async Task TypeConversionAllocation_ExpressionBodiedPropertyExplicitDelegate_NoWarningAsync() - { - // Tests that an explicit delegate creation does not trigger HAA0603. It should be handled by HAA0502. - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_ExpressionBodiedPropertyExplicitDelegate_NoWarningAsync() + { + // Tests that an explicit delegate creation does not trigger HAA0603. It should be handled by HAA0502. + const string snippet = """ + using System; + using Roslyn.Utilities; - class Program - { - void Function(int i) { } + class Program + { + void Function(int i) { } - [PerformanceSensitive("uri")] - Action Obj => new Action(Function); - } - """; + [PerformanceSensitive("uri")] + Action Obj => new Action(Function); + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + await VerifyCS.VerifyAnalyzerAsync(snippet); + } - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Converting_any_enumeration_type_to_System_Enum_typeAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Converting_any_enumeration_type_to_System_Enum_typeAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using Roslyn.Utilities; - enum E { A } + enum E { A } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - System.Enum box = E.A; - } + System.Enum box = E.A; } - """, - // Test0.cs(11,27): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable + } + """, + // Test0.cs(11,27): warning HAA0601: Value type to reference type conversion causes boxing at call site (here), and unboxing at the callee-site. Consider using generics if applicable #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 27)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.ValueTypeToReferenceTypeConversionRule).WithLocation(10, 27)); - [Fact] - [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] - public Task Creating_delegate_from_value_type_instance_methodAsync() - => VerifyCS.VerifyAnalyzerAsync(""" - using System; - using Roslyn.Utilities; + [Fact] + [WorkItem(7995606, "http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp")] + public Task Creating_delegate_from_value_type_instance_methodAsync() + => VerifyCS.VerifyAnalyzerAsync(""" + using System; + using Roslyn.Utilities; - struct S { public void M() {} } + struct S { public void M() {} } - public class MyClass + public class MyClass + { + [PerformanceSensitive("uri")] + public void SomeMethod() { - [PerformanceSensitive("uri")] - public void SomeMethod() - { - Action box = new S().M; - } + Action box = new S().M; } - """, - // Test0.cs(12,22): warning HAA0603: This will allocate a delegate instance + } + """, + // Test0.cs(12,22): warning HAA0603: This will allocate a delegate instance #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(11, 22), + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.MethodGroupAllocationRule).WithLocation(11, 22), #pragma warning restore RS0030 // Do not use banned APIs - // Test0.cs(12,22): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + // Test0.cs(12,22): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction #pragma warning disable RS0030 // Do not use banned APIs - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithLocation(11, 22)); + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithLocation(11, 22)); - [Fact] - public async Task TypeConversionAllocation_NoDiagnosticWhenPassingDelegateAsArgumentAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_NoDiagnosticWhenPassingDelegateAsArgumentAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - struct Foo + struct Foo + { + [PerformanceSensitive("uri")] + void Do(Action process) { - [PerformanceSensitive("uri")] - void Do(Action process) - { - DoMore(process); - } + DoMore(process); + } - void DoMore(Action process) - { - process(); - } + void DoMore(Action process) + { + process(); } - """; - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + } + """; + await VerifyCS.VerifyAnalyzerAsync(snippet); + } - [Fact] - public async Task TypeConversionAllocation_ReportBoxingAllocationForPassingStructInstanceMethodForDelegateConstructorAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_ReportBoxingAllocationForPassingStructInstanceMethodForDelegateConstructorAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var @struct = new MyStruct(); - @struct.ProcessFunc(new Func(FooObjCall)); - } + var @struct = new MyStruct(); + @struct.ProcessFunc(new Func(FooObjCall)); + } - public void ProcessFunc(Func func) - { - } + public void ProcessFunc(Func func) + { + } - private string FooObjCall(object obj) - { - return obj.ToString(); - } + private string FooObjCall(object obj) + { + return obj.ToString(); } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet, - // Test0.cs(11,54): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction - VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(10, 54, 10, 64)); - } + await VerifyCS.VerifyAnalyzerAsync(snippet, + // Test0.cs(11,54): warning HAA0602: Struct instance method being used for delegate creation, this will result in a boxing instruction + VerifyCS.Diagnostic(TypeConversionAllocationAnalyzer.DelegateOnStructInstanceRule).WithSpan(10, 54, 10, 64)); + } - [Fact] - public async Task TypeConversionAllocation_DoNotReportBoxingAllocationForPassingStructStaticMethodForDelegateConstructorAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_DoNotReportBoxingAllocationForPassingStructStaticMethodForDelegateConstructorAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var @struct = new MyStruct(); - @struct.ProcessFunc(new Func(FooObjCall)); - } + var @struct = new MyStruct(); + @struct.ProcessFunc(new Func(FooObjCall)); + } - public void ProcessFunc(Func func) - { - } + public void ProcessFunc(Func func) + { + } - private static string FooObjCall(object obj) - { - return obj.ToString(); - } + private static string FooObjCall(object obj) + { + return obj.ToString(); } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + await VerifyCS.VerifyAnalyzerAsync(snippet); + } - [Fact] - public async Task TypeConversionAllocation_DoNotReportInlineDelegateAsStructInstanceMethodsAsync() - { - const string snippet = """ - using System; - using Roslyn.Utilities; + [Fact] + public async Task TypeConversionAllocation_DoNotReportInlineDelegateAsStructInstanceMethodsAsync() + { + const string snippet = """ + using System; + using Roslyn.Utilities; - public struct MyStruct + public struct MyStruct + { + [PerformanceSensitive("uri")] + public void Testing() { - [PerformanceSensitive("uri")] - public void Testing() - { - var ints = new[] { 5, 4, 3, 2, 1 }; - Array.Sort(ints, delegate(int x, int y) { return x - y; }); - Array.Sort(ints, (x, y) => x - y); - DoSomething(() => throw new Exception()); - DoSomething(delegate() { throw new Exception(); }); + var ints = new[] { 5, 4, 3, 2, 1 }; + Array.Sort(ints, delegate(int x, int y) { return x - y; }); + Array.Sort(ints, (x, y) => x - y); + DoSomething(() => throw new Exception()); + DoSomething(delegate() { throw new Exception(); }); - DoSomething2(x => throw new Exception()); - } + DoSomething2(x => throw new Exception()); + } - private static void DoSomething(Action action) - { - } + private static void DoSomething(Action action) + { + } - private static void DoSomething2(Action action) - { - } + private static void DoSomething2(Action action) + { } - """; + } + """; - await VerifyCS.VerifyAnalyzerAsync(snippet); - } + await VerifyCS.VerifyAnalyzerAsync(snippet); } } diff --git a/src/roslyn/src/Scripting/Core/ScriptBuilder.cs b/src/roslyn/src/Scripting/Core/ScriptBuilder.cs index f345991323d..68e2708651b 100644 --- a/src/roslyn/src/Scripting/Core/ScriptBuilder.cs +++ b/src/roslyn/src/Scripting/Core/ScriptBuilder.cs @@ -152,10 +152,7 @@ private Func> Build( peStream.Position = 0; - if (pdbStreamOpt != null) - { - pdbStreamOpt.Position = 0; - } + pdbStreamOpt?.Position = 0; var assembly = _assemblyLoader.LoadAssemblyFromStream(peStream, pdbStreamOpt); var runtimeEntryPoint = GetEntryPointRuntimeMethod(entryPoint, assembly); diff --git a/src/roslyn/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs b/src/roslyn/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs index b88af7fc759..3783866bf71 100644 --- a/src/roslyn/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs +++ b/src/roslyn/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs @@ -34,10 +34,7 @@ public static void ReportTelemetry() static m => { var histogramLogAggregator = s_histogramLogAggregator.GetValue(ActionInfo.GetInheritanceMarginMembers); - if (histogramLogAggregator != null) - { - histogramLogAggregator.WriteTelemetryPropertiesTo(m, nameof(ActionInfo.GetInheritanceMarginMembers) + "."); - } + histogramLogAggregator?.WriteTelemetryPropertiesTo(m, nameof(ActionInfo.GetInheritanceMarginMembers) + "."); })); } } diff --git a/src/roslyn/src/VisualStudio/Core/Def/Utilities/TaskItemsEnum.cs b/src/roslyn/src/VisualStudio/Core/Def/Utilities/TaskItemsEnum.cs index d64bf30a8c9..b160cefe8ec 100644 --- a/src/roslyn/src/VisualStudio/Core/Def/Utilities/TaskItemsEnum.cs +++ b/src/roslyn/src/VisualStudio/Core/Def/Utilities/TaskItemsEnum.cs @@ -29,10 +29,7 @@ int IVsEnumTaskItems.Next(uint celt, IVsTaskItem[] rgelt, uint[] pceltFetched) _next += i; - if (pceltFetched != null) - { - pceltFetched[0] = (uint)i; - } + pceltFetched?[0] = (uint)i; return (i == celt) ? VSConstants.S_OK : VSConstants.S_FALSE; } diff --git a/src/roslyn/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs b/src/roslyn/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs index f1fed730186..278eb376d90 100644 --- a/src/roslyn/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs +++ b/src/roslyn/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzersCommandHandler.cs @@ -185,10 +185,7 @@ private bool ShouldShowAnalyzerContextMenu(IEnumerable items) private void UpdateAnalyzerContextMenu() { - if (_removeMenuItem != null) - { - _removeMenuItem.Enabled = _allowProjectSystemOperations; - } + _removeMenuItem?.Enabled = _allowProjectSystemOperations; } public IContextMenuController DiagnosticContextMenuController @@ -557,10 +554,7 @@ private static void UpdateProjectConfigurationsToUseRuleSetFile(EnvDTE.Project e { var codeAnalysisRuleSetFileProperty = properties?.Item("CodeAnalysisRuleSet"); - if (codeAnalysisRuleSetFileProperty != null) - { - codeAnalysisRuleSetFileProperty.Value = fileName; - } + codeAnalysisRuleSetFileProperty?.Value = fileName; } catch (ArgumentException) { diff --git a/src/roslyn/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingUsingsOnPaste.cs b/src/roslyn/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingUsingsOnPaste.cs index 1b8c8002231..adbe0cef8d5 100644 --- a/src/roslyn/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingUsingsOnPaste.cs +++ b/src/roslyn/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingUsingsOnPaste.cs @@ -14,13 +14,8 @@ namespace Roslyn.VisualStudio.NewIntegrationTests.CSharp; [Trait(Traits.Feature, Traits.Features.AddMissingImports)] -public class CSharpAddMissingUsingsOnPaste : AbstractEditorTest +public sealed class CSharpAddMissingUsingsOnPaste() : AbstractEditorTest(nameof(CSharpAddMissingUsingsOnPaste)) { - public CSharpAddMissingUsingsOnPaste() - : base(nameof(CSharpAddMissingUsingsOnPaste)) - { - } - protected override string LanguageName => LanguageNames.CSharp; [IdeFact] diff --git a/src/roslyn/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs b/src/roslyn/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs index 88e4c1c58c3..cfb3f834399 100644 --- a/src/roslyn/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs +++ b/src/roslyn/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs @@ -608,7 +608,17 @@ protected static SymbolUsageInfo GetSymbolUsageInfo( while (syntaxFacts.IsQualifiedName(topNameNode.Parent)) topNameNode = topNameNode.Parent; - var isInNamespaceNameContext = syntaxFacts.IsBaseNamespaceDeclaration(topNameNode.Parent); + var parent = topNameNode?.Parent; + + // typeof/sizeof are a special case where we don't want to return a TypeOrNamespaceUsageInfo, but rather a ValueUsageInfo.Name. + // This brings it in line with nameof(...), making all those operators appear in a similar fashion. + if (parent?.RawKind == syntaxFacts.SyntaxKinds.TypeOfExpression || + parent?.RawKind == syntaxFacts.SyntaxKinds.SizeOfExpression) + { + return new(ValueUsageInfo.Name, typeOrNamespaceUsageInfoOpt: null); + } + + var isInNamespaceNameContext = syntaxFacts.IsBaseNamespaceDeclaration(parent); return syntaxFacts.IsInNamespaceOrTypeContext(topNameNode) ? SymbolUsageInfo.Create(GetTypeOrNamespaceUsageInfo()) : GetSymbolUsageInfoCommon(); @@ -677,18 +687,12 @@ SymbolUsageInfo GetSymbolUsageInfoCommon() if (operation is IObjectCreationOperation) return SymbolUsageInfo.Create(TypeOrNamespaceUsageInfo.ObjectCreation); - switch (operation?.Parent) - { - case INameOfOperation: - case ITypeOfOperation: - case ISizeOfOperation: - return SymbolUsageInfo.Create(ValueUsageInfo.Name); - } + // Note: sizeof/typeof also return 'name', but are handled above in GetSymbolUsageInfo. + if (operation?.Parent is INameOfOperation) + return SymbolUsageInfo.Create(ValueUsageInfo.Name); if (node.IsPartOfStructuredTrivia()) - { return SymbolUsageInfo.Create(ValueUsageInfo.Name); - } var symbolInfo = semanticModel.GetSymbolInfo(node, cancellationToken); if (symbolInfo.Symbol != null) diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs index 5afb9f1eadc..e74bd19a931 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs @@ -118,11 +118,13 @@ public int Convert(TSyntaxKind kind) where TSyntaxKind : struct public int ReferenceNotEqualsExpression => (int)SyntaxKind.NotEqualsExpression; public int SimpleAssignmentExpression => (int)SyntaxKind.SimpleAssignmentExpression; public int SimpleMemberAccessExpression => (int)SyntaxKind.SimpleMemberAccessExpression; + public int? SizeOfExpression => (int)SyntaxKind.SizeOfExpression; public int? SuppressNullableWarningExpression => (int)SyntaxKind.SuppressNullableWarningExpression; public int TernaryConditionalExpression => (int)SyntaxKind.ConditionalExpression; public int ThisExpression => (int)SyntaxKind.ThisExpression; public int? ThrowExpression => (int)SyntaxKind.ThrowExpression; public int TupleExpression => (int)SyntaxKind.TupleExpression; + public int TypeOfExpression => (int)SyntaxKind.TypeOfExpression; public int? AndPattern => (int)SyntaxKind.AndPattern; public int? ConstantPattern => (int)SyntaxKind.ConstantPattern; diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs index 7f6b771c13f..4e99b8b60e9 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs @@ -919,7 +919,7 @@ bool IsConditionalCastSafeToRemoveDueToConversionToOtherBranch() return false; // Check if 'y' has the same type as 'z'. - if (!otherSideType.Equals(thisSideRewrittenType)) + if (!otherSideType.Equals(thisSideRewrittenType, SymbolEqualityComparer.IncludeNullability)) return false; // Now check that with the (T) cast removed, that the outer `x ? y : z` is still diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs index 5f38dac59b3..e37d16980e7 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs @@ -122,18 +122,14 @@ SyntaxKind.ForStatement or if (variableDeclaration.Variables is not [{ Initializer.Value: var initializer } variable]) return false; - // Do not suggest var replacement for stackalloc span expressions. - // This will change the bound type from a span to a pointer. - if (!variableDeclaration.Type.IsKind(SyntaxKind.PointerType)) + // Do not suggest var replacement for stackalloc span expressions. This will change the bound type from a + // span to a pointer. Note: this only applies to `var v = stackalloc ...;` If `stackalloc` is anywhere + // lower (including `var v = (stackalloc ...);`), then this is will be a span, and it will be ok to change + // to use 'var'. + if (!variableDeclaration.Type.IsKind(SyntaxKind.PointerType) && + initializer is StackAllocArrayCreationExpressionSyntax) { - var containsStackAlloc = initializer - .DescendantNodesAndSelf(descendIntoChildren: node => node is not AnonymousFunctionExpressionSyntax) - .Any(node => node.IsKind(SyntaxKind.StackAllocArrayCreationExpression)); - - if (containsStackAlloc) - { - return false; - } + return false; } if (AssignmentSupportsStylePreference( diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/SymbolUsageInfo.cs b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/SymbolUsageInfo.cs index d558d96e273..8f485357cbb 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/SymbolUsageInfo.cs +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/SymbolUsageInfo.cs @@ -2,10 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Diagnostics; using System.Runtime.Serialization; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis; @@ -15,7 +13,7 @@ namespace Microsoft.CodeAnalysis; /// For methods, fields, properties, events, locals and parameters, this corresponds to values from . /// [DataContract] -internal readonly struct SymbolUsageInfo : IEquatable +internal readonly record struct SymbolUsageInfo { public static readonly SymbolUsageInfo None = Create(ValueUsageInfo.None); @@ -45,28 +43,4 @@ public bool IsReadFrom() public bool IsWrittenTo() => ValueUsageInfoOpt.HasValue && ValueUsageInfoOpt.Value.IsWrittenTo(); - - public bool IsNameOnly() - => ValueUsageInfoOpt.HasValue && ValueUsageInfoOpt.Value.IsNameOnly(); - - public override bool Equals(object? obj) - => obj is SymbolUsageInfo && Equals((SymbolUsageInfo)obj); - - public bool Equals(SymbolUsageInfo other) - { - if (ValueUsageInfoOpt.HasValue) - { - return other.ValueUsageInfoOpt.HasValue && - ValueUsageInfoOpt.Value == other.ValueUsageInfoOpt.Value; - } - else - { - RoslynDebug.Assert(TypeOrNamespaceUsageInfoOpt.HasValue); - return other.TypeOrNamespaceUsageInfoOpt.HasValue && - TypeOrNamespaceUsageInfoOpt.Value == other.TypeOrNamespaceUsageInfoOpt.Value; - } - } - - public override int GetHashCode() - => Hash.Combine(((int?)ValueUsageInfoOpt)?.GetHashCode() ?? 0, ((int?)TypeOrNamespaceUsageInfoOpt)?.GetHashCode() ?? 0); } diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs index 71cdf02df85..41981d1cb8d 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs @@ -161,11 +161,13 @@ internal interface ISyntaxKinds int ReferenceNotEqualsExpression { get; } int SimpleAssignmentExpression { get; } int SimpleMemberAccessExpression { get; } + int? SizeOfExpression { get; } int? SuppressNullableWarningExpression { get; } int TernaryConditionalExpression { get; } int ThisExpression { get; } int? ThrowExpression { get; } int TupleExpression { get; } + int TypeOfExpression { get; } #endregion diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ParenthesizedExpressionSyntaxExtensions.vb b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ParenthesizedExpressionSyntaxExtensions.vb index da471f2bace..aa7af3efb79 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ParenthesizedExpressionSyntaxExtensions.vb +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/ParenthesizedExpressionSyntaxExtensions.vb @@ -346,6 +346,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions ' Cases: ' (1 + 1) * 8 ' (1 + 1).ToString + ' (1 + 1)?.ToString ' (1 + 1)() If TypeOf expression Is BinaryExpressionSyntax OrElse TypeOf expression Is UnaryExpressionSyntax Then @@ -353,6 +354,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Dim parentExpression = TryCast(node.Parent, ExpressionSyntax) If parentExpression IsNot Nothing Then If parentExpression.IsKind(SyntaxKind.SimpleMemberAccessExpression) OrElse + parentExpression.IsKind(SyntaxKind.ConditionalAccessExpression) OrElse parentExpression.IsKind(SyntaxKind.InvocationExpression) Then Return False End If diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb index 0641f531b5c..104f2d01b47 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb @@ -120,11 +120,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService Public ReadOnly Property ReferenceNotEqualsExpression As Integer = SyntaxKind.IsNotExpression Implements ISyntaxKinds.ReferenceNotEqualsExpression Public ReadOnly Property SimpleAssignmentExpression As Integer = SyntaxKind.SimpleAssignmentStatement Implements ISyntaxKinds.SimpleAssignmentExpression Public ReadOnly Property SimpleMemberAccessExpression As Integer = SyntaxKind.SimpleMemberAccessExpression Implements ISyntaxKinds.SimpleMemberAccessExpression + Public ReadOnly Property SizeOfExpression As Integer? Implements ISyntaxKinds.SizeOfExpression Public ReadOnly Property SuppressNullableWarningExpression As Integer? Implements ISyntaxKinds.SuppressNullableWarningExpression Public ReadOnly Property TernaryConditionalExpression As Integer = SyntaxKind.TernaryConditionalExpression Implements ISyntaxKinds.TernaryConditionalExpression Public ReadOnly Property ThisExpression As Integer = SyntaxKind.MeExpression Implements ISyntaxKinds.ThisExpression Public ReadOnly Property ThrowExpression As Integer? Implements ISyntaxKinds.ThrowExpression Public ReadOnly Property TupleExpression As Integer = SyntaxKind.TupleExpression Implements ISyntaxKinds.TupleExpression + Public ReadOnly Property TypeOfExpression As Integer = SyntaxKind.GetTypeExpression Implements ISyntaxKinds.TypeOfExpression Public ReadOnly Property AndPattern As Integer? Implements ISyntaxKinds.AndPattern Public ReadOnly Property ConstantPattern As Integer? Implements ISyntaxKinds.ConstantPattern diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/CSharpCodeGenerationHelpers.cs b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/CSharpCodeGenerationHelpers.cs index 75d972a22f0..12421618da5 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/CSharpCodeGenerationHelpers.cs +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/CSharpCodeGenerationHelpers.cs @@ -172,14 +172,15 @@ public static SyntaxList Insert( CSharpCodeGenerationContextInfo info, IList? availableIndices, Func, TDeclaration?>? after = null, - Func, TDeclaration?>? before = null) + Func, TDeclaration?>? before = null, + Func, int, bool>? canPlaceAtIndex = null) where TDeclaration : SyntaxNode { var index = GetInsertionIndex( declarationList, declaration, info, availableIndices, CSharpDeclarationComparer.WithoutNamesInstance, CSharpDeclarationComparer.WithNamesInstance, - after, before); + after, before, canPlaceAtIndex); availableIndices?.Insert(index, true); diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/NamedTypeGenerator.cs b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/NamedTypeGenerator.cs index 31c4d36df88..a97d4b64fd1 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/NamedTypeGenerator.cs +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeGeneration/NamedTypeGenerator.cs @@ -59,7 +59,11 @@ public static CompilationUnitSyntax AddNamedTypeTo( CancellationToken cancellationToken) { var declaration = GenerateNamedTypeDeclaration(service, namedType, CodeGenerationDestination.CompilationUnit, info, cancellationToken); - var members = Insert(destination.Members, declaration, info, availableIndices); + var members = Insert( + destination.Members, declaration, info, availableIndices, + // We're adding a named type to a compilation unit. If there are any global statements, we must place it after them. + after: static members => members.LastOrDefault(m => m is GlobalStatementSyntax), + canPlaceAtIndex: static (members, index) => index >= members.Count || members[index] is not GlobalStatementSyntax); return destination.WithMembers(members); } diff --git a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationHelpers.cs b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationHelpers.cs index 476a0c10011..1e653b7a55c 100644 --- a/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationHelpers.cs +++ b/src/roslyn/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationHelpers.cs @@ -193,11 +193,14 @@ public static int GetInsertionIndex( IComparer comparerWithoutNameCheck, IComparer comparerWithNameCheck, Func, TDeclaration?>? after = null, - Func, TDeclaration?>? before = null) + Func, TDeclaration?>? before = null, + Func, int, bool>? canPlaceAtIndex = null) where TDeclaration : SyntaxNode { Contract.ThrowIfTrue(availableIndices != null && availableIndices.Count != declarationList.Count + 1); + canPlaceAtIndex ??= static (_, _) => true; + // Try to strictly obey the after option by inserting immediately after the member containing the location if (info.Context.AfterThisLocation?.SourceTree is { } afterSourceTree && afterSourceTree.FilePath == declarationList.FirstOrDefault()?.SyntaxTree.FilePath) @@ -207,10 +210,8 @@ public static int GetInsertionIndex( { var index = declarationList.IndexOf(afterMember); index = GetPreferredIndex(index + 1, availableIndices, forward: true); - if (index != -1) - { + if (index != -1 && canPlaceAtIndex(declarationList, index)) return index; - } } } diff --git a/src/runtime/docs/area-owners.md b/src/runtime/docs/area-owners.md index 36e950d8bc8..f7853863c5a 100644 --- a/src/runtime/docs/area-owners.md +++ b/src/runtime/docs/area-owners.md @@ -17,7 +17,7 @@ Note: Editing this file doesn't update the mapping used by `@dotnet-policy-servi | area-Build-mono | @lewing | @akoeplinger | | | area-Codeflow | @dotnet/dnr-codeflow | @dotnet/dnr-codeflow | Used for automated PRs that ingest code from other repos | | area-Codegen-AOT-mono | @steveisok | @kotlarmilos | | -| area-CodeGen-coreclr | @JulieLeeMSFT | @BruceForstall @dotnet/jit-contrib | | +| area-CodeGen-coreclr | @JulieLeeMSFT | @dotnet/jit-contrib | | | area-Codegen-Interpreter-coreclr | @vitek-karas | @BrzVlad @janvorli | | | area-Codegen-Interpreter-mono | @vitek-karas | @BrzVlad @kotlarmilos | | | area-Codegen-Intrinsics-mono | @steveisok | | | @@ -25,11 +25,11 @@ Note: Editing this file doesn't update the mapping used by `@dotnet-policy-servi | area-Codegen-LLVM-mono | @steveisok | | | | area-Codegen-meta-mono | @steveisok | | | | area-crossgen2-coreclr | @mangod9 | @dotnet/crossgen-contrib | | -| area-Debugger-mono | @steveisok | @thaystg @dotnet/dotnet-diag | | +| area-Debugger-mono | @steveisok | @thaystg @dotnet/dotnet-diag | | | area-DependencyModel | @ericstj | @dotnet/area-dependencymodel | Included:
  • Microsoft.Extensions.DependencyModel
| -| area-Diagnostics-coreclr | @steveisok | @tommcdon @dotnet/dotnet-diag | | -| area-Diagnostics-mono | @steveisok | @tommcdon @mdh1418 @thaystg | | -| area-EnC-mono | @steveisok | @dotnet/dotnet-diag @thaystg | Hot Reload on WebAssembly, Android, iOS, etc . @lambdageek to consult | +| area-Diagnostics-coreclr | @steveisok | @tommcdon @dotnet/dotnet-diag | | +| area-Diagnostics-mono | @steveisok | @tommcdon @mdh1418 @thaystg | | +| area-EnC-mono | @steveisok | @dotnet/dotnet-diag @thaystg | Hot Reload on WebAssembly, Android, iOS, etc. | | area-ExceptionHandling-coreclr | @mangod9 | @janvorli | | | area-Extensions-Caching | @jeffhandley | @dotnet/area-extensions-caching | Consultants: @mgravell, @sebastienros | | area-Extensions-Configuration | @ericstj | @dotnet/area-extensions-configuration | Consultants: @eerhardt | @@ -44,7 +44,7 @@ Note: Editing this file doesn't update the mapping used by `@dotnet-policy-servi | area-GC-mono | @mangod9 | @mangod9 | @BrzVlad to consult | | area-Host | @agocke | @jeffschwMSFT @elinor-fung | Issues with dotnet.exe including bootstrapping, framework detection, hostfxr.dll and hostpolicy.dll | | area-HostModel | @agocke | @elinor-fung | | -| area-ILTools-coreclr | @JulieLeeMSFT | @BruceForstall @dotnet/jit-contrib | | +| area-ILTools-coreclr | @JulieLeeMSFT | @dotnet/jit-contrib | | | area-Infrastructure | @agocke | @jeffschwMSFT @MichaelSimons | | | area-Infrastructure-coreclr | @agocke | @jeffschwMSFT | | | area-Infrastructure-installer | @MichaelSimons | @NikolaMilosavljevic | | @@ -141,7 +141,7 @@ Note: Editing this file doesn't update the mapping used by `@dotnet-policy-servi | area-System.Xml | @jeffhandley | @dotnet/area-system-xml | | | area-TieredCompilation-coreclr | @mangod9 | @kouvel | | | area-Tools-ILLink | @agocke | @dotnet/illink | | -| area-Tools-ILVerification | @JulieLeeMSFT | @BruceForstall @dotnet/jit-contrib | | +| area-Tools-ILVerification | @JulieLeeMSFT | @dotnet/jit-contrib | | | area-Tracing-coreclr | @steveisok | @dotnet/area-tracing-coreclr | .NET runtime issues for EventPipe and ICorProfiler | | area-Tracing-mono | @steveisok | @dotnet/dotnet-diag @thaystg | | | area-TypeSystem-coreclr | @mangod9 | @davidwrighton @MichalStrehovsky @janvorli @mangod9 | | diff --git a/src/runtime/docs/design/datacontracts/CodeVersions.md b/src/runtime/docs/design/datacontracts/CodeVersions.md index c903bd84007..241b17bbc60 100644 --- a/src/runtime/docs/design/datacontracts/CodeVersions.md +++ b/src/runtime/docs/design/datacontracts/CodeVersions.md @@ -132,7 +132,7 @@ IEnumerable ICodeVersions.GetILCodeVersions(TargetPointer m // CodeVersionManager::GetILCodeVersions GetModuleAndMethodDesc(methodDesc, out TargetPointer module, out uint methodDefToken); - ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandle(module); + ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(module); TargetPointer ilCodeVersionTable = _target.Contracts.Loader.GetLookupTables(moduleHandle).MethodDefToILCodeVersioningState; TargetPointer ilVersionStateAddress = _target.Contracts.Loader.GetModuleLookupMapElement(ilCodeVersionTable, methodDefToken, out var _); @@ -247,7 +247,7 @@ bool ICodeVersions.CodeVersionManagerSupportsMethod(TargetPointer methodDescAddr TypeHandle mt = rts.GetTypeHandle(mtAddr); TargetPointer modAddr = rts.GetModule(mt); ILoader loader = _target.Contracts.Loader; - ModuleHandle mod = loader.GetModuleHandle(modAddr); + ModuleHandle mod = loader.GetModuleHandleFromModulePtr(modAddr); ModuleFlags modFlags = loader.GetFlags(mod); if (modFlags.HasFlag(ModuleFlags.EditAndContinue)) return false; diff --git a/src/runtime/docs/design/datacontracts/Loader.md b/src/runtime/docs/design/datacontracts/Loader.md index 916b4ff03bf..9964998eb51 100644 --- a/src/runtime/docs/design/datacontracts/Loader.md +++ b/src/runtime/docs/design/datacontracts/Loader.md @@ -52,9 +52,11 @@ record struct ModuleLookupTables( ``` ``` csharp -ModuleHandle GetModuleHandle(TargetPointer module); -IEnumerable GetModules(TargetPointer appDomain, AssemblyIterationFlags iterationFlags); +ModuleHandle GetModuleHandleFromModulePtr(TargetPointer module); +ModuleHandle GetModuleHandleFromAssemblyPtr(TargetPointer assemblyPointer); +IEnumerable GetModuleHandles(TargetPointer appDomain, AssemblyIterationFlags iterationFlags); TargetPointer GetRootAssembly(); +TargetPointer GetModule(ModuleHandle handle); TargetPointer GetAssembly(ModuleHandle handle); TargetPointer GetPEAssembly(ModuleHandle handle); bool TryGetLoadedImageContents(ModuleHandle handle, out TargetPointer baseAddress, out uint size, out uint imageFlags); @@ -146,12 +148,18 @@ private enum ModuleFlags_1 : uint ### Method Implementations ``` csharp -ModuleHandle GetModuleHandle(TargetPointer modulePointer) +ModuleHandle GetModuleHandleFromModulePtr(TargetPointer modulePointer) { return new ModuleHandle(modulePointer); } -IEnumerable GetModules(TargetPointer appDomain, AssemblyIterationFlags iterationFlags) +ModuleHandle ILoader.GetModuleHandleFromAssemblyPtr(TargetPointer assemblyPointer) +{ + Data.Assembly assembly = // read Assembly object at assemblyPointer + return new ModuleHandle(assembly.Module); +} + +IEnumerable GetModuleHandles(TargetPointer appDomain, AssemblyIterationFlags iterationFlags) { if (appDomain == TargetPointer.Null) throw new ArgumentException("appDomain must not be null"); @@ -255,6 +263,11 @@ TargetPointer GetRootAssembly() return appDomain.RootAssembly; } +TargetPointer ILoader.GetModule(ModuleHandle handle) +{ + return handle.Address; +} + TargetPointer GetAssembly(ModuleHandle handle) { return target.ReadPointer(handle.Address + /* Module::Assembly offset */); diff --git a/src/runtime/docs/design/datacontracts/RuntimeTypeSystem.md b/src/runtime/docs/design/datacontracts/RuntimeTypeSystem.md index b1d65b7c825..e8b784c35e8 100644 --- a/src/runtime/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/src/runtime/docs/design/datacontracts/RuntimeTypeSystem.md @@ -1004,7 +1004,7 @@ Determining if a method is in a collectible module: { MethodDesc md = _methodDescs[methodDesc.Address]; TargetPointer loaderModuleAddr = GetLoaderModule(md); - ModuleHandle mod = _target.Contracts.Loader.GetModuleHandle(loaderModuleAddr); + ModuleHandle mod = _target.Contracts.Loader.GetModuleHandleFromModulePtr(loaderModuleAddr); return _target.Contracts.Loader.IsCollectible(mod); } diff --git a/src/runtime/eng/pipelines/performance/perf-build.yml b/src/runtime/eng/pipelines/performance/perf-build.yml index ef418994581..10cc3606d94 100644 --- a/src/runtime/eng/pipelines/performance/perf-build.yml +++ b/src/runtime/eng/pipelines/performance/perf-build.yml @@ -14,10 +14,6 @@ parameters: displayName: Build Coreclr Arm64 Windows type: boolean default: true -- name: coreclr_muslx64_linux - displayName: Build Coreclr Musl x64 Linux - type: boolean - default: true - name: coreclr_x64_linux displayName: Build Coreclr x64 Linux type: boolean @@ -110,8 +106,6 @@ extends: - coreclr_arm64_linux - ${{ if eq(parameters.coreclr_arm64_windows, true) }}: - coreclr_arm64_windows - - ${{ if eq(parameters.coreclr_muslx64_linux, true) }}: - - coreclr_muslx64_linux - ${{ if eq(parameters.coreclr_x64_linux, true) }}: - coreclr_x64_linux - ${{ if eq(parameters.coreclr_x64_windows, true) }}: @@ -152,8 +146,6 @@ extends: - coreclr_arm64_linux - ${{ if eq(parameters.coreclr_arm64_windows, true) }}: - coreclr_arm64_windows - - ${{ if eq(parameters.coreclr_muslx64_linux, true) }}: - - coreclr_muslx64_linux - ${{ if eq(parameters.coreclr_x64_linux, true) }}: - coreclr_x64_linux - ${{ if eq(parameters.coreclr_x64_windows, true) }}: @@ -182,7 +174,7 @@ extends: - nativeAot_arm64_ios ${{ if parameters.mauiFramework }}: mauiFramework: ${{ parameters.mauiFramework }} - + - ${{ if and(ne(variables['System.TeamProject'], 'public'), or(eq(variables['Build.Reason'], 'IndividualCI'), parameters.runPrivateJobs)) }}: - stage: UploadArtifacts displayName: 'Upload Artifacts' @@ -200,8 +192,6 @@ extends: - coreclr_arm64_linux - ${{ if eq(parameters.coreclr_arm64_windows, true) }}: - coreclr_arm64_windows - - ${{ if eq(parameters.coreclr_muslx64_linux, true) }}: - - coreclr_muslx64_linux - ${{ if eq(parameters.coreclr_x64_linux, true) }}: - coreclr_x64_linux - ${{ if eq(parameters.coreclr_x64_windows, true) }}: diff --git a/src/runtime/eng/pipelines/performance/templates/perf-build-jobs.yml b/src/runtime/eng/pipelines/performance/templates/perf-build-jobs.yml index 4defede2528..a7ecb34a3f0 100644 --- a/src/runtime/eng/pipelines/performance/templates/perf-build-jobs.yml +++ b/src/runtime/eng/pipelines/performance/templates/perf-build-jobs.yml @@ -8,7 +8,6 @@ jobs: linux_x64: true windows_x64: true windows_x86: true - linux_musl_x64: true android_arm64: true # build mono for AOT diff --git a/src/runtime/eng/pipelines/performance/templates/perf-coreclr-build-jobs.yml b/src/runtime/eng/pipelines/performance/templates/perf-coreclr-build-jobs.yml index ddf103aaf4c..85704ada6a2 100644 --- a/src/runtime/eng/pipelines/performance/templates/perf-coreclr-build-jobs.yml +++ b/src/runtime/eng/pipelines/performance/templates/perf-coreclr-build-jobs.yml @@ -1,6 +1,5 @@ parameters: linux_x64: false - linux_musl_x64: false linux_arm64: false windows_x64: false windows_x86: false @@ -8,7 +7,7 @@ parameters: android_arm64: false jobs: - - ${{ if or(eq(parameters.linux_x64, true), eq(parameters.windows_x64, true), eq(parameters.windows_x86, true), eq(parameters.linux_musl_x64, true), eq(parameters.linux_arm64, true), eq(parameters.windows_arm64, true)) }}: + - ${{ if or(eq(parameters.linux_x64, true), eq(parameters.windows_x64, true), eq(parameters.windows_x86, true), eq(parameters.linux_arm64, true), eq(parameters.windows_arm64, true)) }}: # build coreclr and libraries - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -21,8 +20,6 @@ jobs: - windows_x64 - ${{ if eq(parameters.windows_x86, true) }}: - windows_x86 - - ${{ if eq(parameters.linux_musl_x64, true) }}: - - linux_musl_x64 - ${{ if eq(parameters.linux_arm64, true) }}: - linux_arm64 - ${{ if eq(parameters.windows_arm64, true) }}: diff --git a/src/runtime/eng/slngen.targets b/src/runtime/eng/slngen.targets index d7622098f1e..382ca8d684a 100644 --- a/src/runtime/eng/slngen.targets +++ b/src/runtime/eng/slngen.targets @@ -4,7 +4,7 @@ $(SlnGenSolutionFolder)gen$(SlnGenSolutionInnerFolder) $(SlnGenSolutionFolder)ref$(SlnGenSolutionInnerFolder) $(SlnGenSolutionFolder)tests$(SlnGenSolutionInnerFolder) - $(SlnGenSolutionFolder)src$(SlnGenSolutionInnerFolder) + $(SlnGenSolutionFolder)src$(SlnGenSolutionInnerFolder) diff --git a/src/runtime/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs b/src/runtime/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs index b9b6dbb8794..9f379245a30 100644 --- a/src/runtime/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs +++ b/src/runtime/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs @@ -61,6 +61,15 @@ internal enum CorInfoContinuationFlags // OSR method saved in the beginning of 'Data', or -1 if the continuation // belongs to a tier 0 method. CORINFO_CONTINUATION_OSR_IL_OFFSET_IN_DATA = 4, + // If this bit is set the continuation should continue on the thread + // pool. + CORINFO_CONTINUATION_CONTINUE_ON_THREAD_POOL = 8, + // If this bit is set the continuation has a SynchronizationContext + // that we should continue on. + CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_SYNCHRONIZATION_CONTEXT = 16, + // If this bit is set the continuation has a TaskScheduler + // that we should continue on. + CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_TASK_SCHEDULER = 32, } internal sealed unsafe class Continuation @@ -93,6 +102,29 @@ internal sealed unsafe class Continuation // public byte[]? Data; public object?[]? GCData; + + public object GetContinuationContext() + { + int index = 0; + if ((Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_RESULT_IN_GCDATA) != 0) + index++; + if ((Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_NEEDS_EXCEPTION) != 0) + index++; + Debug.Assert(GCData != null && GCData.Length > index); + object? continuationContext = GCData[index]; + Debug.Assert(continuationContext != null); + return continuationContext; + } + + public void SetException(Exception ex) + { + int index = 0; + if ((Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_RESULT_IN_GCDATA) != 0) + index++; + + Debug.Assert(GCData != null && GCData.Length > index); + GCData[index] = ex; + } } public static partial class AsyncHelpers @@ -171,122 +203,338 @@ private static unsafe object AllocContinuationResultBox(void* ptr) return RuntimeTypeHandle.InternalAllocNoChecks((MethodTable*)pMT); } - // wrapper to await a notifier - private struct AwaitableProxy : ICriticalNotifyCompletion + private interface IThunkTaskOps { - private readonly INotifyCompletion _notifier; + static abstract Action GetContinuationAction(T task); + static abstract Continuation GetContinuationState(T task); + static abstract void SetContinuationState(T task, Continuation value); + static abstract bool SetCompleted(T task, Continuation continuation); + static abstract void PostToSyncContext(T task, SynchronizationContext syncCtx); + } - public AwaitableProxy(INotifyCompletion notifier) + private sealed class ThunkTask : Task + { + public ThunkTask() { - _notifier = notifier; + // We use the base Task's state object field to store the Continuation while posting the task around. + // Ensure that state object isn't published out for others to see. + Debug.Assert((m_stateFlags & (int)InternalTaskOptions.PromiseTask) != 0, "Expected state flags to already be configured."); + Debug.Assert(m_stateObject is null, "Expected to be able to use the state object field for Continuation."); + m_action = MoveNext; + m_stateFlags |= (int)InternalTaskOptions.HiddenState; } - public bool IsCompleted => false; + internal override void ExecuteFromThreadPool(Thread threadPoolThread) + { + MoveNext(); + } - public void OnCompleted(Action action) + private void MoveNext() { - _notifier!.OnCompleted(action); + ThunkTaskCore.MoveNext, Ops>(this); } - public AwaitableProxy GetAwaiter() { return this; } + public void HandleSuspended() + { + ThunkTaskCore.HandleSuspended, Ops>(this); + } - public void UnsafeOnCompleted(Action action) + private static readonly SendOrPostCallback s_postCallback = static state => { - if (_notifier is ICriticalNotifyCompletion criticalNotification) + Debug.Assert(state is ThunkTask); + ((ThunkTask)state).MoveNext(); + }; + + private struct Ops : IThunkTaskOps> + { + public static Action GetContinuationAction(ThunkTask task) => (Action)task.m_action!; + public static void MoveNext(ThunkTask task) => task.MoveNext(); + public static Continuation GetContinuationState(ThunkTask task) => (Continuation)task.m_stateObject!; + public static void SetContinuationState(ThunkTask task, Continuation value) { - criticalNotification.UnsafeOnCompleted(action); + task.m_stateObject = value; } - else + + public static bool SetCompleted(ThunkTask task, Continuation continuation) { - _notifier!.OnCompleted(action); + T result; + if (RuntimeHelpers.IsReferenceOrContainsReferences()) + { + if (typeof(T).IsValueType) + { + result = Unsafe.As(ref continuation.GCData![0]!.GetRawData()); + } + else + { + result = Unsafe.As(ref continuation.GCData![0]!); + } + } + else + { + result = Unsafe.As(ref continuation.Data![0]); + } + + return task.TrySetResult(result); } - } - public void GetResult() { } + public static void PostToSyncContext(ThunkTask task, SynchronizationContext syncContext) + { + syncContext.Post(s_postCallback, task); + } + } } - private static Continuation UnlinkHeadContinuation(out AwaitableProxy awaitableProxy) + private sealed class ThunkTask : Task { - ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; - awaitableProxy = new AwaitableProxy(state.Notifier!); - state.Notifier = null; - - Continuation sentinelContinuation = state.SentinelContinuation!; - Continuation head = sentinelContinuation.Next!; - sentinelContinuation.Next = null; - return head; - } + public ThunkTask() + { + // We use the base Task's state object field to store the Continuation while posting the task around. + // Ensure that state object isn't published out for others to see. + Debug.Assert((m_stateFlags & (int)InternalTaskOptions.PromiseTask) != 0, "Expected state flags to already be configured."); + Debug.Assert(m_stateObject is null, "Expected to be able to use the state object field for Continuation."); + m_action = MoveNext; + m_stateFlags |= (int)InternalTaskOptions.HiddenState; + } - // When a Task-returning thunk gets a continuation result - // it calls here to make a Task that awaits on the current async state. - // NOTE: This cannot be Runtime Async. Must use C# state machine or make one by hand. - private static async Task FinalizeTaskReturningThunk(Continuation continuation) - { - Continuation finalContinuation = new Continuation(); + internal override void ExecuteFromThreadPool(Thread threadPoolThread) + { + MoveNext(); + } - // Note that the exact location the return value is placed is tied - // into getAsyncResumptionStub in the VM, so do not change this - // without also changing that code (and the JIT). - if (RuntimeHelpers.IsReferenceOrContainsReferences()) + private void MoveNext() { - finalContinuation.Flags = CorInfoContinuationFlags.CORINFO_CONTINUATION_RESULT_IN_GCDATA | CorInfoContinuationFlags.CORINFO_CONTINUATION_NEEDS_EXCEPTION; - finalContinuation.GCData = new object[1]; + ThunkTaskCore.MoveNext(this); } - else + + public void HandleSuspended() { - finalContinuation.Flags = CorInfoContinuationFlags.CORINFO_CONTINUATION_NEEDS_EXCEPTION; - finalContinuation.Data = new byte[Unsafe.SizeOf()]; + ThunkTaskCore.HandleSuspended(this); } - continuation.Next = finalContinuation; + private static readonly SendOrPostCallback s_postCallback = static state => + { + Debug.Assert(state is ThunkTask); + ((ThunkTask)state).MoveNext(); + }; - while (true) + private struct Ops : IThunkTaskOps { - Continuation headContinuation = UnlinkHeadContinuation(out var awaitableProxy); - await awaitableProxy; - Continuation? finalResult = DispatchContinuations(headContinuation); - if (finalResult != null) + public static Action GetContinuationAction(ThunkTask task) => (Action)task.m_action!; + public static void MoveNext(ThunkTask task) => task.MoveNext(); + public static Continuation GetContinuationState(ThunkTask task) => (Continuation)task.m_stateObject!; + public static void SetContinuationState(ThunkTask task, Continuation value) { - Debug.Assert(finalResult == finalContinuation); - if (RuntimeHelpers.IsReferenceOrContainsReferences()) + task.m_stateObject = value; + } + + public static bool SetCompleted(ThunkTask task, Continuation continuation) + { + return task.TrySetResult(); + } + + public static void PostToSyncContext(ThunkTask task, SynchronizationContext syncContext) + { + syncContext.Post(s_postCallback, task); + } + } + } + + private static class ThunkTaskCore + { + public static unsafe void MoveNext(T task) where T : Task where TOps : IThunkTaskOps + { + ExecutionAndSyncBlockStore contexts = default; + contexts.Push(); + Continuation continuation = TOps.GetContinuationState(task); + + while (true) + { + try { - if (typeof(T).IsValueType) + Continuation? newContinuation = continuation.Resume(continuation); + + if (newContinuation != null) + { + newContinuation.Next = continuation.Next; + HandleSuspended(task); + contexts.Pop(); + return; + } + + Debug.Assert(continuation.Next != null); + continuation = continuation.Next; + } + catch (Exception ex) + { + Continuation nextContinuation = UnwindToPossibleHandler(continuation); + if (nextContinuation.Resume == null) + { + // Tail of AsyncTaskMethodBuilderT.SetException + bool successfullySet = ex is OperationCanceledException oce ? + task.TrySetCanceled(oce.CancellationToken, oce) : + task.TrySetException(ex); + + contexts.Pop(); + + if (!successfullySet) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted); + } + + return; + } + + nextContinuation.SetException(ex); + + continuation = nextContinuation; + } + + if (continuation.Resume == null) + { + bool successfullySet = TOps.SetCompleted(task, continuation); + + contexts.Pop(); + + if (!successfullySet) { - return Unsafe.As(ref finalResult.GCData![0]!.GetRawData()); + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted); } - return Unsafe.As(ref finalResult.GCData![0]!); + return; + } + + if (QueueContinuationFollowUpActionIfNecessary(task, continuation)) + { + contexts.Pop(); + return; + } + } + } + + private static Continuation UnwindToPossibleHandler(Continuation continuation) + { + while (true) + { + Debug.Assert(continuation.Next != null); + continuation = continuation.Next; + if ((continuation.Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_NEEDS_EXCEPTION) != 0) + return continuation; + } + } + + public static void HandleSuspended(T task) where T : Task where TOps : IThunkTaskOps + { + Continuation headContinuation = UnlinkHeadContinuation(out INotifyCompletion? notifier); + + // Head continuation should be the result of async call to AwaitAwaiter or UnsafeAwaitAwaiter. + // These never have special continuation handling. + const CorInfoContinuationFlags continueFlags = + CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_SYNCHRONIZATION_CONTEXT | + CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_THREAD_POOL | + CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_TASK_SCHEDULER; + Debug.Assert((headContinuation.Flags & continueFlags) == 0); + + TOps.SetContinuationState(task, headContinuation); + + try + { + if (notifier is ICriticalNotifyCompletion crit) + { + crit.UnsafeOnCompleted(TOps.GetContinuationAction(task)); } else { - return Unsafe.As(ref finalResult.Data![0]); + Debug.Assert(notifier != null); + notifier.OnCompleted(TOps.GetContinuationAction(task)); } } + catch (Exception ex) + { + Task.ThrowAsync(ex, targetContext: null); + } } - } - private static async Task FinalizeTaskReturningThunk(Continuation continuation) - { - Continuation finalContinuation = new Continuation + private static Continuation UnlinkHeadContinuation(out INotifyCompletion? notifier) { - Flags = CorInfoContinuationFlags.CORINFO_CONTINUATION_NEEDS_EXCEPTION, - }; - continuation.Next = finalContinuation; + ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; + notifier = state.Notifier; + state.Notifier = null; + + Continuation sentinelContinuation = state.SentinelContinuation!; + Continuation head = sentinelContinuation.Next!; + sentinelContinuation.Next = null; + return head; + } - while (true) + private static bool QueueContinuationFollowUpActionIfNecessary(T task, Continuation continuation) where T : Task where TOps : IThunkTaskOps { - Continuation headContinuation = UnlinkHeadContinuation(out var awaitableProxy); - await awaitableProxy; - Continuation? finalResult = DispatchContinuations(headContinuation); - if (finalResult != null) + if ((continuation.Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_THREAD_POOL) != 0) { - Debug.Assert(finalResult == finalContinuation); - return; + SynchronizationContext? ctx = Thread.CurrentThreadAssumedInitialized._synchronizationContext; + if (ctx == null || ctx.GetType() == typeof(SynchronizationContext)) + { + TaskScheduler? sched = TaskScheduler.InternalCurrent; + if (sched == null || sched == TaskScheduler.Default) + { + // Can inline + return false; + } + } + + TOps.SetContinuationState(task, continuation); + ThreadPool.UnsafeQueueUserWorkItemInternal(task, preferLocal: true); + return true; + } + + if ((continuation.Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_SYNCHRONIZATION_CONTEXT) != 0) + { + object continuationContext = continuation.GetContinuationContext(); + Debug.Assert(continuationContext is SynchronizationContext { }); + SynchronizationContext continuationSyncCtx = (SynchronizationContext)continuationContext; + + if (continuationSyncCtx == Thread.CurrentThreadAssumedInitialized._synchronizationContext) + { + // Inline + return false; + } + + TOps.SetContinuationState(task, continuation); + + try + { + TOps.PostToSyncContext(task, continuationSyncCtx); + } + catch (Exception ex) + { + Task.ThrowAsync(ex, targetContext: null); + } + + return true; + } + + if ((continuation.Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_TASK_SCHEDULER) != 0) + { + object continuationContext = continuation.GetContinuationContext(); + Debug.Assert(continuationContext is TaskScheduler { }); + TaskScheduler sched = (TaskScheduler)continuationContext; + + TOps.SetContinuationState(task, continuation); + // TODO: We do not need TaskSchedulerAwaitTaskContinuation here, just need to refactor its Run method... + var taskSchedCont = new TaskSchedulerAwaitTaskContinuation(sched, TOps.GetContinuationAction(task), flowExecutionContext: false); + taskSchedCont.Run(Task.CompletedTask, canInlineContinuationTask: true); + + return true; } + + return false; } } - private static async ValueTask FinalizeValueTaskReturningThunk(Continuation continuation) + // Change return type to ThunkTask -- no benefit since this is used for Task returning thunks only +#pragma warning disable CA1859 + // When a Task-returning thunk gets a continuation result + // it calls here to make a Task that awaits on the current async state. + private static Task FinalizeTaskReturningThunk(Continuation continuation) { Continuation finalContinuation = new Continuation(); @@ -306,32 +554,12 @@ private static async Task FinalizeTaskReturningThunk(Continuation continuation) continuation.Next = finalContinuation; - while (true) - { - Continuation headContinuation = UnlinkHeadContinuation(out var awaitableProxy); - await awaitableProxy; - Continuation? finalResult = DispatchContinuations(headContinuation); - if (finalResult != null) - { - Debug.Assert(finalResult == finalContinuation); - if (RuntimeHelpers.IsReferenceOrContainsReferences()) - { - if (typeof(T).IsValueType) - { - return Unsafe.As(ref finalResult.GCData![0]!.GetRawData()); - } - - return Unsafe.As(ref finalResult.GCData![0]!); - } - else - { - return Unsafe.As(ref finalResult.Data![0]); - } - } - } + ThunkTask result = new(); + result.HandleSuspended(); + return result; } - private static async ValueTask FinalizeValueTaskReturningThunk(Continuation continuation) + private static Task FinalizeTaskReturningThunk(Continuation continuation) { Continuation finalContinuation = new Continuation { @@ -339,72 +567,21 @@ private static async ValueTask FinalizeValueTaskReturningThunk(Continuation cont }; continuation.Next = finalContinuation; - while (true) - { - Continuation headContinuation = UnlinkHeadContinuation(out var awaitableProxy); - await awaitableProxy; - Continuation? finalResult = DispatchContinuations(headContinuation); - if (finalResult != null) - { - Debug.Assert(finalResult == finalContinuation); - return; - } - } + ThunkTask result = new(); + result.HandleSuspended(); + return result; } - // Return a continuation object if that is the one which has the final - // result of the Task, if the real output of the series of continuations was - // an exception, it is allowed to propagate out. - // OR - // return NULL to indicate that this isn't yet done. - private static unsafe Continuation? DispatchContinuations(Continuation? continuation) + private static ValueTask FinalizeValueTaskReturningThunk(Continuation continuation) { - Debug.Assert(continuation != null); - - while (true) - { - Continuation? newContinuation; - try - { - newContinuation = continuation.Resume(continuation); - } - catch (Exception ex) - { - continuation = UnwindToPossibleHandler(continuation); - if (continuation.Resume == null) - { - throw; - } - - continuation.GCData![(continuation.Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_RESULT_IN_GCDATA) != 0 ? 1 : 0] = ex; - continue; - } - - if (newContinuation != null) - { - newContinuation.Next = continuation.Next; - return null; - } - - continuation = continuation.Next; - Debug.Assert(continuation != null); - - if (continuation.Resume == null) - { - return continuation; // Return the result containing Continuation - } - } + // We only come to these methods in the expensive case (already + // suspended), so ValueTask optimization here is not relevant. + return new ValueTask(FinalizeTaskReturningThunk(continuation)); } - private static Continuation UnwindToPossibleHandler(Continuation continuation) + private static ValueTask FinalizeValueTaskReturningThunk(Continuation continuation) { - while (true) - { - Debug.Assert(continuation.Next != null); - continuation = continuation.Next; - if ((continuation.Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_NEEDS_EXCEPTION) != 0) - return continuation; - } + return new ValueTask(FinalizeTaskReturningThunk(continuation)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -423,5 +600,26 @@ private static void RestoreExecutionContext(ExecutionContext? previousExecutionC ExecutionContext.RestoreChangedContextToThread(thread, previousExecutionCtx, currentExecutionCtx); } } + + private static void CaptureContinuationContext(ref object context, ref CorInfoContinuationFlags flags) + { + SynchronizationContext? syncCtx = Thread.CurrentThreadAssumedInitialized._synchronizationContext; + if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext)) + { + flags |= CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_SYNCHRONIZATION_CONTEXT; + context = syncCtx; + return; + } + + TaskScheduler? sched = TaskScheduler.InternalCurrent; + if (sched != null && sched != TaskScheduler.Default) + { + flags |= CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_TASK_SCHEDULER; + context = sched; + return; + } + + flags |= CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_THREAD_POOL; + } } } diff --git a/src/runtime/src/coreclr/inc/corinfo.h b/src/runtime/src/coreclr/inc/corinfo.h index 6182619dbbf..313d67a11ec 100644 --- a/src/runtime/src/coreclr/inc/corinfo.h +++ b/src/runtime/src/coreclr/inc/corinfo.h @@ -1712,6 +1712,15 @@ enum CorInfoContinuationFlags // OSR method saved in the beginning of 'Data', or -1 if the continuation // belongs to a tier 0 method. CORINFO_CONTINUATION_OSR_IL_OFFSET_IN_DATA = 4, + // If this bit is set the continuation should continue on the thread + // pool. + CORINFO_CONTINUATION_CONTINUE_ON_THREAD_POOL = 8, + // If this bit is set the continuation has a SynchronizationContext + // that we should continue on. + CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_SYNCHRONIZATION_CONTEXT = 16, + // If this bit is set the continuation has a TaskScheduler + // that we should continue on. + CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_TASK_SCHEDULER = 32, }; struct CORINFO_ASYNC_INFO @@ -1737,6 +1746,7 @@ struct CORINFO_ASYNC_INFO CORINFO_METHOD_HANDLE captureExecutionContextMethHnd; // Method handle for AsyncHelpers.RestoreExecutionContext CORINFO_METHOD_HANDLE restoreExecutionContextMethHnd; + CORINFO_METHOD_HANDLE captureContinuationContextMethHnd; }; // Flags passed from JIT to runtime. diff --git a/src/runtime/src/coreclr/inc/jiteeversionguid.h b/src/runtime/src/coreclr/inc/jiteeversionguid.h index 43c4c32332d..79b7eda125f 100644 --- a/src/runtime/src/coreclr/inc/jiteeversionguid.h +++ b/src/runtime/src/coreclr/inc/jiteeversionguid.h @@ -37,11 +37,11 @@ #include -constexpr GUID JITEEVersionIdentifier = { /* 5c7eb9f1-a9cb-4a35-aea6-ae93d1f54c56 */ - 0x5c7eb9f1, - 0xa9cb, - 0x4a35, - {0xae, 0xa6, 0xae, 0x93, 0xd1, 0xf5, 0x4c, 0x56} +constexpr GUID JITEEVersionIdentifier = { /* 952f0344-7651-46af-8ef3-a34539af5c4a */ + 0x952f0344, + 0x7651, + 0x46af, + {0x8e, 0xf3, 0xa3, 0x45, 0x39, 0xaf, 0x5c, 0x4a} }; #endif // JIT_EE_VERSIONING_GUID_H diff --git a/src/runtime/src/coreclr/interpreter/compiler.cpp b/src/runtime/src/coreclr/interpreter/compiler.cpp index f65920a61b2..cb585f78268 100644 --- a/src/runtime/src/coreclr/interpreter/compiler.cpp +++ b/src/runtime/src/coreclr/interpreter/compiler.cpp @@ -2163,10 +2163,14 @@ int32_t InterpCompiler::GetDataItemIndexForHelperFtn(CorInfoHelpFunc ftn) CORINFO_CONST_LOOKUP ftnLookup; m_compHnd->getHelperFtn(ftn, &ftnLookup); void* addr = ftnLookup.addr; - if (ftnLookup.accessType == IAT_PVALUE) + if (ftnLookup.accessType == IAT_VALUE) { - addr = (void*)((size_t)addr | INTERP_INDIRECT_HELPER_TAG); + // We can't use the 1 bit to mark indirect addresses because it is used for real code on arm32 (the thumb bit) + // So instead, we mark direct addresses with a 1 and then on the other end we will clear the 1 and re-set it as needed for thumb + addr = (void*)((size_t)addr | INTERP_DIRECT_HELPER_TAG); } + else if (ftnLookup.accessType == IAT_PPVALUE) + NO_WAY("IAT_PPVALUE helpers not implemented in interpreter"); #ifdef DEBUG if (!PointerInNameMap(addr)) @@ -2181,6 +2185,27 @@ int32_t InterpCompiler::GetDataItemIndexForHelperFtn(CorInfoHelpFunc ftn) return GetDataItemIndex(addr); } +static int32_t GetLdindForType(InterpType interpType) +{ + switch (interpType) + { + case InterpTypeI1: return INTOP_LDIND_I1; + case InterpTypeU1: return INTOP_LDIND_U1; + case InterpTypeI2: return INTOP_LDIND_I2; + case InterpTypeU2: return INTOP_LDIND_U2; + case InterpTypeI4: return INTOP_LDIND_I4; + case InterpTypeI8: return INTOP_LDIND_I8; + case InterpTypeR4: return INTOP_LDIND_R4; + case InterpTypeR8: return INTOP_LDIND_R8; + case InterpTypeO: return INTOP_LDIND_I; + case InterpTypeVT: return INTOP_LDIND_VT; + case InterpTypeByRef: return INTOP_LDIND_I; + default: + assert(0); + } + return -1; +} + bool InterpCompiler::EmitNamedIntrinsicCall(NamedIntrinsic ni, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO sig) { bool mustExpand = (method == m_methodHnd); @@ -2201,6 +2226,135 @@ bool InterpCompiler::EmitNamedIntrinsicCall(NamedIntrinsic ni, CORINFO_CLASS_HAN AddIns(INTOP_THROW_PNSE); return true; + case NI_System_Runtime_CompilerServices_StaticsHelpers_VolatileReadAsByref: + { + CHECK_STACK(1); + + m_pStackPointer--; + int32_t addrVar = m_pStackPointer[0].var; + + InterpType retType = GetInterpType(sig.retType); + int32_t opcode = GetLdindForType(retType); + AddIns(opcode); + m_pLastNewIns->SetSVar(addrVar); + + CORINFO_CLASS_HANDLE clsHnd = NULL; + if (sig.retType == CORINFO_TYPE_CLASS) + { + clsHnd = sig.retTypeClass; + } + PushInterpType(retType, clsHnd); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + + // Acquire barrier after the load + AddIns(INTOP_MEMBAR); + return true; + } + + case NI_System_Threading_Volatile_ReadBarrier: + AddIns(INTOP_MEMBAR); + return true; + + case NI_System_Runtime_CompilerServices_RuntimeHelpers_GetMethodTable: + { + CHECK_STACK(1); + m_pStackPointer--; + AddIns(INTOP_LDIND_I); + m_pLastNewIns->data[0] = 0; + m_pLastNewIns->SetSVar(m_pStackPointer[0].var); + PushStackType(StackTypeI, NULL); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + return true; + } + + case NI_System_Threading_Interlocked_CompareExchange: + { + CHECK_STACK(3); + InterpType retType = GetInterpType(sig.retType); + + int32_t opcode; + switch (retType) + { + case InterpTypeI4: + opcode = INTOP_COMPARE_EXCHANGE_I4; + break; + case InterpTypeI8: + opcode = INTOP_COMPARE_EXCHANGE_I8; + break; + default: + return false; + } + + AddIns(opcode); + m_pStackPointer -= 3; + + int32_t addrVar = m_pStackPointer[0].var; + int32_t valueVar = m_pStackPointer[1].var; + int32_t comparandVar = m_pStackPointer[2].var; + + PushInterpType(retType, nullptr); + m_pLastNewIns->SetSVars3(addrVar, valueVar, comparandVar); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + return true; + } + + case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsReferenceOrContainsReferences: + { + CORINFO_CLASS_HANDLE clsHnd = sig.sigInst.methInst[0]; + bool isValueType = (m_compHnd->getClassAttribs(clsHnd) & CORINFO_FLG_VALUECLASS) != 0; + bool hasGCRefs = false; + + if (isValueType) + { + // Walk the layout to see if any field is a GC pointer + const uint32_t maxSlots = 256; + BYTE gcLayout[maxSlots]; + uint32_t numSlots = m_compHnd->getClassGClayout(clsHnd, gcLayout); + + for (uint32_t i = 0; i < numSlots; ++i) + { + if (gcLayout[i] != TYPE_GC_NONE) + { + hasGCRefs = true; + break; + } + } + } + + int32_t result = (!isValueType || hasGCRefs) ? 1 : 0; + + AddIns(INTOP_LDC_I4); + m_pLastNewIns->data[0] = result; + + PushInterpType(InterpTypeI4, nullptr); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + + return true; + } + case NI_System_Runtime_InteropService_MemoryMarshal_GetArrayDataReference: + { + CHECK_STACK(1); + + m_pStackPointer--; + int32_t arrayVar = m_pStackPointer[0].var; + + AddIns(INTOP_NULLCHECK); + m_pLastNewIns->SetSVar(arrayVar); + + AddIns(INTOP_ADD_P_IMM); + m_pLastNewIns->SetSVar(arrayVar); + m_pLastNewIns->data[0] = OFFSETOF__CORINFO_Array__data; + + PushInterpType(InterpTypeByRef, NULL); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + + return true; + } + + case NI_System_Threading_Thread_FastPollGC: + AddIns(INTOP_SAFEPOINT); + return true; + default: { #ifdef DEBUG @@ -2257,7 +2411,6 @@ bool InterpCompiler::EmitCallIntrinsics(CORINFO_METHOD_HANDLE method, CORINFO_SI return true; } } - // TODO: Add multi-dimensional array getters and setters } return false; @@ -2672,6 +2825,9 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re doCallInsteadOfNew = true; } + bool isPInvoke = callInfo.methodFlags & CORINFO_FLG_PINVOKE; + bool isMarshaledPInvoke = isPInvoke && m_compHnd->pInvokeMarshalingRequired(callInfo.hMethod, &callInfo.sig); + // Process sVars int numArgsFromStack = callInfo.sig.numArgs + (newObj ? 0 : callInfo.sig.hasThis()); int newObjThisArgLocation = newObj && !doCallInsteadOfNew ? 0 : INT_MAX; @@ -2908,8 +3064,17 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re // before the call. // TODO: Add null checking behavior somewhere here! } - AddIns(INTOP_CALL); + AddIns((isPInvoke && !isMarshaledPInvoke) ? INTOP_CALL_PINVOKE : INTOP_CALL); m_pLastNewIns->data[0] = GetMethodDataItemIndex(callInfo.hMethod); + if (isPInvoke && !isMarshaledPInvoke) + { + CORINFO_CONST_LOOKUP lookup; + m_compHnd->getAddressOfPInvokeTarget(callInfo.hMethod, &lookup); + m_pLastNewIns->data[1] = GetDataItemIndex(lookup.addr); + m_pLastNewIns->data[2] = lookup.accessType == IAT_PVALUE; + if (lookup.accessType == IAT_PPVALUE) + NO_WAY("IAT_PPVALUE pinvokes not implemented in interpreter"); + } } break; @@ -2990,27 +3155,6 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re m_ip += 5; } -static int32_t GetLdindForType(InterpType interpType) -{ - switch (interpType) - { - case InterpTypeI1: return INTOP_LDIND_I1; - case InterpTypeU1: return INTOP_LDIND_U1; - case InterpTypeI2: return INTOP_LDIND_I2; - case InterpTypeU2: return INTOP_LDIND_U2; - case InterpTypeI4: return INTOP_LDIND_I4; - case InterpTypeI8: return INTOP_LDIND_I8; - case InterpTypeR4: return INTOP_LDIND_R4; - case InterpTypeR8: return INTOP_LDIND_R8; - case InterpTypeO: return INTOP_LDIND_I; - case InterpTypeVT: return INTOP_LDIND_VT; - case InterpTypeByRef: return INTOP_LDIND_I; - default: - assert(0); - } - return -1; -} - static int32_t GetStindForType(InterpType interpType) { switch (interpType) @@ -5153,6 +5297,9 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) volatile_ = true; m_ip++; break; + case CEE_UNALIGNED: + m_ip += 2; + break; case CEE_INITOBJ: { CHECK_STACK(1); @@ -6165,13 +6312,15 @@ void InterpCompiler::PrintHelperFtn(void* helperDirectOrIndirect) { void* helperAddr = helperDirectOrIndirect; - if (((size_t)helperDirectOrIndirect) & INTERP_INDIRECT_HELPER_TAG) + if (((size_t)helperDirectOrIndirect) & INTERP_DIRECT_HELPER_TAG) { - helperAddr = (void*)(((size_t)helperDirectOrIndirect) & ~INTERP_INDIRECT_HELPER_TAG); - printf(" (indirect)"); + helperAddr = (void*)(((size_t)helperDirectOrIndirect) & ~INTERP_DIRECT_HELPER_TAG); + printf(" (direct)"); } else - printf(" (direct)"); + { + printf(" (indirect)"); + } PrintPointer(helperAddr); } diff --git a/src/runtime/src/coreclr/interpreter/interpretershared.h b/src/runtime/src/coreclr/interpreter/interpretershared.h index 388fa3502e8..210bc1c1ad3 100644 --- a/src/runtime/src/coreclr/interpreter/interpretershared.h +++ b/src/runtime/src/coreclr/interpreter/interpretershared.h @@ -17,7 +17,7 @@ #define INTERP_STACK_SLOT_SIZE 8 // Alignment of each var offset on the interpreter stack #define INTERP_STACK_ALIGNMENT 16 // Alignment of interpreter stack at the start of a frame -#define INTERP_INDIRECT_HELPER_TAG 1 // When a helper ftn's address is indirect we tag it with this tag bit +#define INTERP_DIRECT_HELPER_TAG 1 // When a helper ftn's address is direct we tag it with this tag bit struct CallStubHeader; @@ -137,7 +137,7 @@ struct InterpGenericLookup void* signature; // Here is the helper you must call. It is one of CORINFO_HELP_RUNTIMEHANDLE_* helpers. - + InterpGenericLookupType lookupType; // Number of indirections to get there diff --git a/src/runtime/src/coreclr/interpreter/intops.def b/src/runtime/src/coreclr/interpreter/intops.def index 14bd5d3ba0f..8de811f7b52 100644 --- a/src/runtime/src/coreclr/interpreter/intops.def +++ b/src/runtime/src/coreclr/interpreter/intops.def @@ -23,6 +23,7 @@ OPDEF(INTOP_LDC_R8, "ldc.r8", 4, 1, 0, InterpOpDouble) OPDEF(INTOP_LDPTR, "ldptr", 3, 1, 0, InterpOpLdPtr) OPDEF(INTOP_LDPTR_DEREF, "ldptr.deref", 3, 1, 0, InterpOpLdPtr) +OPDEF(INTOP_NULLCHECK, "nullcheck", 2, 1, 0, InterpOpNoArgs) OPDEF(INTOP_NEWARR, "newarr", 5, 1, 1, InterpOpPointerHelperFtn) OPDEF(INTOP_NEWARR_GENERIC, "newarr.generic", 6, 1, 2, InterpOpGenericHelperFtn) OPDEF(INTOP_NEWMDARR, "newmdarr", 5, 1, 1, InterpOpPointerInt) @@ -357,6 +358,7 @@ OPDEF(INTOP_LDFLDA, "ldflda", 4, 1, 1, InterpOpInt) OPDEF(INTOP_CALL, "call", 4, 1, 1, InterpOpMethodHandle) OPDEF(INTOP_CALLI, "calli", 5, 1, 2, InterpOpLdPtr) OPDEF(INTOP_CALLVIRT, "callvirt", 4, 1, 1, InterpOpMethodHandle) +OPDEF(INTOP_CALL_PINVOKE, "call.pinvoke", 6, 1, 1, InterpOpMethodHandle) // inlined (no marshaling wrapper) pinvokes only OPDEF(INTOP_NEWOBJ, "newobj", 5, 1, 1, InterpOpMethodHandle) OPDEF(INTOP_NEWOBJ_GENERIC, "newobj.generic", 6, 1, 2, InterpOpMethodHandle) OPDEF(INTOP_NEWOBJ_VT, "newobj.vt", 5, 1, 1, InterpOpMethodHandle) @@ -403,6 +405,10 @@ OPDEF(INTOP_GC_COLLECT, "gc.collect", 1, 0, 0, InterpOpNoArgs) OPDEF(INTOP_LOAD_FRAMEVAR, "load.framevar", 2, 1, 0, InterpOpNoArgs) +// Intrinsics +OPDEF(INTOP_COMPARE_EXCHANGE_I4, "compare.exchange.i4", 5, 1, 3, InterpOpNoArgs) +OPDEF(INTOP_COMPARE_EXCHANGE_I8, "compare.exchange.i8", 5, 1, 3, InterpOpNoArgs) + // All instructions after this point are IROPS, instructions that are not emitted/executed OPDEF(INTOP_NOP, "nop", 1, 0, 0, InterpOpNoArgs) OPDEF(INTOP_DEF, "def", 2, 1, 0, InterpOpNoArgs) diff --git a/src/runtime/src/coreclr/interpreter/intrinsics.cpp b/src/runtime/src/coreclr/interpreter/intrinsics.cpp index 1e86a3749a7..c6bc8b05613 100644 --- a/src/runtime/src/coreclr/interpreter/intrinsics.cpp +++ b/src/runtime/src/coreclr/interpreter/intrinsics.cpp @@ -11,7 +11,8 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE comp { const char* className = NULL; const char* namespaceName = NULL; - const char* methodName = compHnd->getMethodNameFromMetadata(method, &className, &namespaceName, NULL, 0); + const char* enclosingClassNames[2] = {nullptr}; + const char* methodName = compHnd->getMethodNameFromMetadata(method, &className, &namespaceName, enclosingClassNames, ArrLen(enclosingClassNames)); // Array methods don't have metadata if (!namespaceName) @@ -76,6 +77,8 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE comp { if (!strcmp(methodName, "IsReferenceOrContainsReferences")) return NI_System_Runtime_CompilerServices_RuntimeHelpers_IsReferenceOrContainsReferences; + else if (!strcmp(methodName, "GetMethodTable")) + return NI_System_Runtime_CompilerServices_RuntimeHelpers_GetMethodTable; } } else if (!strcmp(namespaceName, "System.Runtime.InteropServices")) diff --git a/src/runtime/src/coreclr/interpreter/intrinsics.h b/src/runtime/src/coreclr/interpreter/intrinsics.h index d48d7b2bc05..0fb29eb417a 100644 --- a/src/runtime/src/coreclr/interpreter/intrinsics.h +++ b/src/runtime/src/coreclr/interpreter/intrinsics.h @@ -8,4 +8,10 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE compMethod, CORINFO_METHOD_HANDLE method); +template +inline constexpr unsigned ArrLen(T (&)[size]) +{ + return size; +} + #endif // __INTERPRETER_INTRINSICS_H__ diff --git a/src/runtime/src/coreclr/jit/assertionprop.cpp b/src/runtime/src/coreclr/jit/assertionprop.cpp index b63ea4084e1..787897de5e1 100644 --- a/src/runtime/src/coreclr/jit/assertionprop.cpp +++ b/src/runtime/src/coreclr/jit/assertionprop.cpp @@ -2665,7 +2665,10 @@ GenTree* Compiler::optVNBasedFoldExpr_Call(BasicBlock* block, GenTree* parent, G if (castFrom != NO_CLASS_HANDLE) { CORINFO_CLASS_HANDLE castTo = gtGetHelperArgClassHandle(castClsArg); - if (info.compCompHnd->compareTypesForCast(castFrom, castTo) == TypeCompareState::Must) + // Constant prop may fail to propagate compile time class handles, so verify we have + // a handle before invoking the runtime. + if ((castTo != NO_CLASS_HANDLE) && + info.compCompHnd->compareTypesForCast(castFrom, castTo) == TypeCompareState::Must) { // if castObjArg is not simple, we replace the arg with a temp assignment and // continue using that temp - it allows us reliably extract all side effects diff --git a/src/runtime/src/coreclr/jit/async.cpp b/src/runtime/src/coreclr/jit/async.cpp index e72f1fe7007..7a26ab4b004 100644 --- a/src/runtime/src/coreclr/jit/async.cpp +++ b/src/runtime/src/coreclr/jit/async.cpp @@ -1040,6 +1040,13 @@ ContinuationLayout AsyncTransformation::LayOutContinuation(BasicBlock* block->getTryIndex(), layout.ExceptionGCDataIndex); } + if (call->GetAsyncInfo().ContinuationContextHandling == ContinuationContextHandling::ContinueOnCapturedContext) + { + layout.ContinuationContextGCDataIndex = layout.GCRefsCount++; + JITDUMP(" Continuation continues on captured context; context will be at GC@+%02u in GC data\n", + layout.ContinuationContextGCDataIndex); + } + if (call->GetAsyncInfo().ExecutionContextHandling == ExecutionContextHandling::AsyncSaveAndRestore) { layout.ExecContextGCDataIndex = layout.GCRefsCount++; @@ -1200,13 +1207,16 @@ BasicBlock* AsyncTransformation::CreateSuspension( LIR::AsRange(suspendBB).InsertAtEnd(LIR::SeqTree(m_comp, storeState)); // Fill in 'flags' - unsigned continuationFlags = 0; + const AsyncCallInfo& callInfo = call->GetAsyncInfo(); + unsigned continuationFlags = 0; if (layout.ReturnInGCData) continuationFlags |= CORINFO_CONTINUATION_RESULT_IN_GCDATA; if (block->hasTryIndex()) continuationFlags |= CORINFO_CONTINUATION_NEEDS_EXCEPTION; if (m_comp->doesMethodHavePatchpoints() || m_comp->opts.IsOSR()) continuationFlags |= CORINFO_CONTINUATION_OSR_IL_OFFSET_IN_DATA; + if (callInfo.ContinuationContextHandling == ContinuationContextHandling::ContinueOnThreadPool) + continuationFlags |= CORINFO_CONTINUATION_CONTINUE_ON_THREAD_POOL; newContinuation = m_comp->gtNewLclvNode(m_newContinuationVar, TYP_REF); unsigned flagsOffset = m_comp->info.compCompHnd->getFieldOffset(m_asyncInfo->continuationFlagsFldHnd); @@ -1386,6 +1396,51 @@ void AsyncTransformation::FillInGCPointersOnSuspension(const ContinuationLayout& } } + if (layout.ContinuationContextGCDataIndex != UINT_MAX) + { + // Insert call AsyncHelpers.CaptureContinuationContext(ref + // newContinuation.GCData[ContinuationContextGCDataIndex], ref newContinuation.Flags). + GenTree* contextElementPlaceholder = m_comp->gtNewZeroConNode(TYP_BYREF); + GenTree* flagsPlaceholder = m_comp->gtNewZeroConNode(TYP_BYREF); + GenTreeCall* captureCall = + m_comp->gtNewCallNode(CT_USER_FUNC, m_asyncInfo->captureContinuationContextMethHnd, TYP_VOID); + + captureCall->gtArgs.PushFront(m_comp, NewCallArg::Primitive(flagsPlaceholder)); + captureCall->gtArgs.PushFront(m_comp, NewCallArg::Primitive(contextElementPlaceholder)); + + m_comp->compCurBB = suspendBB; + m_comp->fgMorphTree(captureCall); + + LIR::AsRange(suspendBB).InsertAtEnd(LIR::SeqTree(m_comp, captureCall)); + + // Now replace contextElementPlaceholder with actual address of the context element + LIR::Use use; + bool gotUse = LIR::AsRange(suspendBB).TryGetUse(contextElementPlaceholder, &use); + assert(gotUse); + + GenTree* objectArr = m_comp->gtNewLclvNode(objectArrLclNum, TYP_REF); + unsigned offset = OFFSETOF__CORINFO_Array__data + (layout.ContinuationContextGCDataIndex * TARGET_POINTER_SIZE); + GenTree* contextElementOffset = + m_comp->gtNewOperNode(GT_ADD, TYP_BYREF, objectArr, m_comp->gtNewIconNode((ssize_t)offset, TYP_I_IMPL)); + + LIR::AsRange(suspendBB).InsertBefore(contextElementPlaceholder, LIR::SeqTree(m_comp, contextElementOffset)); + use.ReplaceWith(contextElementOffset); + LIR::AsRange(suspendBB).Remove(contextElementPlaceholder); + + // And now replace flagsPlaceholder with actual address of the flags + gotUse = LIR::AsRange(suspendBB).TryGetUse(flagsPlaceholder, &use); + assert(gotUse); + + newContinuation = m_comp->gtNewLclvNode(m_newContinuationVar, TYP_REF); + unsigned flagsOffset = m_comp->info.compCompHnd->getFieldOffset(m_asyncInfo->continuationFlagsFldHnd); + GenTree* flagsOffsetNode = m_comp->gtNewOperNode(GT_ADD, TYP_BYREF, newContinuation, + m_comp->gtNewIconNode((ssize_t)flagsOffset, TYP_I_IMPL)); + + LIR::AsRange(suspendBB).InsertBefore(flagsPlaceholder, LIR::SeqTree(m_comp, flagsOffsetNode)); + use.ReplaceWith(flagsOffsetNode); + LIR::AsRange(suspendBB).Remove(flagsPlaceholder); + } + if (layout.ExecContextGCDataIndex != UINT_MAX) { GenTreeCall* captureExecContext = diff --git a/src/runtime/src/coreclr/jit/async.h b/src/runtime/src/coreclr/jit/async.h index 83732fd2411..e75f2ac8d15 100644 --- a/src/runtime/src/coreclr/jit/async.h +++ b/src/runtime/src/coreclr/jit/async.h @@ -18,14 +18,15 @@ struct LiveLocalInfo struct ContinuationLayout { - unsigned DataSize = 0; - unsigned GCRefsCount = 0; - ClassLayout* ReturnStructLayout = nullptr; - unsigned ReturnSize = 0; - bool ReturnInGCData = false; - unsigned ReturnValDataOffset = UINT_MAX; - unsigned ExceptionGCDataIndex = UINT_MAX; - unsigned ExecContextGCDataIndex = UINT_MAX; + unsigned DataSize = 0; + unsigned GCRefsCount = 0; + ClassLayout* ReturnStructLayout = nullptr; + unsigned ReturnSize = 0; + bool ReturnInGCData = false; + unsigned ReturnValDataOffset = UINT_MAX; + unsigned ExceptionGCDataIndex = UINT_MAX; + unsigned ExecContextGCDataIndex = UINT_MAX; + unsigned ContinuationContextGCDataIndex = UINT_MAX; const jitstd::vector& Locals; explicit ContinuationLayout(const jitstd::vector& locals) diff --git a/src/runtime/src/coreclr/jit/block.cpp b/src/runtime/src/coreclr/jit/block.cpp index 6a3bc744bcd..52f860ff736 100644 --- a/src/runtime/src/coreclr/jit/block.cpp +++ b/src/runtime/src/coreclr/jit/block.cpp @@ -502,11 +502,8 @@ void BasicBlock::dspFlags() const {BBF_HAS_CALL, "hascall"}, {BBF_DOMINATED_BY_EXCEPTIONAL_ENTRY, "xentry"}, {BBF_GC_SAFE_POINT, "gcsafe"}, - {BBF_HAS_IDX_LEN, "idxlen"}, - {BBF_HAS_MD_IDX_LEN, "mdidxlen"}, {BBF_HAS_NEWOBJ, "newobj"}, {BBF_HAS_NEWARR, "newarr"}, - {BBF_HAS_NULLCHECK, "nullcheck"}, {BBF_BACKWARD_JUMP, "bwd"}, {BBF_BACKWARD_JUMP_TARGET, "bwd-target"}, {BBF_BACKWARD_JUMP_SOURCE, "bwd-src"}, diff --git a/src/runtime/src/coreclr/jit/block.h b/src/runtime/src/coreclr/jit/block.h index 3bb90fba0a5..c541fa5309c 100644 --- a/src/runtime/src/coreclr/jit/block.h +++ b/src/runtime/src/coreclr/jit/block.h @@ -428,48 +428,45 @@ enum BasicBlockFlags : uint64_t BBF_NEEDS_GCPOLL = MAKE_BBFLAG( 6), // BB may need a GC poll because it uses the slow tail call helper BBF_CLONED_FINALLY_BEGIN = MAKE_BBFLAG( 7), // First block of a cloned finally region BBF_CLONED_FINALLY_END = MAKE_BBFLAG( 8), // Last block of a cloned finally region - BBF_HAS_NULLCHECK = MAKE_BBFLAG( 9), // BB contains a null check - BBF_HAS_SUPPRESSGC_CALL = MAKE_BBFLAG(10), // BB contains a call to a method with SuppressGCTransitionAttribute - BBF_RUN_RARELY = MAKE_BBFLAG(11), // BB is rarely run (catch clauses, blocks with throws etc) - BBF_HAS_LABEL = MAKE_BBFLAG(12), // BB needs a label - BBF_LOOP_ALIGN = MAKE_BBFLAG(13), // Block is lexically the first block in a loop we intend to align. - BBF_HAS_ALIGN = MAKE_BBFLAG(14), // BB ends with 'align' instruction - BBF_HAS_JMP = MAKE_BBFLAG(15), // BB executes a JMP instruction (instead of return) - BBF_GC_SAFE_POINT = MAKE_BBFLAG(16), // BB has a GC safe point (e.g. a call) - BBF_HAS_IDX_LEN = MAKE_BBFLAG(17), // BB contains simple index or length expressions on an SD array local var. - BBF_HAS_MD_IDX_LEN = MAKE_BBFLAG(18), // BB contains simple index, length, or lower bound expressions on an MD array local var. - BBF_HAS_MDARRAYREF = MAKE_BBFLAG(19), // Block has a multi-dimensional array reference - BBF_HAS_NEWOBJ = MAKE_BBFLAG(20), // BB contains 'new' of an object type. - - BBF_RETLESS_CALL = MAKE_BBFLAG(21), // BBJ_CALLFINALLY that will never return (and therefore, won't need a paired + BBF_HAS_SUPPRESSGC_CALL = MAKE_BBFLAG( 9), // BB contains a call to a method with SuppressGCTransitionAttribute + BBF_RUN_RARELY = MAKE_BBFLAG(10), // BB is rarely run (catch clauses, blocks with throws etc) + BBF_HAS_LABEL = MAKE_BBFLAG(11), // BB needs a label + BBF_LOOP_ALIGN = MAKE_BBFLAG(12), // Block is lexically the first block in a loop we intend to align. + BBF_HAS_ALIGN = MAKE_BBFLAG(13), // BB ends with 'align' instruction + BBF_HAS_JMP = MAKE_BBFLAG(14), // BB executes a JMP instruction (instead of return) + BBF_GC_SAFE_POINT = MAKE_BBFLAG(15), // BB has a GC safe point (e.g. a call) + BBF_HAS_MDARRAYREF = MAKE_BBFLAG(16), // Block has a multi-dimensional array reference + BBF_HAS_NEWOBJ = MAKE_BBFLAG(17), // BB contains 'new' of an object type. + + BBF_RETLESS_CALL = MAKE_BBFLAG(18), // BBJ_CALLFINALLY that will never return (and therefore, won't need a paired // BBJ_CALLFINALLYRET); see isBBCallFinallyPair(). - BBF_COLD = MAKE_BBFLAG(22), // BB is cold - BBF_PROF_WEIGHT = MAKE_BBFLAG(23), // BB weight is computed from profile data - BBF_KEEP_BBJ_ALWAYS = MAKE_BBFLAG(24), // A special BBJ_ALWAYS block, used by EH code generation. Keep the jump kind + BBF_COLD = MAKE_BBFLAG(19), // BB is cold + BBF_PROF_WEIGHT = MAKE_BBFLAG(20), // BB weight is computed from profile data + BBF_KEEP_BBJ_ALWAYS = MAKE_BBFLAG(21), // A special BBJ_ALWAYS block, used by EH code generation. Keep the jump kind // as BBJ_ALWAYS. Used on x86 for the final step block out of a finally. - BBF_HAS_CALL = MAKE_BBFLAG(25), // BB contains a call - BBF_DOMINATED_BY_EXCEPTIONAL_ENTRY = MAKE_BBFLAG(26), // Block is dominated by exceptional entry. - BBF_BACKWARD_JUMP = MAKE_BBFLAG(27), // BB is surrounded by a backward jump/switch arc - BBF_BACKWARD_JUMP_SOURCE = MAKE_BBFLAG(28), // Block is a source of a backward jump - BBF_BACKWARD_JUMP_TARGET = MAKE_BBFLAG(29), // Block is a target of a backward jump - BBF_PATCHPOINT = MAKE_BBFLAG(30), // Block is a patchpoint - BBF_PARTIAL_COMPILATION_PATCHPOINT = MAKE_BBFLAG(31), // Block is a partial compilation patchpoint - BBF_HAS_HISTOGRAM_PROFILE = MAKE_BBFLAG(32), // BB contains a call needing a histogram profile - BBF_TAILCALL_SUCCESSOR = MAKE_BBFLAG(33), // BB has pred that has potential tail call - BBF_RECURSIVE_TAILCALL = MAKE_BBFLAG(34), // Block has recursive tailcall that may turn into a loop - BBF_NO_CSE_IN = MAKE_BBFLAG(35), // Block should kill off any incoming CSE - BBF_CAN_ADD_PRED = MAKE_BBFLAG(36), // Ok to add pred edge to this block, even when "safe" edge creation disabled - BBF_HAS_VALUE_PROFILE = MAKE_BBFLAG(37), // Block has a node that needs a value probing - BBF_HAS_NEWARR = MAKE_BBFLAG(38), // BB contains 'new' of an array type. - BBF_MAY_HAVE_BOUNDS_CHECKS = MAKE_BBFLAG(39), // BB *likely* has a bounds check (after rangecheck phase). - BBF_ASYNC_RESUMPTION = MAKE_BBFLAG(40), // Block is a resumption block in an async method + BBF_HAS_CALL = MAKE_BBFLAG(22), // BB contains a call + BBF_DOMINATED_BY_EXCEPTIONAL_ENTRY = MAKE_BBFLAG(23), // Block is dominated by exceptional entry. + BBF_BACKWARD_JUMP = MAKE_BBFLAG(24), // BB is surrounded by a backward jump/switch arc + BBF_BACKWARD_JUMP_SOURCE = MAKE_BBFLAG(25), // Block is a source of a backward jump + BBF_BACKWARD_JUMP_TARGET = MAKE_BBFLAG(26), // Block is a target of a backward jump + BBF_PATCHPOINT = MAKE_BBFLAG(27), // Block is a patchpoint + BBF_PARTIAL_COMPILATION_PATCHPOINT = MAKE_BBFLAG(28), // Block is a partial compilation patchpoint + BBF_HAS_HISTOGRAM_PROFILE = MAKE_BBFLAG(29), // BB contains a call needing a histogram profile + BBF_TAILCALL_SUCCESSOR = MAKE_BBFLAG(30), // BB has pred that has potential tail call + BBF_RECURSIVE_TAILCALL = MAKE_BBFLAG(31), // Block has recursive tailcall that may turn into a loop + BBF_NO_CSE_IN = MAKE_BBFLAG(32), // Block should kill off any incoming CSE + BBF_CAN_ADD_PRED = MAKE_BBFLAG(33), // Ok to add pred edge to this block, even when "safe" edge creation disabled + BBF_HAS_VALUE_PROFILE = MAKE_BBFLAG(34), // Block has a node that needs a value probing + BBF_HAS_NEWARR = MAKE_BBFLAG(35), // BB contains 'new' of an array type. + BBF_MAY_HAVE_BOUNDS_CHECKS = MAKE_BBFLAG(36), // BB *likely* has a bounds check (after rangecheck phase). + BBF_ASYNC_RESUMPTION = MAKE_BBFLAG(37), // Block is a resumption block in an async method // The following are sets of flags. // Flags to update when two blocks are compacted - BBF_COMPACT_UPD = BBF_GC_SAFE_POINT | BBF_NEEDS_GCPOLL | BBF_HAS_JMP | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_BACKWARD_JUMP | \ - BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_NULLCHECK | BBF_HAS_MDARRAYREF | BBF_MAY_HAVE_BOUNDS_CHECKS, + BBF_COMPACT_UPD = BBF_GC_SAFE_POINT | BBF_NEEDS_GCPOLL | BBF_HAS_JMP | BBF_BACKWARD_JUMP | \ + BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_MDARRAYREF | BBF_MAY_HAVE_BOUNDS_CHECKS, // Flags a block should not have had before it is split. @@ -484,18 +481,18 @@ enum BasicBlockFlags : uint64_t // Flags gained by the bottom block when a block is split. // Note, this is a conservative guess. - // For example, the bottom block might or might not have BBF_HAS_NULLCHECK, but we assume it has BBF_HAS_NULLCHECK. + // For example, the bottom block might or might not have BBF_HAS_NEWARR, but we assume it has BBF_HAS_NEWARR. // TODO: Should BBF_RUN_RARELY be added to BBF_SPLIT_GAINED ? - BBF_SPLIT_GAINED = BBF_DONT_REMOVE | BBF_HAS_JMP | BBF_BACKWARD_JUMP | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_PROF_WEIGHT | BBF_HAS_NEWARR | \ - BBF_HAS_NEWOBJ | BBF_KEEP_BBJ_ALWAYS | BBF_CLONED_FINALLY_END | BBF_HAS_NULLCHECK | BBF_HAS_HISTOGRAM_PROFILE | BBF_HAS_VALUE_PROFILE | BBF_HAS_MDARRAYREF | BBF_NEEDS_GCPOLL | BBF_MAY_HAVE_BOUNDS_CHECKS | BBF_ASYNC_RESUMPTION, + BBF_SPLIT_GAINED = BBF_DONT_REMOVE | BBF_HAS_JMP | BBF_BACKWARD_JUMP | BBF_PROF_WEIGHT | BBF_HAS_NEWARR | \ + BBF_HAS_NEWOBJ | BBF_KEEP_BBJ_ALWAYS | BBF_CLONED_FINALLY_END | BBF_HAS_HISTOGRAM_PROFILE | BBF_HAS_VALUE_PROFILE | BBF_HAS_MDARRAYREF | BBF_NEEDS_GCPOLL | BBF_MAY_HAVE_BOUNDS_CHECKS | BBF_ASYNC_RESUMPTION, // Flags that must be propagated to a new block if code is copied from a block to a new block. These are flags that // limit processing of a block if the code in question doesn't exist. This is conservative; we might not // have actually copied one of these type of tree nodes, but if we only copy a portion of the block's statements, // we don't know (unless we actually pay close attention during the copy). - BBF_COPY_PROPAGATE = BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_HAS_MDARRAYREF | BBF_MAY_HAVE_BOUNDS_CHECKS, + BBF_COPY_PROPAGATE = BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_MDARRAYREF | BBF_MAY_HAVE_BOUNDS_CHECKS, }; FORCEINLINE diff --git a/src/runtime/src/coreclr/jit/codegenarm.cpp b/src/runtime/src/coreclr/jit/codegenarm.cpp index 0a7f9b21d9e..d8d3a191d41 100644 --- a/src/runtime/src/coreclr/jit/codegenarm.cpp +++ b/src/runtime/src/coreclr/jit/codegenarm.cpp @@ -61,6 +61,11 @@ bool CodeGen::genInstrWithConstant( { case INS_add: case INS_sub: + if (imm < 0) + { + imm = -imm; + ins = (ins == INS_add) ? INS_sub : INS_add; + } immFitsInIns = validImmForInstr(ins, (target_ssize_t)imm, flags); break; diff --git a/src/runtime/src/coreclr/jit/compiler.cpp b/src/runtime/src/coreclr/jit/compiler.cpp index 21321d7c69a..e67f86448d7 100644 --- a/src/runtime/src/coreclr/jit/compiler.cpp +++ b/src/runtime/src/coreclr/jit/compiler.cpp @@ -10506,20 +10506,18 @@ var_types Compiler::gtTypeForNullCheck(GenTree* tree) // // Arguments: // tree - the node to change; -// block - basic block of the node. // // Notes: // the function should not be called after lowering for platforms that do not support // emitting NULLCHECK nodes, like arm32. Use `Lowering::TransformUnusedIndirection` // that handles it and calls this function when appropriate. // -void Compiler::gtChangeOperToNullCheck(GenTree* tree, BasicBlock* block) +void Compiler::gtChangeOperToNullCheck(GenTree* tree) { assert(tree->OperIs(GT_IND, GT_BLK)); tree->ChangeOper(GT_NULLCHECK); tree->ChangeType(gtTypeForNullCheck(tree)); tree->SetIndirExceptionFlags(this); - block->SetFlags(BBF_HAS_NULLCHECK); optMethodFlags |= OMF_HAS_NULLCHECK; } diff --git a/src/runtime/src/coreclr/jit/compiler.h b/src/runtime/src/coreclr/jit/compiler.h index ae47054b200..d30efd26a5e 100644 --- a/src/runtime/src/coreclr/jit/compiler.h +++ b/src/runtime/src/coreclr/jit/compiler.h @@ -3481,13 +3481,13 @@ class Compiler GenTreeIndir* gtNewIndexIndir(GenTreeIndexAddr* indexAddr); - void gtAnnotateNewArrLen(GenTree* arrLen, BasicBlock* block); + void gtAnnotateNewArrLen(GenTree* arrLen); - GenTreeArrLen* gtNewArrLen(var_types typ, GenTree* arrayOp, int lenOffset, BasicBlock* block); + GenTreeArrLen* gtNewArrLen(var_types typ, GenTree* arrayOp, int lenOffset); - GenTreeMDArr* gtNewMDArrLen(GenTree* arrayOp, unsigned dim, unsigned rank, BasicBlock* block); + GenTreeMDArr* gtNewMDArrLen(GenTree* arrayOp, unsigned dim, unsigned rank); - GenTreeMDArr* gtNewMDArrLowerBound(GenTree* arrayOp, unsigned dim, unsigned rank, BasicBlock* block); + GenTreeMDArr* gtNewMDArrLowerBound(GenTree* arrayOp, unsigned dim, unsigned rank); void gtInitializeStoreNode(GenTree* store, GenTree* value); @@ -3530,10 +3530,10 @@ class Compiler return gtNewStoreValueNode(type, nullptr, addr, value, indirFlags); } - GenTree* gtNewNullCheck(GenTree* addr, BasicBlock* basicBlock); + GenTree* gtNewNullCheck(GenTree* addr); var_types gtTypeForNullCheck(GenTree* tree); - void gtChangeOperToNullCheck(GenTree* tree, BasicBlock* block); + void gtChangeOperToNullCheck(GenTree* tree); GenTree* gtNewAtomicNode( genTreeOps oper, var_types type, GenTree* addr, GenTree* value, GenTree* comparand = nullptr); @@ -4430,6 +4430,7 @@ class Compiler #endif // This call is a task await PREFIX_IS_TASK_AWAIT = 0x00000080, + PREFIX_TASK_AWAIT_CONTINUE_ON_CAPTURED_CONTEXT = 0x00000100, }; static void impValidateMemoryAccessOpcode(const BYTE* codeAddr, const BYTE* codeEndp, bool volatilePrefix); @@ -6152,8 +6153,6 @@ class Compiler bool fgExpandRarelyRunBlocks(); - bool fgEhAllowsMoveBlock(BasicBlock* bBefore, BasicBlock* bAfter); - void fgMoveBlocksAfter(BasicBlock* bStart, BasicBlock* bEnd, BasicBlock* insertAfterBlk); PhaseStatus fgHeadTailMerge(bool early); @@ -7645,14 +7644,6 @@ class Compiler GenTree** nullCheckParent, Statement** nullCheckStmt); bool optCanMoveNullCheckPastTree(GenTree* tree, bool isInsideTry, bool checkSideEffectSummary); -#if DEBUG - void optCheckFlagsAreSet(unsigned methodFlag, - const char* methodFlagStr, - unsigned bbFlag, - const char* bbFlagStr, - GenTree* tree, - BasicBlock* basicBlock); -#endif PhaseStatus optInductionVariables(); diff --git a/src/runtime/src/coreclr/jit/compiler.hpp b/src/runtime/src/coreclr/jit/compiler.hpp index 0f9b1de014a..38c092ebfa2 100644 --- a/src/runtime/src/coreclr/jit/compiler.hpp +++ b/src/runtime/src/coreclr/jit/compiler.hpp @@ -1752,9 +1752,8 @@ inline GenTreeIndir* Compiler::gtNewIndexIndir(GenTreeIndexAddr* indexAddr) // // Arguments: // arrLen - The new GT_ARR_LENGTH or GT_MDARR_LENGTH node -// block - Basic block that will contain the new length node // -inline void Compiler::gtAnnotateNewArrLen(GenTree* arrLen, BasicBlock* block) +inline void Compiler::gtAnnotateNewArrLen(GenTree* arrLen) { assert(arrLen->OperIs(GT_ARR_LENGTH, GT_MDARR_LENGTH)); static_assert_no_msg(GTF_ARRLEN_NONFAULTING == GTF_IND_NONFAULTING); @@ -1769,19 +1768,14 @@ inline void Compiler::gtAnnotateNewArrLen(GenTree* arrLen, BasicBlock* block) // typ - Type of the node // arrayOp - Array node // lenOffset - Offset of the length field -// block - Basic block that will contain the result // // Return Value: // New GT_ARR_LENGTH node // -inline GenTreeArrLen* Compiler::gtNewArrLen(var_types typ, GenTree* arrayOp, int lenOffset, BasicBlock* block) +inline GenTreeArrLen* Compiler::gtNewArrLen(var_types typ, GenTree* arrayOp, int lenOffset) { GenTreeArrLen* arrLen = new (this, GT_ARR_LENGTH) GenTreeArrLen(typ, arrayOp, lenOffset); - gtAnnotateNewArrLen(arrLen, block); - if (block != nullptr) - { - block->SetFlags(BBF_HAS_IDX_LEN); - } + gtAnnotateNewArrLen(arrLen); optMethodFlags |= OMF_HAS_ARRAYREF; return arrLen; } @@ -1793,19 +1787,14 @@ inline GenTreeArrLen* Compiler::gtNewArrLen(var_types typ, GenTree* arrayOp, int // arrayOp - Array node // dim - MD array dimension of interest // rank - MD array rank -// block - Basic block that will contain the result // // Return Value: // New GT_MDARR_LENGTH node // -inline GenTreeMDArr* Compiler::gtNewMDArrLen(GenTree* arrayOp, unsigned dim, unsigned rank, BasicBlock* block) +inline GenTreeMDArr* Compiler::gtNewMDArrLen(GenTree* arrayOp, unsigned dim, unsigned rank) { GenTreeMDArr* arrLen = new (this, GT_MDARR_LENGTH) GenTreeMDArr(GT_MDARR_LENGTH, arrayOp, dim, rank); - gtAnnotateNewArrLen(arrLen, block); - if (block != nullptr) - { - block->SetFlags(BBF_HAS_MD_IDX_LEN); - } + gtAnnotateNewArrLen(arrLen); assert((optMethodFlags & OMF_HAS_MDARRAYREF) != 0); // Should have been set in the importer. return arrLen; } @@ -1817,21 +1806,16 @@ inline GenTreeMDArr* Compiler::gtNewMDArrLen(GenTree* arrayOp, unsigned dim, uns // arrayOp - Array node // dim - MD array dimension of interest // rank - MD array rank -// block - Basic block that will contain the result // // Return Value: // New GT_MDARR_LOWER_BOUND node // -inline GenTreeMDArr* Compiler::gtNewMDArrLowerBound(GenTree* arrayOp, unsigned dim, unsigned rank, BasicBlock* block) +inline GenTreeMDArr* Compiler::gtNewMDArrLowerBound(GenTree* arrayOp, unsigned dim, unsigned rank) { GenTreeMDArr* arrOp = new (this, GT_MDARR_LOWER_BOUND) GenTreeMDArr(GT_MDARR_LOWER_BOUND, arrayOp, dim, rank); static_assert_no_msg(GTF_MDARRLOWERBOUND_NONFAULTING == GTF_IND_NONFAULTING); arrOp->SetIndirExceptionFlags(this); - if (block != nullptr) - { - block->SetFlags(BBF_HAS_MD_IDX_LEN); - } assert((optMethodFlags & OMF_HAS_MDARRAYREF) != 0); // Should have been set in the importer. return arrOp; } @@ -1841,17 +1825,15 @@ inline GenTreeMDArr* Compiler::gtNewMDArrLowerBound(GenTree* arrayOp, unsigned d // // Arguments: // addr - Address to null check -// basicBlock - Basic block of the node // // Return Value: // New GT_NULLCHECK node -inline GenTree* Compiler::gtNewNullCheck(GenTree* addr, BasicBlock* basicBlock) +inline GenTree* Compiler::gtNewNullCheck(GenTree* addr) { assert(fgAddrCouldBeNull(addr)); GenTree* nullCheck = gtNewOperNode(GT_NULLCHECK, TYP_BYTE, addr); nullCheck->gtFlags |= GTF_EXCEPT; - basicBlock->SetFlags(BBF_HAS_NULLCHECK); optMethodFlags |= OMF_HAS_NULLCHECK; return nullCheck; } diff --git a/src/runtime/src/coreclr/jit/earlyprop.cpp b/src/runtime/src/coreclr/jit/earlyprop.cpp index c35feaabd33..b606e66399d 100644 --- a/src/runtime/src/coreclr/jit/earlyprop.cpp +++ b/src/runtime/src/coreclr/jit/earlyprop.cpp @@ -18,55 +18,11 @@ bool Compiler::optDoEarlyPropForFunc() { // TODO-MDArray: bool propMDArrayLen = (optMethodFlags & OMF_HAS_MDNEWARRAY) && (optMethodFlags & // OMF_HAS_MDARRAYREF); - bool propArrayLen = (optMethodFlags & OMF_HAS_NEWARRAY) && (optMethodFlags & OMF_HAS_ARRAYREF); + bool propArrayLen = (optMethodFlags & OMF_HAS_ARRAYREF) != 0; bool propNullCheck = (optMethodFlags & OMF_HAS_NULLCHECK) != 0; return propArrayLen || propNullCheck; } -bool Compiler::optDoEarlyPropForBlock(BasicBlock* block) -{ - // TODO-MDArray: bool bbHasMDArrayRef = block->HasFlag(BBF_HAS_MID_IDX_LEN); - bool bbHasArrayRef = block->HasFlag(BBF_HAS_IDX_LEN); - bool bbHasNullCheck = block->HasFlag(BBF_HAS_NULLCHECK); - return bbHasArrayRef || bbHasNullCheck; -} - -#ifdef DEBUG -//----------------------------------------------------------------------------- -// optCheckFlagsAreSet: Check that the method flag and the basic block flag are set. -// -// Arguments: -// methodFlag - The method flag to check. -// methodFlagStr - String representation of the method flag. -// bbFlag - The basic block flag to check. -// bbFlagStr - String representation of the basic block flag. -// tree - Tree that makes the flags required. -// basicBlock - The basic block to check the flag on. - -void Compiler::optCheckFlagsAreSet(unsigned methodFlag, - const char* methodFlagStr, - unsigned bbFlag, - const char* bbFlagStr, - GenTree* tree, - BasicBlock* basicBlock) -{ - if ((optMethodFlags & methodFlag) == 0) - { - printf("%s is not set on optMethodFlags but is required because of the following tree\n", methodFlagStr); - gtDispTree(tree); - assert(false); - } - - if (!basicBlock->HasFlag((BasicBlockFlags)bbFlag)) - { - printf("%s is not set on " FMT_BB " but is required because of the following tree \n", bbFlagStr, - basicBlock->bbNum); - gtDispTree(tree); - assert(false); - } -} -#endif - //------------------------------------------------------------------------------------------ // optEarlyProp: The entry point of the early value propagation. // @@ -97,13 +53,6 @@ PhaseStatus Compiler::optEarlyProp() for (BasicBlock* const block : Blocks()) { -#ifndef DEBUG - if (!optDoEarlyPropForBlock(block)) - { - continue; - } -#endif - compCurBB = block; CompAllocator allocator(getAllocator(CMK_EarlyProp)); @@ -114,6 +63,12 @@ PhaseStatus Compiler::optEarlyProp() // Preserve the next link before the propagation and morph. Statement* next = stmt->GetNextStmt(); + if (stmt->GetRootNode() == nullptr || ((stmt->GetRootNode()->gtFlags & GTF_ALL_EFFECT) == 0)) + { + stmt = next; + continue; + } + compCurStmt = stmt; // Walk the stmt tree in linear order to rewrite any array length reference with a @@ -134,7 +89,6 @@ PhaseStatus Compiler::optEarlyProp() if (isRewritten) { // Make sure the transformation happens in debug, check, and release build. - assert(optDoEarlyPropForFunc() && optDoEarlyPropForBlock(block)); gtSetStmtInfo(stmt); fgSetStmtSeq(stmt); numChanges++; @@ -189,16 +143,6 @@ GenTree* Compiler::optEarlyPropRewriteTree(GenTree* tree, LocalNumberToNullCheck { return folded ? tree : nullptr; } -#ifdef DEBUG - else - { - if (propKind == optPropKind::OPK_ARRAYLEN) - { - optCheckFlagsAreSet(OMF_HAS_ARRAYREF, "OMF_HAS_ARRAYREF", BBF_HAS_IDX_LEN, "BBF_HAS_IDX_LEN", tree, - compCurBB); - } - } -#endif unsigned lclNum = objectRefPtr->AsLclVarCommon()->GetLclNum(); unsigned ssaNum = objectRefPtr->AsLclVarCommon()->GetSsaNum(); @@ -372,19 +316,6 @@ GenTree* Compiler::optPropGetValueRec(unsigned lclNum, unsigned ssaNum, optPropK bool Compiler::optFoldNullCheck(GenTree* tree, LocalNumberToNullCheckTreeMap* nullCheckMap) { -#ifdef DEBUG - if (tree->OperIs(GT_NULLCHECK)) - { - optCheckFlagsAreSet(OMF_HAS_NULLCHECK, "OMF_HAS_NULLCHECK", BBF_HAS_NULLCHECK, "BBF_HAS_NULLCHECK", tree, - compCurBB); - } -#else - if (!compCurBB->HasFlag(BBF_HAS_NULLCHECK)) - { - return false; - } -#endif - GenTree* nullCheckTree = optFindNullCheckToFold(tree, nullCheckMap); GenTree* nullCheckParent = nullptr; Statement* nullCheckStmt = nullptr; @@ -392,7 +323,6 @@ bool Compiler::optFoldNullCheck(GenTree* tree, LocalNumberToNullCheckTreeMap* nu if ((nullCheckTree != nullptr) && optIsNullCheckFoldingLegal(tree, nullCheckTree, &nullCheckParent, &nullCheckStmt)) { // Make sure the transformation happens in debug, check, and release build. - assert(optDoEarlyPropForFunc() && optDoEarlyPropForBlock(compCurBB) && compCurBB->HasFlag(BBF_HAS_NULLCHECK)); JITDUMP("optEarlyProp Marking a null check for removal\n"); DISPTREE(nullCheckTree); JITDUMP("\n"); diff --git a/src/runtime/src/coreclr/jit/emitriscv64.cpp b/src/runtime/src/coreclr/jit/emitriscv64.cpp index de93b6810ba..bf11222800d 100644 --- a/src/runtime/src/coreclr/jit/emitriscv64.cpp +++ b/src/runtime/src/coreclr/jit/emitriscv64.cpp @@ -3131,7 +3131,7 @@ BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instructio const int offset = id->idAddr()->iiaGetJitDataOffset(); assert(offset >= 0); - assert(offset < emitDataSize()); + assert((UNATIVE_OFFSET)offset < emitDataSize()); *ins = id->idIns(); const regNumber reg1 = id->idReg1(); diff --git a/src/runtime/src/coreclr/jit/fgbasic.cpp b/src/runtime/src/coreclr/jit/fgbasic.cpp index e3b19f68a96..e6e11155230 100644 --- a/src/runtime/src/coreclr/jit/fgbasic.cpp +++ b/src/runtime/src/coreclr/jit/fgbasic.cpp @@ -5309,18 +5309,6 @@ bool Compiler::fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bDest, BasicBloc return result; } -/***************************************************************************** - * - * Returns true if it is allowable (based upon the EH regions) - * to place block bAfter immediately after bBefore. It is allowable - * if the 'bBefore' and 'bAfter' blocks are in the exact same EH region. - */ - -bool Compiler::fgEhAllowsMoveBlock(BasicBlock* bBefore, BasicBlock* bAfter) -{ - return BasicBlock::sameEHRegion(bBefore, bAfter); -} - /***************************************************************************** * * Function called to move the range of blocks [bStart .. bEnd]. diff --git a/src/runtime/src/coreclr/jit/fginline.cpp b/src/runtime/src/coreclr/jit/fginline.cpp index eb973be0434..93faa18b858 100644 --- a/src/runtime/src/coreclr/jit/fginline.cpp +++ b/src/runtime/src/coreclr/jit/fginline.cpp @@ -2266,7 +2266,7 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) GenTree* thisOp = impInlineFetchArg(inlArgInfo[0], lclVarInfo[0]); if (fgAddrCouldBeNull(thisOp)) { - nullcheck = gtNewNullCheck(thisOp, block); + nullcheck = gtNewNullCheck(thisOp); // The NULL-check statement will be inserted to the statement list after those statements // that assign arguments to temps and before the actual body of the inlinee method. } diff --git a/src/runtime/src/coreclr/jit/fgopt.cpp b/src/runtime/src/coreclr/jit/fgopt.cpp index 9b63fb63cfd..49362517371 100644 --- a/src/runtime/src/coreclr/jit/fgopt.cpp +++ b/src/runtime/src/coreclr/jit/fgopt.cpp @@ -4517,8 +4517,10 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication /* = false */, bool isPh { // In the join free case, we also need to move bDest right after bNext // to create same flow as in the isJumpAroundEmpty case. + // However, we cannot move bDest if it will break EH invariants. // - if (!fgEhAllowsMoveBlock(bNext, bDest) || bDest->isBBCallFinallyPair()) + if (!BasicBlock::sameEHRegion(bNext, bDest) || bbIsTryBeg(bDest) || bbIsHandlerBeg(bDest) || + bDest->isBBCallFinallyPair()) { optimizeJump = false; } diff --git a/src/runtime/src/coreclr/jit/gentree.cpp b/src/runtime/src/coreclr/jit/gentree.cpp index 489e5d08c70..29682889d4d 100644 --- a/src/runtime/src/coreclr/jit/gentree.cpp +++ b/src/runtime/src/coreclr/jit/gentree.cpp @@ -5501,9 +5501,9 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) case GT_MDARR_LOWER_BOUND: level++; - // Array meta-data access should be the same as an indirection, which has a costEx of IND_COST_EX. - costEx = IND_COST_EX - 1; - costSz = 2; + // Array meta-data access should be the same as an IND(ADD(ADDR, SMALL_CNS)). + costEx = IND_COST_EX + 1; + costSz = 2 * 2; break; case GT_BLK: @@ -9596,18 +9596,15 @@ GenTree* Compiler::gtCloneExpr(GenTree* tree) break; case GT_ARR_LENGTH: - copy = - gtNewArrLen(tree->TypeGet(), tree->AsArrLen()->ArrRef(), tree->AsArrLen()->ArrLenOffset(), nullptr); + copy = gtNewArrLen(tree->TypeGet(), tree->AsArrLen()->ArrRef(), tree->AsArrLen()->ArrLenOffset()); break; case GT_MDARR_LENGTH: - copy = - gtNewMDArrLen(tree->AsMDArr()->ArrRef(), tree->AsMDArr()->Dim(), tree->AsMDArr()->Rank(), nullptr); + copy = gtNewMDArrLen(tree->AsMDArr()->ArrRef(), tree->AsMDArr()->Dim(), tree->AsMDArr()->Rank()); break; case GT_MDARR_LOWER_BOUND: - copy = gtNewMDArrLowerBound(tree->AsMDArr()->ArrRef(), tree->AsMDArr()->Dim(), tree->AsMDArr()->Rank(), - nullptr); + copy = gtNewMDArrLowerBound(tree->AsMDArr()->ArrRef(), tree->AsMDArr()->Dim(), tree->AsMDArr()->Rank()); break; case GT_QMARK: @@ -14218,7 +14215,7 @@ GenTree* Compiler::gtFoldTypeCompare(GenTree* tree) { // we still have to emit a null-check // obj.GetType == typeof() -> (nullcheck) true/false - GenTree* nullcheck = gtNewNullCheck(objOp, compCurBB); + GenTree* nullcheck = gtNewNullCheck(objOp); return gtNewOperNode(GT_COMMA, tree->TypeGet(), nullcheck, compareResult); } else if (objOp->gtFlags & GTF_ALL_EFFECT) @@ -17373,7 +17370,7 @@ void Compiler::gtExtractSideEffList(GenTree* expr, if (node->OperIsBlk() && !node->OperIsStoreBlk()) { JITDUMP("Replace an unused BLK node [%06d] with a NULLCHECK\n", dspTreeID(node)); - m_compiler->gtChangeOperToNullCheck(node, m_compiler->compCurBB); + m_compiler->gtChangeOperToNullCheck(node); } Append(node); @@ -28654,6 +28651,31 @@ bool GenTreeHWIntrinsic::OperIsMemoryLoad(GenTree** pAddr) const case NI_Sve_Load2xVectorAndUnzip: case NI_Sve_Load3xVectorAndUnzip: case NI_Sve_Load4xVectorAndUnzip: + case NI_Sve_LoadVectorByteNonFaultingZeroExtendToInt16: + case NI_Sve_LoadVectorByteNonFaultingZeroExtendToInt32: + case NI_Sve_LoadVectorByteNonFaultingZeroExtendToInt64: + case NI_Sve_LoadVectorByteNonFaultingZeroExtendToUInt16: + case NI_Sve_LoadVectorByteNonFaultingZeroExtendToUInt32: + case NI_Sve_LoadVectorByteNonFaultingZeroExtendToUInt64: + case NI_Sve_LoadVectorInt16NonFaultingSignExtendToInt32: + case NI_Sve_LoadVectorInt16NonFaultingSignExtendToInt64: + case NI_Sve_LoadVectorInt16NonFaultingSignExtendToUInt32: + case NI_Sve_LoadVectorInt16NonFaultingSignExtendToUInt64: + case NI_Sve_LoadVectorInt32NonFaultingSignExtendToInt64: + case NI_Sve_LoadVectorInt32NonFaultingSignExtendToUInt64: + case NI_Sve_LoadVectorNonFaulting: + case NI_Sve_LoadVectorSByteNonFaultingSignExtendToInt16: + case NI_Sve_LoadVectorSByteNonFaultingSignExtendToInt32: + case NI_Sve_LoadVectorSByteNonFaultingSignExtendToInt64: + case NI_Sve_LoadVectorSByteNonFaultingSignExtendToUInt16: + case NI_Sve_LoadVectorSByteNonFaultingSignExtendToUInt32: + case NI_Sve_LoadVectorSByteNonFaultingSignExtendToUInt64: + case NI_Sve_LoadVectorUInt16NonFaultingZeroExtendToInt32: + case NI_Sve_LoadVectorUInt16NonFaultingZeroExtendToInt64: + case NI_Sve_LoadVectorUInt16NonFaultingZeroExtendToUInt32: + case NI_Sve_LoadVectorUInt16NonFaultingZeroExtendToUInt64: + case NI_Sve_LoadVectorUInt32NonFaultingZeroExtendToInt64: + case NI_Sve_LoadVectorUInt32NonFaultingZeroExtendToUInt64: addr = Op(2); break; @@ -32529,45 +32551,6 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) } #endif // FEATURE_MASKED_HW_INTRINSICS && TARGET_XARCH - switch (ni) - { - // There's certain IR simplifications that are possible and which - // unblock other constant folding, so do those early here. - -#if defined(TARGET_XARCH) - case NI_AVX_Compare: - case NI_AVX_CompareScalar: - case NI_AVX512_CompareMask: - { - assert(tree->GetOperandCount() == 3); - - if (!op3->IsCnsIntOrI()) - { - break; - } - - FloatComparisonMode mode = static_cast(op3->AsIntConCommon()->IntegralValue()); - NamedIntrinsic id = HWIntrinsicInfo::lookupIdForFloatComparisonMode(ni, mode, simdBaseType, simdSize); - - if (id == ni) - { - break; - } - - tree->ResetHWIntrinsicId(id, op1, op2); - DEBUG_DESTROY_NODE(op3); - - tree->SetMorphed(this); - return gtFoldExprHWIntrinsic(tree); - } -#endif // TARGET_XARCH - - default: - { - break; - } - } - GenTree* cnsNode = nullptr; GenTree* otherNode = nullptr; @@ -32576,12 +32559,23 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) cnsNode = op1; otherNode = op2; } - else if ((op2 != nullptr) && op2->OperIsConst()) + else if (op2 != nullptr) { - cnsNode = op2; - otherNode = op1; + if (op2->OperIsConst()) + { + cnsNode = op2; + otherNode = op1; + } + else if (op3 != nullptr) + { + if (op3->OperIsConst()) + { + cnsNode = op3; + } + } } - else + + if (cnsNode == nullptr) { // No constants, so nothing to fold return tree; @@ -32589,11 +32583,8 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) GenTree* resultNode = tree; - if (otherNode == nullptr) + if (opCount == 1) { - assert(op2 == nullptr); - assert(op3 == nullptr); - if (oper != GT_NONE) { if (varTypeIsMask(retType)) @@ -32809,284 +32800,153 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) break; } - default: +#ifdef TARGET_ARM64 + case NI_ArmBase_ReverseElementBits: { + assert(!varTypeIsSmall(retType) && !varTypeIsLong(retType)); + + int32_t value = static_cast(cnsNode->AsIntConCommon()->IconValue()); + uint32_t result = BitOperations::ReverseBits(static_cast(value)); + + cnsNode->AsIntConCommon()->SetIconValue(static_cast(result)); + resultNode = cnsNode; break; } - } - } - } - else if (otherNode->OperIsConst()) - { - if (oper != GT_NONE) - { - assert(op3 == nullptr); - if (varTypeIsMask(retType)) - { - if (varTypeIsMask(cnsNode)) - { - cnsNode->AsMskCon()->EvaluateBinaryInPlace(oper, isScalar, simdBaseType, simdSize, - otherNode->AsMskCon()); - } - else - { - cnsNode->AsVecCon()->EvaluateBinaryInPlace(oper, isScalar, simdBaseType, otherNode->AsVecCon()); - } - } - else - { -#if defined(TARGET_XARCH) - if ((oper == GT_LSH) || (oper == GT_RSH) || (oper == GT_RSZ)) + case NI_ArmBase_Arm64_ReverseElementBits: { - if (otherNode->TypeIs(TYP_SIMD16)) - { - if (!HWIntrinsicInfo::IsVariableShift(ni)) - { - // The xarch shift instructions support taking the shift amount as - // a simd16, in which case they take the shift amount from the lower - // 64-bits. - - int64_t shiftAmount = otherNode->AsVecCon()->GetElementIntegral(TYP_LONG, 0); - - if (static_cast(shiftAmount) >= - (static_cast(genTypeSize(simdBaseType)) * BITS_PER_BYTE)) - { - // Set to -1 to indicate an explicit overshift - shiftAmount = -1; - } + assert(varTypeIsLong(retType)); - // Ensure we broadcast to the right vector size - otherNode->gtType = retType; + int64_t value = cnsNode->AsIntConCommon()->IntegralValue(); + uint64_t result = BitOperations::ReverseBits(static_cast(value)); - otherNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, shiftAmount); - } - } + cnsNode->AsIntConCommon()->SetIntegralValue(static_cast(result)); + resultNode = cnsNode; + break; } -#endif // TARGET_XARCH +#endif // TARGET_ARM64 - if (otherNode->IsIntegralConst()) +#ifdef TARGET_XARCH + case NI_AVX2_TrailingZeroCount: { - int64_t scalar = otherNode->AsIntConCommon()->IntegralValue(); + assert(!varTypeIsSmall(retType) && !varTypeIsLong(retType)); + + int32_t value = static_cast(cnsNode->AsIntConCommon()->IconValue()); + uint32_t result = BitOperations::TrailingZeroCount(static_cast(value)); - otherNode = gtNewVconNode(retType); - otherNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, scalar); + cnsNode->AsIntConCommon()->SetIconValue(static_cast(result)); + resultNode = cnsNode; + break; } - cnsNode->AsVecCon()->EvaluateBinaryInPlace(oper, isScalar, simdBaseType, otherNode->AsVecCon()); - } - resultNode = cnsNode; - } - else - { - switch (ni) - { - case NI_Vector128_GetElement: -#ifdef TARGET_ARM64 - case NI_Vector64_GetElement: -#else - case NI_Vector256_GetElement: - case NI_Vector512_GetElement: -#endif + case NI_AVX2_X64_TrailingZeroCount: { - assert(op3 == nullptr); - uint32_t index = static_cast(otherNode->AsIntConCommon()->IconValue()); + assert(varTypeIsLong(retType)); - if (index >= GenTreeVecCon::ElementCount(simdSize, simdBaseType)) - { - // Nothing to fold for out of range indexes - break; - } + int64_t value = cnsNode->AsIntConCommon()->IntegralValue(); + uint32_t result = BitOperations::TrailingZeroCount(static_cast(value)); - var_types simdType = getSIMDTypeForSize(simdSize); + cnsNode->AsIntConCommon()->SetIntegralValue(static_cast(result)); + resultNode = cnsNode; + break; + } - if (varTypeIsFloating(retType)) - { - double result = cnsNode->AsVecCon()->GetElementFloating(simdBaseType, index); + case NI_SSE42_PopCount: + { + assert(!varTypeIsSmall(retType) && !varTypeIsLong(retType)); - resultNode = gtNewDconNode(result, retType); - } - else - { - assert(varTypeIsIntegral(retType)); - int64_t result = cnsNode->AsVecCon()->GetElementIntegral(simdBaseType, index); + int32_t value = static_cast(cnsNode->AsIntConCommon()->IconValue()); + uint32_t result = BitOperations::PopCount(static_cast(value)); - if (varTypeIsLong(retType)) - { - resultNode = gtNewLconNode(result); - } - else - { - resultNode = gtNewIconNode(static_cast(result), retType); - } - } + cnsNode->AsIntConCommon()->SetIconValue(static_cast(result)); + resultNode = cnsNode; break; } -#ifdef TARGET_ARM64 - case NI_AdvSimd_MultiplyByScalar: - case NI_AdvSimd_Arm64_MultiplyByScalar: + case NI_SSE42_X64_PopCount: { - assert(op3 == nullptr); - - // MultiplyByScalar takes a vector as the second operand but only utilizes element 0 - // We need to extract it and then functionally broadcast it up for the evaluation to - // work as expected. Ensuring we broadcast up to the target vector size. - - otherNode->gtType = retType; + assert(varTypeIsLong(retType)); - if (varTypeIsFloating(simdBaseType)) - { - double scalar = otherNode->AsVecCon()->ToScalarFloating(simdBaseType); - otherNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, scalar); - } - else - { - assert(varTypeIsIntegral(simdBaseType)); - int64_t scalar = otherNode->AsVecCon()->ToScalarIntegral(simdBaseType); - otherNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, scalar); - } + int64_t value = cnsNode->AsIntConCommon()->IntegralValue(); + uint32_t result = BitOperations::PopCount(static_cast(value)); - cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_MUL, isScalar, simdBaseType, otherNode->AsVecCon()); + cnsNode->AsIntConCommon()->SetIntegralValue(static_cast(result)); resultNode = cnsNode; break; } -#endif - case NI_Vector128_WithElement: -#ifdef TARGET_ARM64 - case NI_Vector64_WithElement: -#else - case NI_Vector256_WithElement: - case NI_Vector512_WithElement: -#endif + case NI_X86Base_BitScanForward: { - if (!op3->OperIsConst()) - { - break; - } + assert(!varTypeIsSmall(retType) && !varTypeIsLong(retType)); - uint32_t index = static_cast(op2->AsIntConCommon()->IconValue()); + int32_t value = static_cast(cnsNode->AsIntConCommon()->IconValue()); - if (index >= GenTreeVecCon::ElementCount(simdSize, simdBaseType)) + if (value == 0) { - // Nothing to fold for out of range indexes + // bsf is undefined for 0 break; } + uint32_t result = BitOperations::BitScanForward(static_cast(value)); - var_types simdType = getSIMDTypeForSize(simdSize); - - if (varTypeIsFloating(simdBaseType)) - { - double value = op3->AsDblCon()->DconValue(); - cnsNode->AsVecCon()->SetElementFloating(simdBaseType, index, value); - resultNode = cnsNode; - } - else - { - assert(varTypeIsIntegral(simdBaseType)); - int64_t value = op3->AsIntConCommon()->IntegralValue(); - cnsNode->AsVecCon()->SetElementIntegral(simdBaseType, index, value); - resultNode = cnsNode; - } - break; - } - -#ifdef TARGET_ARM64 - case NI_Vector128_WithLower: - { - assert(retType == TYP_SIMD16); - assert(cnsNode->TypeIs(TYP_SIMD16)); - assert(otherNode->TypeIs(TYP_SIMD8)); - cnsNode->AsVecCon()->gtSimd16Val.v64[0] = otherNode->AsVecCon()->gtSimd8Val; - + cnsNode->AsIntConCommon()->SetIconValue(static_cast(result)); resultNode = cnsNode; break; } -#else - case NI_Vector256_WithLower: + + case NI_X86Base_X64_BitScanForward: { - assert(retType == TYP_SIMD32); - assert(cnsNode->TypeIs(TYP_SIMD32)); - assert(otherNode->TypeIs(TYP_SIMD16)); - cnsNode->AsVecCon()->gtSimd32Val.v128[0] = otherNode->AsVecCon()->gtSimd16Val; + assert(varTypeIsLong(retType)); - resultNode = cnsNode; - break; - } + int64_t value = cnsNode->AsIntConCommon()->IntegralValue(); - case NI_Vector512_WithLower: - { - assert(retType == TYP_SIMD64); - assert(cnsNode->TypeIs(TYP_SIMD64)); - assert(otherNode->TypeIs(TYP_SIMD32)); - cnsNode->AsVecCon()->gtSimd64Val.v256[0] = otherNode->AsVecCon()->gtSimd32Val; + if (value == 0) + { + // bsf is undefined for 0 + break; + } + uint32_t result = BitOperations::BitScanForward(static_cast(value)); + cnsNode->AsIntConCommon()->SetIntegralValue(static_cast(result)); resultNode = cnsNode; break; } -#endif -#ifdef TARGET_ARM64 - case NI_Vector128_WithUpper: + case NI_X86Base_BitScanReverse: { - assert(retType == TYP_SIMD16); - assert(cnsNode->TypeIs(TYP_SIMD16)); - assert(otherNode->TypeIs(TYP_SIMD8)); - cnsNode->AsVecCon()->gtSimd16Val.v64[1] = otherNode->AsVecCon()->gtSimd8Val; + assert(!varTypeIsSmall(retType) && !varTypeIsLong(retType)); - resultNode = cnsNode; - break; - } -#else - case NI_Vector256_WithUpper: - { - assert(retType == TYP_SIMD32); - assert(cnsNode->TypeIs(TYP_SIMD32)); - assert(otherNode->TypeIs(TYP_SIMD16)); - cnsNode->AsVecCon()->gtSimd32Val.v128[1] = otherNode->AsVecCon()->gtSimd16Val; + int32_t value = static_cast(cnsNode->AsIntConCommon()->IconValue()); + + if (value == 0) + { + // bsr is undefined for 0 + break; + } + uint32_t result = BitOperations::BitScanReverse(static_cast(value)); + cnsNode->AsIntConCommon()->SetIconValue(static_cast(result)); resultNode = cnsNode; break; } - case NI_Vector512_WithUpper: + case NI_X86Base_X64_BitScanReverse: { - assert(retType == TYP_SIMD64); - assert(cnsNode->TypeIs(TYP_SIMD64)); - assert(otherNode->TypeIs(TYP_SIMD32)); - cnsNode->AsVecCon()->gtSimd64Val.v256[1] = otherNode->AsVecCon()->gtSimd32Val; + assert(varTypeIsLong(retType)); - resultNode = cnsNode; - break; - } -#endif + int64_t value = cnsNode->AsIntConCommon()->IntegralValue(); - case NI_Vector128_op_Equality: -#if defined(TARGET_ARM64) - case NI_Vector64_op_Equality: -#elif defined(TARGET_XARCH) - case NI_Vector256_op_Equality: - case NI_Vector512_op_Equality: -#endif // !TARGET_ARM64 && !TARGET_XARCH - { - cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_EQ, isScalar, simdBaseType, otherNode->AsVecCon()); - resultNode = gtNewIconNode(cnsNode->AsVecCon()->IsAllBitsSet() ? 1 : 0, retType); - break; - } + if (value == 0) + { + // bsr is undefined for 0 + break; + } + uint32_t result = BitOperations::BitScanReverse(static_cast(value)); - case NI_Vector128_op_Inequality: -#if defined(TARGET_ARM64) - case NI_Vector64_op_Inequality: -#elif defined(TARGET_XARCH) - case NI_Vector256_op_Inequality: - case NI_Vector512_op_Inequality: -#endif // !TARGET_ARM64 && !TARGET_XARCH - { - cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_NE, isScalar, simdBaseType, otherNode->AsVecCon()); - resultNode = gtNewIconNode(cnsNode->AsVecCon()->IsZero() ? 0 : 1, retType); + cnsNode->AsIntConCommon()->SetIntegralValue(static_cast(result)); + resultNode = cnsNode; break; } +#endif // TARGET_XARCH default: { @@ -33095,372 +32955,671 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) } } } - else if (op3 == nullptr) + else if (opCount == 2) { - if (isScalar) - { - // We don't support folding for scalars when only one input is constant - // because it means one value is computed and the remaining values are - // either zeroed or preserved based on the underlying target architecture - oper = GT_NONE; - } - - // For mask nodes in particular, the foldings below are done under the presumption - // that we only produce something like `AddMask(op1, op2)` if op1 and op2 are compatible - // masks. On xarch, for example, this means that it'd be adding 8, 16, 32, or 64-bits - // together with the same size. We wouldn't ever encounter something like an 8 and 16 bit - // masks being added. This ensures that we don't end up with a case where folding would - // cause a different result to be produced, such as because the remaining upper bits are - // no longer zeroed. - - switch (oper) + if (otherNode->OperIsConst()) { - case GT_ADD: + if (oper != GT_NONE) { if (varTypeIsMask(retType)) { - // Handle `x + 0 == x` and `0 + x == x` - if (cnsNode->IsMaskZero()) + if (varTypeIsMask(cnsNode)) { - resultNode = otherNode; + cnsNode->AsMskCon()->EvaluateBinaryInPlace(oper, isScalar, simdBaseType, simdSize, + otherNode->AsMskCon()); + } + else + { + cnsNode->AsVecCon()->EvaluateBinaryInPlace(oper, isScalar, simdBaseType, otherNode->AsVecCon()); } - break; } - - if (varTypeIsFloating(simdBaseType)) + else { - // Handle `x + NaN == NaN` and `NaN + x == NaN` - // This is safe for all floats since we do not fault for sNaN - - if (cnsNode->IsVectorNaN(simdBaseType)) +#if defined(TARGET_XARCH) + if ((oper == GT_LSH) || (oper == GT_RSH) || (oper == GT_RSZ)) { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; - } + if (otherNode->TypeIs(TYP_SIMD16)) + { + if (!HWIntrinsicInfo::IsVariableShift(ni)) + { + // The xarch shift instructions support taking the shift amount as + // a simd16, in which case they take the shift amount from the lower + // 64-bits. - // Handle `x + -0 == x` and `-0 + x == x` + int64_t shiftAmount = otherNode->AsVecCon()->GetElementIntegral(TYP_LONG, 0); - if (cnsNode->IsVectorNegativeZero(simdBaseType)) - { - resultNode = otherNode; - break; + if (static_cast(shiftAmount) >= + (static_cast(genTypeSize(simdBaseType)) * BITS_PER_BYTE)) + { + // Set to -1 to indicate an explicit overshift + shiftAmount = -1; + } + + // Ensure we broadcast to the right vector size + otherNode->gtType = retType; + + otherNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, shiftAmount); + } + } } +#endif // TARGET_XARCH - // We cannot handle `x + 0 == x` or `0 + x == x` since `-0 + 0 == 0` - break; - } + if (otherNode->IsIntegralConst()) + { + int64_t scalar = otherNode->AsIntConCommon()->IntegralValue(); - // Handle `x + 0 == x` and `0 + x == x` - if (cnsNode->IsVectorZero()) - { - resultNode = otherNode; + otherNode = gtNewVconNode(retType); + otherNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, scalar); + } + + cnsNode->AsVecCon()->EvaluateBinaryInPlace(oper, isScalar, simdBaseType, otherNode->AsVecCon()); } - break; + resultNode = cnsNode; } - - case GT_AND: + else { - if (varTypeIsMask(retType)) + switch (ni) { - // Handle `x & 0 == 0` and `0 & x == 0` - if (cnsNode->IsMaskZero()) + case NI_Vector128_GetElement: +#ifdef TARGET_ARM64 + case NI_Vector64_GetElement: +#else + case NI_Vector256_GetElement: + case NI_Vector512_GetElement: +#endif { - resultNode = otherNode; + uint32_t index = static_cast(otherNode->AsIntConCommon()->IconValue()); + + if (index >= GenTreeVecCon::ElementCount(simdSize, simdBaseType)) + { + // Nothing to fold for out of range indexes + break; + } + + var_types simdType = getSIMDTypeForSize(simdSize); + + if (varTypeIsFloating(retType)) + { + double result = cnsNode->AsVecCon()->GetElementFloating(simdBaseType, index); + + resultNode = gtNewDconNode(result, retType); + } + else + { + assert(varTypeIsIntegral(retType)); + int64_t result = cnsNode->AsVecCon()->GetElementIntegral(simdBaseType, index); + + if (varTypeIsLong(retType)) + { + resultNode = gtNewLconNode(result); + } + else + { + resultNode = gtNewIconNode(static_cast(result), retType); + } + } break; } - // Handle `x & AllBitsSet == x` and `AllBitsSet & x == x` - if (cnsNode->IsMaskAllBitsSet()) +#ifdef TARGET_ARM64 + case NI_AdvSimd_MultiplyByScalar: + case NI_AdvSimd_Arm64_MultiplyByScalar: { - resultNode = otherNode; + // MultiplyByScalar takes a vector as the second operand but only utilizes element 0 + // We need to extract it and then functionally broadcast it up for the evaluation to + // work as expected. Ensuring we broadcast up to the target vector size. + + otherNode->gtType = retType; + + if (varTypeIsFloating(simdBaseType)) + { + double scalar = otherNode->AsVecCon()->ToScalarFloating(simdBaseType); + otherNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, scalar); + } + else + { + assert(varTypeIsIntegral(simdBaseType)); + int64_t scalar = otherNode->AsVecCon()->ToScalarIntegral(simdBaseType); + otherNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, scalar); + } + + cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_MUL, isScalar, simdBaseType, + otherNode->AsVecCon()); + resultNode = cnsNode; + break; } - break; - } +#endif - // Handle `x & 0 == 0` and `0 & x == 0` - if (cnsNode->IsVectorZero()) - { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; - } +#ifdef TARGET_ARM64 + case NI_Vector128_WithLower: + { + assert(retType == TYP_SIMD16); + assert(cnsNode->TypeIs(TYP_SIMD16)); + assert(otherNode->TypeIs(TYP_SIMD8)); + cnsNode->AsVecCon()->gtSimd16Val.v64[0] = otherNode->AsVecCon()->gtSimd8Val; - // Handle `x & AllBitsSet == x` and `AllBitsSet & x == x` - if (cnsNode->IsVectorAllBitsSet()) - { - resultNode = otherNode; - } - break; - } + resultNode = cnsNode; + break; + } +#else + case NI_Vector256_WithLower: + { + assert(retType == TYP_SIMD32); + assert(cnsNode->TypeIs(TYP_SIMD32)); + assert(otherNode->TypeIs(TYP_SIMD16)); + cnsNode->AsVecCon()->gtSimd32Val.v128[0] = otherNode->AsVecCon()->gtSimd16Val; - case GT_DIV: - { - assert(!varTypeIsMask(retType)); + resultNode = cnsNode; + break; + } - if (varTypeIsFloating(simdBaseType)) - { - // Handle `x / NaN == NaN` and `NaN / x == NaN` - // This is safe for all floats since we do not fault for sNaN + case NI_Vector512_WithLower: + { + assert(retType == TYP_SIMD64); + assert(cnsNode->TypeIs(TYP_SIMD64)); + assert(otherNode->TypeIs(TYP_SIMD32)); + cnsNode->AsVecCon()->gtSimd64Val.v256[0] = otherNode->AsVecCon()->gtSimd32Val; + + resultNode = cnsNode; + break; + } +#endif + +#ifdef TARGET_ARM64 + case NI_Vector128_WithUpper: + { + assert(retType == TYP_SIMD16); + assert(cnsNode->TypeIs(TYP_SIMD16)); + assert(otherNode->TypeIs(TYP_SIMD8)); + cnsNode->AsVecCon()->gtSimd16Val.v64[1] = otherNode->AsVecCon()->gtSimd8Val; - if (cnsNode->IsVectorNaN(simdBaseType)) + resultNode = cnsNode; + break; + } +#else + case NI_Vector256_WithUpper: { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + assert(retType == TYP_SIMD32); + assert(cnsNode->TypeIs(TYP_SIMD32)); + assert(otherNode->TypeIs(TYP_SIMD16)); + cnsNode->AsVecCon()->gtSimd32Val.v128[1] = otherNode->AsVecCon()->gtSimd16Val; + + resultNode = cnsNode; break; } - } - // Handle `x / 1 == x`. - // This is safe for all floats since we do not fault for sNaN + case NI_Vector512_WithUpper: + { + assert(retType == TYP_SIMD64); + assert(cnsNode->TypeIs(TYP_SIMD64)); + assert(otherNode->TypeIs(TYP_SIMD32)); + cnsNode->AsVecCon()->gtSimd64Val.v256[1] = otherNode->AsVecCon()->gtSimd32Val; - if (cnsNode != op2) - { - break; - } + resultNode = cnsNode; + break; + } +#endif - if (!cnsNode->IsVectorBroadcast(simdBaseType)) - { - break; - } + case NI_Vector128_op_Equality: +#if defined(TARGET_ARM64) + case NI_Vector64_op_Equality: +#elif defined(TARGET_XARCH) + case NI_Vector256_op_Equality: + case NI_Vector512_op_Equality: +#endif // !TARGET_ARM64 && !TARGET_XARCH + { + cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_EQ, isScalar, simdBaseType, + otherNode->AsVecCon()); + resultNode = gtNewIconNode(cnsNode->AsVecCon()->IsAllBitsSet() ? 1 : 0, retType); + break; + } - if (cnsNode->AsVecCon()->IsScalarOne(simdBaseType)) - { - resultNode = otherNode; - } - break; - } + case NI_Vector128_op_Inequality: +#if defined(TARGET_ARM64) + case NI_Vector64_op_Inequality: +#elif defined(TARGET_XARCH) + case NI_Vector256_op_Inequality: + case NI_Vector512_op_Inequality: +#endif // !TARGET_ARM64 && !TARGET_XARCH + { + cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_NE, isScalar, simdBaseType, + otherNode->AsVecCon()); + resultNode = gtNewIconNode(cnsNode->AsVecCon()->IsZero() ? 0 : 1, retType); + break; + } - case GT_EQ: - { - if (varTypeIsFloating(simdBaseType)) - { - // Handle `(x == NaN) == false` and `(NaN == x) == false` for floating-point types - if (cnsNode->IsVectorNaN(simdBaseType)) + default: { - int64_t zero = 0; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); break; } } - break; + } + } + else + { + if (isScalar) + { + // We don't support folding for scalars when only one input is constant + // because it means one value is computed and the remaining values are + // either zeroed or preserved based on the underlying target architecture + oper = GT_NONE; } - case GT_GT: + // For mask nodes in particular, the foldings below are done under the presumption + // that we only produce something like `AddMask(op1, op2)` if op1 and op2 are compatible + // masks. On xarch, for example, this means that it'd be adding 8, 16, 32, or 64-bits + // together with the same size. We wouldn't ever encounter something like an 8 and 16 bit + // masks being added. This ensures that we don't end up with a case where folding would + // cause a different result to be produced, such as because the remaining upper bits are + // no longer zeroed. + + switch (oper) { - if (varTypeIsUnsigned(simdBaseType)) + case GT_ADD: { - // Handle `(0 > x) == false` for unsigned types. - if ((cnsNode == op1) && cnsNode->IsVectorZero()) + if (varTypeIsMask(retType)) { - int64_t zero = 0; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + // Handle `x + 0 == x` and `0 + x == x` + if (cnsNode->IsMaskZero()) + { + resultNode = otherNode; + } break; } - } - else if (varTypeIsFloating(simdBaseType)) - { - // Handle `(x > NaN) == false` and `(NaN > x) == false` for floating-point types - if (cnsNode->IsVectorNaN(simdBaseType)) + + if (varTypeIsFloating(simdBaseType)) { - int64_t zero = 0; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + // Handle `x + NaN == NaN` and `NaN + x == NaN` + // This is safe for all floats since we do not fault for sNaN + + if (cnsNode->IsVectorNaN(simdBaseType)) + { + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + + // Handle `x + -0 == x` and `-0 + x == x` + + if (cnsNode->IsVectorNegativeZero(simdBaseType)) + { + resultNode = otherNode; + break; + } + + // We cannot handle `x + 0 == x` or `0 + x == x` since `-0 + 0 == 0` break; } + + // Handle `x + 0 == x` and `0 + x == x` + if (cnsNode->IsVectorZero()) + { + resultNode = otherNode; + } + break; } - break; - } - case GT_GE: - { - if (varTypeIsUnsigned(simdBaseType)) + case GT_AND: { - // Handle `x >= 0 == true` for unsigned types. - if ((cnsNode == op2) && cnsNode->IsVectorZero()) + if (varTypeIsMask(retType)) { - int64_t allBitsSet = -1; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, allBitsSet); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + // Handle `x & 0 == 0` and `0 & x == 0` + if (cnsNode->IsMaskZero()) + { + resultNode = otherNode; + break; + } + + // Handle `x & AllBitsSet == x` and `AllBitsSet & x == x` + if (cnsNode->IsMaskAllBitsSet()) + { + resultNode = otherNode; + } break; } - } - else if (varTypeIsFloating(simdBaseType)) - { - // Handle `(x >= NaN) == false` and `(NaN >= x) == false` for floating-point types - if (cnsNode->IsVectorNaN(simdBaseType)) + + // Handle `x & 0 == 0` and `0 & x == 0` + if (cnsNode->IsVectorZero()) { - int64_t zero = 0; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); break; } + + // Handle `x & AllBitsSet == x` and `AllBitsSet & x == x` + if (cnsNode->IsVectorAllBitsSet()) + { + resultNode = otherNode; + } + break; } - break; - } - case GT_LT: - { - if (varTypeIsUnsigned(simdBaseType)) + case GT_DIV: { - // Handle `x < 0 == false` for unsigned types. - if ((cnsNode == op2) && cnsNode->IsVectorZero()) + assert(!varTypeIsMask(retType)); + + if (varTypeIsFloating(simdBaseType)) + { + // Handle `x / NaN == NaN` and `NaN / x == NaN` + // This is safe for all floats since we do not fault for sNaN + + if (cnsNode->IsVectorNaN(simdBaseType)) + { + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + } + + // Handle `x / 1 == x`. + // This is safe for all floats since we do not fault for sNaN + + if (cnsNode != op2) + { + break; + } + + if (!cnsNode->IsVectorBroadcast(simdBaseType)) { - int64_t zero = 0; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); break; } + + if (cnsNode->AsVecCon()->IsScalarOne(simdBaseType)) + { + resultNode = otherNode; + } + break; } - else if (varTypeIsFloating(simdBaseType)) + + case GT_EQ: { - // Handle `(x < NaN) == false` and `(NaN < x) == false` for floating-point types - if (cnsNode->IsVectorNaN(simdBaseType)) + if (varTypeIsFloating(simdBaseType)) { - int64_t zero = 0; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; + // Handle `(x == NaN) == false` and `(NaN == x) == false` for floating-point types + if (cnsNode->IsVectorNaN(simdBaseType)) + { + int64_t zero = 0; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + } + else if (otherNode->OperIsHWIntrinsic()) + { + GenTreeHWIntrinsic* otherIntrinsic = otherNode->AsHWIntrinsic(); + NamedIntrinsic otherIntrinsicId = otherIntrinsic->GetHWIntrinsicId(); + + if (HWIntrinsicInfo::ReturnsPerElementMask(otherIntrinsicId) && + (genTypeSize(simdBaseType) == genTypeSize(otherIntrinsic->GetSimdBaseType()))) + { + // This optimization is only safe if we know the other node produces + // AllBitsSet or Zero per element and if the outer comparison is the + // same size as what the other node produces for its mask + + // Handle `(Mask == AllBitsSet) == Mask` and `(AllBitsSet == Mask) == Mask` for integrals + if (cnsNode->IsVectorAllBitsSet()) + { + resultNode = otherNode; + break; + } + } } + break; } - break; - } - case GT_LE: - { - if (varTypeIsUnsigned(simdBaseType)) + case GT_GT: { - // Handle `0 <= x == true` for unsigned types. - if ((cnsNode == op1) && cnsNode->IsVectorZero()) + if (varTypeIsUnsigned(simdBaseType)) { - int64_t allBitsSet = -1; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, allBitsSet); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; + // Handle `(0 > x) == false` for unsigned types. + if ((cnsNode == op1) && cnsNode->IsVectorZero()) + { + int64_t zero = 0; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } } + else if (varTypeIsFloating(simdBaseType)) + { + // Handle `(x > NaN) == false` and `(NaN > x) == false` for floating-point types + if (cnsNode->IsVectorNaN(simdBaseType)) + { + int64_t zero = 0; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + } + break; } - else if (varTypeIsFloating(simdBaseType)) + + case GT_GE: { - // Handle `(x <= NaN) == false` and `(NaN <= x) == false` for floating-point types - if (cnsNode->IsVectorNaN(simdBaseType)) + if (varTypeIsUnsigned(simdBaseType)) { - int64_t zero = 0; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; + // Handle `x >= 0 == true` for unsigned types. + if ((cnsNode == op2) && cnsNode->IsVectorZero()) + { + int64_t allBitsSet = -1; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, allBitsSet); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + } + else if (varTypeIsFloating(simdBaseType)) + { + // Handle `(x >= NaN) == false` and `(NaN >= x) == false` for floating-point types + if (cnsNode->IsVectorNaN(simdBaseType)) + { + int64_t zero = 0; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } } + break; } - break; - } - case GT_MUL: - { - assert(!varTypeIsMask(retType)); + case GT_LT: + { + if (varTypeIsUnsigned(simdBaseType)) + { + // Handle `x < 0 == false` for unsigned types. + if ((cnsNode == op2) && cnsNode->IsVectorZero()) + { + int64_t zero = 0; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + } + else if (varTypeIsFloating(simdBaseType)) + { + // Handle `(x < NaN) == false` and `(NaN < x) == false` for floating-point types + if (cnsNode->IsVectorNaN(simdBaseType)) + { + int64_t zero = 0; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + } + break; + } - if (!varTypeIsFloating(simdBaseType)) + case GT_LE: { - // Handle `x * 0 == 0` and `0 * x == 0` - // Not safe for floating-point when x == -0.0, NaN, +Inf, -Inf - if (cnsNode->IsVectorZero()) + if (varTypeIsUnsigned(simdBaseType)) { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; + // Handle `0 <= x == true` for unsigned types. + if ((cnsNode == op1) && cnsNode->IsVectorZero()) + { + int64_t allBitsSet = -1; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, allBitsSet); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + } + else if (varTypeIsFloating(simdBaseType)) + { + // Handle `(x <= NaN) == false` and `(NaN <= x) == false` for floating-point types + if (cnsNode->IsVectorNaN(simdBaseType)) + { + int64_t zero = 0; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, zero); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } } + break; } - else + + case GT_MUL: { - // Handle `x * NaN == NaN` and `NaN * x == NaN` - // This is safe for all floats since we do not fault for sNaN + assert(!varTypeIsMask(retType)); - if (cnsNode->IsVectorNaN(simdBaseType)) + if (!varTypeIsFloating(simdBaseType)) { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; + // Handle `x * 0 == 0` and `0 * x == 0` + // Not safe for floating-point when x == -0.0, NaN, +Inf, -Inf + if (cnsNode->IsVectorZero()) + { + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } } + else + { + // Handle `x * NaN == NaN` and `NaN * x == NaN` + // This is safe for all floats since we do not fault for sNaN - // We cannot handle `x * 0 == 0` or ` 0 * x == 0` since `-0 * 0 == -0` - // We cannot handle `x * -0 == -0` or `-0 * x == -0` since `-0 * -0 == 0` - } + if (cnsNode->IsVectorNaN(simdBaseType)) + { + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } - // Handle `x * 1 == x` and `1 * x == x` - // This is safe for all floats since we do not fault for sNaN + // We cannot handle `x * 0 == 0` or ` 0 * x == 0` since `-0 * 0 == -0` + // We cannot handle `x * -0 == -0` or `-0 * x == -0` since `-0 * -0 == 0` + } - if (!cnsNode->IsVectorBroadcast(simdBaseType)) - { + // Handle `x * 1 == x` and `1 * x == x` + // This is safe for all floats since we do not fault for sNaN + + if (!cnsNode->IsVectorBroadcast(simdBaseType)) + { + break; + } + + if (cnsNode->AsVecCon()->IsScalarOne(simdBaseType)) + { + resultNode = otherNode; + } break; } - if (cnsNode->AsVecCon()->IsScalarOne(simdBaseType)) + case GT_NE: { - resultNode = otherNode; + if (varTypeIsFloating(simdBaseType)) + { + // Handle `(x != NaN) == true` and `(NaN != x) == true` for floating-point types + if (cnsNode->IsVectorNaN(simdBaseType)) + { + int64_t allBitsSet = -1; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, allBitsSet); + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + } + else if (otherNode->OperIsHWIntrinsic()) + { + GenTreeHWIntrinsic* otherIntrinsic = otherNode->AsHWIntrinsic(); + NamedIntrinsic otherIntrinsicId = otherIntrinsic->GetHWIntrinsicId(); + + if (HWIntrinsicInfo::ReturnsPerElementMask(otherIntrinsicId) && + (genTypeSize(simdBaseType) == genTypeSize(otherIntrinsic->GetSimdBaseType()))) + { + // This optimization is only safe if we know the other node produces + // AllBitsSet or Zero per element and if the outer comparison is the + // same size as what the other node produces for its mask + + // Handle `(Mask != Zero) == Mask` and `(Zero != Mask) == Mask` for integral types + if (cnsNode->IsVectorZero()) + { + resultNode = otherNode; + break; + } + } + } + break; } - break; - } - case GT_NE: - { - if (varTypeIsFloating(simdBaseType)) + case GT_OR: { - // Handle `(x != NaN) == true` and `(NaN != x) == true` for floating-point types - if (cnsNode->IsVectorNaN(simdBaseType)) + if (varTypeIsMask(retType)) { - int64_t allBitsSet = -1; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(TYP_LONG, allBitsSet); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + // Handle `x | 0 == x` and `0 | x == x` + if (cnsNode->IsMaskZero()) + { + resultNode = otherNode; + break; + } + + // Handle `x | AllBitsSet == AllBitsSet` and `AllBitsSet | x == AllBitsSet` + if (cnsNode->IsMaskAllBitsSet()) + { + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + } break; } - } - break; - } - case GT_OR: - { - if (varTypeIsMask(retType)) - { // Handle `x | 0 == x` and `0 | x == x` - if (cnsNode->IsMaskZero()) + if (cnsNode->IsVectorZero()) { resultNode = otherNode; break; } // Handle `x | AllBitsSet == AllBitsSet` and `AllBitsSet | x == AllBitsSet` - if (cnsNode->IsMaskAllBitsSet()) + if (cnsNode->IsVectorAllBitsSet()) { resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); } break; } - // Handle `x | 0 == x` and `0 | x == x` - if (cnsNode->IsVectorZero()) - { - resultNode = otherNode; - break; - } - - // Handle `x | AllBitsSet == AllBitsSet` and `AllBitsSet | x == AllBitsSet` - if (cnsNode->IsVectorAllBitsSet()) + case GT_ROL: + case GT_ROR: + case GT_LSH: + case GT_RSH: + case GT_RSZ: { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - } - break; - } + // Handle `x rol 0 == x` and `0 rol x == 0` + // Handle `x ror 0 == x` and `0 ror x == 0` + // Handle `x << 0 == x` and `0 << x == 0` + // Handle `x >> 0 == x` and `0 >> x == 0` + // Handle `x >>> 0 == x` and `0 >>> x == 0` - case GT_ROL: - case GT_ROR: - case GT_LSH: - case GT_RSH: - case GT_RSZ: - { - // Handle `x rol 0 == x` and `0 rol x == 0` - // Handle `x ror 0 == x` and `0 ror x == 0` - // Handle `x << 0 == x` and `0 << x == 0` - // Handle `x >> 0 == x` and `0 >> x == 0` - // Handle `x >>> 0 == x` and `0 >>> x == 0` + if (varTypeIsMask(retType)) + { + if (cnsNode->IsMaskZero()) + { + if (cnsNode == op2) + { + resultNode = otherNode; + } + else + { + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + } + } + else if (cnsNode->IsIntegralConst(0)) + { + assert(cnsNode == op2); + resultNode = otherNode; + } + break; + } - if (varTypeIsMask(retType)) - { - if (cnsNode->IsMaskZero()) + if (cnsNode->IsVectorZero()) { if (cnsNode == op2) { @@ -33479,207 +33638,190 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) break; } - if (cnsNode->IsVectorZero()) + case GT_SUB: { - if (cnsNode == op2) + assert(!varTypeIsMask(retType)); + + if (varTypeIsFloating(simdBaseType)) { - resultNode = otherNode; + // Handle `x - NaN == NaN` and `NaN - x == NaN` + // This is safe for all floats since we do not fault for sNaN + + if (cnsNode->IsVectorNaN(simdBaseType)) + { + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + + // We cannot handle `x - -0 == x` since `-0 - -0 == 0` } - else + + // Handle `x - 0 == x` + if ((op2 == cnsNode) && cnsNode->IsVectorZero()) { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + resultNode = otherNode; } + break; } - else if (cnsNode->IsIntegralConst(0)) - { - assert(cnsNode == op2); - resultNode = otherNode; - } - break; - } - - case GT_SUB: - { - assert(!varTypeIsMask(retType)); - if (varTypeIsFloating(simdBaseType)) + case GT_XOR: { - // Handle `x - NaN == NaN` and `NaN - x == NaN` - // This is safe for all floats since we do not fault for sNaN - - if (cnsNode->IsVectorNaN(simdBaseType)) + if (varTypeIsMask(retType)) { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + // Handle `x ^ 0 == x` and `0 ^ x == x` + if (cnsNode->IsMaskZero()) + { + resultNode = otherNode; + } break; } - // We cannot handle `x - -0 == x` since `-0 - -0 == 0` - } - - // Handle `x - 0 == x` - if ((op2 == cnsNode) && cnsNode->IsVectorZero()) - { - resultNode = otherNode; - } - break; - } - - case GT_XOR: - { - if (varTypeIsMask(retType)) - { // Handle `x ^ 0 == x` and `0 ^ x == x` - if (cnsNode->IsMaskZero()) + if (cnsNode->IsVectorZero()) { resultNode = otherNode; } break; } - // Handle `x ^ 0 == x` and `0 ^ x == x` - if (cnsNode->IsVectorZero()) + default: { - resultNode = otherNode; + break; } - break; } - default: + switch (ni) { - break; - } - } - - switch (ni) - { #ifdef TARGET_ARM64 - case NI_Sve_ConvertVectorToMask: - resultNode = gtFoldExprConvertVecCnsToMask(tree, cnsNode->AsVecCon()); - break; + case NI_Sve_ConvertVectorToMask: + resultNode = gtFoldExprConvertVecCnsToMask(tree, cnsNode->AsVecCon()); + break; - case NI_AdvSimd_MultiplyByScalar: - case NI_AdvSimd_Arm64_MultiplyByScalar: - { - if (!varTypeIsFloating(simdBaseType)) + case NI_AdvSimd_MultiplyByScalar: + case NI_AdvSimd_Arm64_MultiplyByScalar: { - // Handle `x * 0 == 0` and `0 * x == 0` - // Not safe for floating-point when x == -0.0, NaN, +Inf, -Inf - if (cnsNode == op1) + if (!varTypeIsFloating(simdBaseType)) { - if (cnsNode->IsVectorZero()) + // Handle `x * 0 == 0` and `0 * x == 0` + // Not safe for floating-point when x == -0.0, NaN, +Inf, -Inf + if (cnsNode == op1) { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; + if (cnsNode->IsVectorZero()) + { + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } } - } - else - { - assert(cnsNode == op2); - - if (cnsNode->AsVecCon()->IsScalarZero(simdBaseType)) + else { - int64_t val = 0; + assert(cnsNode == op2); - cnsNode->gtType = retType; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, val); + if (cnsNode->AsVecCon()->IsScalarZero(simdBaseType)) + { + int64_t val = 0; - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; - } - } - } - else - { - // Handle `x * NaN == NaN` and `NaN * x == NaN` - // This is safe for all floats since we do not fault for sNaN + cnsNode->gtType = retType; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, val); - if (cnsNode == op1) - { - if (cnsNode->IsVectorNaN(simdBaseType)) - { - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } } } else { - assert(cnsNode == op2); - double val = cnsNode->AsVecCon()->GetElementFloating(simdBaseType, 0); + // Handle `x * NaN == NaN` and `NaN * x == NaN` + // This is safe for all floats since we do not fault for sNaN - if (FloatingPointUtils::isNaN(val)) + if (cnsNode == op1) + { + if (cnsNode->IsVectorNaN(simdBaseType)) + { + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } + } + else { - cnsNode->gtType = retType; - cnsNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, val); + assert(cnsNode == op2); + double val = cnsNode->AsVecCon()->GetElementFloating(simdBaseType, 0); - resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); - break; + if (FloatingPointUtils::isNaN(val)) + { + cnsNode->gtType = retType; + cnsNode->AsVecCon()->EvaluateBroadcastInPlace(simdBaseType, val); + + resultNode = gtWrapWithSideEffects(cnsNode, otherNode, GTF_ALL_EFFECT); + break; + } } - } - // We cannot handle `x * 0 == 0` or ` 0 * x == 0` since `-0 * 0 == -0` - // We cannot handle `x * -0 == -0` or `-0 * x == -0` since `-0 * -0 == 0` - } + // We cannot handle `x * 0 == 0` or ` 0 * x == 0` since `-0 * 0 == -0` + // We cannot handle `x * -0 == -0` or `-0 * x == -0` since `-0 * -0 == 0` + } - // Handle x * 1 => x, but only if the scalar RHS is <1, ...>. - if ((cnsNode == op2) && cnsNode->AsVecCon()->IsScalarOne(simdBaseType)) - { - resultNode = otherNode; + // Handle x * 1 => x, but only if the scalar RHS is <1, ...>. + if ((cnsNode == op2) && cnsNode->AsVecCon()->IsScalarOne(simdBaseType)) + { + resultNode = otherNode; + } + break; } - break; - } #endif - case NI_Vector128_op_Equality: + case NI_Vector128_op_Equality: #if defined(TARGET_ARM64) - case NI_Vector64_op_Equality: + case NI_Vector64_op_Equality: #elif defined(TARGET_XARCH) - case NI_Vector256_op_Equality: - case NI_Vector512_op_Equality: + case NI_Vector256_op_Equality: + case NI_Vector512_op_Equality: #endif // !TARGET_ARM64 && !TARGET_XARCH - { - if (varTypeIsFloating(simdBaseType)) { - // Handle `(x == NaN) == false` and `(NaN == x) == false` for floating-point types - if (cnsNode->IsVectorNaN(simdBaseType)) + if (varTypeIsFloating(simdBaseType)) { - resultNode = gtNewIconNode(0, retType); - resultNode = gtWrapWithSideEffects(resultNode, otherNode, GTF_ALL_EFFECT); - break; + // Handle `(x == NaN) == false` and `(NaN == x) == false` for floating-point types + if (cnsNode->IsVectorNaN(simdBaseType)) + { + resultNode = gtNewIconNode(0, retType); + resultNode = gtWrapWithSideEffects(resultNode, otherNode, GTF_ALL_EFFECT); + break; + } } + break; } - break; - } - case NI_Vector128_op_Inequality: + case NI_Vector128_op_Inequality: #if defined(TARGET_ARM64) - case NI_Vector64_op_Inequality: + case NI_Vector64_op_Inequality: #elif defined(TARGET_XARCH) - case NI_Vector256_op_Inequality: - case NI_Vector512_op_Inequality: + case NI_Vector256_op_Inequality: + case NI_Vector512_op_Inequality: #endif // !TARGET_ARM64 && !TARGET_XARCH - { - if (varTypeIsFloating(simdBaseType)) { - // Handle `(x != NaN) == true` and `(NaN != x) == true` for floating-point types - if (cnsNode->IsVectorNaN(simdBaseType)) + if (varTypeIsFloating(simdBaseType)) { - resultNode = gtNewIconNode(1, retType); - resultNode = gtWrapWithSideEffects(resultNode, otherNode, GTF_ALL_EFFECT); - break; + // Handle `(x != NaN) == true` and `(NaN != x) == true` for floating-point types + if (cnsNode->IsVectorNaN(simdBaseType)) + { + resultNode = gtNewIconNode(1, retType); + resultNode = gtWrapWithSideEffects(resultNode, otherNode, GTF_ALL_EFFECT); + break; + } } + break; } - break; - } - default: - { - break; + default: + { + break; + } } } } - - if (op3 != nullptr) + else { + assert(opCount == 3); + switch (ni) { #if defined(TARGET_XARCH) @@ -33792,6 +33934,96 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) } #endif // TARGET_ARM64 + case NI_Vector128_WithElement: +#ifdef TARGET_ARM64 + case NI_Vector64_WithElement: +#else + case NI_Vector256_WithElement: + case NI_Vector512_WithElement: +#endif + { + if ((cnsNode != op1) || !op3->OperIsConst()) + { + break; + } + + uint32_t index = static_cast(op2->AsIntConCommon()->IconValue()); + + if (index >= GenTreeVecCon::ElementCount(simdSize, simdBaseType)) + { + // Nothing to fold for out of range indexes + break; + } + + var_types simdType = getSIMDTypeForSize(simdSize); + + if (varTypeIsFloating(simdBaseType)) + { + double value = op3->AsDblCon()->DconValue(); + cnsNode->AsVecCon()->SetElementFloating(simdBaseType, index, value); + resultNode = cnsNode; + } + else + { + assert(varTypeIsIntegral(simdBaseType)); + int64_t value = op3->AsIntConCommon()->IntegralValue(); + cnsNode->AsVecCon()->SetElementIntegral(simdBaseType, index, value); + resultNode = cnsNode; + } + break; + } + +#if defined(TARGET_XARCH) + case NI_AVX_Compare: + case NI_AVX_CompareScalar: + case NI_AVX512_CompareMask: + { + if (!op3->IsCnsIntOrI()) + { + break; + } + + FloatComparisonMode mode = static_cast(op3->AsIntConCommon()->IntegralValue()); + NamedIntrinsic id = ni; + + switch (mode) + { + case FloatComparisonMode::OrderedFalseNonSignaling: + case FloatComparisonMode::OrderedFalseSignaling: + { + resultNode = gtNewZeroConNode(retType); + resultNode = gtWrapWithSideEffects(resultNode, tree, GTF_ALL_EFFECT); + break; + } + + case FloatComparisonMode::UnorderedTrueNonSignaling: + case FloatComparisonMode::UnorderedTrueSignaling: + { + resultNode = gtNewAllBitsSetConNode(retType); + resultNode = gtWrapWithSideEffects(resultNode, tree, GTF_ALL_EFFECT); + break; + } + + default: + { + id = HWIntrinsicInfo::lookupIdForFloatComparisonMode(ni, mode, simdBaseType, simdSize); + break; + } + } + + if (id == ni) + { + break; + } + + tree->ResetHWIntrinsicId(id, op1, op2); + DEBUG_DESTROY_NODE(op3); + + tree->SetMorphed(this); + return gtFoldExprHWIntrinsic(tree); + } +#endif // TARGET_XARCH + default: { break; diff --git a/src/runtime/src/coreclr/jit/gentree.h b/src/runtime/src/coreclr/jit/gentree.h index 26a09c44963..33690a76ef9 100644 --- a/src/runtime/src/coreclr/jit/gentree.h +++ b/src/runtime/src/coreclr/jit/gentree.h @@ -4328,10 +4328,21 @@ enum class ExecutionContextHandling AsyncSaveAndRestore, }; +enum class ContinuationContextHandling +{ + // No special handling of SynchronizationContext/TaskScheduler is required. + None, + // Continue on SynchronizationContext/TaskScheduler + ContinueOnCapturedContext, + // Continue on thread pool thread + ContinueOnThreadPool, +}; + // Additional async call info. struct AsyncCallInfo { - ExecutionContextHandling ExecutionContextHandling = ExecutionContextHandling::None; + ExecutionContextHandling ExecutionContextHandling = ExecutionContextHandling::None; + ContinuationContextHandling ContinuationContextHandling = ContinuationContextHandling::None; }; // Return type descriptor of a GT_CALL node. diff --git a/src/runtime/src/coreclr/jit/gtlist.h b/src/runtime/src/coreclr/jit/gtlist.h index 0ec112781c0..93fb4dfd358 100644 --- a/src/runtime/src/coreclr/jit/gtlist.h +++ b/src/runtime/src/coreclr/jit/gtlist.h @@ -280,19 +280,19 @@ GTNODE(SELECT_NEGCC , GenTreeOpCC ,0,0,GTK_BINOP|DBK_NOTHIR) #ifdef TARGET_RISCV64 // Maps to riscv64 sh1add instruction. Computes result = op2 + (op1 << 1). GTNODE(SH1ADD , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) -// Maps to riscv64 sh1add.uw instruction. Computes result = op2 + zext(op1[31..0] << 1). +// Maps to riscv64 sh1add.uw instruction. Computes result = op2 + (zext(op1[31..0]) << 1). GTNODE(SH1ADD_UW , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // Maps to riscv64 sh2add instruction. Computes result = op2 + (op1 << 2). GTNODE(SH2ADD , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) -// Maps to riscv64 sh2add.uw instruction. Computes result = op2 + zext(op1[31..0] << 2). +// Maps to riscv64 sh2add.uw instruction. Computes result = op2 + (zext(op1[31..0]) << 2). GTNODE(SH2ADD_UW , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // Maps to riscv64 sh3add instruction. Computes result = op2 + (op1 << 3). GTNODE(SH3ADD , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) -// Maps to riscv64 sh3add.uw instruction. Computes result = op2 + zext(op1[31..0] << 3). +// Maps to riscv64 sh3add.uw instruction. Computes result = op2 + (zext(op1[31..0]) << 3). GTNODE(SH3ADD_UW , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // Maps to riscv64 add.uw instruction. Computes result = op2 + zext(op1[31..0]). GTNODE(ADD_UW , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) -// Maps to riscv64 slli.uw instruction. Computes result = zext(op1[31..0] << imm). +// Maps to riscv64 slli.uw instruction. Computes result = zext(op1[31..0]) << imm. GTNODE(SLLI_UW , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) #endif diff --git a/src/runtime/src/coreclr/jit/hwintrinsicarm64.cpp b/src/runtime/src/coreclr/jit/hwintrinsicarm64.cpp index f636ca7c0b0..6631da478c9 100644 --- a/src/runtime/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/runtime/src/coreclr/jit/hwintrinsicarm64.cpp @@ -3405,6 +3405,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Sve2_AddWideningEven: + case NI_Sve2_AddWideningOdd: case NI_Sve2_SubtractWideningEven: case NI_Sve2_SubtractWideningOdd: { diff --git a/src/runtime/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/runtime/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 964a67283a1..6f825a38c45 100644 --- a/src/runtime/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/runtime/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -670,38 +670,6 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // Perform the actual "predicated" operation so that `embMaskOp1Reg` is the first operand.. switch (intrinEmbMask.id) { - case NI_Sve_LoadVectorByteNonFaultingZeroExtendToInt16: - case NI_Sve_LoadVectorByteNonFaultingZeroExtendToInt32: - case NI_Sve_LoadVectorByteNonFaultingZeroExtendToInt64: - case NI_Sve_LoadVectorByteNonFaultingZeroExtendToUInt16: - case NI_Sve_LoadVectorByteNonFaultingZeroExtendToUInt32: - case NI_Sve_LoadVectorByteNonFaultingZeroExtendToUInt64: - case NI_Sve_LoadVectorInt16NonFaultingSignExtendToInt32: - case NI_Sve_LoadVectorInt16NonFaultingSignExtendToInt64: - case NI_Sve_LoadVectorInt16NonFaultingSignExtendToUInt32: - case NI_Sve_LoadVectorInt16NonFaultingSignExtendToUInt64: - case NI_Sve_LoadVectorInt32NonFaultingSignExtendToInt64: - case NI_Sve_LoadVectorInt32NonFaultingSignExtendToUInt64: - case NI_Sve_LoadVectorNonFaulting: - case NI_Sve_LoadVectorSByteNonFaultingSignExtendToInt16: - case NI_Sve_LoadVectorSByteNonFaultingSignExtendToInt32: - case NI_Sve_LoadVectorSByteNonFaultingSignExtendToInt64: - case NI_Sve_LoadVectorSByteNonFaultingSignExtendToUInt16: - case NI_Sve_LoadVectorSByteNonFaultingSignExtendToUInt32: - case NI_Sve_LoadVectorSByteNonFaultingSignExtendToUInt64: - case NI_Sve_LoadVectorUInt16NonFaultingZeroExtendToInt32: - case NI_Sve_LoadVectorUInt16NonFaultingZeroExtendToInt64: - case NI_Sve_LoadVectorUInt16NonFaultingZeroExtendToUInt32: - case NI_Sve_LoadVectorUInt16NonFaultingZeroExtendToUInt64: - case NI_Sve_LoadVectorUInt32NonFaultingZeroExtendToInt64: - case NI_Sve_LoadVectorUInt32NonFaultingZeroExtendToUInt64: - { - - GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp1Reg, - opt); - break; - } - case NI_Sve_And_Predicates: case NI_Sve_BitwiseClear_Predicates: case NI_Sve_Or_Predicates: @@ -2175,14 +2143,14 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case NI_Sve_LoadVectorUInt32NonFaultingZeroExtendToInt64: case NI_Sve_LoadVectorUInt32NonFaultingZeroExtendToUInt64: { - if (intrin.numOperands == 2) + if (intrin.numOperands == 3) { - // We have extra argument which means there is a "use" of FFR here. Restore it back in FFR - // register. - assert(op2Reg != REG_NA); - GetEmitter()->emitIns_R(INS_sve_wrffr, emitSize, op2Reg, opt); + // We have extra argument which means there is a "use" of FFR here. Restore it back in FFR register. + assert(op3Reg != REG_NA); + GetEmitter()->emitIns_R(INS_sve_wrffr, emitSize, op3Reg, opt); } - GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg); + + GetEmitter()->emitIns_R_R_R_I(ins, emitSize, targetReg, op1Reg, op2Reg, 0, opt); break; } @@ -2719,6 +2687,31 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitInsSve_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); break; + case NI_Sve2_AddWideningEven: + { + var_types returnType = node->AsHWIntrinsic()->GetSimdBaseType(); + var_types op1Type = node->AsHWIntrinsic()->GetAuxiliaryType(); + if (returnType != op1Type) + { + ins = varTypeIsUnsigned(intrin.baseType) ? INS_sve_uaddlb : INS_sve_saddlb; + } + + GetEmitter()->emitInsSve_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); + break; + } + + case NI_Sve2_AddWideningOdd: + { + var_types returnType = node->AsHWIntrinsic()->GetSimdBaseType(); + var_types op1Type = node->AsHWIntrinsic()->GetAuxiliaryType(); + if (returnType != op1Type) + { + ins = varTypeIsUnsigned(intrin.baseType) ? INS_sve_uaddlt : INS_sve_saddlt; + } + GetEmitter()->emitInsSve_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); + break; + } + case NI_Sve2_BitwiseClearXor: case NI_Sve2_Xor: if (targetReg != op1Reg) diff --git a/src/runtime/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/runtime/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index 361e9ae8eee..9402f64ffcf 100644 --- a/src/runtime/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/runtime/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -2056,6 +2056,14 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) } baseReg = (isEBPbased) ? REG_EBP : REG_ESP; } + else if (op1->IsCnsVec()) + { + CORINFO_FIELD_HANDLE hnd = + GetEmitter()->emitSimdConst(&op1->AsVecCon()->gtSimdVal, emitTypeSize(op1)); + + baseReg = internalRegisters.GetSingle(node); + GetEmitter()->emitIns_R_C(INS_lea, emitTypeSize(TYP_I_IMPL), baseReg, hnd, 0, INS_OPTS_NONE); + } else { // Require GT_IND addr to be not contained. diff --git a/src/runtime/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/runtime/src/coreclr/jit/hwintrinsiclistarm64sve.h index 4de5245fafa..e122c847bb5 100644 --- a/src/runtime/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/runtime/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -154,12 +154,12 @@ HARDWARE_INTRINSIC(Sve, Load3xVectorAndUnzip, HARDWARE_INTRINSIC(Sve, Load4xVectorAndUnzip, -1, 2, {INS_sve_ld4b, INS_sve_ld4b, INS_sve_ld4h, INS_sve_ld4h, INS_sve_ld4w, INS_sve_ld4w, INS_sve_ld4d, INS_sve_ld4d, INS_sve_ld4w, INS_sve_ld4d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_MultiReg|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_NeedsConsecutiveRegisters|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Sve, LoadVector, -1, 2, {INS_sve_ld1b, INS_sve_ld1b, INS_sve_ld1h, INS_sve_ld1h, INS_sve_ld1w, INS_sve_ld1w, INS_sve_ld1d, INS_sve_ld1d, INS_sve_ld1w, INS_sve_ld1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVector128AndReplicateToVector, -1, 2, {INS_sve_ld1rqb, INS_sve_ld1rqb, INS_sve_ld1rqh, INS_sve_ld1rqh, INS_sve_ld1rqw, INS_sve_ld1rqw, INS_sve_ld1rqd, INS_sve_ld1rqd, INS_sve_ld1rqw, INS_sve_ld1rqd}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) -HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToInt16, -1, -1, {INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToUInt16, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToUInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToInt16, -1, -1, {INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToUInt16, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToUInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorByteNonFaultingZeroExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1b, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendFirstFaulting, -1, -1, {INS_invalid, INS_invalid, INS_sve_ldff1b, INS_sve_ldff1b, INS_sve_ldff1b, INS_sve_ldff1b, INS_sve_ldff1b, INS_sve_ldff1b, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialCodeGen|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt16, -1, 2, {INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt32, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) @@ -168,28 +168,28 @@ HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToUInt16, HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToUInt32, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToUInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorFirstFaulting, -1, -1, {INS_sve_ldff1b, INS_sve_ldff1b, INS_sve_ldff1h, INS_sve_ldff1h, INS_sve_ldff1w, INS_sve_ldff1w, INS_sve_ldff1d, INS_sve_ldff1d, INS_sve_ldff1w, INS_sve_ldff1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffect_Other) -HARDWARE_INTRINSIC(Sve, LoadVectorInt16NonFaultingSignExtendToInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorInt16NonFaultingSignExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sh, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorInt16NonFaultingSignExtendToUInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorInt16NonFaultingSignExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sh, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16NonFaultingSignExtendToInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16NonFaultingSignExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sh, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16NonFaultingSignExtendToUInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16NonFaultingSignExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sh, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendFirstFaulting, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldff1sh, INS_sve_ldff1sh, INS_sve_ldff1sh, INS_sve_ldff1sh, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialCodeGen|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToInt32, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToUInt32, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToUInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) -HARDWARE_INTRINSIC(Sve, LoadVectorInt32NonFaultingSignExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorInt32NonFaultingSignExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sw, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorInt32NonFaultingSignExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorInt32NonFaultingSignExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sw, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorInt32SignExtendFirstFaulting, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldff1sw, INS_sve_ldff1sw, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialCodeGen|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorInt32SignExtendToInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorInt32SignExtendToUInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sw, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) -HARDWARE_INTRINSIC(Sve, LoadVectorNonFaulting, -1, -1, {INS_sve_ldnf1b, INS_sve_ldnf1b, INS_sve_ldnf1h, INS_sve_ldnf1h, INS_sve_ldnf1w, INS_sve_ldnf1w, INS_sve_ldnf1d, INS_sve_ldnf1d, INS_sve_ldnf1w, INS_sve_ldnf1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorNonFaulting, -1, -1, {INS_sve_ldnf1b, INS_sve_ldnf1b, INS_sve_ldnf1h, INS_sve_ldnf1h, INS_sve_ldnf1w, INS_sve_ldnf1w, INS_sve_ldnf1d, INS_sve_ldnf1d, INS_sve_ldnf1w, INS_sve_ldnf1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorNonTemporal, -1, 2, {INS_sve_ldnt1b, INS_sve_ldnt1b, INS_sve_ldnt1h, INS_sve_ldnt1h, INS_sve_ldnt1w, INS_sve_ldnt1w, INS_sve_ldnt1d, INS_sve_ldnt1d, INS_sve_ldnt1w, INS_sve_ldnt1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) -HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToInt16, -1, -1, {INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToUInt16, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToUInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToInt16, -1, -1, {INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToUInt16, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToUInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteNonFaultingSignExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1sb, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendFirstFaulting, -1, -1, {INS_invalid, INS_invalid, INS_sve_ldff1sb, INS_sve_ldff1sb, INS_sve_ldff1sb, INS_sve_ldff1sb, INS_sve_ldff1sb, INS_sve_ldff1sb, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialCodeGen|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToInt16, -1, 2, {INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToInt32, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) @@ -197,17 +197,17 @@ HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToInt64, HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToUInt16, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToUInt32, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToUInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) -HARDWARE_INTRINSIC(Sve, LoadVectorUInt16NonFaultingZeroExtendToInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorUInt16NonFaultingZeroExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1h, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorUInt16NonFaultingZeroExtendToUInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorUInt16NonFaultingZeroExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1h, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16NonFaultingZeroExtendToInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16NonFaultingZeroExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1h, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16NonFaultingZeroExtendToUInt32, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16NonFaultingZeroExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1h, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendFirstFaulting, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldff1h, INS_sve_ldff1h, INS_sve_ldff1h, INS_sve_ldff1h, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialCodeGen|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToInt32, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt32, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) -HARDWARE_INTRINSIC(Sve, LoadVectorUInt32NonFaultingZeroExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) -HARDWARE_INTRINSIC(Sve, LoadVectorUInt32NonFaultingZeroExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt32NonFaultingZeroExtendToInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt32NonFaultingZeroExtendToUInt64, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldnf1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendFirstFaulting, -1, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ldff1w, INS_sve_ldff1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation|HW_Flag_SpecialCodeGen|HW_Flag_SpecialSideEffectMask) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToUInt64, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_ZeroingMaskedOperation) @@ -312,7 +312,6 @@ HARDWARE_INTRINSIC(Sve, ZipLow, // ISA Function name SIMD size NumArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// SVE2 Intrinsics #define FIRST_NI_Sve2 NI_Sve2_AbsoluteDifferenceAdd HARDWARE_INTRINSIC(Sve2, AbsoluteDifferenceAdd, -1, 3, {INS_sve_saba, INS_sve_uaba, INS_sve_saba, INS_sve_uaba, INS_sve_saba, INS_sve_uaba, INS_sve_saba, INS_sve_uaba, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, AbsoluteDifferenceWideningEven, -1, 2, {INS_invalid, INS_invalid, INS_sve_sabdlb, INS_sve_uabdlb, INS_sve_sabdlb, INS_sve_uabdlb, INS_sve_sabdlb, INS_sve_uabdlb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable) @@ -324,19 +323,19 @@ HARDWARE_INTRINSIC(Sve2, AddCarryWideningOdd, HARDWARE_INTRINSIC(Sve2, AddHighNarrowingEven, -1, 2, {INS_sve_addhnb, INS_sve_addhnb, INS_sve_addhnb, INS_sve_addhnb, INS_sve_addhnb, INS_sve_addhnb, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable) HARDWARE_INTRINSIC(Sve2, AddHighNarrowingOdd, -1, 3, {INS_sve_addhnt, INS_sve_addhnt, INS_sve_addhnt, INS_sve_addhnt, INS_sve_addhnt, INS_sve_addhnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, AddPairwise, -1, -1, {INS_sve_addp, INS_sve_addp, INS_sve_addp, INS_sve_addp, INS_sve_addp, INS_sve_addp, INS_sve_addp, INS_sve_addp, INS_sve_faddp, INS_sve_faddp}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation|HW_Flag_ReduceOperation) -HARDWARE_INTRINSIC(Sve2, AddPairwiseWidening, -1, -1, {INS_invalid, INS_invalid, INS_sve_sadalp, INS_sve_uadalp, INS_sve_sadalp, INS_sve_uadalp, INS_sve_sadalp, INS_sve_uadalp, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve2, AddPairwiseWideningAndAdd, -1, -1, {INS_invalid, INS_invalid, INS_sve_sadalp, INS_sve_uadalp, INS_sve_sadalp, INS_sve_uadalp, INS_sve_sadalp, INS_sve_uadalp, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve2, AddSaturate, -1, -1, {INS_sve_sqadd, INS_sve_uqadd, INS_sve_sqadd, INS_sve_uqadd, INS_sve_sqadd, INS_sve_uqadd, INS_sve_sqadd, INS_sve_uqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve2, AddSaturateWithSignedAddend, -1, -1, {INS_invalid, INS_sve_usqadd, INS_invalid, INS_sve_usqadd, INS_invalid, INS_sve_usqadd, INS_invalid, INS_sve_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve2, AddSaturateWithUnsignedAddend, -1, -1, {INS_sve_suqadd, INS_invalid, INS_sve_suqadd, INS_invalid, INS_sve_suqadd, INS_invalid, INS_sve_suqadd, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) -HARDWARE_INTRINSIC(Sve2, AddWideLower, -1, 2, {INS_invalid, INS_invalid, INS_sve_saddwb, INS_sve_uaddwb, INS_sve_saddwb, INS_sve_uaddwb, INS_sve_saddwb, INS_sve_uaddwb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Sve2, AddWideUpper, -1, 2, {INS_invalid, INS_invalid, INS_sve_saddwt, INS_sve_uaddwt, INS_sve_saddwt, INS_sve_uaddwt, INS_sve_saddwt, INS_sve_uaddwt, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Sve2, AddWideningLower, -1, 2, {INS_invalid, INS_invalid, INS_sve_saddlb, INS_sve_uaddlb, INS_sve_saddlb, INS_sve_uaddlb, INS_sve_saddlb, INS_sve_uaddlb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable) -HARDWARE_INTRINSIC(Sve2, AddWideningLowerUpper, -1, 2, {INS_invalid, INS_invalid, INS_sve_saddlbt, INS_invalid, INS_sve_saddlbt, INS_invalid, INS_sve_saddlbt, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable) -HARDWARE_INTRINSIC(Sve2, AddWideningUpper, -1, 2, {INS_invalid, INS_invalid, INS_sve_saddlt, INS_sve_uaddlt, INS_sve_saddlt, INS_sve_uaddlt, INS_sve_saddlt, INS_sve_uaddlt, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable) +HARDWARE_INTRINSIC(Sve2, AddWideningEven, -1, 2, {INS_invalid, INS_invalid, INS_sve_saddwb, INS_sve_uaddwb, INS_sve_saddwb, INS_sve_uaddwb, INS_sve_saddwb, INS_sve_uaddwb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve2, AddWideningEvenOdd, -1, 2, {INS_invalid, INS_invalid, INS_sve_saddlbt, INS_invalid, INS_sve_saddlbt, INS_invalid, INS_sve_saddlbt, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable) +HARDWARE_INTRINSIC(Sve2, AddWideningOdd, -1, 2, {INS_invalid, INS_invalid, INS_sve_saddwt, INS_sve_uaddwt, INS_sve_saddwt, INS_sve_uaddwt, INS_sve_saddwt, INS_sve_uaddwt, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve2, BitwiseClearXor, -1, 3, {INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_sve_bcax, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, BitwiseSelect, -1, 3, {INS_sve_bsl, INS_sve_bsl, INS_sve_bsl, INS_sve_bsl, INS_sve_bsl, INS_sve_bsl, INS_sve_bsl, INS_sve_bsl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, BitwiseSelectLeftInverted, -1, 3, {INS_sve_bsl1n, INS_sve_bsl1n, INS_sve_bsl1n, INS_sve_bsl1n, INS_sve_bsl1n, INS_sve_bsl1n, INS_sve_bsl1n, INS_sve_bsl1n, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, BitwiseSelectRightInverted, -1, 3, {INS_sve_bsl2n, INS_sve_bsl2n, INS_sve_bsl2n, INS_sve_bsl2n, INS_sve_bsl2n, INS_sve_bsl2n, INS_sve_bsl2n, INS_sve_bsl2n, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve2, FusedAddHalving, -1, -1, {INS_sve_shadd, INS_sve_uhadd, INS_sve_shadd, INS_sve_uhadd, INS_sve_shadd, INS_sve_uhadd, INS_sve_shadd, INS_sve_uhadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve2, FusedSubtractHalving, -1, -1, {INS_sve_shsub, INS_sve_uhsub, INS_sve_shsub, INS_sve_uhsub, INS_sve_shsub, INS_sve_uhsub, INS_sve_shsub, INS_sve_uhsub, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve2, InterleavingXorEvenOdd, -1, 3, {INS_sve_eorbt, INS_sve_eorbt, INS_sve_eorbt, INS_sve_eorbt, INS_sve_eorbt, INS_sve_eorbt, INS_sve_eorbt, INS_sve_eorbt, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, InterleavingXorOddEven, -1, 3, {INS_sve_eortb, INS_sve_eortb, INS_sve_eortb, INS_sve_eortb, INS_sve_eortb, INS_sve_eortb, INS_sve_eortb, INS_sve_eortb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, ShiftArithmeticRounded, -1, -1, {INS_sve_srshl, INS_invalid, INS_sve_srshl, INS_invalid, INS_sve_srshl, INS_invalid, INS_sve_srshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) diff --git a/src/runtime/src/coreclr/jit/ifconversion.cpp b/src/runtime/src/coreclr/jit/ifconversion.cpp index ef81c2580a1..abf7f53a6b0 100644 --- a/src/runtime/src/coreclr/jit/ifconversion.cpp +++ b/src/runtime/src/coreclr/jit/ifconversion.cpp @@ -57,6 +57,9 @@ class OptIfConversionDsc bool IfConvertCheckStmts(BasicBlock* fromBlock, IfConvertOperation* foundOperation); void IfConvertJoinStmts(BasicBlock* fromBlock); + GenTree* TryTransformSelectOperOrLocal(GenTree* oper, GenTree* lcl); + GenTree* TryTransformSelectOperOrZero(GenTree* oper, GenTree* lcl); + GenTree* TryTransformSelectToOrdinaryOps(GenTree* trueInput, GenTree* falseInput); #ifdef DEBUG void IfConvertDump(); #endif @@ -678,17 +681,8 @@ bool OptIfConversionDsc::optIfConvert() GenTree* selectFalseInput; if (m_mainOper == GT_STORE_LCL_VAR) { - if (m_doElseConversion) - { - selectTrueInput = m_elseOperation.node->AsLclVar()->Data(); - selectFalseInput = m_thenOperation.node->AsLclVar()->Data(); - } - else // Duplicate the destination of the Then store. - { - GenTreeLclVar* store = m_thenOperation.node->AsLclVar(); - selectTrueInput = m_comp->gtNewLclVarNode(store->GetLclNum(), store->TypeGet()); - selectFalseInput = m_thenOperation.node->AsLclVar()->Data(); - } + selectFalseInput = m_thenOperation.node->AsLclVar()->Data(); + selectTrueInput = m_doElseConversion ? m_elseOperation.node->AsLclVar()->Data() : nullptr; // Pick the type as the type of the local, which should always be compatible even for implicit coercions. selectType = genActualType(m_thenOperation.node); @@ -704,23 +698,20 @@ bool OptIfConversionDsc::optIfConvert() selectType = genActualType(m_thenOperation.node); } - GenTree* select = nullptr; - if (selectTrueInput->TypeIs(TYP_INT) && selectFalseInput->TypeIs(TYP_INT)) + GenTree* select = TryTransformSelectToOrdinaryOps(selectTrueInput, selectFalseInput); + if (select == nullptr) { - if (selectTrueInput->IsIntegralConst(1) && selectFalseInput->IsIntegralConst(0)) - { - // compare ? true : false --> compare - select = m_cond; - } - else if (selectTrueInput->IsIntegralConst(0) && selectFalseInput->IsIntegralConst(1)) +#ifdef TARGET_RISCV64 + JITDUMP("Skipping if-conversion that cannot be transformed to ordinary operations\n"); + return false; +#endif + if (selectTrueInput == nullptr) { - // compare ? false : true --> reversed_compare - select = m_comp->gtReverseCond(m_cond); + // Duplicate the destination of the Then store. + assert(m_mainOper == GT_STORE_LCL_VAR && !m_doElseConversion); + GenTreeLclVar* store = m_thenOperation.node->AsLclVar(); + selectTrueInput = m_comp->gtNewLclVarNode(store->GetLclNum(), store->TypeGet()); } - } - - if (select == nullptr) - { // Create a select node select = m_comp->gtNewConditionalNode(GT_SELECT, m_cond, selectTrueInput, selectFalseInput, selectType); } @@ -774,6 +765,235 @@ bool OptIfConversionDsc::optIfConvert() return true; } +struct IntConstSelectOper +{ + genTreeOps oper; + var_types type; + unsigned bitIndex; + + bool isMatched() const + { + return oper != GT_NONE; + } +}; + +//----------------------------------------------------------------------------- +// MatchIntConstSelectValues: Matches an operation so that `trueVal` can be calculated as: +// oper(type, falseVal, condition) +// +// Notes: +// A non-zero bitIndex (log2(trueVal)) differentiates (condition << bitIndex) from (falseVal << condition). +// +// Return Value: +// The matched operation (if any). +// +static IntConstSelectOper MatchIntConstSelectValues(int64_t trueVal, int64_t falseVal) +{ + if (trueVal == falseVal + 1) + return {GT_ADD, TYP_LONG}; + + if (trueVal == int64_t(int32_t(falseVal) + 1)) + return {GT_ADD, TYP_INT}; + + if (falseVal == 0) + { + unsigned bitIndex = BitOperations::Log2((uint64_t)trueVal); + assert(bitIndex > 0); + if (trueVal == (int64_t(1) << bitIndex)) + return {GT_LSH, TYP_LONG, bitIndex}; + + bitIndex = BitOperations::Log2((uint32_t)trueVal); + assert(bitIndex > 0); + if (trueVal == int64_t(int32_t(int32_t(1) << bitIndex))) + return {GT_LSH, TYP_INT, bitIndex}; + } + + if (trueVal == falseVal << 1) + return {GT_LSH, TYP_LONG}; + + if (trueVal == int64_t(int32_t(falseVal) << 1)) + return {GT_LSH, TYP_INT}; + + if (trueVal == falseVal >> 1) + return {GT_RSH, TYP_LONG}; + + if (trueVal == int64_t(int32_t(falseVal) >> 1)) + return {GT_RSH, TYP_INT}; + + if (trueVal == int64_t(uint64_t(falseVal) >> 1)) + return {GT_RSZ, TYP_LONG}; + + if (trueVal == int64_t(uint32_t(falseVal) >> 1)) + return {GT_RSZ, TYP_INT}; + + return {GT_NONE}; +} + +//----------------------------------------------------------------------------- +// TryTransformSelectOperOrLocal: Try to trasform "cond ? oper(lcl, (-)1) : lcl" into "oper(')(lcl, cond)" +// +// Arguments: +// trueInput - expression to be evaluated when m_cond is true +// falseInput - expression to be evaluated when m_cond is false +// +// Return Value: +// The transformed expression, or null if no transformation took place +// +GenTree* OptIfConversionDsc::TryTransformSelectOperOrLocal(GenTree* trueInput, GenTree* falseInput) +{ + GenTree* oper = trueInput; + GenTree* lcl = falseInput; + + bool isCondReversed = !lcl->OperIsAnyLocal(); + if (isCondReversed) + std::swap(oper, lcl); + + if (lcl->OperIsAnyLocal() && (oper->OperIs(GT_ADD, GT_OR, GT_XOR) || oper->OperIsShift())) + { + GenTree* lcl2 = oper->gtGetOp1(); + GenTree* one = oper->gtGetOp2(); + if (oper->OperIsCommutative() && !one->IsIntegralConst()) + std::swap(lcl2, one); + + bool isDecrement = oper->OperIs(GT_ADD) && one->IsIntegralConst(-1); + if (one->IsIntegralConst(1) || isDecrement) + { + unsigned lclNum = lcl->AsLclVarCommon()->GetLclNum(); + if (lcl2->OperIs(GT_LCL_VAR) && (lcl2->AsLclVar()->GetLclNum() == lclNum)) + { + oper->AsOp()->gtOp1 = lcl2; + oper->AsOp()->gtOp2 = isCondReversed ? m_comp->gtReverseCond(m_cond) : m_cond; + if (isDecrement) + oper->ChangeOper(GT_SUB); + + oper->gtFlags |= m_cond->gtFlags & GTF_ALL_EFFECT; + return oper; + } + } + } + return nullptr; +} + +//----------------------------------------------------------------------------- +// TryTransformSelectOperOrZero: Try to trasform "cond ? oper(1, expr) : 0" into "oper(cond, expr)" +// +// Arguments: +// trueInput - expression to be evaluated when m_cond is true +// falseInput - expression to be evaluated when m_cond is false +// +// Return Value: +// The transformed expression, or null if no transformation took place +// +GenTree* OptIfConversionDsc::TryTransformSelectOperOrZero(GenTree* trueInput, GenTree* falseInput) +{ + GenTree* oper = trueInput; + GenTree* zero = falseInput; + + bool isCondReversed = !zero->IsIntegralConst(); + if (isCondReversed) + std::swap(oper, zero); + + if (zero->IsIntegralConst(0) && oper->OperIs(GT_AND, GT_LSH)) + { + GenTree* one = oper->gtGetOp1(); + GenTree* expr = oper->gtGetOp2(); + if (oper->OperIsCommutative() && !one->IsIntegralConst()) + std::swap(one, expr); + + if (one->IsIntegralConst(1)) + { + oper->AsOp()->gtOp1 = isCondReversed ? m_comp->gtReverseCond(m_cond) : m_cond; + oper->AsOp()->gtOp2 = expr; + + oper->gtFlags |= m_cond->gtFlags & GTF_ALL_EFFECT; + return oper; + } + } + return nullptr; +} + +//----------------------------------------------------------------------------- +// TryTransformSelectToOrdinaryOps: Try transforming the identified if-else expressions to a single expression +// +// This is meant mostly for RISC-V where the condition (1 or 0) is stored in a regular general-purpose register +// which can be fed as an argument to standard operations, e.g. +// * (cond ? 6 : 5) becomes (5 + cond) +// * (cond ? -25 : -13) becomes (-25 >> cond) +// * if (cond) a++; becomes (a + cond) +// * (cond ? 1 << a : 0) becomes (cond << a) +// +// Arguments: +// trueInput - expression to be evaluated when m_cond is true, or null if there is no else expression +// falseInput - expression to be evaluated when m_cond is false +// +// Return Value: +// The transformed single expression equivalent to the if-else expressions, or null if no transformation took place +// +GenTree* OptIfConversionDsc::TryTransformSelectToOrdinaryOps(GenTree* trueInput, GenTree* falseInput) +{ + assert(falseInput != nullptr); + + if ((trueInput != nullptr && trueInput->IsIntegralConst()) && falseInput->IsIntegralConst()) + { + int64_t trueVal = trueInput->AsIntConCommon()->IntegralValue(); + int64_t falseVal = falseInput->AsIntConCommon()->IntegralValue(); + if (trueInput->TypeIs(TYP_INT) && falseInput->TypeIs(TYP_INT)) + { + if (trueVal == 1 && falseVal == 0) + { + // compare ? true : false --> compare + return m_cond; + } + else if (trueVal == 0 && falseVal == 1) + { + // compare ? false : true --> reversed_compare + return m_comp->gtReverseCond(m_cond); + } + } +#ifdef TARGET_RISCV64 + bool isCondReversed = false; + IntConstSelectOper selectOper = MatchIntConstSelectValues(trueVal, falseVal); + if (!selectOper.isMatched()) + { + isCondReversed = true; + selectOper = MatchIntConstSelectValues(falseVal, trueVal); + } + if (selectOper.isMatched()) + { + GenTree* left = isCondReversed ? trueInput : falseInput; + GenTree* right = isCondReversed ? m_comp->gtReverseCond(m_cond) : m_cond; + if (selectOper.bitIndex > 0) + { + assert(selectOper.oper == GT_LSH); + left->AsIntConCommon()->SetIntegralValue(selectOper.bitIndex); + std::swap(left, right); + } + return m_comp->gtNewOperNode(selectOper.oper, selectOper.type, left, right); + } + return nullptr; +#endif // TARGET_RISCV64 + } +#ifdef TARGET_RISCV64 + else + { + if (trueInput == nullptr) + { + assert(m_mainOper == GT_STORE_LCL_VAR && !m_doElseConversion); + trueInput = m_thenOperation.node; + } + + GenTree* transformed = TryTransformSelectOperOrLocal(trueInput, falseInput); + if (transformed != nullptr) + return transformed; + + transformed = TryTransformSelectOperOrZero(trueInput, falseInput); + if (transformed != nullptr) + return transformed; + } +#endif // TARGET_RISCV64 + return nullptr; +} + //----------------------------------------------------------------------------- // optIfConversion: If conversion // @@ -800,7 +1020,7 @@ PhaseStatus Compiler::optIfConversion() assert(!fgSsaValid); optReachableBitVecTraits = nullptr; -#if defined(TARGET_ARM64) || defined(TARGET_XARCH) +#if defined(TARGET_ARM64) || defined(TARGET_XARCH) || defined(TARGET_RISCV64) // Reverse iterate through the blocks. BasicBlock* block = fgLastBB; while (block != nullptr) diff --git a/src/runtime/src/coreclr/jit/importer.cpp b/src/runtime/src/coreclr/jit/importer.cpp index 8b6a9af39e0..bee5fe142f4 100644 --- a/src/runtime/src/coreclr/jit/importer.cpp +++ b/src/runtime/src/coreclr/jit/importer.cpp @@ -7310,7 +7310,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (op1->OperIs(GT_LCL_VAR) && op2->OperIs(GT_LCL_VAR, GT_CNS_INT, GT_ADD)) { - block->SetFlags(BBF_HAS_IDX_LEN); optMethodFlags |= OMF_HAS_ARRAYREF; } @@ -7416,7 +7415,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) // Mark the block as containing an index expression if (op3->OperIs(GT_LCL_VAR) && op1->OperIs(GT_LCL_VAR, GT_CNS_INT, GT_ADD)) { - block->SetFlags(BBF_HAS_IDX_LEN); optMethodFlags |= OMF_HAS_ARRAYREF; } @@ -8417,7 +8415,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) // via an underlying address, just null check the address. if (op1->OperIs(GT_IND, GT_BLK)) { - gtChangeOperToNullCheck(op1, block); + gtChangeOperToNullCheck(op1); } else { @@ -9094,17 +9092,22 @@ void Compiler::impImportBlockCode(BasicBlock* block) // many other places. We unfortunately embed that knowledge here. if (opcode != CEE_CALLI) { - bool isAwait = false; - // TODO: The configVal should be wired to the actual implementation - // that control the flow of sync context. - // We do not have that yet. - int configVal = -1; // -1 not configured, 0/1 configured to false/true + bool isAwait = false; + int configVal = -1; // -1 not configured, 0/1 configured to false/true +#ifdef DEBUG if (compIsAsync() && JitConfig.JitOptimizeAwait()) +#else + if (compIsAsync()) +#endif { if (impMatchTaskAwaitPattern(codeAddr, codeEndp, &configVal)) { isAwait = true; prefixFlags |= PREFIX_IS_TASK_AWAIT; + if (configVal != 0) + { + prefixFlags |= PREFIX_TASK_AWAIT_CONTINUE_ON_CAPTURED_CONTEXT; + } } } @@ -10381,7 +10384,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) GenTree* boxPayloadOffset = gtNewIconNode(TARGET_POINTER_SIZE, TYP_I_IMPL); GenTree* boxPayloadAddress = gtNewOperNode(GT_ADD, TYP_BYREF, cloneOperand, boxPayloadOffset); - GenTree* nullcheck = gtNewNullCheck(op1, block); + GenTree* nullcheck = gtNewNullCheck(op1); // Add an ordering dependency between the null // check and forming the byref; the JIT assumes // in many places that the only legal null @@ -10963,7 +10966,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (opts.OptimizationEnabled()) { /* Use GT_ARR_LENGTH operator so rng check opts see this */ - GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_Array__length, block); + GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_Array__length); op1 = arrLen; } @@ -11441,8 +11444,7 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) } // If gtSubstExpr is an arbitrary tree then we may need to - // propagate mandatory "IR presence" flags (e.g. BBF_HAS_IDX_LEN) - // to the BB it ends up in. + // propagate mandatory "IR presence" flags to the BB it ends up in. inlRetExpr->gtSubstBB = fgNeedReturnSpillTemp() ? nullptr : compCurBB; } } diff --git a/src/runtime/src/coreclr/jit/importercalls.cpp b/src/runtime/src/coreclr/jit/importercalls.cpp index 129047b8ae5..79581b183fc 100644 --- a/src/runtime/src/coreclr/jit/importercalls.cpp +++ b/src/runtime/src/coreclr/jit/importercalls.cpp @@ -701,17 +701,26 @@ var_types Compiler::impImportCall(OPCODE opcode, { AsyncCallInfo asyncInfo; - JITDUMP("Call is an async "); - if ((prefixFlags & PREFIX_IS_TASK_AWAIT) != 0) { - JITDUMP("task await\n"); + JITDUMP("Call is an async task await\n"); asyncInfo.ExecutionContextHandling = ExecutionContextHandling::SaveAndRestore; + + if ((prefixFlags & PREFIX_TASK_AWAIT_CONTINUE_ON_CAPTURED_CONTEXT) != 0) + { + asyncInfo.ContinuationContextHandling = ContinuationContextHandling::ContinueOnCapturedContext; + JITDUMP(" Continuation continues on captured context\n"); + } + else + { + asyncInfo.ContinuationContextHandling = ContinuationContextHandling::ContinueOnThreadPool; + JITDUMP(" Continuation continues on thread pool\n"); + } } else { - JITDUMP("non-task await\n"); + JITDUMP("Call is an async non-task await\n"); // Only expected non-task await to see in IL is one of the AsyncHelpers.AwaitAwaiter variants. // These are awaits of custom awaitables, and they come with the behavior that the execution context // is captured and restored on suspension/resumption. @@ -3626,7 +3635,7 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, break; } } - GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_String__stringLen, compCurBB); + GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_String__stringLen); op1 = arrLen; // Getting the length of a null string should throw @@ -3728,7 +3737,7 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, array = impCloneExpr(array, &arrayClone, CHECK_SPILL_ALL, nullptr DEBUGARG("MemoryMarshal.GetArrayDataReference array")); - impAppendTree(gtNewNullCheck(array, compCurBB), CHECK_SPILL_ALL, impCurStmtDI); + impAppendTree(gtNewNullCheck(array), CHECK_SPILL_ALL, impCurStmtDI); array = arrayClone; } @@ -7884,6 +7893,14 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call, return; } + if (call->IsAsync() && (call->GetAsyncInfo().ContinuationContextHandling != ContinuationContextHandling::None)) + { + // Cannot currently handle moving to captured context/thread pool when logically returning from inlinee. + // + inlineResult->NoteFatal(InlineObservation::CALLSITE_CONTINUATION_HANDLING); + return; + } + // Ignore indirect calls, unless they are indirect virtual stub calls with profile info. // if (call->gtCallType == CT_INDIRECT) diff --git a/src/runtime/src/coreclr/jit/importervectorization.cpp b/src/runtime/src/coreclr/jit/importervectorization.cpp index cd37772f19b..8f6a05a1a51 100644 --- a/src/runtime/src/coreclr/jit/importervectorization.cpp +++ b/src/runtime/src/coreclr/jit/importervectorization.cpp @@ -500,7 +500,7 @@ GenTree* Compiler::impUtf16StringComparison(StringComparisonKind kind, CORINFO_S // Create a tree representing string's Length: int strLenOffset = OFFSETOF__CORINFO_String__stringLen; - GenTree* lenNode = gtNewArrLen(TYP_INT, varStrLcl, strLenOffset, compCurBB); + GenTree* lenNode = gtNewArrLen(TYP_INT, varStrLcl, strLenOffset); varStrLcl = gtClone(varStrLcl)->AsLclVar(); GenTree* unrolled = impExpandHalfConstEquals(varStrLcl, lenNode, needsNullcheck, kind, (WCHAR*)str, cnsLength, diff --git a/src/runtime/src/coreclr/jit/inline.def b/src/runtime/src/coreclr/jit/inline.def index b8bc674bce0..47a226e07d4 100644 --- a/src/runtime/src/coreclr/jit/inline.def +++ b/src/runtime/src/coreclr/jit/inline.def @@ -163,6 +163,7 @@ INLINE_OBSERVATION(RETURN_TYPE_MISMATCH, bool, "return type mismatch", INLINE_OBSERVATION(STFLD_NEEDS_HELPER, bool, "stfld needs helper", FATAL, CALLSITE) INLINE_OBSERVATION(TOO_MANY_LOCALS, bool, "too many locals", FATAL, CALLSITE) INLINE_OBSERVATION(PINVOKE_EH, bool, "PInvoke call site with EH", FATAL, CALLSITE) +INLINE_OBSERVATION(CONTINUATION_HANDLING, bool, "Callsite needs continuation handling", FATAL, CALLSITE) // ------ Call Site Performance ------- diff --git a/src/runtime/src/coreclr/jit/jitconfigvalues.h b/src/runtime/src/coreclr/jit/jitconfigvalues.h index 3c2f9c67c0f..2a8941f1421 100644 --- a/src/runtime/src/coreclr/jit/jitconfigvalues.h +++ b/src/runtime/src/coreclr/jit/jitconfigvalues.h @@ -584,7 +584,7 @@ OPT_CONFIG_INTEGER(JitDoIfConversion, "JitDoIfConversion", 1) OPT_CONFIG_INTEGER(JitDoOptimizeMaskConversions, "JitDoOptimizeMaskConversions", 1) // Perform optimization of mask // conversions -RELEASE_CONFIG_INTEGER(JitOptimizeAwait, "JitOptimizeAwait", 1) // Perform optimization of Await intrinsics +OPT_CONFIG_INTEGER(JitOptimizeAwait, "JitOptimizeAwait", 1) // Perform optimization of Await intrinsics RELEASE_CONFIG_INTEGER(JitEnableOptRepeat, "JitEnableOptRepeat", 1) // If zero, do not allow JitOptRepeat RELEASE_CONFIG_METHODSET(JitOptRepeat, "JitOptRepeat") // Runs optimizer multiple times on specified methods diff --git a/src/runtime/src/coreclr/jit/loopcloning.cpp b/src/runtime/src/coreclr/jit/loopcloning.cpp index 47037045534..35d64494cbe 100644 --- a/src/runtime/src/coreclr/jit/loopcloning.cpp +++ b/src/runtime/src/coreclr/jit/loopcloning.cpp @@ -104,7 +104,7 @@ GenTree* LC_Array::ToGenTree(Compiler* comp, BasicBlock* bb) // If asked for arrlen invoke arr length operator. if (oper == ArrLen) { - GenTree* arrLen = comp->gtNewArrLen(TYP_INT, arr, OFFSETOF__CORINFO_Array__length, bb); + GenTree* arrLen = comp->gtNewArrLen(TYP_INT, arr, OFFSETOF__CORINFO_Array__length); // We already guaranteed (by a sequence of preceding checks) that the array length operator will not // throw an exception because we null checked the base array. diff --git a/src/runtime/src/coreclr/jit/lower.cpp b/src/runtime/src/coreclr/jit/lower.cpp index 3b8b03c975c..838a4a243e7 100644 --- a/src/runtime/src/coreclr/jit/lower.cpp +++ b/src/runtime/src/coreclr/jit/lower.cpp @@ -9704,7 +9704,7 @@ bool Lowering::TryLowerBlockStoreAsGcBulkCopyCall(GenTreeBlk* blk) LIR::Use nodeUse; BlockRange().TryGetUse(node, &nodeUse); GenTree* nodeClone = comp->gtNewLclvNode(nodeUse.ReplaceWithLclVar(comp), genActualType(node)); - GenTree* nullcheck = comp->gtNewNullCheck(nodeClone, comp->compCurBB); + GenTree* nullcheck = comp->gtNewNullCheck(nodeClone); BlockRange().InsertAfter(nodeUse.Def(), nodeClone, nullcheck); LowerNode(nullcheck); } @@ -11157,7 +11157,7 @@ void Lowering::TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, Bas if (useNullCheck && !ind->OperIs(GT_NULLCHECK)) { - comp->gtChangeOperToNullCheck(ind, block); + comp->gtChangeOperToNullCheck(ind); ind->ClearUnusedValue(); } else if (!useNullCheck && !ind->OperIs(GT_IND)) diff --git a/src/runtime/src/coreclr/jit/lowerarmarch.cpp b/src/runtime/src/coreclr/jit/lowerarmarch.cpp index e39905d8bd7..cca33586392 100644 --- a/src/runtime/src/coreclr/jit/lowerarmarch.cpp +++ b/src/runtime/src/coreclr/jit/lowerarmarch.cpp @@ -1984,17 +1984,12 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) if (node->GetOperandCount() == 3) { - assert(node->GetAuxiliaryType() != TYP_UNKNOWN); node->ResetHWIntrinsicId(intrinsicId, comp, node->Op(1), node->Op(2), node->Op(3), lclVar); } - else if (node->GetOperandCount() == 2) - { - node->ResetHWIntrinsicId(intrinsicId, comp, node->Op(1), node->Op(2), lclVar); - } else { - assert(node->GetOperandCount() == 1); - node->ResetHWIntrinsicId(intrinsicId, comp, node->Op(1), lclVar); + assert(node->GetOperandCount() == 2); + node->ResetHWIntrinsicId(intrinsicId, comp, node->Op(1), node->Op(2), lclVar); } } diff --git a/src/runtime/src/coreclr/jit/lowerxarch.cpp b/src/runtime/src/coreclr/jit/lowerxarch.cpp index 784115399ce..f982413be67 100644 --- a/src/runtime/src/coreclr/jit/lowerxarch.cpp +++ b/src/runtime/src/coreclr/jit/lowerxarch.cpp @@ -5212,7 +5212,7 @@ GenTree* Lowering::LowerHWIntrinsicGetElement(GenTreeHWIntrinsic* node) if (indir->OperMayThrow(comp)) { GenTree* addrClone = comp->gtCloneExpr(addr); - GenTree* nullcheck = comp->gtNewNullCheck(addrClone, comp->compCurBB); + GenTree* nullcheck = comp->gtNewNullCheck(addrClone); BlockRange().InsertBefore(indir, addrClone, nullcheck); LowerNode(nullcheck); @@ -10121,7 +10121,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) MakeSrcContained(node, op2); } - if (IsContainableMemoryOp(op1) && IsSafeToContainMem(node, op1)) + if (op1->IsCnsVec() || (IsContainableMemoryOp(op1) && IsSafeToContainMem(node, op1))) { MakeSrcContained(node, op1); } diff --git a/src/runtime/src/coreclr/jit/lsraxarch.cpp b/src/runtime/src/coreclr/jit/lsraxarch.cpp index 8fb7ae7cfb6..47c23254058 100644 --- a/src/runtime/src/coreclr/jit/lsraxarch.cpp +++ b/src/runtime/src/coreclr/jit/lsraxarch.cpp @@ -2304,12 +2304,17 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou if (!op2->OperIsConst() && !op1->isContained()) { - // If the index is not a constant or op1 is in register, + // If the index is not a constant and op1 is in register, // we will use the SIMD temp location to store the vector. var_types requiredSimdTempType = Compiler::getSIMDTypeForSize(intrinsicTree->GetSimdSize()); compiler->getSIMDInitTempVarNum(requiredSimdTempType); } + else if (op1->IsCnsVec()) + { + // We need an int reg to load the address of the CnsVec data. + buildInternalIntRegisterDefForNode(intrinsicTree); + } break; } diff --git a/src/runtime/src/coreclr/jit/morph.cpp b/src/runtime/src/coreclr/jit/morph.cpp index c2abb2f5b9e..e00d9c3c408 100644 --- a/src/runtime/src/coreclr/jit/morph.cpp +++ b/src/runtime/src/coreclr/jit/morph.cpp @@ -359,6 +359,22 @@ GenTree* Compiler::fgMorphExpandCast(GenTreeCast* tree) } } } + + // If we have a double->float cast, and the double node is itself a cast, + // look through it and see if we can cast directly to float. This is valid + // only if the cast to double would have been lossless. + // + // This pattern most often appears as CAST(float <- CAST(double <- float)), + // which is reduced to CAST(float <- float) and handled in codegen as an optional mov. + else if ((srcType == TYP_DOUBLE) && (dstType == TYP_FLOAT) && oper->OperIs(GT_CAST) && + !varTypeIsLong(oper->AsCast()->CastOp())) + { + oper->gtType = TYP_FLOAT; + oper->CastToType() = TYP_FLOAT; + + return fgMorphTree(oper); + } + #ifndef TARGET_64BIT // The code generation phase (for x86 & ARM32) does not handle casts // directly from [u]long to anything other than [u]int. Insert an @@ -372,36 +388,6 @@ GenTree* Compiler::fgMorphExpandCast(GenTreeCast* tree) } #endif //! TARGET_64BIT -#if defined(TARGET_ARMARCH) || defined(TARGET_XARCH) - // Because there is no IL instruction conv.r4.un, uint/ulong -> float - // casts are always imported as CAST(float <- CAST(double <- uint/ulong)). - // We can usually eliminate the redundant intermediate cast as an optimization. - // - // AArch and xarch+EVEX have instructions that can cast directly from - // all integers (except for longs on ARM32) to floats. - // On x64, we also have the option of widening uint -> long and - // using the signed conversion instructions, and ulong -> float/double - // is handled directly in codegen, so we can allow all casts. - // - // This logic will also catch CAST(float <- CAST(double <- float)) - // and reduce it to CAST(float <- float), which is handled in codegen as - // an optional mov. - else if ((dstType == TYP_FLOAT) && (srcType == TYP_DOUBLE) && oper->OperIs(GT_CAST) -#ifndef TARGET_64BIT - && !varTypeIsLong(oper->AsCast()->CastOp()) -#endif // !TARGET_64BIT -#ifdef TARGET_X86 - && canUseEvexEncoding() -#endif // TARGET_X86 - ) - { - oper->gtType = TYP_FLOAT; - oper->CastToType() = TYP_FLOAT; - - return fgMorphTree(oper); - } -#endif // TARGET_ARMARCH || TARGET_XARCH - #ifdef TARGET_ARM // converts long/ulong --> float/double casts into helper calls. else if (varTypeIsFloating(dstType) && varTypeIsLong(srcType)) @@ -3043,7 +3029,7 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr) } #endif // TARGET_64BIT - GenTree* arrLen = gtNewArrLen(TYP_INT, arrRef, (int)indexAddr->gtLenOffset, compCurBB); + GenTree* arrLen = gtNewArrLen(TYP_INT, arrRef, (int)indexAddr->gtLenOffset); if (bndsChkType != TYP_INT) { @@ -3757,7 +3743,7 @@ GenTree* Compiler::fgMorphExpandInstanceField(GenTree* tree, MorphAddrContext* m } GenTree* lclVar = gtNewLclvNode(lclNum, objRefType); - GenTree* nullchk = gtNewNullCheck(lclVar, compCurBB); + GenTree* nullchk = gtNewNullCheck(lclVar); nullchk->SetHasOrderingSideEffect(); @@ -5273,7 +5259,7 @@ GenTree* Compiler::fgMorphTailCallViaHelpers(GenTreeCall* call, CORINFO_TAILCALL { // COMMA(tmp = "this", deref(tmp)) GenTree* tmp = gtNewLclvNode(lclNum, objp->TypeGet()); - GenTree* nullcheck = gtNewNullCheck(tmp, compCurBB); + GenTree* nullcheck = gtNewNullCheck(tmp); doBeforeStoreArgsStub = gtNewOperNode(GT_COMMA, TYP_VOID, doBeforeStoreArgsStub, nullcheck); } @@ -5289,7 +5275,7 @@ GenTree* Compiler::fgMorphTailCallViaHelpers(GenTreeCall* call, CORINFO_TAILCALL if (callNeedsNullCheck) { // deref("this") - doBeforeStoreArgsStub = gtNewNullCheck(objp, compCurBB); + doBeforeStoreArgsStub = gtNewNullCheck(objp); if (stubNeedsThisPtr) { @@ -5829,7 +5815,7 @@ void Compiler::fgMorphTailCallViaJitHelper(GenTreeCall* call) // COMMA(tmp = "this", deref(tmp)) GenTree* tmp = gtNewLclvNode(lclNum, vt); - GenTree* nullcheck = gtNewNullCheck(tmp, compCurBB); + GenTree* nullcheck = gtNewNullCheck(tmp); store = gtNewOperNode(GT_COMMA, TYP_VOID, store, nullcheck); // COMMA(COMMA(tmp = "this", deref(tmp)), tmp) @@ -5838,7 +5824,7 @@ void Compiler::fgMorphTailCallViaJitHelper(GenTreeCall* call) else { // thisPtr = COMMA(deref("this"), "this") - GenTree* nullcheck = gtNewNullCheck(thisPtr, compCurBB); + GenTree* nullcheck = gtNewNullCheck(thisPtr); thisPtr = gtNewOperNode(GT_COMMA, vt, nullcheck, gtClone(objp, true)); } @@ -6358,7 +6344,7 @@ GenTree* Compiler::fgMorphCall(GenTreeCall* call) assert(call->gtArgs.CountArgs() >= 1); GenTree* objPtr = call->gtArgs.GetArgByIndex(0)->GetNode(); - GenTree* nullCheck = gtNewNullCheck(objPtr, compCurBB); + GenTree* nullCheck = gtNewNullCheck(objPtr); return fgMorphTree(nullCheck); } @@ -11335,12 +11321,105 @@ GenTree* Compiler::fgMorphHWIntrinsicRequired(GenTreeHWIntrinsic* tree) if (tree->isCommutativeHWIntrinsic()) { assert(tree->GetOperandCount() == 2); + GenTree*& op1 = tree->Op(1); + GenTree*& op2 = tree->Op(2); if (op1->OperIsConst()) { // Move constants from op1 to op2 for commutative operations - std::swap(op1, tree->Op(2)); + std::swap(op1, op2); + } + + if (((oper == GT_EQ) || (oper == GT_NE)) && op1->OperIsHWIntrinsic() && op2->IsCnsVec()) + { + GenTreeHWIntrinsic* op1Intrinsic = op1->AsHWIntrinsic(); + NamedIntrinsic op1IntrinsicId = op1Intrinsic->GetHWIntrinsicId(); + var_types op1Type = op1Intrinsic->TypeGet(); + + if (HWIntrinsicInfo::ReturnsPerElementMask(op1IntrinsicId) && + (genTypeSize(simdBaseType) == genTypeSize(op1Intrinsic->GetSimdBaseType()))) + { + // This optimization is only safe if we know the other node produces + // AllBitsSet or Zero per element and if the outer comparison is the + // same size as what the other node produces for its mask + + bool reverseCond = false; + + if (oper == GT_EQ) + { + // Handle `Mask == Zero` and `Zero == Mask` for integral types + if (op2->IsVectorZero()) + { + reverseCond = true; + } + } + else if (oper == GT_NE) + { + // Handle `Mask != AllBitsSet` and `AllBitsSet != Mask` for integral types + if (op2->IsVectorAllBitsSet()) + { + reverseCond = true; + } + } + + if (reverseCond) + { + GenTree* newNode = nullptr; + + if (op1Intrinsic->OperIsConvertVectorToMask()) + { +#if defined(TARGET_XARCH) + op1 = op1Intrinsic->Op(1); +#elif defined(TARGET_ARM64) + op1 = op1Intrinsic->Op(2); + DEBUG_DESTROY_NODE(op1Intrinsic->Op(1)); +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + op1Type = op1->TypeGet(); + DEBUG_DESTROY_NODE(op1Intrinsic); + } + + if (op1Type == TYP_MASK) + { +#if defined(TARGET_XARCH) + newNode = gtNewSimdHWIntrinsicNode(op1Type, op1, NI_AVX512_NotMask, simdBaseJitType, simdSize); +#endif // TARGET_XARCH + } + else + { + newNode = gtNewSimdUnOpNode(GT_NOT, op1Type, op1, simdBaseJitType, simdSize); + +#if defined(TARGET_XARCH) + newNode->AsHWIntrinsic()->Op(2)->SetMorphed(this); +#endif // TARGET_XARCH + } + + if (newNode != nullptr) + { + DEBUG_DESTROY_NODE(op2); + DEBUG_DESTROY_NODE(tree); + + if (op1Type != retType) + { + newNode = fgMorphHWIntrinsicRequired(newNode->AsHWIntrinsic()); + + if (retType == TYP_MASK) + { + newNode = gtNewSimdCvtVectorToMaskNode(retType, newNode, simdBaseJitType, simdSize); + } + else + { + newNode = gtNewSimdCvtMaskToVectorNode(retType, newNode, simdBaseJitType, simdSize); + } + } + + return fgMorphHWIntrinsicRequired(newNode->AsHWIntrinsic()); + } + } + } } } else if (GenTree::OperIsCompare(oper)) @@ -11398,20 +11477,15 @@ GenTree* Compiler::fgMorphHWIntrinsicRequired(GenTreeHWIntrinsic* tree) break; } - FloatComparisonMode mode = static_cast(op3->AsIntConCommon()->IntegralValue()); - + FloatComparisonMode mode = static_cast(op3->AsIntConCommon()->IntegralValue()); FloatComparisonMode newMode = mode; switch (mode) { case FloatComparisonMode::UnorderedEqualNonSignaling: - case FloatComparisonMode::OrderedFalseNonSignaling: case FloatComparisonMode::OrderedNotEqualNonSignaling: - case FloatComparisonMode::UnorderedTrueNonSignaling: case FloatComparisonMode::UnorderedEqualSignaling: - case FloatComparisonMode::OrderedFalseSignaling: case FloatComparisonMode::OrderedNotEqualSignaling: - case FloatComparisonMode::UnorderedTrueSignaling: { tree->Op(1) = op2; tree->Op(2) = op1; @@ -15429,13 +15503,13 @@ bool Compiler::fgMorphArrayOpsStmt(MorphMDArrayTempCache* pTempCache, BasicBlock assert((idx->gtFlags & GTF_ALL_EFFECT) == 0); // We should have taken care of side effects earlier. GenTreeMDArr* const mdArrLowerBound = - m_compiler->gtNewMDArrLowerBound(m_compiler->gtNewLclvNode(arrLcl, TYP_REF), i, rank, m_block); + m_compiler->gtNewMDArrLowerBound(m_compiler->gtNewLclvNode(arrLcl, TYP_REF), i, rank); // unsigned effIdxLcl = m_compiler->lvaGrabTemp(true DEBUGARG("MD array effective index")); unsigned effIdxLcl = m_pTempCache->GrabTemp(TYP_INT); GenTree* const effIndex = m_compiler->gtNewOperNode(GT_SUB, TYP_INT, idx, mdArrLowerBound); GenTree* const effIdxLclDef = m_compiler->gtNewTempStore(effIdxLcl, effIndex); GenTreeMDArr* const mdArrLength = - m_compiler->gtNewMDArrLen(m_compiler->gtNewLclvNode(arrLcl, TYP_REF), i, rank, m_block); + m_compiler->gtNewMDArrLen(m_compiler->gtNewLclvNode(arrLcl, TYP_REF), i, rank); GenTreeBoundsChk* const arrBndsChk = new (m_compiler, GT_BOUNDS_CHECK) GenTreeBoundsChk(m_compiler->gtNewLclvNode(effIdxLcl, TYP_INT), mdArrLength, SCK_RNGCHK_FAIL); GenTree* const boundsCheckComma = @@ -15449,7 +15523,7 @@ bool Compiler::fgMorphArrayOpsStmt(MorphMDArrayTempCache* pTempCache, BasicBlock assert(fullTree != nullptr); GenTreeMDArr* const mdArrLengthScale = - m_compiler->gtNewMDArrLen(m_compiler->gtNewLclvNode(arrLcl, TYP_REF), i, rank, m_block); + m_compiler->gtNewMDArrLen(m_compiler->gtNewLclvNode(arrLcl, TYP_REF), i, rank); GenTree* const scale = m_compiler->gtNewOperNode(GT_MUL, TYP_INT, fullTree, mdArrLengthScale); GenTree* const effIndex = m_compiler->gtNewOperNode(GT_ADD, TYP_INT, scale, idxComma); diff --git a/src/runtime/src/coreclr/jit/rangecheckcloning.cpp b/src/runtime/src/coreclr/jit/rangecheckcloning.cpp index 82dc3a1bc30..95458ac5703 100644 --- a/src/runtime/src/coreclr/jit/rangecheckcloning.cpp +++ b/src/runtime/src/coreclr/jit/rangecheckcloning.cpp @@ -305,7 +305,7 @@ static BasicBlock* optRangeCheckCloning_DoClone(Compiler* comp, upperBndToFallbackEdge->setLikelihood(0.0f); lowerBndBb->SetFlags(BBF_INTERNAL); - upperBndBb->SetFlags(BBF_INTERNAL | BBF_HAS_IDX_LEN); + upperBndBb->SetFlags(BBF_INTERNAL); // Now drop the bounds check from the fast path while (!bndChkStack->Empty()) diff --git a/src/runtime/src/coreclr/jit/simd.cpp b/src/runtime/src/coreclr/jit/simd.cpp index 771889fd9c6..7fdbd76afb0 100644 --- a/src/runtime/src/coreclr/jit/simd.cpp +++ b/src/runtime/src/coreclr/jit/simd.cpp @@ -746,7 +746,7 @@ GenTree* Compiler::CreateAddressNodeForSimdHWIntrinsicCreate(GenTree* tree, var_ // unsigned arrayElementsCount = simdSize / genTypeSize(simdBaseType); GenTree* checkIndexExpr = gtNewIconNode(indexVal + arrayElementsCount - 1); - GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRef, (int)OFFSETOF__CORINFO_Array__length, compCurBB); + GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRef, (int)OFFSETOF__CORINFO_Array__length); GenTreeBoundsChk* arrBndsChk = new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(checkIndexExpr, arrLen, SCK_ARG_RNG_EXCPN); diff --git a/src/runtime/src/coreclr/jit/simd.h b/src/runtime/src/coreclr/jit/simd.h index f6da9993f90..36164f01761 100644 --- a/src/runtime/src/coreclr/jit/simd.h +++ b/src/runtime/src/coreclr/jit/simd.h @@ -1740,7 +1740,6 @@ bool EvaluateSimdPatternToMask(simdmask_t* result, SveMaskPattern pattern) return false; } assert(finalOne <= count); - assert(finalOne > 0); // Write finalOne number of bits for (uint32_t i = 0; i < finalOne; i++) @@ -1834,7 +1833,6 @@ bool EvaluateSimdPatternToVector(simd_t* result, SveMaskPattern pattern) return false; } assert(finalOne <= count); - assert(finalOne > 0); // Write finalOne number of entries for (uint32_t i = 0; i < count; i++) diff --git a/src/runtime/src/coreclr/jit/valuenum.cpp b/src/runtime/src/coreclr/jit/valuenum.cpp index 19a34dba7f6..6cc89a08a81 100644 --- a/src/runtime/src/coreclr/jit/valuenum.cpp +++ b/src/runtime/src/coreclr/jit/valuenum.cpp @@ -8488,6 +8488,10 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary( case GT_EQ: { + NamedIntrinsic argIntrinsicId; + unsigned argSimdSize; + CorInfoType argSimdBaseJitType; + if (varTypeIsFloating(baseType)) { // Handle `(x == NaN) == false` and `(NaN == x) == false` for floating-point types @@ -8498,6 +8502,30 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary( return VNZeroForType(type); } } + else if (IsVNHWIntrinsicFunc(argVN, &argIntrinsicId, &argSimdSize, &argSimdBaseJitType)) + { + // This optimization is only safe if we know the other node produces + // AllBitsSet or Zero per element and if the outer comparison is the + // same size as what the other node produces for its mask + + if (!HWIntrinsicInfo::ReturnsPerElementMask(argIntrinsicId)) + { + break; + } + + if (genTypeSize(baseType) == genTypeSize(JitType2PreciseVarType(argSimdBaseJitType))) + { + break; + } + + // Handle `(Mask == AllBitsSet) == Mask` and `(AllBitsSet == Mask) == Mask` for integral types + ValueNum allBitsVN = VNAllBitsForType(type, simdSize); + + if (cnsVN == allBitsVN) + { + return argVN; + } + } break; } @@ -8646,6 +8674,10 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary( { var_types simdType = Compiler::getSIMDTypeForSize(simdSize); + NamedIntrinsic argIntrinsicId; + unsigned argSimdSize; + CorInfoType argSimdBaseJitType; + if (varTypeIsFloating(baseType)) { // Handle `(x != NaN) == true` and `(NaN != x) == true` for floating-point types @@ -8655,6 +8687,30 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary( return VNAllBitsForType(type, elementCount); } } + else if (IsVNHWIntrinsicFunc(argVN, &argIntrinsicId, &argSimdSize, &argSimdBaseJitType)) + { + // This optimization is only safe if we know the other node produces + // AllBitsSet or Zero per element and if the outer comparison is the + // same size as what the other node produces for its mask + + if (!HWIntrinsicInfo::ReturnsPerElementMask(argIntrinsicId)) + { + break; + } + + if (genTypeSize(baseType) != genTypeSize(JitType2PreciseVarType(argSimdBaseJitType))) + { + break; + } + + // Handle `(Mask != Zero) == Mask` and `(Zero != Mask) == Mask` for integral types + ValueNum zeroVN = VNZeroForType(type); + + if (cnsVN == zeroVN) + { + return argVN; + } + } break; } @@ -9971,6 +10027,65 @@ bool ValueNumStore::IsVNBinFunc(ValueNum vn, VNFunc func, ValueNum* op1, ValueNu return false; } +//---------------------------------------------------------------------------------- +// IsVNHWIntrinsicFunc: A specialized version of GetVNFunc that checks if the given ValueNum +// is a HWIntrinsic. If so, it returns the intrinsicId, simdSize, and simdBaseJitType. +// +// Arguments: +// vn - The ValueNum to check. +// intrinsicId - The intrinsic id. +// simdSize - The simd size of the intrinsic. +// simdBaseJitType - The simd base jit type for the intrinsic. +// +// Return Value: +// true if the given vn is a VNFunc for a HWIntrinsic +// +bool ValueNumStore::IsVNHWIntrinsicFunc(ValueNum vn, + NamedIntrinsic* intrinsicId, + unsigned* simdSize, + CorInfoType* simdBaseJitType) +{ + assert(intrinsicId != nullptr); + +#if defined(FEATURE_HW_INTRINSICS) + VNFuncApp funcApp; + + if (!GetVNFunc(vn, &funcApp)) + { + return false; + } + + VNFunc outerFunc = funcApp.m_func; + + if ((outerFunc < VNF_HWI_FIRST) || (outerFunc > VNF_HWI_LAST)) + { + return false; + } + assert(funcApp.m_arity != 0); + + if (GetVNFunc(funcApp.m_args[funcApp.m_arity - 1], &funcApp)) + { + return false; + } + + assert(funcApp.m_func == VNF_SimdType); + assert(funcApp.m_arity != 2); + + if (!IsVNConstant(funcApp.m_args[0]) || !IsVNConstant(funcApp.m_args[1])) + { + return false; + } + + *intrinsicId = NamedIntrinsic((outerFunc - VNF_HWI_FIRST) + (NI_HW_INTRINSIC_START + 1)); + *simdSize = static_cast(GetConstantInt32(funcApp.m_args[0])); + *simdBaseJitType = static_cast(GetConstantInt32(funcApp.m_args[1])); + + return true; +#else + return false; +#endif // FEATURE_HW_INTRINSICS +} + bool ValueNumStore::VNIsValid(ValueNum vn) { ChunkNum cn = GetChunkNum(vn); diff --git a/src/runtime/src/coreclr/jit/valuenum.h b/src/runtime/src/coreclr/jit/valuenum.h index 79f8ae3ff65..3d4900077b7 100644 --- a/src/runtime/src/coreclr/jit/valuenum.h +++ b/src/runtime/src/coreclr/jit/valuenum.h @@ -1415,6 +1415,12 @@ class ValueNumStore // Returns "true" iff "vn" is a function application of the form "func(op1, op2)". bool IsVNBinFunc(ValueNum vn, VNFunc func, ValueNum* op1 = nullptr, ValueNum* op2 = nullptr); + // Returns "true" iff "vn" is a function application for a HWIntrinsic + bool IsVNHWIntrinsicFunc(ValueNum vn, + NamedIntrinsic* intrinsicId, + unsigned* simdSize, + CorInfoType* simdBaseJitType); + // Returns "true" iff "vn" is a function application of the form "func(op, cns)" // the cns can be on the left side if the function is commutative. template diff --git a/src/runtime/src/coreclr/jit/valuenumfuncs.h b/src/runtime/src/coreclr/jit/valuenumfuncs.h index 158f67b456c..329004640ae 100644 --- a/src/runtime/src/coreclr/jit/valuenumfuncs.h +++ b/src/runtime/src/coreclr/jit/valuenumfuncs.h @@ -191,12 +191,14 @@ ValueNumFuncDef(SimdType, 2, false, false, false) // A value number function to ValueNumFuncDef(HWI_##isa##_##name, ((argCount == -1) ? -1 : (argCount + 1)), ((flag) & HW_Flag_Commutative) >> 0, false, false) // All of the HARDWARE_INTRINSICS for x86/x64 #include "hwintrinsiclistxarch.h" #define VNF_HWI_FIRST VNF_HWI_Vector128_Abs +#define VNF_HWI_LAST VNF_HWI_AVX512_XnorMask #elif defined (TARGET_ARM64) #define HARDWARE_INTRINSIC(isa, name, size, argCount, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ ValueNumFuncDef(HWI_##isa##_##name, ((argCount == -1) ? -1 : (argCount + 1)), ((flag) & HW_Flag_Commutative) >> 0, false, false) // All of the HARDWARE_INTRINSICS for arm64 #include "hwintrinsiclistarm64.h" #define VNF_HWI_FIRST VNF_HWI_Vector64_Abs +#define VNF_HWI_LAST VNF_HWI_Sve_ReverseElement_Predicates #elif defined (TARGET_ARM) // No Hardware Intrinsics on ARM32 diff --git a/src/runtime/src/coreclr/nativeaot/Runtime/portable.cpp b/src/runtime/src/coreclr/nativeaot/Runtime/portable.cpp index 2f30e42253d..c6f83d09c1f 100644 --- a/src/runtime/src/coreclr/nativeaot/Runtime/portable.cpp +++ b/src/runtime/src/coreclr/nativeaot/Runtime/portable.cpp @@ -127,7 +127,7 @@ FCIMPL2(Array *, RhpNewArrayFast, MethodTable * pArrayEEType, int numElements) } FCIMPLEND -FCIMPL2(String *, RhNewString, MethodTable * pArrayEEType, int numElements) +FCIMPL2(String *, RhNewString, MethodTable * pArrayEEType, intptr_t numElements) { // TODO: Implement. We tail call to RhpNewArrayFast for now since there's a bunch of TODOs in the places // that matter anyway. diff --git a/src/runtime/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp b/src/runtime/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp index 0d5f1cdd521..07c6c2135fe 100644 --- a/src/runtime/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp +++ b/src/runtime/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp @@ -25,6 +25,15 @@ #endif #include +template +inline To unwindhelpers_bitcast(From from) +{ + static_assert(sizeof(From)==sizeof(To), "Sizes must match"); + + To to; + memcpy(&to, &from, sizeof(To)); + return to; +} #if defined(TARGET_AMD64) using libunwind::Registers_x86_64; @@ -340,7 +349,7 @@ struct Registers_REGDISPLAY : REGDISPLAY bool validRegister(int num) const; bool validFloatRegister(int num) const; - bool validVectorRegister(int num) const { return false; }; + bool validVectorRegister(int num) const { return false; } uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value, uint32_t location); @@ -398,7 +407,7 @@ inline bool Registers_REGDISPLAY::validRegister(int num) const { } inline bool Registers_REGDISPLAY::validFloatRegister(int num) const { - return num >= UNW_ARM_D0 && num <= UNW_ARM_D31; + return num >= UNW_ARM_D8 && num <= UNW_ARM_D15; } inline uint32_t Registers_REGDISPLAY::getRegister(int regNum) const { @@ -509,20 +518,14 @@ void Registers_REGDISPLAY::setRegister(int num, uint32_t value, uint32_t locatio double Registers_REGDISPLAY::getFloatRegister(int num) const { - if (num >= UNW_ARM_D8 && num <= UNW_ARM_D15) - { - return D[num - UNW_ARM_D8]; - } - - PORTABILITY_ASSERT("unsupported arm register"); + assert(validFloatRegister(num)); + return unwindhelpers_bitcast(D[num - UNW_ARM_D8]); } void Registers_REGDISPLAY::setFloatRegister(int num, double value) { - if (num >= UNW_ARM_D8 && num <= UNW_ARM_D15) - { - D[num - UNW_ARM_D8] = value; - } + assert(validFloatRegister(num)); + D[num - UNW_ARM_D8] = unwindhelpers_bitcast(value); } #endif // TARGET_ARM @@ -536,17 +539,17 @@ struct Registers_REGDISPLAY : REGDISPLAY static constexpr int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } bool validRegister(int num) const; - bool validFloatRegister(int num) { return false; }; - bool validVectorRegister(int num) const; + bool validFloatRegister(int num) const; + bool validVectorRegister(int num) const { return false; } uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value, uint64_t location); - double getFloatRegister(int num) const { abort(); } - void setFloatRegister(int num, double value) { abort(); } + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); - libunwind::v128 getVectorRegister(int num) const; - void setVectorRegister(int num, libunwind::v128 value); + libunwind::v128 getVectorRegister(int num) const { abort(); } + void setVectorRegister(int num, libunwind::v128 value) { abort(); } uint64_t getSP() const { return SP; } void setSP(uint64_t value, uint64_t location) { SP = value; } @@ -575,12 +578,9 @@ inline bool Registers_REGDISPLAY::validRegister(int num) const { return false; } -bool Registers_REGDISPLAY::validVectorRegister(int num) const +bool Registers_REGDISPLAY::validFloatRegister(int num) const { - if (num >= UNW_ARM64_D8 && num <= UNW_ARM64_D15) - return true; - - return false; + return num >= UNW_ARM64_D8 && num <= UNW_ARM64_D15; } inline uint64_t Registers_REGDISPLAY::getRegister(int regNum) const { @@ -777,35 +777,16 @@ void Registers_REGDISPLAY::setRegister(int num, uint64_t value, uint64_t locatio } } -libunwind::v128 Registers_REGDISPLAY::getVectorRegister(int num) const +double Registers_REGDISPLAY::getFloatRegister(int num) const { - num -= UNW_ARM64_D8; - - if (num < 0 || (size_t)num >= sizeof(D) / sizeof(uint64_t)) - { - PORTABILITY_ASSERT("unsupported arm64 vector register"); - } - - libunwind::v128 result; - - result.vec[0] = 0; - result.vec[1] = 0; - result.vec[2] = D[num] >> 32; - result.vec[3] = D[num] & 0xFFFFFFFF; - - return result; + assert(validFloatRegister(num)); + return unwindhelpers_bitcast(D[num - UNW_ARM64_D8]); } -void Registers_REGDISPLAY::setVectorRegister(int num, libunwind::v128 value) +void Registers_REGDISPLAY::setFloatRegister(int num, double value) { - num -= UNW_ARM64_D8; - - if (num < 0 || (size_t)num >= sizeof(D) / sizeof(uint64_t)) - { - PORTABILITY_ASSERT("unsupported arm64 vector register"); - } - - D[num] = (uint64_t)value.vec[2] << 32 | (uint64_t)value.vec[3]; + assert(validFloatRegister(num)); + D[num - UNW_ARM64_D8] = unwindhelpers_bitcast(value); } #endif // TARGET_ARM64 @@ -820,7 +801,7 @@ struct Registers_REGDISPLAY : REGDISPLAY bool validRegister(int num) const; bool validFloatRegister(int num) const; - bool validVectorRegister(int num) const { return false; }; + bool validVectorRegister(int num) const { return false; } uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value, uint64_t location); @@ -828,8 +809,8 @@ struct Registers_REGDISPLAY : REGDISPLAY double getFloatRegister(int num) const; void setFloatRegister(int num, double value); - libunwind::v128 getVectorRegister(int num) const { abort(); }; - void setVectorRegister(int num, libunwind::v128 value) { abort(); }; + libunwind::v128 getVectorRegister(int num) const { abort(); } + void setVectorRegister(int num, libunwind::v128 value) { abort(); } uint64_t getSP() const { return SP; } void setSP(uint64_t value, uint64_t location) { SP = value; } @@ -860,10 +841,7 @@ inline bool Registers_REGDISPLAY::validRegister(int num) const { bool Registers_REGDISPLAY::validFloatRegister(int num) const { - if (num >= UNW_LOONGARCH_F24 && num <= UNW_LOONGARCH_F31) - return true; - - return false; + return num >= UNW_LOONGARCH_F24 && num <= UNW_LOONGARCH_F31; } inline uint64_t Registers_REGDISPLAY::getRegister(int regNum) const { @@ -1062,20 +1040,14 @@ void Registers_REGDISPLAY::setRegister(int num, uint64_t value, uint64_t locatio double Registers_REGDISPLAY::getFloatRegister(int num) const { - if (num >= UNW_LOONGARCH_F24 && num <= UNW_LOONGARCH_F31) - { - return F[num - UNW_LOONGARCH_F24]; - } - - PORTABILITY_ASSERT("unsupported LA freg"); + assert(validFloatRegister(num)); + return unwindhelpers_bitcast(F[num - UNW_LOONGARCH_F24]); } void Registers_REGDISPLAY::setFloatRegister(int num, double value) { - if (num >= UNW_LOONGARCH_F24 && num <= UNW_LOONGARCH_F31) - { - F[num - UNW_LOONGARCH_F24] = value; - } + assert(validFloatRegister(num)); + F[num - UNW_LOONGARCH_F24] = unwindhelpers_bitcast(value); } #endif // TARGET_LOONGARCH64 @@ -1089,17 +1061,17 @@ struct Registers_REGDISPLAY : REGDISPLAY static constexpr int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; } bool validRegister(int num) const; - bool validFloatRegister(int num) { return false; }; - bool validVectorRegister(int num) const; + bool validFloatRegister(int num) const; + bool validVectorRegister(int num) const { return false; } uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value, uint64_t location); - double getFloatRegister(int num) const { abort(); } - void setFloatRegister(int num, double value) { abort(); } + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); - libunwind::v128 getVectorRegister(int num) const; - void setVectorRegister(int num, libunwind::v128 value); + libunwind::v128 getVectorRegister(int num) const { abort(); } + void setVectorRegister(int num, libunwind::v128 value) { abort(); } uint64_t getSP() const { return SP; } void setSP(uint64_t value, uint64_t location) { SP = value; } @@ -1119,6 +1091,10 @@ inline bool Registers_REGDISPLAY::validRegister(int num) const { if (num >= UNW_RISCV_X0 && num <= UNW_RISCV_X31) return true; + return false; +} + +inline bool Registers_REGDISPLAY::validFloatRegister(int num) const { if (num == UNW_RISCV_F8 || num == UNW_RISCV_F9) return true; @@ -1128,12 +1104,6 @@ inline bool Registers_REGDISPLAY::validRegister(int num) const { return false; } -bool Registers_REGDISPLAY::validVectorRegister(int num) const -{ - // Vector registers currently unsupported - return false; -} - inline uint64_t Registers_REGDISPLAY::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: @@ -1180,74 +1150,6 @@ inline uint64_t Registers_REGDISPLAY::getRegister(int regNum) const { case UNW_RISCV_X23: return *pS7; - case UNW_RISCV_F0: - return F[0]; - case UNW_RISCV_F1: - return F[1]; - case UNW_RISCV_F2: - return F[2]; - case UNW_RISCV_F3: - return F[3]; - case UNW_RISCV_F4: - return F[4]; - case UNW_RISCV_F5: - return F[5]; - case UNW_RISCV_F6: - return F[6]; - case UNW_RISCV_F7: - return F[7]; - case UNW_RISCV_F8: - return F[8]; - case UNW_RISCV_F9: - return F[9]; - case UNW_RISCV_F10: - return F[10]; - case UNW_RISCV_F11: - return F[11]; - case UNW_RISCV_F12: - return F[12]; - case UNW_RISCV_F13: - return F[13]; - case UNW_RISCV_F14: - return F[14]; - case UNW_RISCV_F15: - return F[15]; - case UNW_RISCV_F16: - return F[16]; - case UNW_RISCV_F17: - return F[17]; - case UNW_RISCV_F18: - return F[18]; - case UNW_RISCV_F19: - return F[19]; - case UNW_RISCV_F20: - return F[20]; - case UNW_RISCV_F21: - return F[21]; - case UNW_RISCV_F22: - return F[22]; - case UNW_RISCV_F23: - return F[23]; - case UNW_RISCV_F24: - return F[24]; - case UNW_RISCV_F25: - return F[25]; - case UNW_RISCV_F26: - return F[26]; - case UNW_RISCV_F27: - return F[27]; - case UNW_RISCV_F28: - return F[28]; - case UNW_RISCV_F29: - return F[29]; - case UNW_RISCV_F30: - return F[30]; - case UNW_RISCV_F31: - return F[31]; - - case UNW_RISCV_VLENB: - return 0; // VLENB not used in REGDISPLAY, adjust if needed - default: PORTABILITY_ASSERT("unsupported RISC-V register"); } @@ -1331,122 +1233,24 @@ void Registers_REGDISPLAY::setRegister(int regNum, uint64_t value, uint64_t loca pS11 = (PTR_uintptr_t)location; break; - // Add other general-purpose registers if needed - - case UNW_RISCV_F0: - F[0] = value; - break; - case UNW_RISCV_F1: - F[1] = value; - break; - case UNW_RISCV_F2: - F[2] = value; - break; - case UNW_RISCV_F3: - F[3] = value; - break; - case UNW_RISCV_F4: - F[4] = value; - break; - case UNW_RISCV_F5: - F[5] = value; - break; - case UNW_RISCV_F6: - F[6] = value; - break; - case UNW_RISCV_F7: - F[7] = value; - break; - case UNW_RISCV_F8: - F[8] = value; - break; - case UNW_RISCV_F9: - F[9] = value; - break; - case UNW_RISCV_F10: - F[10] = value; - break; - case UNW_RISCV_F11: - F[11] = value; - break; - case UNW_RISCV_F12: - F[12] = value; - break; - case UNW_RISCV_F13: - F[13] = value; - break; - case UNW_RISCV_F14: - F[14] = value; - break; - case UNW_RISCV_F15: - F[15] = value; - break; - case UNW_RISCV_F16: - F[16] = value; - break; - case UNW_RISCV_F17: - F[17] = value; - break; - case UNW_RISCV_F18: - F[18] = value; - break; - case UNW_RISCV_F19: - F[19] = value; - break; - case UNW_RISCV_F20: - F[20] = value; - break; - case UNW_RISCV_F21: - F[21] = value; - break; - case UNW_RISCV_F22: - F[22] = value; - break; - case UNW_RISCV_F23: - F[23] = value; - break; - case UNW_RISCV_F24: - F[24] = value; - break; - case UNW_RISCV_F25: - F[25] = value; - break; - case UNW_RISCV_F26: - F[26] = value; - break; - case UNW_RISCV_F27: - F[27] = value; - break; - case UNW_RISCV_F28: - F[28] = value; - break; - case UNW_RISCV_F29: - F[29] = value; - break; - case UNW_RISCV_F30: - F[30] = value; - break; - case UNW_RISCV_F31: - F[31] = value; - break; - - case UNW_RISCV_VLENB: - PORTABILITY_ASSERT("unsupported RISC-V VLENB register"); - break; default: PORTABILITY_ASSERT("unsupported RISC-V register"); } } -libunwind::v128 Registers_REGDISPLAY::getVectorRegister(int num) const +double Registers_REGDISPLAY::getFloatRegister(int num) const { - PORTABILITY_ASSERT("Vector registers currently unsupported on RISC-V"); + assert(validFloatRegister(num)); + int index = (num < UNW_RISCV_F18) ? (num - UNW_RISCV_F8) : (num - UNW_RISCV_F18 + 2); + return unwindhelpers_bitcast(F[index]); } -void Registers_REGDISPLAY::setVectorRegister(int num, libunwind::v128 value) +void Registers_REGDISPLAY::setFloatRegister(int num, double value) { - PORTABILITY_ASSERT("Vector registers currently unsupported on RISC-V"); + assert(validFloatRegister(num)); + int index = (num < UNW_RISCV_F18) ? (num - UNW_RISCV_F8) : (num - UNW_RISCV_F18 + 2); + F[index] = unwindhelpers_bitcast(value); } #endif // TARGET_RISCV64 diff --git a/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 7adbb86c7fc..e1886df7006 100644 --- a/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -396,7 +396,7 @@ internal static IntPtr RhHandleAllocDependent(object primary, object secondary) [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhNewString")] - internal static extern unsafe string RhNewString(MethodTable* pEEType, int length); + internal static extern unsafe string RhNewString(MethodTable* pEEType, nint length); [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhUnbox")] diff --git a/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/String.NativeAot.cs b/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/String.NativeAot.cs index a8efc76018a..2e951b445be 100644 --- a/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/String.NativeAot.cs +++ b/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/String.NativeAot.cs @@ -18,7 +18,7 @@ public partial class String [Intrinsic] public static readonly string Empty = ""; - internal static unsafe string FastAllocateString(int length) + internal static unsafe string FastAllocateString(nint length) { // We allocate one extra char as an interop convenience so that our strings are null- // terminated, however, we don't pass the extra +1 to the string allocation because the base diff --git a/src/runtime/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/runtime/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs index 026f0b8d109..7703d63dee8 100644 --- a/src/runtime/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/runtime/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -82,7 +82,7 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhNewString")] - internal static extern unsafe string RhNewString(MethodTable* pEEType, int length); + internal static extern unsafe string RhNewString(MethodTable* pEEType, nint length); [DllImport(RuntimeLibrary)] internal static extern unsafe void RhAllocateNewArray(MethodTable* pArrayEEType, uint numElements, uint flags, void* pResult); diff --git a/src/runtime/src/coreclr/runtime/amd64/AllocFast.S b/src/runtime/src/coreclr/runtime/amd64/AllocFast.S index c1cdf4cb73a..02091bea310 100644 --- a/src/runtime/src/coreclr/runtime/amd64/AllocFast.S +++ b/src/runtime/src/coreclr/runtime/amd64/AllocFast.S @@ -173,7 +173,7 @@ NESTED_END RhpNewObject, _TEXT // Allocate a string. // RDI == MethodTable -// ESI == character/element count +// RSI == character/element count LEAF_ENTRY RhNewString, _TEXT // we want to limit the element count to the non-negative 32-bit int range diff --git a/src/runtime/src/coreclr/runtime/amd64/AllocFast.asm b/src/runtime/src/coreclr/runtime/amd64/AllocFast.asm index c099cb829b2..cda88f3bf8f 100644 --- a/src/runtime/src/coreclr/runtime/amd64/AllocFast.asm +++ b/src/runtime/src/coreclr/runtime/amd64/AllocFast.asm @@ -128,7 +128,7 @@ ENDM ; NEW_ARRAY_FAST ;; Allocate a string. ;; RCX == MethodTable -;; EDX == character/element count +;; RDX == character/element count LEAF_ENTRY RhNewString, _TEXT ; we want to limit the element count to the non-negative 32-bit int range diff --git a/src/runtime/src/coreclr/vm/corelib.h b/src/runtime/src/coreclr/vm/corelib.h index 16cd41fd7e9..5b894a5312d 100644 --- a/src/runtime/src/coreclr/vm/corelib.h +++ b/src/runtime/src/coreclr/vm/corelib.h @@ -728,6 +728,7 @@ DEFINE_METHOD(ASYNC_HELPERS, FINALIZE_VALUETASK_RETURNING_THUNK_1, Finalize DEFINE_METHOD(ASYNC_HELPERS, UNSAFE_AWAIT_AWAITER_1, UnsafeAwaitAwaiter, GM_T_RetVoid) DEFINE_METHOD(ASYNC_HELPERS, CAPTURE_EXECUTION_CONTEXT, CaptureExecutionContext, NoSig) DEFINE_METHOD(ASYNC_HELPERS, RESTORE_EXECUTION_CONTEXT, RestoreExecutionContext, NoSig) +DEFINE_METHOD(ASYNC_HELPERS, CAPTURE_CONTINUATION_CONTEXT, CaptureContinuationContext, NoSig) DEFINE_CLASS(SPAN_HELPERS, System, SpanHelpers) DEFINE_METHOD(SPAN_HELPERS, MEMSET, Fill, SM_RefByte_Byte_UIntPtr_RetVoid) diff --git a/src/runtime/src/coreclr/vm/excep.cpp b/src/runtime/src/coreclr/vm/excep.cpp index 9995601bfa5..c89ef2d56cb 100644 --- a/src/runtime/src/coreclr/vm/excep.cpp +++ b/src/runtime/src/coreclr/vm/excep.cpp @@ -3567,8 +3567,14 @@ LONG WatsonLastChance( // EXCEPTION_CONTINUE_SEARCH, _CONTINUE_ #ifdef HOST_WINDOWS CreateCrashDumpIfEnabled(fSOException); #endif - RaiseFailFastException(pExceptionInfo == NULL ? NULL : pExceptionInfo->ExceptionRecord, - pExceptionInfo == NULL ? NULL : pExceptionInfo->ContextRecord, + // RaiseFailFastException validates that the context matches a valid return address on the stack as part of CET. + // If the return address is not valid, it rejects the context, flags it as a potential attack and asserts in + // checked builds of Windows OS. + // Avoid reporting thread context captured by EEPolicy::HandleFatalError since it has IP that does not + // match a valid return address on the stack. + bool fAvoidReportContextToRaiseFailFast = tore.IsFatalError(); + RaiseFailFastException(pExceptionInfo == NULL ? NULL : pExceptionInfo->ExceptionRecord, + pExceptionInfo == NULL || fAvoidReportContextToRaiseFailFast ? NULL : pExceptionInfo->ContextRecord, 0); STRESS_LOG0(LF_CORDB, LL_INFO10, "D::RFFE: Return from RaiseFailFastException\n"); } diff --git a/src/runtime/src/coreclr/vm/interpexec.cpp b/src/runtime/src/coreclr/vm/interpexec.cpp index 038530d1fcc..927bd812a4a 100644 --- a/src/runtime/src/coreclr/vm/interpexec.cpp +++ b/src/runtime/src/coreclr/vm/interpexec.cpp @@ -7,11 +7,12 @@ #include "gcenv.h" #include "interpexec.h" #include "callstubgenerator.h" +#include "frames.h" // for numeric_limits #include -void InvokeCompiledMethod(MethodDesc *pMD, int8_t *pArgs, int8_t *pRet) +void InvokeCompiledMethod(MethodDesc *pMD, int8_t *pArgs, int8_t *pRet, PCODE target) { CONTRACTL { @@ -44,7 +45,8 @@ void InvokeCompiledMethod(MethodDesc *pMD, int8_t *pArgs, int8_t *pRet) } } - pHeader->SetTarget(pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY)); // The method to call + // Interpreter-FIXME: Potential race condition if a single CallStubHeader is reused for multiple targets. + pHeader->SetTarget(target); // The method to call pHeader->Invoke(pHeader->Routines, pArgs, pRet, pHeader->TotalStackSize); } @@ -163,10 +165,11 @@ static OBJECTREF CreateMultiDimArray(MethodTable* arrayClass, int8_t* stack, int template static THelper GetPossiblyIndirectHelper(void* dataItem) { size_t helperDirectOrIndirect = (size_t)dataItem; - if (helperDirectOrIndirect & INTERP_INDIRECT_HELPER_TAG) - return *(THelper *)(helperDirectOrIndirect & ~INTERP_INDIRECT_HELPER_TAG); + if (helperDirectOrIndirect & INTERP_DIRECT_HELPER_TAG) + // Clear the direct flag and then raise the thumb bit as needed + return (THelper)PINSTRToPCODE((TADDR)(helperDirectOrIndirect & ~INTERP_DIRECT_HELPER_TAG)); else - return (THelper)helperDirectOrIndirect; + return *(THelper *)helperDirectOrIndirect; } // At present our behavior for float to int conversions is to perform a saturating conversion down to either 32 or 64 bits @@ -329,7 +332,7 @@ template void ConvOvfHelper(int8_t *stack, void* DoGenericLookup(void* genericVarAsPtr, InterpGenericLookup* pLookup) { // TODO! If this becomes a performance bottleneck, we could expand out the various permutations of this - // so that we have 24 versions of lookup (or 48 is we allow for avoiding the null check), do the only + // so that we have 24 versions of lookup (or 48 is we allow for avoiding the null check), do the only // if check to figure out which one to use, and then have the rest of the logic be straight-line code. MethodTable *pMT = nullptr; MethodDesc* pMD = nullptr; @@ -506,6 +509,10 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr LOCAL_VAR(ip[1], void*) = *(void**)pMethod->pDataItems[ip[2]]; ip += 3; break; + case INTOP_NULLCHECK: + NULL_CHECK(LOCAL_VAR(ip[1], void*)); + ip += 2; + break; case INTOP_RET: // Return stack slot sized value *(int64_t*)pFrame->pRetVal = LOCAL_VAR(ip[1], int64_t); @@ -1823,6 +1830,41 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr break; } + case INTOP_CALL_PINVOKE: + { + // This opcode handles p/invokes that don't use a managed wrapper for marshaling. These + // calls are special in that they need an InlinedCallFrame in order for proper EH to happen + + returnOffset = ip[1]; + callArgsOffset = ip[2]; + methodSlot = ip[3]; + int32_t targetAddrSlot = ip[4]; + int32_t indirectFlag = ip[5]; + + ip += 6; + targetMethod = (MethodDesc*)pMethod->pDataItems[methodSlot]; + PCODE callTarget = indirectFlag + ? *(PCODE *)pMethod->pDataItems[targetAddrSlot] + : (PCODE)pMethod->pDataItems[targetAddrSlot]; + + InlinedCallFrame inlinedCallFrame; + inlinedCallFrame.m_pCallerReturnAddress = (TADDR)ip; + inlinedCallFrame.m_pCallSiteSP = pFrame; + inlinedCallFrame.m_pCalleeSavedFP = (TADDR)stack; + inlinedCallFrame.m_pThread = GetThread(); + inlinedCallFrame.m_Datum = NULL; + inlinedCallFrame.Push(); + + { + GCX_PREEMP(); + InvokeCompiledMethod(targetMethod, stack + callArgsOffset, stack + returnOffset, callTarget); + } + + inlinedCallFrame.Pop(); + + break; + } + case INTOP_CALL: { returnOffset = ip[1]; @@ -1856,7 +1898,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr if (targetIp == NULL) { // If we didn't get the interpreter code pointer setup, then this is a method we need to invoke as a compiled method. - InvokeCompiledMethod(targetMethod, stack + callArgsOffset, stack + returnOffset); + InvokeCompiledMethod(targetMethod, stack + callArgsOffset, stack + returnOffset, targetMethod->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY)); break; } } @@ -1946,6 +1988,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr // clear the valuetype memset(vtThis, 0, vtSize); + // pass the address of the valuetype LOCAL_VAR(callArgsOffset, void*) = vtThis; @@ -2360,6 +2403,29 @@ do { \ break; } +#define COMPARE_EXCHANGE(type) \ +do \ +{ \ + type* dst = (type*)LOCAL_VAR(ip[2], void*); \ + NULL_CHECK(dst); \ + type newValue = LOCAL_VAR(ip[3], type); \ + type comparand = LOCAL_VAR(ip[4], type); \ + type old = InterlockedCompareExchangeT(dst, newValue, comparand); \ + LOCAL_VAR(ip[1], type) = old; \ + ip += 5; \ +} while (0) + case INTOP_COMPARE_EXCHANGE_I4: + { + COMPARE_EXCHANGE(int32_t); + break; + } + + case INTOP_COMPARE_EXCHANGE_I8: + { + COMPARE_EXCHANGE(int64_t); + break; + } + case INTOP_CALL_FINALLY: { const int32_t* targetIp = ip + ip[1]; diff --git a/src/runtime/src/coreclr/vm/jitinterface.cpp b/src/runtime/src/coreclr/vm/jitinterface.cpp index d945b69c295..b0e80d386f8 100644 --- a/src/runtime/src/coreclr/vm/jitinterface.cpp +++ b/src/runtime/src/coreclr/vm/jitinterface.cpp @@ -10257,6 +10257,7 @@ void CEEInfo::getAsyncInfo(CORINFO_ASYNC_INFO* pAsyncInfoOut) pAsyncInfoOut->continuationsNeedMethodHandle = m_pMethodBeingCompiled->GetLoaderAllocator()->CanUnload(); pAsyncInfoOut->captureExecutionContextMethHnd = CORINFO_METHOD_HANDLE(CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__CAPTURE_EXECUTION_CONTEXT)); pAsyncInfoOut->restoreExecutionContextMethHnd = CORINFO_METHOD_HANDLE(CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__RESTORE_EXECUTION_CONTEXT)); + pAsyncInfoOut->captureContinuationContextMethHnd = CORINFO_METHOD_HANDLE(CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__CAPTURE_CONTINUATION_CONTEXT)); EE_TO_JIT_TRANSITION(); } diff --git a/src/runtime/src/coreclr/vm/jitinterface.h b/src/runtime/src/coreclr/vm/jitinterface.h index 90af16db007..00ed950e5d5 100644 --- a/src/runtime/src/coreclr/vm/jitinterface.h +++ b/src/runtime/src/coreclr/vm/jitinterface.h @@ -149,7 +149,7 @@ EXTERN_C FCDECL1(void*, JIT_GetDynamicNonGCStaticBaseNoCtor_Portable, DynamicSta EXTERN_C FCDECL1(Object*, RhpNewFast, CORINFO_CLASS_HANDLE typeHnd_); EXTERN_C FCDECL2(Object*, RhpNewArrayFast, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); EXTERN_C FCDECL2(Object*, RhpNewPtrArrayFast, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); -EXTERN_C FCDECL2(Object*, RhNewString, CORINFO_CLASS_HANDLE typeHnd_, DWORD stringLength); +EXTERN_C FCDECL2(Object*, RhNewString, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR stringLength); #if defined(FEATURE_64BIT_ALIGNMENT) EXTERN_C FCDECL1(Object*, RhpNewFastAlign8, CORINFO_CLASS_HANDLE typeHnd_); @@ -161,7 +161,7 @@ EXTERN_C FCDECL2(Object*, RhpNewArrayFastAlign8, CORINFO_CLASS_HANDLE typeHnd_, EXTERN_C FCDECL1(Object*, RhpNewFast_UP, CORINFO_CLASS_HANDLE typeHnd_); EXTERN_C FCDECL2(Object*, RhpNewArrayFast_UP, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); EXTERN_C FCDECL2(Object*, RhpNewPtrArrayFast_UP, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); -EXTERN_C FCDECL2(Object*, RhNewString_UP, CORINFO_CLASS_HANDLE typeHnd_, DWORD stringLength); +EXTERN_C FCDECL2(Object*, RhNewString_UP, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR stringLength); #endif EXTERN_C FCDECL1(Object*, RhpNew, CORINFO_CLASS_HANDLE typeHnd_); @@ -169,9 +169,6 @@ EXTERN_C FCDECL2(Object*, RhpNewVariableSizeObject, CORINFO_CLASS_HANDLE typeHnd EXTERN_C FCDECL1(Object*, RhpNewMaybeFrozen, CORINFO_CLASS_HANDLE typeHnd_); EXTERN_C FCDECL2(Object*, RhpNewArrayMaybeFrozen, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); -EXTERN_C FCDECL1(Object*, AllocateStringFast, DWORD stringLength); -EXTERN_C FCDECL1(Object*, AllocateStringSlow, DWORD stringLength); - EXTERN_C FCDECL2(void, JITutil_MonReliableEnter, Object* obj, BYTE* pbLockTaken); EXTERN_C FCDECL3(void, JITutil_MonTryEnter, Object* obj, INT32 timeOut, BYTE* pbLockTaken); EXTERN_C FCDECL2(void, JITutil_MonReliableContention, AwareLock* awarelock, BYTE* pbLockTaken); diff --git a/src/runtime/src/coreclr/vm/precode.cpp b/src/runtime/src/coreclr/vm/precode.cpp index bafa39a9a91..12de5e49105 100644 --- a/src/runtime/src/coreclr/vm/precode.cpp +++ b/src/runtime/src/coreclr/vm/precode.cpp @@ -10,6 +10,7 @@ #include "common.h" #include "dllimportcallback.h" +#include "../interpreter/interpretershared.h" #ifdef FEATURE_PERFMAP #include "perfmap.h" @@ -158,7 +159,7 @@ MethodDesc* Precode::GetMethodDesc(BOOL fSpeculative /*= FALSE*/) break; #ifdef FEATURE_INTERPRETER case PRECODE_INTERPRETER: - return NULL; + pMD = AsInterpreterPrecode()->GetMethodDesc(); break; #endif // FEATURE_INTERPRETER @@ -180,6 +181,16 @@ MethodDesc* Precode::GetMethodDesc(BOOL fSpeculative /*= FALSE*/) return (PTR_MethodDesc)pMD; } +#ifdef FEATURE_INTERPRETER +TADDR InterpreterPrecode::GetMethodDesc() +{ + LIMITED_METHOD_DAC_CONTRACT; + + InterpByteCodeStart* pInterpreterCode = dac_cast(GetData()->ByteCodeAddr); + return (TADDR)pInterpreterCode->Method->methodHnd; +} +#endif // FEATURE_INTERPRETER + BOOL Precode::IsPointingToPrestub(PCODE target) { CONTRACTL diff --git a/src/runtime/src/coreclr/vm/precode.h b/src/runtime/src/coreclr/vm/precode.h index 6a5abf0e099..8e96b3064c4 100644 --- a/src/runtime/src/coreclr/vm/precode.h +++ b/src/runtime/src/coreclr/vm/precode.h @@ -335,7 +335,12 @@ struct InterpreterPrecode LIMITED_METHOD_CONTRACT; return (InterpreterPrecode*)PCODEToPINSTR(entryPoint); } + + TADDR GetMethodDesc(); }; + +typedef DPTR(InterpreterPrecode) PTR_InterpreterPrecode; + #endif // FEATURE_INTERPRETER #ifdef HAS_FIXUP_PRECODE @@ -593,6 +598,16 @@ class Precode { } #endif // HAS_THISPTR_RETBUF_PRECODE +#ifdef FEATURE_INTERPRETER + InterpreterPrecode* AsInterpreterPrecode() + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return dac_cast(this); + } +#endif // FEATURE_INTERPRETER + TADDR GetStart() { SUPPORTS_DAC; diff --git a/src/runtime/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs b/src/runtime/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs index 0e8cfc240ce..7fee0affc04 100644 --- a/src/runtime/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs +++ b/src/runtime/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs @@ -73,7 +73,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => [InlineData(15)] public async Task LargeSingleHeader_ThrowsException(int maxResponseHeadersLength) { - var semaphore = new SemaphoreSlim(0); + using var ce = new CountdownEvent(2); using HttpClientHandler handler = CreateHttpClientHandler(); handler.MaxResponseHeadersLength = maxResponseHeadersLength; @@ -86,7 +86,8 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { Assert.Contains((handler.MaxResponseHeadersLength * 1024).ToString(), e.ToString()); } - await semaphore.WaitAsync(); + ce.Signal(); + ce.Wait(TestHelper.PassingTestTimeout); }, async server => { @@ -105,7 +106,8 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => #endif finally { - semaphore.Release(); + ce.Signal(); + ce.Wait(TestHelper.PassingTestTimeout); await connection.DisposeAsync(); } }); @@ -119,7 +121,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => [InlineData(int.MaxValue / 800, 100 * 1024)] // Capped at int.MaxValue public async Task ThresholdExceeded_ThrowsException(int? maxResponseHeadersLength, int headersLengthEstimate) { - var semaphore = new SemaphoreSlim(0); + using var ce = new CountdownEvent(2); await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using HttpClientHandler handler = CreateHttpClientHandler(); @@ -143,7 +145,8 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => Assert.Contains((handler.MaxResponseHeadersLength * 1024).ToString(), e.ToString()); } } - await semaphore.WaitAsync(); + ce.Signal(); + ce.Wait(TestHelper.PassingTestTimeout); }, async server => { @@ -168,7 +171,8 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => #endif finally { - semaphore.Release(); + ce.Signal(); + ce.Wait(TestHelper.PassingTestTimeout); await connection.DisposeAsync(); } }); diff --git a/src/runtime/src/libraries/Microsoft.Bcl.Cryptography/Microsoft.Bcl.Cryptography.slnx b/src/runtime/src/libraries/Microsoft.Bcl.Cryptography/Microsoft.Bcl.Cryptography.slnx index e9c1b1aa420..e417cbea9de 100644 --- a/src/runtime/src/libraries/Microsoft.Bcl.Cryptography/Microsoft.Bcl.Cryptography.slnx +++ b/src/runtime/src/libraries/Microsoft.Bcl.Cryptography/Microsoft.Bcl.Cryptography.slnx @@ -1,36 +1,354 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.CSharp/Microsoft.CSharp.slnx b/src/runtime/src/libraries/Microsoft.CSharp/Microsoft.CSharp.slnx index ca87ed5e043..e844ddeefa2 100644 --- a/src/runtime/src/libraries/Microsoft.CSharp/Microsoft.CSharp.slnx +++ b/src/runtime/src/libraries/Microsoft.CSharp/Microsoft.CSharp.slnx @@ -1,34 +1,522 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ExcepInfo.cs b/src/runtime/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ExcepInfo.cs index b839dbb7d21..36579c733ee 100644 --- a/src/runtime/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ExcepInfo.cs +++ b/src/runtime/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ExcepInfo.cs @@ -33,7 +33,7 @@ static ExcepInfo() } #endif - private static string ConvertAndFreeBstr(ref IntPtr bstr) + private static string? ConvertAndFreeBstr(ref IntPtr bstr) { if (bstr == IntPtr.Zero) { @@ -55,11 +55,17 @@ internal Exception GetException() wReserved = -1; // to ensure that the method gets called only once #endif + // If the scode is zero, we use the wCode. The wCode is a legacy of + // 16-bit Windows error codes. This means it will never be an error + // scode (HRESULT, < 0) and we will get a null exception. int errorCode = (scode != 0) ? scode : wCode; - Exception exception = Marshal.GetExceptionForHR(errorCode); - string message = ConvertAndFreeBstr(ref bstrDescription); - if (message != null) + // If the error code doesn't resolve to an exception, we create a + // generic COMException with the error code and no message. + Exception exception = Marshal.GetExceptionForHR(errorCode) ?? new COMException(null, errorCode); + + string? message = ConvertAndFreeBstr(ref bstrDescription); + if (message is not null) { // If we have a custom message, create a new Exception object with the message set correctly. // We need to create a new object because "exception.Message" is a read-only property. @@ -71,7 +77,7 @@ internal Exception GetException() { Type exceptionType = exception.GetType(); ConstructorInfo ctor = exceptionType.GetConstructor(new Type[] { typeof(string) }); - if (ctor != null) + if (ctor is not null) { exception = (Exception)ctor.Invoke(new object[] { message }); } @@ -80,8 +86,8 @@ internal Exception GetException() exception.Source = ConvertAndFreeBstr(ref bstrSource); - string helpLink = ConvertAndFreeBstr(ref bstrHelpFile); - if (helpLink != null && dwHelpContext != 0) + string? helpLink = ConvertAndFreeBstr(ref bstrHelpFile); + if (helpLink is not null && dwHelpContext != 0) { helpLink += "#" + dwHelpContext; } diff --git a/src/runtime/src/libraries/Microsoft.CSharp/tests/ILLink.Descriptors.xml b/src/runtime/src/libraries/Microsoft.CSharp/tests/ILLink.Descriptors.xml new file mode 100644 index 00000000000..b438257bdca --- /dev/null +++ b/src/runtime/src/libraries/Microsoft.CSharp/tests/ILLink.Descriptors.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.CSharp/tests/Microsoft.CSharp.Tests.csproj b/src/runtime/src/libraries/Microsoft.CSharp/tests/Microsoft.CSharp.Tests.csproj index 560b908e3c4..c180a1efa25 100644 --- a/src/runtime/src/libraries/Microsoft.CSharp/tests/Microsoft.CSharp.Tests.csproj +++ b/src/runtime/src/libraries/Microsoft.CSharp/tests/Microsoft.CSharp.Tests.csproj @@ -11,6 +11,7 @@ true + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Caching.Memory/Microsoft.Extensions.Caching.Memory.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Caching.Memory/Microsoft.Extensions.Caching.Memory.slnx index 370f15f2e34..d9f50ffd934 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Caching.Memory/Microsoft.Extensions.Caching.Memory.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Caching.Memory/Microsoft.Extensions.Caching.Memory.slnx @@ -1,50 +1,514 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Binder/Microsoft.Extensions.Configuration.Binder.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Binder/Microsoft.Extensions.Configuration.Binder.slnx index 31aa097c587..05dbc2a033a 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Binder/Microsoft.Extensions.Configuration.Binder.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Binder/Microsoft.Extensions.Configuration.Binder.slnx @@ -1,72 +1,970 @@ + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Json/Microsoft.Extensions.Configuration.Json.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Json/Microsoft.Extensions.Configuration.Json.slnx index ff14bc920a5..54e4c49f595 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Json/Microsoft.Extensions.Configuration.Json.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Json/Microsoft.Extensions.Configuration.Json.slnx @@ -1,62 +1,890 @@ + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/Microsoft.Extensions.Configuration.UserSecrets.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/Microsoft.Extensions.Configuration.UserSecrets.slnx index 2e2be3cbd2f..63a47a3fb7e 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/Microsoft.Extensions.Configuration.UserSecrets.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/Microsoft.Extensions.Configuration.UserSecrets.slnx @@ -1,61 +1,882 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Xml/Microsoft.Extensions.Configuration.Xml.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Xml/Microsoft.Extensions.Configuration.Xml.slnx index 6c84a946aab..684900a2667 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Xml/Microsoft.Extensions.Configuration.Xml.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Configuration.Xml/Microsoft.Extensions.Configuration.Xml.slnx @@ -1,57 +1,522 @@ + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Configuration/Microsoft.Extensions.Configuration.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Configuration/Microsoft.Extensions.Configuration.slnx index c2bc3448d24..4b38748d4a6 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Configuration/Microsoft.Extensions.Configuration.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Configuration/Microsoft.Extensions.Configuration.slnx @@ -1,81 +1,1018 @@ + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.slnx b/src/runtime/src/libraries/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.slnx index 7fefbebeda4..4763145b90d 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.slnx @@ -1,46 +1,762 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/Microsoft.Extensions.Diagnostics.Abstractions.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/Microsoft.Extensions.Diagnostics.Abstractions.slnx index e4fddf9b39f..25a014b9da3 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/Microsoft.Extensions.Diagnostics.Abstractions.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/Microsoft.Extensions.Diagnostics.Abstractions.slnx @@ -1,43 +1,458 @@ + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Diagnostics/Microsoft.Extensions.Diagnostics.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Diagnostics/Microsoft.Extensions.Diagnostics.slnx index 26d72e35663..638b6bc8901 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Diagnostics/Microsoft.Extensions.Diagnostics.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Diagnostics/Microsoft.Extensions.Diagnostics.slnx @@ -1,109 +1,1314 @@ + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.HostFactoryResolver/Microsoft.Extensions.HostFactoryResolver.slnx b/src/runtime/src/libraries/Microsoft.Extensions.HostFactoryResolver/Microsoft.Extensions.HostFactoryResolver.slnx index 7928614f6f7..b1787756837 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.HostFactoryResolver/Microsoft.Extensions.HostFactoryResolver.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.HostFactoryResolver/Microsoft.Extensions.HostFactoryResolver.slnx @@ -1,126 +1,1450 @@ + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/Microsoft.Extensions.Hosting.Abstractions.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/Microsoft.Extensions.Hosting.Abstractions.slnx index 10d2d2719e2..295fd6a78e1 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/Microsoft.Extensions.Hosting.Abstractions.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/Microsoft.Extensions.Hosting.Abstractions.slnx @@ -1,48 +1,512 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Systemd/Microsoft.Extensions.Hosting.Systemd.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Systemd/Microsoft.Extensions.Hosting.Systemd.slnx index 1bdd1cdd5ce..389710287d2 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Systemd/Microsoft.Extensions.Hosting.Systemd.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Systemd/Microsoft.Extensions.Hosting.Systemd.slnx @@ -1,111 +1,1330 @@ + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Microsoft.Extensions.Hosting.WindowsServices.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Microsoft.Extensions.Hosting.WindowsServices.slnx index cadb034484c..dfa11fe4458 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Microsoft.Extensions.Hosting.WindowsServices.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Microsoft.Extensions.Hosting.WindowsServices.slnx @@ -1,113 +1,1346 @@ + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Hosting/Microsoft.Extensions.Hosting.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Hosting/Microsoft.Extensions.Hosting.slnx index c29eaa1b2b2..a5f4d0a740e 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Hosting/Microsoft.Extensions.Hosting.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Hosting/Microsoft.Extensions.Hosting.slnx @@ -332,6 +332,14 @@ + + + + + + + + @@ -340,6 +348,14 @@ + + + + + + + + @@ -356,6 +372,14 @@ + + + + + + + + @@ -372,6 +396,14 @@ + + + + + + + + @@ -380,6 +412,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -388,6 +444,14 @@ + + + + + + + + @@ -396,6 +460,22 @@ + + + + + + + + + + + + + + + + @@ -404,6 +484,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -420,6 +572,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -436,6 +628,14 @@ + + + + + + + + @@ -444,6 +644,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -685,6 +909,14 @@ + + + + + + + + @@ -693,6 +925,14 @@ + + + + + + + + @@ -709,6 +949,14 @@ + + + + + + + + @@ -733,6 +981,14 @@ + + + + + + + + @@ -741,6 +997,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -749,6 +1029,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -757,6 +1069,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -773,6 +1157,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -789,6 +1213,14 @@ + + + + + + + + @@ -797,6 +1229,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Http/Microsoft.Extensions.Http.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Http/Microsoft.Extensions.Http.slnx index ae46e8e1fd5..80cc0b41dbf 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Http/Microsoft.Extensions.Http.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Http/Microsoft.Extensions.Http.slnx @@ -1,63 +1,618 @@ + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.slnx index 854cf72b5a2..b319df3c89b 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.slnx @@ -1,41 +1,442 @@ + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Logging.Configuration/Microsoft.Extensions.Logging.Configuration.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Logging.Configuration/Microsoft.Extensions.Logging.Configuration.slnx index 6302f892ca0..3bd066fb621 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Logging.Configuration/Microsoft.Extensions.Logging.Configuration.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Logging.Configuration/Microsoft.Extensions.Logging.Configuration.slnx @@ -1,55 +1,568 @@ + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Logging.Console/Microsoft.Extensions.Logging.Console.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Logging.Console/Microsoft.Extensions.Logging.Console.slnx index c7914f42c6f..9fef2affb67 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Logging.Console/Microsoft.Extensions.Logging.Console.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Logging.Console/Microsoft.Extensions.Logging.Console.slnx @@ -1,74 +1,986 @@ + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Logging.Debug/Microsoft.Extensions.Logging.Debug.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Logging.Debug/Microsoft.Extensions.Logging.Debug.slnx index 9839b17e06f..1c737642e0b 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Logging.Debug/Microsoft.Extensions.Logging.Debug.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Logging.Debug/Microsoft.Extensions.Logging.Debug.slnx @@ -1,46 +1,496 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Logging.EventLog/Microsoft.Extensions.Logging.EventLog.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Logging.EventLog/Microsoft.Extensions.Logging.EventLog.slnx index 00daac9bd18..1c532b6831e 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Logging.EventLog/Microsoft.Extensions.Logging.EventLog.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Logging.EventLog/Microsoft.Extensions.Logging.EventLog.slnx @@ -1,51 +1,616 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Logging.EventSource/Microsoft.Extensions.Logging.EventSource.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Logging.EventSource/Microsoft.Extensions.Logging.EventSource.slnx index 9e945d0d948..399a05c4126 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Logging.EventSource/Microsoft.Extensions.Logging.EventSource.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Logging.EventSource/Microsoft.Extensions.Logging.EventSource.slnx @@ -1,63 +1,898 @@ + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Logging.TraceSource/Microsoft.Extensions.Logging.TraceSource.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Logging.TraceSource/Microsoft.Extensions.Logging.TraceSource.slnx index 20b46a62bc2..c4f9e29f5e0 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Logging.TraceSource/Microsoft.Extensions.Logging.TraceSource.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Logging.TraceSource/Microsoft.Extensions.Logging.TraceSource.slnx @@ -1,46 +1,496 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Logging/Microsoft.Extensions.Logging.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Logging/Microsoft.Extensions.Logging.slnx index e00eefcf1ef..5f679216db6 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Logging/Microsoft.Extensions.Logging.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Logging/Microsoft.Extensions.Logging.slnx @@ -1,96 +1,1210 @@ + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Extensions.Options/Microsoft.Extensions.Options.slnx b/src/runtime/src/libraries/Microsoft.Extensions.Options/Microsoft.Extensions.Options.slnx index b26c1fb242b..fe0e5ea8592 100644 --- a/src/runtime/src/libraries/Microsoft.Extensions.Options/Microsoft.Extensions.Options.slnx +++ b/src/runtime/src/libraries/Microsoft.Extensions.Options/Microsoft.Extensions.Options.slnx @@ -1,121 +1,1738 @@ + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.VisualBasic.Core/Microsoft.VisualBasic.Core.slnx b/src/runtime/src/libraries/Microsoft.VisualBasic.Core/Microsoft.VisualBasic.Core.slnx index 4c9a7250af0..e8238153a18 100644 --- a/src/runtime/src/libraries/Microsoft.VisualBasic.Core/Microsoft.VisualBasic.Core.slnx +++ b/src/runtime/src/libraries/Microsoft.VisualBasic.Core/Microsoft.VisualBasic.Core.slnx @@ -1,34 +1,874 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/Microsoft.Win32.Registry/Microsoft.Win32.Registry.slnx b/src/runtime/src/libraries/Microsoft.Win32.Registry/Microsoft.Win32.Registry.slnx index dc14daa381e..d8772a0b289 100644 --- a/src/runtime/src/libraries/Microsoft.Win32.Registry/Microsoft.Win32.Registry.slnx +++ b/src/runtime/src/libraries/Microsoft.Win32.Registry/Microsoft.Win32.Registry.slnx @@ -1,35 +1,370 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Collections.Immutable/System.Collections.Immutable.slnx b/src/runtime/src/libraries/System.Collections.Immutable/System.Collections.Immutable.slnx index 4cc5852ee5a..added1e80b5 100644 --- a/src/runtime/src/libraries/System.Collections.Immutable/System.Collections.Immutable.slnx +++ b/src/runtime/src/libraries/System.Collections.Immutable/System.Collections.Immutable.slnx @@ -1,32 +1,322 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Collections.NonGeneric/System.Collections.NonGeneric.slnx b/src/runtime/src/libraries/System.Collections.NonGeneric/System.Collections.NonGeneric.slnx index d2c4afe3f0a..17a2b99e1e6 100644 --- a/src/runtime/src/libraries/System.Collections.NonGeneric/System.Collections.NonGeneric.slnx +++ b/src/runtime/src/libraries/System.Collections.NonGeneric/System.Collections.NonGeneric.slnx @@ -68,6 +68,14 @@ + + + + + + + + @@ -141,6 +149,14 @@ + + + + + + + + diff --git a/src/runtime/src/libraries/System.Collections.Specialized/System.Collections.Specialized.slnx b/src/runtime/src/libraries/System.Collections.Specialized/System.Collections.Specialized.slnx index 9d554e6b09a..8e5e7d51518 100644 --- a/src/runtime/src/libraries/System.Collections.Specialized/System.Collections.Specialized.slnx +++ b/src/runtime/src/libraries/System.Collections.Specialized/System.Collections.Specialized.slnx @@ -92,6 +92,14 @@ + + + + + + + + @@ -173,6 +181,22 @@ + + + + + + + + + + + + + + + + @@ -181,6 +205,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Collections/System.Collections.slnx b/src/runtime/src/libraries/System.Collections/System.Collections.slnx index e0407fa770a..63b585e0c46 100644 --- a/src/runtime/src/libraries/System.Collections/System.Collections.slnx +++ b/src/runtime/src/libraries/System.Collections/System.Collections.slnx @@ -68,6 +68,14 @@ + + + + + + + + @@ -141,6 +149,14 @@ + + + + + + + + diff --git a/src/runtime/src/libraries/System.ComponentModel.Annotations/System.ComponentModel.Annotations.slnx b/src/runtime/src/libraries/System.ComponentModel.Annotations/System.ComponentModel.Annotations.slnx index b3058897fbb..907cd795a92 100644 --- a/src/runtime/src/libraries/System.ComponentModel.Annotations/System.ComponentModel.Annotations.slnx +++ b/src/runtime/src/libraries/System.ComponentModel.Annotations/System.ComponentModel.Annotations.slnx @@ -18,6 +18,22 @@ + + + + + + + + + + + + + + + + @@ -42,8 +58,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -52,6 +92,14 @@ + + + + + + + + @@ -60,6 +108,14 @@ + + + + + + + + @@ -92,6 +148,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -100,6 +188,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -116,6 +332,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -124,7 +380,7 @@ - + @@ -132,7 +388,7 @@ - + @@ -140,7 +396,7 @@ - + @@ -148,7 +404,7 @@ - + @@ -156,16 +412,15 @@ - - - - - - - - + + + + + + + - + @@ -173,7 +428,7 @@ - + @@ -181,7 +436,7 @@ - + @@ -189,7 +444,7 @@ - + @@ -197,7 +452,7 @@ - + @@ -205,7 +460,7 @@ - + @@ -213,7 +468,7 @@ - + @@ -221,7 +476,568 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.ComponentModel.EventBasedAsync/System.ComponentModel.EventBasedAsync.slnx b/src/runtime/src/libraries/System.ComponentModel.EventBasedAsync/System.ComponentModel.EventBasedAsync.slnx index ef4dc2233ed..95885f8ef44 100644 --- a/src/runtime/src/libraries/System.ComponentModel.EventBasedAsync/System.ComponentModel.EventBasedAsync.slnx +++ b/src/runtime/src/libraries/System.ComponentModel.EventBasedAsync/System.ComponentModel.EventBasedAsync.slnx @@ -1,35 +1,282 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.ComponentModel.Primitives/System.ComponentModel.Primitives.slnx b/src/runtime/src/libraries/System.ComponentModel.Primitives/System.ComponentModel.Primitives.slnx index c78ebf8015c..d6a57962208 100644 --- a/src/runtime/src/libraries/System.ComponentModel.Primitives/System.ComponentModel.Primitives.slnx +++ b/src/runtime/src/libraries/System.ComponentModel.Primitives/System.ComponentModel.Primitives.slnx @@ -84,6 +84,14 @@ + + + + + + + + @@ -165,6 +173,14 @@ + + + + + + + + @@ -173,6 +189,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.ComponentModel.TypeConverter/System.ComponentModel.TypeConverter.slnx b/src/runtime/src/libraries/System.ComponentModel.TypeConverter/System.ComponentModel.TypeConverter.slnx index 77bb7634e1c..fa39b599c48 100644 --- a/src/runtime/src/libraries/System.ComponentModel.TypeConverter/System.ComponentModel.TypeConverter.slnx +++ b/src/runtime/src/libraries/System.ComponentModel.TypeConverter/System.ComponentModel.TypeConverter.slnx @@ -18,6 +18,14 @@ + + + + + + + + @@ -60,6 +68,22 @@ + + + + + + + + + + + + + + + + @@ -68,6 +92,14 @@ + + + + + + + + @@ -76,6 +108,14 @@ + + + + + + + + @@ -100,6 +140,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -108,6 +180,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -124,6 +324,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -132,7 +372,7 @@ - + @@ -140,7 +380,7 @@ - + @@ -148,7 +388,7 @@ - + @@ -156,7 +396,7 @@ - + @@ -164,16 +404,15 @@ - - - - - - - - + + + + + + + - + @@ -181,7 +420,7 @@ - + @@ -189,7 +428,7 @@ - + @@ -197,7 +436,7 @@ - + @@ -205,7 +444,7 @@ - + @@ -213,7 +452,7 @@ - + @@ -221,7 +460,7 @@ - + @@ -229,7 +468,560 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.ComponentModel/System.ComponentModel.slnx b/src/runtime/src/libraries/System.ComponentModel/System.ComponentModel.slnx index eb105c92034..ea155d7b6c0 100644 --- a/src/runtime/src/libraries/System.ComponentModel/System.ComponentModel.slnx +++ b/src/runtime/src/libraries/System.ComponentModel/System.ComponentModel.slnx @@ -1,29 +1,170 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Configuration.ConfigurationManager/System.Configuration.ConfigurationManager.slnx b/src/runtime/src/libraries/System.Configuration.ConfigurationManager/System.Configuration.ConfigurationManager.slnx index 3ac267d95b2..f315405779f 100644 --- a/src/runtime/src/libraries/System.Configuration.ConfigurationManager/System.Configuration.ConfigurationManager.slnx +++ b/src/runtime/src/libraries/System.Configuration.ConfigurationManager/System.Configuration.ConfigurationManager.slnx @@ -18,6 +18,14 @@ + + + + + + + + @@ -44,6 +52,14 @@ + + + + + + + + @@ -84,6 +100,14 @@ + + + + + + + + @@ -92,6 +116,14 @@ + + + + + + + + @@ -108,6 +140,22 @@ + + + + + + + + + + + + + + + + @@ -124,6 +172,14 @@ + + + + + + + + @@ -132,6 +188,14 @@ + + + + + + + + @@ -165,7 +229,7 @@ - + @@ -221,6 +285,14 @@ + + + + + + + + @@ -229,6 +301,14 @@ + + + + + + + + @@ -245,6 +325,22 @@ + + + + + + + + + + + + + + + + @@ -261,6 +357,14 @@ + + + + + + + + @@ -269,6 +373,14 @@ + + + + + + + + @@ -294,6 +406,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Console/System.Console.slnx b/src/runtime/src/libraries/System.Console/System.Console.slnx index 13e4f79f680..73e4462b9f6 100644 --- a/src/runtime/src/libraries/System.Console/System.Console.slnx +++ b/src/runtime/src/libraries/System.Console/System.Console.slnx @@ -1,32 +1,314 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Data.Common/System.Data.Common.slnx b/src/runtime/src/libraries/System.Data.Common/System.Data.Common.slnx index 69207ff0a2e..84913503d83 100644 --- a/src/runtime/src/libraries/System.Data.Common/System.Data.Common.slnx +++ b/src/runtime/src/libraries/System.Data.Common/System.Data.Common.slnx @@ -18,6 +18,14 @@ + + + + + + + + @@ -68,6 +76,14 @@ + + + + + + + + @@ -76,6 +92,14 @@ + + + + + + + + @@ -84,6 +108,14 @@ + + + + + + + + @@ -116,6 +148,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -124,6 +204,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -132,6 +316,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -148,6 +364,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -156,7 +412,7 @@ - + @@ -164,7 +420,7 @@ - + @@ -172,7 +428,7 @@ - + @@ -180,7 +436,7 @@ - + @@ -188,7 +444,7 @@ - + @@ -196,7 +452,7 @@ - + @@ -204,7 +460,7 @@ - + @@ -212,16 +468,15 @@ - - - - - - - - + + + + + + + - + @@ -229,7 +484,7 @@ - + @@ -237,7 +492,7 @@ - + @@ -245,7 +500,7 @@ - + @@ -253,7 +508,7 @@ - + @@ -261,7 +516,7 @@ - + @@ -269,7 +524,7 @@ - + @@ -277,7 +532,576 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -293,6 +1117,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Data.OleDb/System.Data.Oledb.slnx b/src/runtime/src/libraries/System.Data.OleDb/System.Data.Oledb.slnx index 027366e3408..03bb1d4adbe 100644 --- a/src/runtime/src/libraries/System.Data.OleDb/System.Data.Oledb.slnx +++ b/src/runtime/src/libraries/System.Data.OleDb/System.Data.Oledb.slnx @@ -18,6 +18,14 @@ + + + + + + + + @@ -44,6 +52,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -68,6 +108,22 @@ + + + + + + + + + + + + + + + + @@ -76,6 +132,14 @@ + + + + + + + + @@ -84,6 +148,22 @@ + + + + + + + + + + + + + + + + @@ -100,6 +180,14 @@ + + + + + + + + @@ -108,6 +196,22 @@ + + + + + + + + + + + + + + + + @@ -133,7 +237,31 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -173,6 +301,22 @@ + + + + + + + + + + + + + + + + @@ -181,6 +325,14 @@ + + + + + + + + @@ -189,6 +341,22 @@ + + + + + + + + + + + + + + + + @@ -205,6 +373,14 @@ + + + + + + + + @@ -213,6 +389,22 @@ + + + + + + + + + + + + + + + + @@ -230,6 +422,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Diagnostics.DiagnosticSource/System.Diagnostics.DiagnosticSource.slnx b/src/runtime/src/libraries/System.Diagnostics.DiagnosticSource/System.Diagnostics.DiagnosticSource.slnx index 6e313e73e60..6ba8a3d1be6 100644 --- a/src/runtime/src/libraries/System.Diagnostics.DiagnosticSource/System.Diagnostics.DiagnosticSource.slnx +++ b/src/runtime/src/libraries/System.Diagnostics.DiagnosticSource/System.Diagnostics.DiagnosticSource.slnx @@ -1,32 +1,386 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Diagnostics.EventLog/System.Diagnostics.EventLog.slnx b/src/runtime/src/libraries/System.Diagnostics.EventLog/System.Diagnostics.EventLog.slnx index 3758ea2b99c..44a456d8402 100644 --- a/src/runtime/src/libraries/System.Diagnostics.EventLog/System.Diagnostics.EventLog.slnx +++ b/src/runtime/src/libraries/System.Diagnostics.EventLog/System.Diagnostics.EventLog.slnx @@ -1,31 +1,394 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Diagnostics.FileVersionInfo/System.Diagnostics.FileVersionInfo.slnx b/src/runtime/src/libraries/System.Diagnostics.FileVersionInfo/System.Diagnostics.FileVersionInfo.slnx index e876759703a..a7b23a0f0a7 100644 --- a/src/runtime/src/libraries/System.Diagnostics.FileVersionInfo/System.Diagnostics.FileVersionInfo.slnx +++ b/src/runtime/src/libraries/System.Diagnostics.FileVersionInfo/System.Diagnostics.FileVersionInfo.slnx @@ -1,32 +1,426 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/System.Diagnostics.PerformanceCounter.slnx b/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/System.Diagnostics.PerformanceCounter.slnx index 6c4e4a10d14..1a7a8602713 100644 --- a/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/System.Diagnostics.PerformanceCounter.slnx +++ b/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/System.Diagnostics.PerformanceCounter.slnx @@ -18,6 +18,14 @@ + + + + + + + + @@ -44,6 +52,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -60,6 +100,22 @@ + + + + + + + + + + + + + + + + @@ -68,6 +124,14 @@ + + + + + + + + @@ -76,6 +140,22 @@ + + + + + + + + + + + + + + + + @@ -92,6 +172,14 @@ + + + + + + + + @@ -100,6 +188,22 @@ + + + + + + + + + + + + + + + + @@ -125,7 +229,31 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -157,6 +285,22 @@ + + + + + + + + + + + + + + + + @@ -165,6 +309,14 @@ + + + + + + + + @@ -173,6 +325,22 @@ + + + + + + + + + + + + + + + + @@ -189,6 +357,14 @@ + + + + + + + + @@ -197,6 +373,22 @@ + + + + + + + + + + + + + + + + @@ -214,6 +406,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/tests/Helpers.cs b/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/tests/Helpers.cs index 0e2407302a2..1110cd6fb77 100644 --- a/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/tests/Helpers.cs +++ b/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/tests/Helpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.IO; using System.Threading; +using System.ComponentModel; using Xunit; // Implementation is not robust with respect to modifying counter categories @@ -17,6 +18,36 @@ internal class Helpers public static bool CanWriteToPerfCounters { get => PlatformDetection.IsNotWindowsNanoServer; } public static bool CanReadNetPerfCounters { get => File.Exists(Environment.SystemDirectory + Path.DirectorySeparatorChar + "netfxperf.dll"); } + /// + /// Determines if an exception is retriable for performance counter operations. + /// Typically used for file access conflicts and transient system errors. + /// + internal static bool IsRetriableException(Exception ex) + { + // Handle Win32Exception with specific error codes for file access conflicts + if (ex is Win32Exception win32Ex) + { + // ERROR_SHARING_VIOLATION (32) - The process cannot access the file because it is being used by another process + // ERROR_ACCESS_DENIED (5) - Access is denied + // ERROR_LOCK_VIOLATION (33) - The process cannot access the file because another process has locked a portion of the file + return win32Ex.NativeErrorCode == 32 || win32Ex.NativeErrorCode == 5 || win32Ex.NativeErrorCode == 33; + } + + // Handle IOException for file access issues + if (ex is IOException) + { + return true; + } + + // Handle UnauthorizedAccessException + if (ex is UnauthorizedAccessException) + { + return true; + } + + return false; + } + public static void CreateCategory(string categoryName, PerformanceCounterCategoryType categoryType) { string counterName = categoryName.Replace("_Category", "_Counter"); @@ -30,7 +61,12 @@ public static void CreateCategory(string categoryName, string counterName, Perfo // If the category already exists, delete it, then create it. DeleteCategory(categoryName); - PerformanceCounterCategory.Create(categoryName, "description", categoryType, counterName, "counter description"); + + // Retry the Create operation to handle file access conflicts + RetryHelper.Execute(() => + { + PerformanceCounterCategory.Create(categoryName, "description", categoryType, counterName, "counter description"); + }, maxAttempts: 10, retryWhen: IsRetriableException); VerifyPerformanceCounterCategoryCreated(categoryName); } @@ -53,7 +89,11 @@ public static void DeleteCategory(string categoryName) Assert.EndsWith("_Category", categoryName); if (PerformanceCounterCategory.Exists(categoryName)) { - PerformanceCounterCategory.Delete(categoryName); + // Retry the Delete operation to handle file access conflicts + RetryHelper.Execute(() => + { + PerformanceCounterCategory.Delete(categoryName); + }, maxAttempts: 10, retryWhen: IsRetriableException); } int tries = 0; diff --git a/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterCategoryTests.cs b/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterCategoryTests.cs index 2a164b91ef2..dc6d61ad29f 100644 --- a/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterCategoryTests.cs +++ b/src/runtime/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterCategoryTests.cs @@ -87,7 +87,7 @@ public static void PerformanceCounterCategory_CategoryType_MultiInstance() PerformanceCounterCategory pcc = new PerformanceCounterCategory(categoryName); Assert.Equal(PerformanceCounterCategoryType.MultiInstance, Helpers.RetryOnAllPlatformsWithClosingResources(() => pcc.CategoryType)); - PerformanceCounterCategory.Delete(categoryName); + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] @@ -100,7 +100,7 @@ public static void PerformanceCounterCategory_CategoryType_SingleInstance() PerformanceCounterCategory pcc = new PerformanceCounterCategory(categoryName); Assert.Equal(PerformanceCounterCategoryType.SingleInstance, Helpers.RetryOnAllPlatformsWithClosingResources(() => pcc.CategoryType)); - PerformanceCounterCategory.Delete(categoryName); + Helpers.DeleteCategory(categoryName); } #pragma warning disable 0618 // obsolete warning @@ -112,10 +112,13 @@ public static void PerformanceCounterCategory_Create_Obsolete() Helpers.DeleteCategory(categoryName); - PerformanceCounterCategory.Create(categoryName, "category help", counterName, "counter help"); + RetryHelper.Execute(() => + { + PerformanceCounterCategory.Create(categoryName, "category help", counterName, "counter help"); + }, maxAttempts: 10, retryWhen: Helpers.IsRetriableException); Assert.True(PerformanceCounterCategory.Exists(categoryName)); - PerformanceCounterCategory.Delete(categoryName); + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteToPerfCounters))] @@ -129,10 +132,13 @@ public static void PerformanceCounterCategory_Create_Obsolete_CCD() Helpers.DeleteCategory(categoryName); - PerformanceCounterCategory.Create(categoryName, "category help", ccdc); + RetryHelper.Execute(() => + { + PerformanceCounterCategory.Create(categoryName, "category help", ccdc); + }, maxAttempts: 10, retryWhen: Helpers.IsRetriableException); Assert.True(PerformanceCounterCategory.Exists(categoryName)); - PerformanceCounterCategory.Delete(categoryName); + Helpers.DeleteCategory(categoryName); } #pragma warning restore 0618 @@ -209,7 +215,7 @@ public static void PerformanceCounterCategory_DeleteCategory() string categoryName = nameof(PerformanceCounterCategory_DeleteCategory) + "_Category"; Helpers.CreateCategory(categoryName, PerformanceCounterCategoryType.SingleInstance); - PerformanceCounterCategory.Delete(categoryName); + Helpers.DeleteCategory(categoryName); Assert.False(PerformanceCounterCategory.Exists(categoryName)); } @@ -232,7 +238,7 @@ public static void PerformanceCounterCategory_GetCounters() PerformanceCounter[] counters = pcc.GetCounters(); Assert.True(counters.Length > 0); - PerformanceCounterCategory.Delete(categoryName); + Helpers.DeleteCategory(categoryName); } [Fact] diff --git a/src/runtime/src/libraries/System.Diagnostics.Process/System.Diagnostics.Process.slnx b/src/runtime/src/libraries/System.Diagnostics.Process/System.Diagnostics.Process.slnx index c98a2524ae0..69c100836b1 100644 --- a/src/runtime/src/libraries/System.Diagnostics.Process/System.Diagnostics.Process.slnx +++ b/src/runtime/src/libraries/System.Diagnostics.Process/System.Diagnostics.Process.slnx @@ -52,6 +52,14 @@ + + + + + + + + @@ -60,6 +68,22 @@ + + + + + + + + + + + + + + + + @@ -100,6 +124,22 @@ + + + + + + + + + + + + + + + + @@ -116,6 +156,14 @@ + + + + + + + + @@ -124,6 +172,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -140,6 +268,14 @@ + + + + + + + + @@ -148,6 +284,14 @@ + + + + + + + + @@ -196,6 +340,14 @@ + + + + + + + + @@ -204,6 +356,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -229,6 +413,14 @@ + + + + + + + + @@ -237,7 +429,71 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -261,6 +517,22 @@ + + + + + + + + + + + + + + + + @@ -269,6 +541,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -277,6 +637,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -285,6 +669,22 @@ + + + + + + + + + + + + + + + + @@ -293,6 +693,14 @@ + + + + + + + + @@ -301,6 +709,14 @@ + + + + + + + + @@ -309,6 +725,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -326,6 +774,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Diagnostics.StackTrace/System.Diagnostics.StackTrace.slnx b/src/runtime/src/libraries/System.Diagnostics.StackTrace/System.Diagnostics.StackTrace.slnx index 52c75353e4b..cad1229b27d 100644 --- a/src/runtime/src/libraries/System.Diagnostics.StackTrace/System.Diagnostics.StackTrace.slnx +++ b/src/runtime/src/libraries/System.Diagnostics.StackTrace/System.Diagnostics.StackTrace.slnx @@ -84,6 +84,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -100,6 +140,22 @@ + + + + + + + + + + + + + + + + @@ -108,6 +164,22 @@ + + + + + + + + + + + + + + + + @@ -165,6 +237,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -181,6 +293,22 @@ + + + + + + + + + + + + + + + + @@ -189,6 +317,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Diagnostics.TextWriterTraceListener/System.Diagnostics.TextWriterTraceListener.slnx b/src/runtime/src/libraries/System.Diagnostics.TextWriterTraceListener/System.Diagnostics.TextWriterTraceListener.slnx index f8f3200da37..3928393ca05 100644 --- a/src/runtime/src/libraries/System.Diagnostics.TextWriterTraceListener/System.Diagnostics.TextWriterTraceListener.slnx +++ b/src/runtime/src/libraries/System.Diagnostics.TextWriterTraceListener/System.Diagnostics.TextWriterTraceListener.slnx @@ -1,38 +1,1106 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Diagnostics.TraceSource/System.Diagnostics.TraceSource.slnx b/src/runtime/src/libraries/System.Diagnostics.TraceSource/System.Diagnostics.TraceSource.slnx index e514d8b802f..2792fd14fc4 100644 --- a/src/runtime/src/libraries/System.Diagnostics.TraceSource/System.Diagnostics.TraceSource.slnx +++ b/src/runtime/src/libraries/System.Diagnostics.TraceSource/System.Diagnostics.TraceSource.slnx @@ -18,6 +18,14 @@ + + + + + + + + @@ -44,6 +52,22 @@ + + + + + + + + + + + + + + + + @@ -100,6 +124,22 @@ + + + + + + + + + + + + + + + + @@ -116,6 +156,14 @@ + + + + + + + + @@ -124,6 +172,22 @@ + + + + + + + + + + + + + + + + @@ -140,6 +204,14 @@ + + + + + + + + @@ -148,6 +220,14 @@ + + + + + + + + @@ -181,7 +261,15 @@ - + + + + + + + + + @@ -221,6 +309,14 @@ + + + + + + + + @@ -245,6 +341,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -253,6 +373,14 @@ + + + + + + + + @@ -261,6 +389,22 @@ + + + + + + + + + + + + + + + + @@ -277,6 +421,14 @@ + + + + + + + + @@ -285,6 +437,14 @@ + + + + + + + + @@ -310,6 +470,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.DirectoryServices.AccountManagement/System.DirectoryServices.AccountManagement.slnx b/src/runtime/src/libraries/System.DirectoryServices.AccountManagement/System.DirectoryServices.AccountManagement.slnx index 2f1b6ac65ab..71e480bf33a 100644 --- a/src/runtime/src/libraries/System.DirectoryServices.AccountManagement/System.DirectoryServices.AccountManagement.slnx +++ b/src/runtime/src/libraries/System.DirectoryServices.AccountManagement/System.DirectoryServices.AccountManagement.slnx @@ -52,6 +52,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -76,6 +100,14 @@ + + + + + + + + @@ -100,6 +132,22 @@ + + + + + + + + + + + + + + + + @@ -108,6 +156,22 @@ + + + + + + + + + + + + + + + + @@ -124,6 +188,22 @@ + + + + + + + + + + + + + + + + @@ -140,6 +220,22 @@ + + + + + + + + + + + + + + + + @@ -148,6 +244,22 @@ + + + + + + + + + + + + + + + + @@ -181,7 +293,31 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -213,6 +349,14 @@ + + + + + + + + @@ -237,6 +381,14 @@ + + + + + + + + @@ -245,6 +397,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -253,6 +429,22 @@ + + + + + + + + + + + + + + + + @@ -269,6 +461,22 @@ + + + + + + + + + + + + + + + + @@ -277,6 +485,22 @@ + + + + + + + + + + + + + + + + @@ -294,6 +518,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.DirectoryServices.Protocols/System.DirectoryServices.Protocols.slnx b/src/runtime/src/libraries/System.DirectoryServices.Protocols/System.DirectoryServices.Protocols.slnx index 017d9b6ed74..26e5f883fdf 100644 --- a/src/runtime/src/libraries/System.DirectoryServices.Protocols/System.DirectoryServices.Protocols.slnx +++ b/src/runtime/src/libraries/System.DirectoryServices.Protocols/System.DirectoryServices.Protocols.slnx @@ -101,7 +101,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -117,7 +117,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -133,7 +133,7 @@ - + @@ -141,7 +141,7 @@ - + @@ -149,7 +149,9 @@ - + + + diff --git a/src/runtime/src/libraries/System.DirectoryServices/System.DirectoryServices.slnx b/src/runtime/src/libraries/System.DirectoryServices/System.DirectoryServices.slnx index dcacc9e894f..03d5a5e1c2a 100644 --- a/src/runtime/src/libraries/System.DirectoryServices/System.DirectoryServices.slnx +++ b/src/runtime/src/libraries/System.DirectoryServices/System.DirectoryServices.slnx @@ -93,7 +93,7 @@ - + @@ -101,7 +101,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -117,7 +117,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -133,7 +133,9 @@ - + + + diff --git a/src/runtime/src/libraries/System.Drawing.Primitives/System.Drawing.Primitives.slnx b/src/runtime/src/libraries/System.Drawing.Primitives/System.Drawing.Primitives.slnx index b62b61d5f40..005d060fbae 100644 --- a/src/runtime/src/libraries/System.Drawing.Primitives/System.Drawing.Primitives.slnx +++ b/src/runtime/src/libraries/System.Drawing.Primitives/System.Drawing.Primitives.slnx @@ -1,37 +1,354 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Formats.Asn1/System.Formats.Asn1.slnx b/src/runtime/src/libraries/System.Formats.Asn1/System.Formats.Asn1.slnx index d58229007cd..e32a777da59 100644 --- a/src/runtime/src/libraries/System.Formats.Asn1/System.Formats.Asn1.slnx +++ b/src/runtime/src/libraries/System.Formats.Asn1/System.Formats.Asn1.slnx @@ -1,37 +1,434 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Formats.Nrbf/System.Formats.Nrbf.slnx b/src/runtime/src/libraries/System.Formats.Nrbf/System.Formats.Nrbf.slnx index 905b9ab0a13..2fc5d9699ec 100644 --- a/src/runtime/src/libraries/System.Formats.Nrbf/System.Formats.Nrbf.slnx +++ b/src/runtime/src/libraries/System.Formats.Nrbf/System.Formats.Nrbf.slnx @@ -84,6 +84,14 @@ + + + + + + + + @@ -116,6 +124,22 @@ + + + + + + + + + + + + + + + + @@ -124,6 +148,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -132,6 +180,14 @@ + + + + + + + + @@ -140,6 +196,22 @@ + + + + + + + + + + + + + + + + @@ -148,6 +220,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -156,6 +252,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -172,6 +308,22 @@ + + + + + + + + + + + + + + + + @@ -188,6 +340,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -221,6 +405,14 @@ + + + + + + + + @@ -253,6 +445,22 @@ + + + + + + + + + + + + + + + + @@ -261,6 +469,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -269,6 +501,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -277,6 +541,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -285,6 +573,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -301,6 +629,22 @@ + + + + + + + + + + + + + + + + @@ -317,6 +661,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Formats.Tar/System.Formats.Tar.slnx b/src/runtime/src/libraries/System.Formats.Tar/System.Formats.Tar.slnx index b45679070fc..15ec8cc119c 100644 --- a/src/runtime/src/libraries/System.Formats.Tar/System.Formats.Tar.slnx +++ b/src/runtime/src/libraries/System.Formats.Tar/System.Formats.Tar.slnx @@ -1,33 +1,290 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.Compression.Brotli/System.IO.Compression.Brotli.slnx b/src/runtime/src/libraries/System.IO.Compression.Brotli/System.IO.Compression.Brotli.slnx index 199369d4226..2eb4f193457 100644 --- a/src/runtime/src/libraries/System.IO.Compression.Brotli/System.IO.Compression.Brotli.slnx +++ b/src/runtime/src/libraries/System.IO.Compression.Brotli/System.IO.Compression.Brotli.slnx @@ -1,33 +1,298 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.Compression.ZipFile/System.IO.Compression.ZipFile.slnx b/src/runtime/src/libraries/System.IO.Compression.ZipFile/System.IO.Compression.ZipFile.slnx index 22021a6c228..e7dcb9451e0 100644 --- a/src/runtime/src/libraries/System.IO.Compression.ZipFile/System.IO.Compression.ZipFile.slnx +++ b/src/runtime/src/libraries/System.IO.Compression.ZipFile/System.IO.Compression.ZipFile.slnx @@ -1,32 +1,290 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.Compression/System.IO.Compression.slnx b/src/runtime/src/libraries/System.IO.Compression/System.IO.Compression.slnx index b4d9f77110d..2325ce22e7b 100644 --- a/src/runtime/src/libraries/System.IO.Compression/System.IO.Compression.slnx +++ b/src/runtime/src/libraries/System.IO.Compression/System.IO.Compression.slnx @@ -1,32 +1,282 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.FileSystem.AccessControl/System.IO.FileSystem.AccessControl.slnx b/src/runtime/src/libraries/System.IO.FileSystem.AccessControl/System.IO.FileSystem.AccessControl.slnx index 7a373a78e0c..8f10cbb4cb9 100644 --- a/src/runtime/src/libraries/System.IO.FileSystem.AccessControl/System.IO.FileSystem.AccessControl.slnx +++ b/src/runtime/src/libraries/System.IO.FileSystem.AccessControl/System.IO.FileSystem.AccessControl.slnx @@ -52,6 +52,22 @@ + + + + + + + + + + + + + + + + @@ -60,6 +76,22 @@ + + + + + + + + + + + + + + + + @@ -68,6 +100,14 @@ + + + + + + + + @@ -76,6 +116,14 @@ + + + + + + + + @@ -116,6 +164,22 @@ + + + + + + + + + + + + + + + + @@ -141,7 +205,39 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -157,6 +253,14 @@ + + + + + + + + @@ -165,6 +269,14 @@ + + + + + + + + @@ -173,6 +285,22 @@ + + + + + + + + + + + + + + + + @@ -181,6 +309,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -198,6 +350,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.FileSystem.DriveInfo/System.IO.FileSystem.DriveInfo.slnx b/src/runtime/src/libraries/System.IO.FileSystem.DriveInfo/System.IO.FileSystem.DriveInfo.slnx index 10e58898bcc..8dddff37347 100644 --- a/src/runtime/src/libraries/System.IO.FileSystem.DriveInfo/System.IO.FileSystem.DriveInfo.slnx +++ b/src/runtime/src/libraries/System.IO.FileSystem.DriveInfo/System.IO.FileSystem.DriveInfo.slnx @@ -1,31 +1,274 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.FileSystem.Watcher/System.IO.FileSystem.Watcher.slnx b/src/runtime/src/libraries/System.IO.FileSystem.Watcher/System.IO.FileSystem.Watcher.slnx index 7479c081c52..4e5425460e5 100644 --- a/src/runtime/src/libraries/System.IO.FileSystem.Watcher/System.IO.FileSystem.Watcher.slnx +++ b/src/runtime/src/libraries/System.IO.FileSystem.Watcher/System.IO.FileSystem.Watcher.slnx @@ -1,36 +1,386 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.IsolatedStorage/System.IO.IsolatedStorage.slnx b/src/runtime/src/libraries/System.IO.IsolatedStorage/System.IO.IsolatedStorage.slnx index cfae5ca420b..8b9dca24207 100644 --- a/src/runtime/src/libraries/System.IO.IsolatedStorage/System.IO.IsolatedStorage.slnx +++ b/src/runtime/src/libraries/System.IO.IsolatedStorage/System.IO.IsolatedStorage.slnx @@ -18,6 +18,14 @@ + + + + + + + + @@ -44,6 +52,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -52,6 +124,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -60,6 +196,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -68,6 +236,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -76,6 +268,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -101,7 +325,63 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -117,6 +397,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -125,6 +469,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -133,6 +509,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -141,6 +541,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -158,6 +590,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.MemoryMappedFiles/System.IO.MemoryMappedFiles.slnx b/src/runtime/src/libraries/System.IO.MemoryMappedFiles/System.IO.MemoryMappedFiles.slnx index 778d00327a2..d5727f97ffd 100644 --- a/src/runtime/src/libraries/System.IO.MemoryMappedFiles/System.IO.MemoryMappedFiles.slnx +++ b/src/runtime/src/libraries/System.IO.MemoryMappedFiles/System.IO.MemoryMappedFiles.slnx @@ -1,34 +1,298 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.Pipelines/System.IO.Pipelines.slnx b/src/runtime/src/libraries/System.IO.Pipelines/System.IO.Pipelines.slnx index c7d909e1a77..db01326ffc1 100644 --- a/src/runtime/src/libraries/System.IO.Pipelines/System.IO.Pipelines.slnx +++ b/src/runtime/src/libraries/System.IO.Pipelines/System.IO.Pipelines.slnx @@ -1,31 +1,250 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.Pipes.AccessControl/System.IO.Pipes.AccessControl.slnx b/src/runtime/src/libraries/System.IO.Pipes.AccessControl/System.IO.Pipes.AccessControl.slnx index d2af834d4bb..035fd7260d0 100644 --- a/src/runtime/src/libraries/System.IO.Pipes.AccessControl/System.IO.Pipes.AccessControl.slnx +++ b/src/runtime/src/libraries/System.IO.Pipes.AccessControl/System.IO.Pipes.AccessControl.slnx @@ -1,37 +1,562 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.Pipes/System.IO.Pipes.slnx b/src/runtime/src/libraries/System.IO.Pipes/System.IO.Pipes.slnx index b232b982db4..b32b3228c47 100644 --- a/src/runtime/src/libraries/System.IO.Pipes/System.IO.Pipes.slnx +++ b/src/runtime/src/libraries/System.IO.Pipes/System.IO.Pipes.slnx @@ -52,6 +52,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -68,6 +92,22 @@ + + + + + + + + + + + + + + + + @@ -76,6 +116,14 @@ + + + + + + + + @@ -108,6 +156,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -116,6 +212,22 @@ + + + + + + + + + + + + + + + + @@ -132,6 +244,22 @@ + + + + + + + + + + + + + + + + @@ -148,6 +276,22 @@ + + + + + + + + + + + + + + + + @@ -156,6 +300,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -189,7 +365,31 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -205,6 +405,22 @@ + + + + + + + + + + + + + + + + @@ -221,6 +437,14 @@ + + + + + + + + @@ -253,6 +477,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -261,6 +533,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -269,6 +565,22 @@ + + + + + + + + + + + + + + + + @@ -285,6 +597,22 @@ + + + + + + + + + + + + + + + + @@ -293,6 +621,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -310,6 +670,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.IO.Ports/System.IO.Ports.slnx b/src/runtime/src/libraries/System.IO.Ports/System.IO.Ports.slnx index 6e71f023e5a..7ada1d5f80e 100644 --- a/src/runtime/src/libraries/System.IO.Ports/System.IO.Ports.slnx +++ b/src/runtime/src/libraries/System.IO.Ports/System.IO.Ports.slnx @@ -1,50 +1,426 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Linq.AsyncEnumerable/System.Linq.AsyncEnumerable.slnx b/src/runtime/src/libraries/System.Linq.AsyncEnumerable/System.Linq.AsyncEnumerable.slnx index 38aa4ec5fcd..3cbb875fd4f 100644 --- a/src/runtime/src/libraries/System.Linq.AsyncEnumerable/System.Linq.AsyncEnumerable.slnx +++ b/src/runtime/src/libraries/System.Linq.AsyncEnumerable/System.Linq.AsyncEnumerable.slnx @@ -1,37 +1,378 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Linq.Expressions/System.Linq.Expressions.slnx b/src/runtime/src/libraries/System.Linq.Expressions/System.Linq.Expressions.slnx index fa24bd6fe63..d8f9e781a05 100644 --- a/src/runtime/src/libraries/System.Linq.Expressions/System.Linq.Expressions.slnx +++ b/src/runtime/src/libraries/System.Linq.Expressions/System.Linq.Expressions.slnx @@ -1,31 +1,506 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Linq.Parallel/System.Linq.Parallel.slnx b/src/runtime/src/libraries/System.Linq.Parallel/System.Linq.Parallel.slnx index 6a9b53667d7..9b22915d042 100644 --- a/src/runtime/src/libraries/System.Linq.Parallel/System.Linq.Parallel.slnx +++ b/src/runtime/src/libraries/System.Linq.Parallel/System.Linq.Parallel.slnx @@ -1,32 +1,322 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Linq.Queryable/System.Linq.Queryable.slnx b/src/runtime/src/libraries/System.Linq.Queryable/System.Linq.Queryable.slnx index df1f239e0f0..bebd879b5cf 100644 --- a/src/runtime/src/libraries/System.Linq.Queryable/System.Linq.Queryable.slnx +++ b/src/runtime/src/libraries/System.Linq.Queryable/System.Linq.Queryable.slnx @@ -1,33 +1,522 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Linq/System.Linq.slnx b/src/runtime/src/libraries/System.Linq/System.Linq.slnx index c8162ab025f..40fae272387 100644 --- a/src/runtime/src/libraries/System.Linq/System.Linq.slnx +++ b/src/runtime/src/libraries/System.Linq/System.Linq.slnx @@ -1,32 +1,306 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Memory.Data/System.Memory.Data.slnx b/src/runtime/src/libraries/System.Memory.Data/System.Memory.Data.slnx index 94f1a825f58..d16807b1adc 100644 --- a/src/runtime/src/libraries/System.Memory.Data/System.Memory.Data.slnx +++ b/src/runtime/src/libraries/System.Memory.Data/System.Memory.Data.slnx @@ -1,45 +1,754 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Http.Json/System.Net.Http.Json.slnx b/src/runtime/src/libraries/System.Net.Http.Json/System.Net.Http.Json.slnx index a6948e64533..f2c836d9371 100644 --- a/src/runtime/src/libraries/System.Net.Http.Json/System.Net.Http.Json.slnx +++ b/src/runtime/src/libraries/System.Net.Http.Json/System.Net.Http.Json.slnx @@ -1,59 +1,1010 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Http.WinHttpHandler/System.Net.Http.WinHttpHandler.slnx b/src/runtime/src/libraries/System.Net.Http.WinHttpHandler/System.Net.Http.WinHttpHandler.slnx index 20b48b55330..5b7ad4c9582 100644 --- a/src/runtime/src/libraries/System.Net.Http.WinHttpHandler/System.Net.Http.WinHttpHandler.slnx +++ b/src/runtime/src/libraries/System.Net.Http.WinHttpHandler/System.Net.Http.WinHttpHandler.slnx @@ -1,63 +1,1042 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Http/System.Net.Http.slnx b/src/runtime/src/libraries/System.Net.Http/System.Net.Http.slnx index 092cfc4a08c..cd4a62e6c40 100644 --- a/src/runtime/src/libraries/System.Net.Http/System.Net.Http.slnx +++ b/src/runtime/src/libraries/System.Net.Http/System.Net.Http.slnx @@ -68,6 +68,14 @@ + + + + + + + + @@ -76,6 +84,14 @@ + + + + + + + + @@ -92,6 +108,14 @@ + + + + + + + + @@ -100,6 +124,14 @@ + + + + + + + + @@ -124,6 +156,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -132,6 +196,22 @@ + + + + + + + + + + + + + + + + @@ -140,6 +220,14 @@ + + + + + + + + @@ -156,6 +244,14 @@ + + + + + + + + @@ -164,6 +260,14 @@ + + + + + + + + @@ -180,6 +284,14 @@ + + + + + + + + @@ -196,6 +308,22 @@ + + + + + + + + + + + + + + + + @@ -204,6 +332,22 @@ + + + + + + + + + + + + + + + + @@ -212,6 +356,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -245,6 +413,22 @@ + + + + + + + + + + + + + + + + @@ -253,6 +437,22 @@ + + + + + + + + + + + + + + + + @@ -261,6 +461,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -277,6 +501,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -285,6 +613,14 @@ + + + + + + + + @@ -293,6 +629,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -301,6 +661,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -309,6 +709,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.HttpListener/System.Net.HttpListener.slnx b/src/runtime/src/libraries/System.Net.HttpListener/System.Net.HttpListener.slnx index 93a834f8b9d..a645d9b07d2 100644 --- a/src/runtime/src/libraries/System.Net.HttpListener/System.Net.HttpListener.slnx +++ b/src/runtime/src/libraries/System.Net.HttpListener/System.Net.HttpListener.slnx @@ -1,48 +1,946 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Mail/System.Net.Mail.slnx b/src/runtime/src/libraries/System.Net.Mail/System.Net.Mail.slnx index 8bc0871e0ed..0eb97778a78 100644 --- a/src/runtime/src/libraries/System.Net.Mail/System.Net.Mail.slnx +++ b/src/runtime/src/libraries/System.Net.Mail/System.Net.Mail.slnx @@ -1,53 +1,938 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.NameResolution/System.Net.NameResolution.slnx b/src/runtime/src/libraries/System.Net.NameResolution/System.Net.NameResolution.slnx index d31378b110c..daecfaf79aa 100644 --- a/src/runtime/src/libraries/System.Net.NameResolution/System.Net.NameResolution.slnx +++ b/src/runtime/src/libraries/System.Net.NameResolution/System.Net.NameResolution.slnx @@ -1,36 +1,474 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.NetworkInformation/System.Net.NetworkInformation.slnx b/src/runtime/src/libraries/System.Net.NetworkInformation/System.Net.NetworkInformation.slnx index 95a6b7aba68..30c63322741 100644 --- a/src/runtime/src/libraries/System.Net.NetworkInformation/System.Net.NetworkInformation.slnx +++ b/src/runtime/src/libraries/System.Net.NetworkInformation/System.Net.NetworkInformation.slnx @@ -1,35 +1,530 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Ping/System.Net.Ping.slnx b/src/runtime/src/libraries/System.Net.Ping/System.Net.Ping.slnx index 90677118c72..996318f1a4c 100644 --- a/src/runtime/src/libraries/System.Net.Ping/System.Net.Ping.slnx +++ b/src/runtime/src/libraries/System.Net.Ping/System.Net.Ping.slnx @@ -1,41 +1,770 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Primitives/System.Net.Primitives.slnx b/src/runtime/src/libraries/System.Net.Primitives/System.Net.Primitives.slnx index 1adf38dac62..9db1a07d6cf 100644 --- a/src/runtime/src/libraries/System.Net.Primitives/System.Net.Primitives.slnx +++ b/src/runtime/src/libraries/System.Net.Primitives/System.Net.Primitives.slnx @@ -1,36 +1,346 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Quic/System.Net.Quic.slnx b/src/runtime/src/libraries/System.Net.Quic/System.Net.Quic.slnx index c5b48ea70df..38336578f79 100644 --- a/src/runtime/src/libraries/System.Net.Quic/System.Net.Quic.slnx +++ b/src/runtime/src/libraries/System.Net.Quic/System.Net.Quic.slnx @@ -1,42 +1,738 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Requests/System.Net.Requests.slnx b/src/runtime/src/libraries/System.Net.Requests/System.Net.Requests.slnx index 1c8c7d14307..3313719ac56 100644 --- a/src/runtime/src/libraries/System.Net.Requests/System.Net.Requests.slnx +++ b/src/runtime/src/libraries/System.Net.Requests/System.Net.Requests.slnx @@ -18,6 +18,14 @@ + + + + + + + + @@ -60,6 +68,14 @@ + + + + + + + + @@ -68,6 +84,14 @@ + + + + + + + + @@ -108,6 +132,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -124,6 +172,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -132,6 +212,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -140,6 +244,14 @@ + + + + + + + + @@ -148,6 +260,14 @@ + + + + + + + + @@ -156,6 +276,14 @@ + + + + + + + + @@ -172,6 +300,22 @@ + + + + + + + + + + + + + + + + @@ -180,6 +324,14 @@ + + + + + + + + @@ -204,6 +356,22 @@ + + + + + + + + + + + + + + + + @@ -212,6 +380,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -237,6 +453,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -245,6 +485,14 @@ + + + + + + + + @@ -253,6 +501,14 @@ + + + + + + + + @@ -261,6 +517,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -269,6 +565,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -277,6 +701,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -293,6 +757,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Security/System.Net.Security.slnx b/src/runtime/src/libraries/System.Net.Security/System.Net.Security.slnx index aa80c218e39..48139a04e72 100644 --- a/src/runtime/src/libraries/System.Net.Security/System.Net.Security.slnx +++ b/src/runtime/src/libraries/System.Net.Security/System.Net.Security.slnx @@ -68,6 +68,14 @@ + + + + + + + + @@ -84,6 +92,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -100,6 +132,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -108,6 +164,14 @@ + + + + + + + + @@ -116,6 +180,22 @@ + + + + + + + + + + + + + + + + @@ -124,6 +204,14 @@ + + + + + + + + @@ -132,6 +220,14 @@ + + + + + + + + @@ -188,6 +284,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -221,6 +349,14 @@ + + + + + + + + @@ -229,6 +365,14 @@ + + + + + + + + @@ -245,6 +389,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -261,6 +429,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -269,6 +501,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -285,6 +549,14 @@ + + + + + + + + @@ -293,6 +565,14 @@ + + + + + + + + @@ -301,6 +581,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.ServerSentEvents/System.Net.ServerSentEvents.slnx b/src/runtime/src/libraries/System.Net.ServerSentEvents/System.Net.ServerSentEvents.slnx index 20574f56d2c..d5109c9f2c8 100644 --- a/src/runtime/src/libraries/System.Net.ServerSentEvents/System.Net.ServerSentEvents.slnx +++ b/src/runtime/src/libraries/System.Net.ServerSentEvents/System.Net.ServerSentEvents.slnx @@ -1,47 +1,754 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.Sockets/System.Net.Sockets.slnx b/src/runtime/src/libraries/System.Net.Sockets/System.Net.Sockets.slnx index 0c89c0d5bea..cd6713bffc8 100644 --- a/src/runtime/src/libraries/System.Net.Sockets/System.Net.Sockets.slnx +++ b/src/runtime/src/libraries/System.Net.Sockets/System.Net.Sockets.slnx @@ -1,36 +1,522 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.WebClient/System.Net.WebClient.slnx b/src/runtime/src/libraries/System.Net.WebClient/System.Net.WebClient.slnx index 90fb02c334e..eea09d6b638 100644 --- a/src/runtime/src/libraries/System.Net.WebClient/System.Net.WebClient.slnx +++ b/src/runtime/src/libraries/System.Net.WebClient/System.Net.WebClient.slnx @@ -1,47 +1,946 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.WebHeaderCollection/System.Net.WebHeaderCollection.slnx b/src/runtime/src/libraries/System.Net.WebHeaderCollection/System.Net.WebHeaderCollection.slnx index a34a1950ff5..ceb6c3277de 100644 --- a/src/runtime/src/libraries/System.Net.WebHeaderCollection/System.Net.WebHeaderCollection.slnx +++ b/src/runtime/src/libraries/System.Net.WebHeaderCollection/System.Net.WebHeaderCollection.slnx @@ -1,35 +1,314 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.WebProxy/System.Net.WebProxy.slnx b/src/runtime/src/libraries/System.Net.WebProxy/System.Net.WebProxy.slnx index 5a30979cf64..b98eae4930e 100644 --- a/src/runtime/src/libraries/System.Net.WebProxy/System.Net.WebProxy.slnx +++ b/src/runtime/src/libraries/System.Net.WebProxy/System.Net.WebProxy.slnx @@ -1,37 +1,698 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.WebSockets.Client/System.Net.WebSockets.Client.slnx b/src/runtime/src/libraries/System.Net.WebSockets.Client/System.Net.WebSockets.Client.slnx index c3ba39587cb..b8bee4eafde 100644 --- a/src/runtime/src/libraries/System.Net.WebSockets.Client/System.Net.WebSockets.Client.slnx +++ b/src/runtime/src/libraries/System.Net.WebSockets.Client/System.Net.WebSockets.Client.slnx @@ -26,6 +26,14 @@ + + + + + + + + @@ -60,6 +68,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -100,6 +132,14 @@ + + + + + + + + @@ -108,6 +148,22 @@ + + + + + + + + + + + + + + + + @@ -116,6 +172,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -132,6 +220,22 @@ + + + + + + + + + + + + + + + + @@ -140,6 +244,14 @@ + + + + + + + + @@ -156,6 +268,14 @@ + + + + + + + + @@ -164,6 +284,14 @@ + + + + + + + + @@ -180,6 +308,14 @@ + + + + + + + + @@ -196,6 +332,14 @@ + + + + + + + + @@ -212,6 +356,22 @@ + + + + + + + + + + + + + + + + @@ -220,6 +380,22 @@ + + + + + + + + + + + + + + + + @@ -228,6 +404,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -261,6 +461,246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -269,6 +709,14 @@ + + + + + + + + @@ -277,6 +725,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -285,6 +757,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -293,6 +805,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Net.WebSockets/System.Net.WebSockets.slnx b/src/runtime/src/libraries/System.Net.WebSockets/System.Net.WebSockets.slnx index a038728b9e6..ae484296a87 100644 --- a/src/runtime/src/libraries/System.Net.WebSockets/System.Net.WebSockets.slnx +++ b/src/runtime/src/libraries/System.Net.WebSockets/System.Net.WebSockets.slnx @@ -1,40 +1,618 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.ObjectModel/System.ObjectModel.slnx b/src/runtime/src/libraries/System.ObjectModel/System.ObjectModel.slnx index 3dae700e442..78c35d02f4a 100644 --- a/src/runtime/src/libraries/System.ObjectModel/System.ObjectModel.slnx +++ b/src/runtime/src/libraries/System.ObjectModel/System.ObjectModel.slnx @@ -76,6 +76,14 @@ + + + + + + + + @@ -157,6 +165,14 @@ + + + + + + + + diff --git a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index de14da6dd01..b68bf0403eb 100644 --- a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -1442,7 +1442,10 @@ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* rel if (ex is EventSourceException) throw; else - ThrowEventSourceException(m_eventData[eventId].Name, ex); + { + ref EventMetadata metadata = ref CollectionsMarshal.GetValueRefOrNullRef(m_eventData, eventId); + ThrowEventSourceException(metadata.Name, ex); + } } } } @@ -2072,7 +2075,10 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object if (ex is EventSourceException) throw; else - ThrowEventSourceException(m_eventData[eventId].Name, ex); + { + ref EventMetadata metadata = ref CollectionsMarshal.GetValueRefOrNullRef(m_eventData, eventId); + ThrowEventSourceException(metadata.Name, ex); + } } } } @@ -2084,7 +2090,8 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object private object?[] SerializeEventArgs(int eventId, object?[] args) { Debug.Assert(m_eventData != null); - TraceLoggingEventTypes eventTypes = m_eventData[eventId].TraceLoggingEventTypes; + ref EventMetadata metadata = ref CollectionsMarshal.GetValueRefOrNullRef(m_eventData, eventId); + TraceLoggingEventTypes eventTypes = metadata.TraceLoggingEventTypes; int paramCount = Math.Min(eventTypes.typeInfos.Length, args.Length); // parameter count mismatch get logged in LogEventArgsMismatches var eventData = new object?[eventTypes.typeInfos.Length]; for (int i = 0; i < paramCount; i++) @@ -2103,7 +2110,8 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object private void LogEventArgsMismatches(int eventId, object?[] args) { Debug.Assert(m_eventData != null); - ParameterInfo[] infos = m_eventData[eventId].Parameters; + ref EventMetadata metadata = ref CollectionsMarshal.GetValueRefOrNullRef(m_eventData, eventId); + ParameterInfo[] infos = metadata.Parameters; if (args.Length != infos.Length) { @@ -2360,9 +2368,10 @@ private bool IsEnabledByDefault(int eventNum, bool enable, EventLevel currentLev return false; Debug.Assert(m_eventData != null); - EventLevel eventLevel = (EventLevel)m_eventData[eventNum].Descriptor.Level; - EventKeywords eventKeywords = unchecked((EventKeywords)((ulong)m_eventData[eventNum].Descriptor.Keywords & (~(SessionMask.All.ToEventKeywords())))); - EventChannel channel = unchecked((EventChannel)m_eventData[eventNum].Descriptor.Channel); + ref EventMetadata metadata = ref CollectionsMarshal.GetValueRefOrNullRef(m_eventData, eventNum); + EventLevel eventLevel = (EventLevel)metadata.Descriptor.Level; + EventKeywords eventKeywords = unchecked((EventKeywords)((ulong)metadata.Descriptor.Keywords & (~(SessionMask.All.ToEventKeywords())))); + EventChannel channel = unchecked((EventChannel)metadata.Descriptor.Channel); return IsEnabledCommon(enable, currentLevel, currentMatchAnyKeyword, eventLevel, eventKeywords, channel); } diff --git a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index 1157c428f3b..f37e70545e9 100644 --- a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -5701,7 +5701,7 @@ internal Arm64() { } /// svint16_t svldnf1ub_s16(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt16(byte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt16(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and zero-extend, non-faulting @@ -5710,7 +5710,7 @@ internal Arm64() { } /// svint32_t svldnf1ub_s32(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt32(byte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt32(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and zero-extend, non-faulting @@ -5719,7 +5719,7 @@ internal Arm64() { } /// svint64_t svldnf1ub_s64(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt64(byte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt64(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and zero-extend, non-faulting @@ -5728,7 +5728,7 @@ internal Arm64() { } /// svuint16_t svldnf1ub_u16(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt16(byte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt16(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and zero-extend, non-faulting @@ -5737,7 +5737,7 @@ internal Arm64() { } /// svuint32_t svldnf1ub_u32(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt32(byte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt32(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and zero-extend, non-faulting @@ -5746,7 +5746,7 @@ internal Arm64() { } /// svuint64_t svldnf1ub_u64(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt64(byte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt64(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } /// @@ -5909,7 +5909,7 @@ internal Arm64() { } /// svint32_t svldnf1sh_s32(svbool_t pg, const int16_t *base) /// LDNF1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToInt32(short* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToInt32(Vector mask, short* address) { throw new PlatformNotSupportedException(); } // Load 16-bit data and sign-extend, non-faulting @@ -5918,7 +5918,7 @@ internal Arm64() { } /// svint64_t svldnf1sh_s64(svbool_t pg, const int16_t *base) /// LDNF1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToInt64(short* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToInt64(Vector mask, short* address) { throw new PlatformNotSupportedException(); } // Load 16-bit data and sign-extend, non-faulting @@ -5927,7 +5927,7 @@ internal Arm64() { } /// svuint32_t svldnf1sh_u32(svbool_t pg, const int16_t *base) /// LDNF1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToUInt32(short* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToUInt32(Vector mask, short* address) { throw new PlatformNotSupportedException(); } // Load 16-bit data and sign-extend, non-faulting @@ -5936,7 +5936,7 @@ internal Arm64() { } /// svuint64_t svldnf1sh_u64(svbool_t pg, const int16_t *base) /// LDNF1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToUInt64(short* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToUInt64(Vector mask, short* address) { throw new PlatformNotSupportedException(); } // Load 16-bit data and sign-extend, first-faulting @@ -6008,7 +6008,7 @@ internal Arm64() { } /// svint64_t svldnf1sw_s64(svbool_t pg, const int32_t *base) /// LDNF1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt32NonFaultingSignExtendToInt64(int* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorInt32NonFaultingSignExtendToInt64(Vector mask, int* address) { throw new PlatformNotSupportedException(); } // Load 32-bit data and sign-extend, non-faulting @@ -6017,7 +6017,7 @@ internal Arm64() { } /// svuint64_t svldnf1sw_u64(svbool_t pg, const int32_t *base) /// LDNF1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt32NonFaultingSignExtendToUInt64(int* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorInt32NonFaultingSignExtendToUInt64(Vector mask, int* address) { throw new PlatformNotSupportedException(); } // Load 32-bit data and sign-extend, first-faulting @@ -6059,61 +6059,61 @@ internal Arm64() { } /// svuint8_t svldnf1[_u8](svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(byte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } /// /// svfloat64_t svldnf1[_f64](svbool_t pg, const float64_t *base) /// LDNF1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(double* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, double* address) { throw new PlatformNotSupportedException(); } /// /// svint16_t svldnf1[_s16](svbool_t pg, const int16_t *base) /// LDNF1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(short* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, short* address) { throw new PlatformNotSupportedException(); } /// /// svint32_t svldnf1[_s32](svbool_t pg, const int32_t *base) /// LDNF1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(int* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, int* address) { throw new PlatformNotSupportedException(); } /// /// svint64_t svldnf1[_s64](svbool_t pg, const int64_t *base) /// LDNF1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(long* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, long* address) { throw new PlatformNotSupportedException(); } /// /// svint8_t svldnf1[_s8](svbool_t pg, const int8_t *base) /// LDNF1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(sbyte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } /// /// svfloat32_t svldnf1[_f32](svbool_t pg, const float32_t *base) /// LDNF1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(float* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, float* address) { throw new PlatformNotSupportedException(); } /// /// svuint16_t svldnf1[_u16](svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(ushort* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } /// /// svuint32_t svldnf1[_u32](svbool_t pg, const uint32_t *base) /// LDNF1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(uint* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } /// /// svuint64_t svldnf1[_u64](svbool_t pg, const uint64_t *base) /// LDNF1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(ulong* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorNonFaulting(Vector mask, ulong* address) { throw new PlatformNotSupportedException(); } // Unextended load, non-temporal @@ -6185,7 +6185,7 @@ internal Arm64() { } /// svint16_t svldnf1sb_s16(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt16(sbyte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt16(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and sign-extend, non-faulting @@ -6194,7 +6194,7 @@ internal Arm64() { } /// svint32_t svldnf1sb_s32(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt32(sbyte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt32(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and sign-extend, non-faulting @@ -6203,7 +6203,7 @@ internal Arm64() { } /// svint64_t svldnf1sb_s64(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt64(sbyte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt64(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and sign-extend, non-faulting @@ -6212,7 +6212,7 @@ internal Arm64() { } /// svuint16_t svldnf1sb_u16(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt16(sbyte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt16(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and sign-extend, non-faulting @@ -6221,7 +6221,7 @@ internal Arm64() { } /// svuint32_t svldnf1sb_u32(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt32(sbyte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt32(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and sign-extend, non-faulting @@ -6230,7 +6230,7 @@ internal Arm64() { } /// svuint64_t svldnf1sb_u64(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt64(sbyte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt64(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } // Load 8-bit data and sign-extend, first-faulting @@ -6332,7 +6332,7 @@ internal Arm64() { } /// svint32_t svldnf1uh_s32(svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToInt32(ushort* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToInt32(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } // Load 16-bit data and zero-extend, non-faulting @@ -6341,7 +6341,7 @@ internal Arm64() { } /// svint64_t svldnf1uh_s64(svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToInt64(ushort* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToInt64(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } // Load 16-bit data and zero-extend, non-faulting @@ -6350,7 +6350,7 @@ internal Arm64() { } /// svuint32_t svldnf1uh_u32(svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToUInt32(ushort* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToUInt32(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } // Load 16-bit data and zero-extend, non-faulting @@ -6359,7 +6359,7 @@ internal Arm64() { } /// svuint64_t svldnf1uh_u64(svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToUInt64(ushort* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToUInt64(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } // Load 16-bit data and zero-extend, first-faulting @@ -6431,7 +6431,7 @@ internal Arm64() { } /// svint64_t svldnf1uw_s64(svbool_t pg, const uint32_t *base) /// LDNF1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt32NonFaultingZeroExtendToInt64(uint* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorUInt32NonFaultingZeroExtendToInt64(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } // Load 32-bit data and zero-extend, non-faulting @@ -6440,7 +6440,7 @@ internal Arm64() { } /// svuint64_t svldnf1uw_u64(svbool_t pg, const uint32_t *base) /// LDNF1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt32NonFaultingZeroExtendToUInt64(uint* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector LoadVectorUInt32NonFaultingZeroExtendToUInt64(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } // Load 32-bit data and zero-extend, first-faulting diff --git a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index dc8c6341fb1..bd5069e9366 100644 --- a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -5698,7 +5698,7 @@ internal Arm64() { } /// svint16_t svldnf1ub_s16(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt16(byte* address) => LoadVectorByteNonFaultingZeroExtendToInt16(address); + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt16(Vector mask, byte* address) => LoadVectorByteNonFaultingZeroExtendToInt16(mask, address); // Load 8-bit data and zero-extend, non-faulting @@ -5707,7 +5707,7 @@ internal Arm64() { } /// svint32_t svldnf1ub_s32(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt32(byte* address) => LoadVectorByteNonFaultingZeroExtendToInt32(address); + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt32(Vector mask, byte* address) => LoadVectorByteNonFaultingZeroExtendToInt32(mask, address); // Load 8-bit data and zero-extend, non-faulting @@ -5716,7 +5716,7 @@ internal Arm64() { } /// svint64_t svldnf1ub_s64(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt64(byte* address) => LoadVectorByteNonFaultingZeroExtendToInt64(address); + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToInt64(Vector mask, byte* address) => LoadVectorByteNonFaultingZeroExtendToInt64(mask, address); // Load 8-bit data and zero-extend, non-faulting @@ -5725,7 +5725,7 @@ internal Arm64() { } /// svuint16_t svldnf1ub_u16(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt16(byte* address) => LoadVectorByteNonFaultingZeroExtendToUInt16(address); + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt16(Vector mask, byte* address) => LoadVectorByteNonFaultingZeroExtendToUInt16(mask, address); // Load 8-bit data and zero-extend, non-faulting @@ -5734,7 +5734,7 @@ internal Arm64() { } /// svuint32_t svldnf1ub_u32(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt32(byte* address) => LoadVectorByteNonFaultingZeroExtendToUInt32(address); + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt32(Vector mask, byte* address) => LoadVectorByteNonFaultingZeroExtendToUInt32(mask, address); // Load 8-bit data and zero-extend, non-faulting @@ -5743,7 +5743,7 @@ internal Arm64() { } /// svuint64_t svldnf1ub_u64(svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt64(byte* address) => LoadVectorByteNonFaultingZeroExtendToUInt64(address); + public static unsafe Vector LoadVectorByteNonFaultingZeroExtendToUInt64(Vector mask, byte* address) => LoadVectorByteNonFaultingZeroExtendToUInt64(mask, address); /// @@ -5904,7 +5904,7 @@ internal Arm64() { } /// svint32_t svldnf1sh_s32(svbool_t pg, const int16_t *base) /// LDNF1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToInt32(short* address) => LoadVectorInt16NonFaultingSignExtendToInt32(address); + public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToInt32(Vector mask, short* address) => LoadVectorInt16NonFaultingSignExtendToInt32(mask, address); // Load 16-bit data and sign-extend, non-faulting @@ -5913,7 +5913,7 @@ internal Arm64() { } /// svint64_t svldnf1sh_s64(svbool_t pg, const int16_t *base) /// LDNF1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToInt64(short* address) => LoadVectorInt16NonFaultingSignExtendToInt64(address); + public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToInt64(Vector mask, short* address) => LoadVectorInt16NonFaultingSignExtendToInt64(mask, address); // Load 16-bit data and sign-extend, non-faulting @@ -5922,7 +5922,7 @@ internal Arm64() { } /// svuint32_t svldnf1sh_u32(svbool_t pg, const int16_t *base) /// LDNF1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToUInt32(short* address) => LoadVectorInt16NonFaultingSignExtendToUInt32(address); + public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToUInt32(Vector mask, short* address) => LoadVectorInt16NonFaultingSignExtendToUInt32(mask, address); // Load 16-bit data and sign-extend, non-faulting @@ -5931,7 +5931,7 @@ internal Arm64() { } /// svuint64_t svldnf1sh_u64(svbool_t pg, const int16_t *base) /// LDNF1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToUInt64(short* address) => LoadVectorInt16NonFaultingSignExtendToUInt64(address); + public static unsafe Vector LoadVectorInt16NonFaultingSignExtendToUInt64(Vector mask, short* address) => LoadVectorInt16NonFaultingSignExtendToUInt64(mask, address); /// Load 16-bit data and sign-extend, first-faulting @@ -6003,7 +6003,7 @@ internal Arm64() { } /// svint64_t svldnf1sw_s64(svbool_t pg, const int32_t *base) /// LDNF1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt32NonFaultingSignExtendToInt64(int* address) => LoadVectorInt32NonFaultingSignExtendToInt64(address); + public static unsafe Vector LoadVectorInt32NonFaultingSignExtendToInt64(Vector mask, int* address) => LoadVectorInt32NonFaultingSignExtendToInt64(mask, address); // Load 32-bit data and sign-extend, non-faulting @@ -6012,7 +6012,7 @@ internal Arm64() { } /// svuint64_t svldnf1sw_u64(svbool_t pg, const int32_t *base) /// LDNF1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorInt32NonFaultingSignExtendToUInt64(int* address) => LoadVectorInt32NonFaultingSignExtendToUInt64(address); + public static unsafe Vector LoadVectorInt32NonFaultingSignExtendToUInt64(Vector mask, int* address) => LoadVectorInt32NonFaultingSignExtendToUInt64(mask, address); /// Load 32-bit data and sign-extend, first-faulting @@ -6054,61 +6054,61 @@ internal Arm64() { } /// svuint8_t svldnf1[_u8](svbool_t pg, const uint8_t *base) /// LDNF1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(byte* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, byte* address) => LoadVectorNonFaulting(mask, address); /// /// svfloat64_t svldnf1[_f64](svbool_t pg, const float64_t *base) /// LDNF1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(double* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, double* address) => LoadVectorNonFaulting(mask, address); /// /// svint16_t svldnf1[_s16](svbool_t pg, const int16_t *base) /// LDNF1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(short* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, short* address) => LoadVectorNonFaulting(mask, address); /// /// svint32_t svldnf1[_s32](svbool_t pg, const int32_t *base) /// LDNF1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(int* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, int* address) => LoadVectorNonFaulting(mask, address); /// /// svint64_t svldnf1[_s64](svbool_t pg, const int64_t *base) /// LDNF1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(long* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, long* address) => LoadVectorNonFaulting(mask, address); /// /// svint8_t svldnf1[_s8](svbool_t pg, const int8_t *base) /// LDNF1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(sbyte* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, sbyte* address) => LoadVectorNonFaulting(mask, address); /// /// svfloat32_t svldnf1[_f32](svbool_t pg, const float32_t *base) /// LDNF1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(float* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, float* address) => LoadVectorNonFaulting(mask, address); /// /// svuint16_t svldnf1[_u16](svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(ushort* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, ushort* address) => LoadVectorNonFaulting(mask, address); /// /// svuint32_t svldnf1[_u32](svbool_t pg, const uint32_t *base) /// LDNF1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(uint* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, uint* address) => LoadVectorNonFaulting(mask, address); /// /// svuint64_t svldnf1[_u64](svbool_t pg, const uint64_t *base) /// LDNF1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorNonFaulting(ulong* address) => LoadVectorNonFaulting(address); + public static unsafe Vector LoadVectorNonFaulting(Vector mask, ulong* address) => LoadVectorNonFaulting(mask, address); // Unextended load, non-temporal @@ -6180,7 +6180,7 @@ internal Arm64() { } /// svint16_t svldnf1sb_s16(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt16(sbyte* address) => LoadVectorSByteNonFaultingSignExtendToInt16(address); + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt16(Vector mask, sbyte* address) => LoadVectorSByteNonFaultingSignExtendToInt16(mask, address); // Load 8-bit data and sign-extend, non-faulting @@ -6189,7 +6189,7 @@ internal Arm64() { } /// svint32_t svldnf1sb_s32(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt32(sbyte* address) => LoadVectorSByteNonFaultingSignExtendToInt32(address); + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt32(Vector mask, sbyte* address) => LoadVectorSByteNonFaultingSignExtendToInt32(mask, address); // Load 8-bit data and sign-extend, non-faulting @@ -6198,7 +6198,7 @@ internal Arm64() { } /// svint64_t svldnf1sb_s64(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt64(sbyte* address) => LoadVectorSByteNonFaultingSignExtendToInt64(address); + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToInt64(Vector mask, sbyte* address) => LoadVectorSByteNonFaultingSignExtendToInt64(mask, address); // Load 8-bit data and sign-extend, non-faulting @@ -6207,7 +6207,7 @@ internal Arm64() { } /// svuint16_t svldnf1sb_u16(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt16(sbyte* address) => LoadVectorSByteNonFaultingSignExtendToUInt16(address); + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt16(Vector mask, sbyte* address) => LoadVectorSByteNonFaultingSignExtendToUInt16(mask, address); // Load 8-bit data and sign-extend, non-faulting @@ -6216,7 +6216,7 @@ internal Arm64() { } /// svuint32_t svldnf1sb_u32(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt32(sbyte* address) => LoadVectorSByteNonFaultingSignExtendToUInt32(address); + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt32(Vector mask, sbyte* address) => LoadVectorSByteNonFaultingSignExtendToUInt32(mask, address); // Load 8-bit data and sign-extend, non-faulting @@ -6225,7 +6225,7 @@ internal Arm64() { } /// svuint64_t svldnf1sb_u64(svbool_t pg, const int8_t *base) /// LDNF1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt64(sbyte* address) => LoadVectorSByteNonFaultingSignExtendToUInt64(address); + public static unsafe Vector LoadVectorSByteNonFaultingSignExtendToUInt64(Vector mask, sbyte* address) => LoadVectorSByteNonFaultingSignExtendToUInt64(mask, address); /// Load 8-bit data and sign-extend, first-faulting @@ -6327,7 +6327,7 @@ internal Arm64() { } /// svint32_t svldnf1uh_s32(svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToInt32(ushort* address) => LoadVectorUInt16NonFaultingZeroExtendToInt32(address); + public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToInt32(Vector mask, ushort* address) => LoadVectorUInt16NonFaultingZeroExtendToInt32(mask, address); // Load 16-bit data and zero-extend, non-faulting @@ -6336,7 +6336,7 @@ internal Arm64() { } /// svint64_t svldnf1uh_s64(svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToInt64(ushort* address) => LoadVectorUInt16NonFaultingZeroExtendToInt64(address); + public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToInt64(Vector mask, ushort* address) => LoadVectorUInt16NonFaultingZeroExtendToInt64(mask, address); // Load 16-bit data and zero-extend, non-faulting @@ -6345,7 +6345,7 @@ internal Arm64() { } /// svuint32_t svldnf1uh_u32(svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToUInt32(ushort* address) => LoadVectorUInt16NonFaultingZeroExtendToUInt32(address); + public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToUInt32(Vector mask, ushort* address) => LoadVectorUInt16NonFaultingZeroExtendToUInt32(mask, address); // Load 16-bit data and zero-extend, non-faulting @@ -6354,7 +6354,7 @@ internal Arm64() { } /// svuint64_t svldnf1uh_u64(svbool_t pg, const uint16_t *base) /// LDNF1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToUInt64(ushort* address) => LoadVectorUInt16NonFaultingZeroExtendToUInt64(address); + public static unsafe Vector LoadVectorUInt16NonFaultingZeroExtendToUInt64(Vector mask, ushort* address) => LoadVectorUInt16NonFaultingZeroExtendToUInt64(mask, address); /// @@ -6424,7 +6424,7 @@ internal Arm64() { } /// svint64_t svldnf1uw_s64(svbool_t pg, const uint32_t *base) /// LDNF1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt32NonFaultingZeroExtendToInt64(uint* address) => LoadVectorUInt32NonFaultingZeroExtendToInt64(address); + public static unsafe Vector LoadVectorUInt32NonFaultingZeroExtendToInt64(Vector mask, uint* address) => LoadVectorUInt32NonFaultingZeroExtendToInt64(mask, address); // Load 32-bit data and zero-extend, non-faulting @@ -6433,7 +6433,7 @@ internal Arm64() { } /// svuint64_t svldnf1uw_u64(svbool_t pg, const uint32_t *base) /// LDNF1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] /// - public static unsafe Vector LoadVectorUInt32NonFaultingZeroExtendToUInt64(uint* address) => LoadVectorUInt32NonFaultingZeroExtendToUInt64(address); + public static unsafe Vector LoadVectorUInt32NonFaultingZeroExtendToUInt64(Vector mask, uint* address) => LoadVectorUInt32NonFaultingZeroExtendToUInt64(mask, address); /// diff --git a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs index 8e5b0f107cb..f909cd61615 100644 --- a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs +++ b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs @@ -426,7 +426,7 @@ internal Arm64() { } /// SADALP Ztied1.H, Pg/M, Zop2.B /// SADALP Ztied1.H, Pg/M, Zop2.B /// - public static Vector AddPairwiseWidening(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint32_t svadalp[_s32]_m(svbool_t pg, svint32_t op1, svint16_t op2) @@ -435,7 +435,7 @@ internal Arm64() { } /// SADALP Ztied1.S, Pg/M, Zop2.H /// SADALP Ztied1.S, Pg/M, Zop2.H /// - public static Vector AddPairwiseWidening(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint64_t svadalp[_s64]_m(svbool_t pg, svint64_t op1, svint32_t op2) @@ -444,7 +444,7 @@ internal Arm64() { } /// SADALP Ztied1.D, Pg/M, Zop2.S /// SADALP Ztied1.D, Pg/M, Zop2.S /// - public static Vector AddPairwiseWidening(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint16_t svadalp[_u16]_m(svbool_t pg, svuint16_t op1, svuint8_t op2) @@ -453,7 +453,7 @@ internal Arm64() { } /// UADALP Ztied1.H, Pg/M, Zop2.B /// UADALP Ztied1.H, Pg/M, Zop2.B /// - public static Vector AddPairwiseWidening(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint32_t svadalp[_u32]_m(svbool_t pg, svuint32_t op1, svuint16_t op2) @@ -462,7 +462,7 @@ internal Arm64() { } /// UADALP Ztied1.S, Pg/M, Zop2.H /// UADALP Ztied1.S, Pg/M, Zop2.H /// - public static Vector AddPairwiseWidening(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint64_t svadalp[_u64]_m(svbool_t pg, svuint64_t op1, svuint32_t op2) @@ -471,7 +471,7 @@ internal Arm64() { } /// UADALP Ztied1.D, Pg/M, Zop2.S /// UADALP Ztied1.D, Pg/M, Zop2.S /// - public static Vector AddPairwiseWidening(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } // Saturating add @@ -637,113 +637,73 @@ internal Arm64() { } /// svint16_t svaddwb[_s16](svint16_t op1, svint8_t op2) /// SADDWB Zresult.H, Zop1.H, Zop2.B /// - public static Vector AddWideLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint32_t svaddwb[_s32](svint32_t op1, svint16_t op2) /// SADDWB Zresult.S, Zop1.S, Zop2.H /// - public static Vector AddWideLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint64_t svaddwb[_s64](svint64_t op1, svint32_t op2) /// SADDWB Zresult.D, Zop1.D, Zop2.S /// - public static Vector AddWideLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint16_t svaddwb[_u16](svuint16_t op1, svuint8_t op2) /// UADDWB Zresult.H, Zop1.H, Zop2.B /// - public static Vector AddWideLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint32_t svaddwb[_u32](svuint32_t op1, svuint16_t op2) /// UADDWB Zresult.S, Zop1.S, Zop2.H /// - public static Vector AddWideLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint64_t svaddwb[_u64](svuint64_t op1, svuint32_t op2) /// UADDWB Zresult.D, Zop1.D, Zop2.S /// - public static Vector AddWideLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - // Add wide (top) - - /// - /// svint16_t svaddwt[_s16](svint16_t op1, svint8_t op2) - /// SADDWT Zresult.H, Zop1.H, Zop2.B - /// - public static Vector AddWideUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svint32_t svaddwt[_s32](svint32_t op1, svint16_t op2) - /// SADDWT Zresult.S, Zop1.S, Zop2.H - /// - public static Vector AddWideUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svint64_t svaddwt[_s64](svint64_t op1, svint32_t op2) - /// SADDWT Zresult.D, Zop1.D, Zop2.S - /// - public static Vector AddWideUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svuint16_t svaddwt[_u16](svuint16_t op1, svuint8_t op2) - /// UADDWT Zresult.H, Zop1.H, Zop2.B - /// - public static Vector AddWideUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svuint32_t svaddwt[_u32](svuint32_t op1, svuint16_t op2) - /// UADDWT Zresult.S, Zop1.S, Zop2.H - /// - public static Vector AddWideUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - /// - /// svuint64_t svaddwt[_u64](svuint64_t op1, svuint32_t op2) - /// UADDWT Zresult.D, Zop1.D, Zop2.S - /// - public static Vector AddWideUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - - // Add long (bottom) + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint16_t svaddlb[_s16](svint8_t op1, svint8_t op2) /// SADDLB Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint32_t svaddlb[_s32](svint16_t op1, svint16_t op2) /// SADDLB Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint64_t svaddlb[_s64](svint32_t op1, svint32_t op2) /// SADDLB Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint16_t svaddlb[_u16](svuint8_t op1, svuint8_t op2) /// UADDLB Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint32_t svaddlb[_u32](svuint16_t op1, svuint16_t op2) /// UADDLB Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint64_t svaddlb[_u64](svuint32_t op1, svuint32_t op2) /// UADDLB Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningLower(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } // Add long (bottom + top) @@ -751,57 +711,93 @@ internal Arm64() { } /// svint16_t svaddlbt[_s16](svint8_t op1, svint8_t op2) /// SADDLBT Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningLowerUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEvenOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint32_t svaddlbt[_s32](svint16_t op1, svint16_t op2) /// SADDLBT Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningLowerUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEvenOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint64_t svaddlbt[_s64](svint32_t op1, svint32_t op2) /// SADDLBT Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningLowerUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEvenOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + // Add wide (top) + + /// + /// svint16_t svaddwt[_s16](svint16_t op1, svint8_t op2) + /// SADDWT Zresult.H, Zop1.H, Zop2.B + /// + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svaddwt[_s32](svint32_t op1, svint16_t op2) + /// SADDWT Zresult.S, Zop1.S, Zop2.H + /// + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svaddwt[_s64](svint64_t op1, svint32_t op2) + /// SADDWT Zresult.D, Zop1.D, Zop2.S + /// + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svaddwt[_u16](svuint16_t op1, svuint8_t op2) + /// UADDWT Zresult.H, Zop1.H, Zop2.B + /// + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svaddwt[_u32](svuint32_t op1, svuint16_t op2) + /// UADDWT Zresult.S, Zop1.S, Zop2.H + /// + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - // Add long (top) + /// + /// svuint64_t svaddwt[_u64](svuint64_t op1, svuint32_t op2) + /// UADDWT Zresult.D, Zop1.D, Zop2.S + /// + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint16_t svaddlt[_s16](svint8_t op1, svint8_t op2) /// SADDLT Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint32_t svaddlt[_s32](svint16_t op1, svint16_t op2) /// SADDLT Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svint64_t svaddlt[_s64](svint32_t op1, svint32_t op2) /// SADDLT Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint16_t svaddlt[_u16](svuint8_t op1, svuint8_t op2) /// UADDLT Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint32_t svaddlt[_u32](svuint16_t op1, svuint16_t op2) /// UADDLT Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// /// svuint64_t svaddlt[_u64](svuint32_t op1, svuint32_t op2) /// UADDLT Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningUpper(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } // Bitwise clear and exclusive OR @@ -1006,6 +1002,170 @@ internal Arm64() { } /// public static Vector BitwiseSelectRightInverted(Vector select, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + // Halving add + + /// + /// svuint8_t svhadd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svhadd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svhadd[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UHADD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UHADD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UHADD Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static Vector FusedAddHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svhadd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svhadd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svhadd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SHADD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SHADD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SHADD Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static Vector FusedAddHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svhadd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svhadd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svhadd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SHADD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SHADD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SHADD Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static Vector FusedAddHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svhadd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svhadd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svhadd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SHADD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SHADD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SHADD Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static Vector FusedAddHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svhadd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svhadd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svhadd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SHADD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SHADD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SHADD Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static Vector FusedAddHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svhadd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svhadd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svhadd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UHADD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UHADD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UHADD Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static Vector FusedAddHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svhadd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svhadd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svhadd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UHADD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UHADD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UHADD Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static Vector FusedAddHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svhadd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svhadd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svhadd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UHADD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UHADD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UHADD Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static Vector FusedAddHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + // Halving subtract + + /// + /// svuint8_t svhsub[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svhsub[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svhsub[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UHSUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UHSUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UHSUBR Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svhsub[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svhsub[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svhsub[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SHSUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SHSUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SHSUBR Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svhsub[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svhsub[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svhsub[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SHSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SHSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SHSUBR Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svhsub[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svhsub[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svhsub[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SHSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SHSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SHSUBR Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svhsub[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svhsub[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svhsub[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SHSUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SHSUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SHSUBR Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svhsub[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svhsub[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svhsub[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UHSUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UHSUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UHSUBR Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svhsub[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svhsub[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svhsub[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UHSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UHSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UHSUBR Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svhsub[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svhsub[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svhsub[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UHSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UHSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UHSUBR Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// Interleaving Xor /// diff --git a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs index 6c1f6a22226..bab0e4e55dd 100644 --- a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs +++ b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs @@ -425,7 +425,7 @@ internal Arm64() { } /// SADALP Ztied1.H, Pg/M, Zop2.B /// SADALP Ztied1.H, Pg/M, Zop2.B /// - public static Vector AddPairwiseWidening(Vector left, Vector right) => AddPairwiseWidening(left, right); + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) => AddPairwiseWideningAndAdd(left, right); /// /// svint32_t svadalp[_s32]_m(svbool_t pg, svint32_t op1, svint16_t op2) @@ -434,7 +434,7 @@ internal Arm64() { } /// SADALP Ztied1.S, Pg/M, Zop2.H /// SADALP Ztied1.S, Pg/M, Zop2.H /// - public static Vector AddPairwiseWidening(Vector left, Vector right) => AddPairwiseWidening(left, right); + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) => AddPairwiseWideningAndAdd(left, right); /// /// svint64_t svadalp[_s64]_m(svbool_t pg, svint64_t op1, svint32_t op2) @@ -443,7 +443,7 @@ internal Arm64() { } /// SADALP Ztied1.D, Pg/M, Zop2.S /// SADALP Ztied1.D, Pg/M, Zop2.S /// - public static Vector AddPairwiseWidening(Vector left, Vector right) => AddPairwiseWidening(left, right); + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) => AddPairwiseWideningAndAdd(left, right); /// /// svuint16_t svadalp[_u16]_m(svbool_t pg, svuint16_t op1, svuint8_t op2) @@ -452,7 +452,7 @@ internal Arm64() { } /// UADALP Ztied1.H, Pg/M, Zop2.B /// UADALP Ztied1.H, Pg/M, Zop2.B /// - public static Vector AddPairwiseWidening(Vector left, Vector right) => AddPairwiseWidening(left, right); + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) => AddPairwiseWideningAndAdd(left, right); /// /// svuint32_t svadalp[_u32]_m(svbool_t pg, svuint32_t op1, svuint16_t op2) @@ -461,7 +461,7 @@ internal Arm64() { } /// UADALP Ztied1.S, Pg/M, Zop2.H /// UADALP Ztied1.S, Pg/M, Zop2.H /// - public static Vector AddPairwiseWidening(Vector left, Vector right) => AddPairwiseWidening(left, right); + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) => AddPairwiseWideningAndAdd(left, right); /// /// svuint64_t svadalp[_u64]_m(svbool_t pg, svuint64_t op1, svuint32_t op2) @@ -470,7 +470,7 @@ internal Arm64() { } /// UADALP Ztied1.D, Pg/M, Zop2.S /// UADALP Ztied1.D, Pg/M, Zop2.S /// - public static Vector AddPairwiseWidening(Vector left, Vector right) => AddPairwiseWidening(left, right); + public static Vector AddPairwiseWideningAndAdd(Vector left, Vector right) => AddPairwiseWideningAndAdd(left, right); // Saturating add @@ -637,113 +637,73 @@ internal Arm64() { } /// svint16_t svaddwb[_s16](svint16_t op1, svint8_t op2) /// SADDWB Zresult.H, Zop1.H, Zop2.B /// - public static Vector AddWideLower(Vector left, Vector right) => AddWideLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svint32_t svaddwb[_s32](svint32_t op1, svint16_t op2) /// SADDWB Zresult.S, Zop1.S, Zop2.H /// - public static Vector AddWideLower(Vector left, Vector right) => AddWideLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svint64_t svaddwb[_s64](svint64_t op1, svint32_t op2) /// SADDWB Zresult.D, Zop1.D, Zop2.S /// - public static Vector AddWideLower(Vector left, Vector right) => AddWideLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svuint16_t svaddwb[_u16](svuint16_t op1, svuint8_t op2) /// UADDWB Zresult.H, Zop1.H, Zop2.B /// - public static Vector AddWideLower(Vector left, Vector right) => AddWideLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svuint32_t svaddwb[_u32](svuint32_t op1, svuint16_t op2) /// UADDWB Zresult.S, Zop1.S, Zop2.H /// - public static Vector AddWideLower(Vector left, Vector right) => AddWideLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svuint64_t svaddwb[_u64](svuint64_t op1, svuint32_t op2) /// UADDWB Zresult.D, Zop1.D, Zop2.S /// - public static Vector AddWideLower(Vector left, Vector right) => AddWideLower(left, right); - - // Add wide (top) - - /// - /// svint16_t svaddwt[_s16](svint16_t op1, svint8_t op2) - /// SADDWT Zresult.H, Zop1.H, Zop2.B - /// - public static Vector AddWideUpper(Vector left, Vector right) => AddWideUpper(left, right); - - /// - /// svint32_t svaddwt[_s32](svint32_t op1, svint16_t op2) - /// SADDWT Zresult.S, Zop1.S, Zop2.H - /// - public static Vector AddWideUpper(Vector left, Vector right) => AddWideUpper(left, right); - - /// - /// svint64_t svaddwt[_s64](svint64_t op1, svint32_t op2) - /// SADDWT Zresult.D, Zop1.D, Zop2.S - /// - public static Vector AddWideUpper(Vector left, Vector right) => AddWideUpper(left, right); - - /// - /// svuint16_t svaddwt[_u16](svuint16_t op1, svuint8_t op2) - /// UADDWT Zresult.H, Zop1.H, Zop2.B - /// - public static Vector AddWideUpper(Vector left, Vector right) => AddWideUpper(left, right); - - /// - /// svuint32_t svaddwt[_u32](svuint32_t op1, svuint16_t op2) - /// UADDWT Zresult.S, Zop1.S, Zop2.H - /// - public static Vector AddWideUpper(Vector left, Vector right) => AddWideUpper(left, right); - - /// - /// svuint64_t svaddwt[_u64](svuint64_t op1, svuint32_t op2) - /// UADDWT Zresult.D, Zop1.D, Zop2.S - /// - public static Vector AddWideUpper(Vector left, Vector right) => AddWideUpper(left, right); - - // Add long (bottom) + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svint16_t svaddlb[_s16](svint8_t op1, svint8_t op2) /// SADDLB Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningLower(Vector left, Vector right) => AddWideningLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svint32_t svaddlb[_s32](svint16_t op1, svint16_t op2) /// SADDLB Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningLower(Vector left, Vector right) => AddWideningLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svint64_t svaddlb[_s64](svint32_t op1, svint32_t op2) /// SADDLB Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningLower(Vector left, Vector right) => AddWideningLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svuint16_t svaddlb[_u16](svuint8_t op1, svuint8_t op2) /// UADDLB Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningLower(Vector left, Vector right) => AddWideningLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svuint32_t svaddlb[_u32](svuint16_t op1, svuint16_t op2) /// UADDLB Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningLower(Vector left, Vector right) => AddWideningLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); /// /// svuint64_t svaddlb[_u64](svuint32_t op1, svuint32_t op2) /// UADDLB Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningLower(Vector left, Vector right) => AddWideningLower(left, right); + public static Vector AddWideningEven(Vector left, Vector right) => AddWideningEven(left, right); // Add long (bottom + top) @@ -751,57 +711,93 @@ internal Arm64() { } /// svint16_t svaddlbt[_s16](svint8_t op1, svint8_t op2) /// SADDLBT Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningLowerUpper(Vector left, Vector right) => AddWideningLowerUpper(left, right); + public static Vector AddWideningEvenOdd(Vector left, Vector right) => AddWideningEvenOdd(left, right); /// /// svint32_t svaddlbt[_s32](svint16_t op1, svint16_t op2) /// SADDLBT Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningLowerUpper(Vector left, Vector right) => AddWideningLowerUpper(left, right); + public static Vector AddWideningEvenOdd(Vector left, Vector right) => AddWideningEvenOdd(left, right); /// /// svint64_t svaddlbt[_s64](svint32_t op1, svint32_t op2) /// SADDLBT Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningLowerUpper(Vector left, Vector right) => AddWideningLowerUpper(left, right); + public static Vector AddWideningEvenOdd(Vector left, Vector right) => AddWideningEvenOdd(left, right); + + // Add wide (top) + + /// + /// svint16_t svaddwt[_s16](svint16_t op1, svint8_t op2) + /// SADDWT Zresult.H, Zop1.H, Zop2.B + /// + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); + + /// + /// svint32_t svaddwt[_s32](svint32_t op1, svint16_t op2) + /// SADDWT Zresult.S, Zop1.S, Zop2.H + /// + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); + + /// + /// svint64_t svaddwt[_s64](svint64_t op1, svint32_t op2) + /// SADDWT Zresult.D, Zop1.D, Zop2.S + /// + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); + + /// + /// svuint16_t svaddwt[_u16](svuint16_t op1, svuint8_t op2) + /// UADDWT Zresult.H, Zop1.H, Zop2.B + /// + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); + + /// + /// svuint32_t svaddwt[_u32](svuint32_t op1, svuint16_t op2) + /// UADDWT Zresult.S, Zop1.S, Zop2.H + /// + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); - // Add long (top) + /// + /// svuint64_t svaddwt[_u64](svuint64_t op1, svuint32_t op2) + /// UADDWT Zresult.D, Zop1.D, Zop2.S + /// + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); /// /// svint16_t svaddlt[_s16](svint8_t op1, svint8_t op2) /// SADDLT Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningUpper(Vector left, Vector right) => AddWideningUpper(left, right); + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); /// /// svint32_t svaddlt[_s32](svint16_t op1, svint16_t op2) /// SADDLT Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningUpper(Vector left, Vector right) => AddWideningUpper(left, right); + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); /// /// svint64_t svaddlt[_s64](svint32_t op1, svint32_t op2) /// SADDLT Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningUpper(Vector left, Vector right) => AddWideningUpper(left, right); + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); /// /// svuint16_t svaddlt[_u16](svuint8_t op1, svuint8_t op2) /// UADDLT Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningUpper(Vector left, Vector right) => AddWideningUpper(left, right); + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); /// /// svuint32_t svaddlt[_u32](svuint16_t op1, svuint16_t op2) /// UADDLT Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningUpper(Vector left, Vector right) => AddWideningUpper(left, right); + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); /// /// svuint64_t svaddlt[_u64](svuint32_t op1, svuint32_t op2) /// UADDLT Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningUpper(Vector left, Vector right) => AddWideningUpper(left, right); + public static Vector AddWideningOdd(Vector left, Vector right) => AddWideningOdd(left, right); // Bitwise clear and exclusive OR @@ -1006,6 +1002,170 @@ internal Arm64() { } /// public static Vector BitwiseSelectRightInverted(Vector select, Vector left, Vector right) => BitwiseSelectRightInverted(select, left, right); + // Halving add + + /// + /// svuint8_t svhadd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svhadd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svhadd[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UHADD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UHADD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UHADD Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static Vector FusedAddHalving(Vector left, Vector right) => FusedAddHalving(left, right); + + /// + /// svint16_t svhadd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svhadd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svhadd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SHADD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SHADD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SHADD Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static Vector FusedAddHalving(Vector left, Vector right) => FusedAddHalving(left, right); + + /// + /// svint32_t svhadd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svhadd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svhadd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SHADD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SHADD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SHADD Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static Vector FusedAddHalving(Vector left, Vector right) => FusedAddHalving(left, right); + + /// + /// svint64_t svhadd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svhadd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svhadd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SHADD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SHADD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SHADD Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static Vector FusedAddHalving(Vector left, Vector right) => FusedAddHalving(left, right); + + /// + /// svint8_t svhadd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svhadd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svhadd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SHADD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SHADD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SHADD Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static Vector FusedAddHalving(Vector left, Vector right) => FusedAddHalving(left, right); + + /// + /// svuint16_t svhadd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svhadd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svhadd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UHADD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UHADD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UHADD Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static Vector FusedAddHalving(Vector left, Vector right) => FusedAddHalving(left, right); + + /// + /// svuint32_t svhadd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svhadd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svhadd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UHADD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UHADD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UHADD Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static Vector FusedAddHalving(Vector left, Vector right) => FusedAddHalving(left, right); + + /// + /// svuint64_t svhadd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svhadd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svhadd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UHADD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UHADD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UHADD Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static Vector FusedAddHalving(Vector left, Vector right) => FusedAddHalving(left, right); + + // Halving subtract + + /// + /// svuint8_t svhsub[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svhsub[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svhsub[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UHSUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UHSUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UHSUBR Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) => FusedSubtractHalving(left, right); + + /// + /// svint16_t svhsub[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svhsub[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svhsub[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SHSUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SHSUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SHSUBR Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) => FusedSubtractHalving(left, right); + + /// + /// svint32_t svhsub[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svhsub[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svhsub[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SHSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SHSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SHSUBR Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) => FusedSubtractHalving(left, right); + + /// + /// svint64_t svhsub[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svhsub[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svhsub[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SHSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SHSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SHSUBR Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) => FusedSubtractHalving(left, right); + + /// + /// svint8_t svhsub[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svhsub[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svhsub[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SHSUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SHSUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SHSUBR Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) => FusedSubtractHalving(left, right); + + /// + /// svuint16_t svhsub[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svhsub[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svhsub[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UHSUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UHSUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UHSUBR Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) => FusedSubtractHalving(left, right); + + /// + /// svuint32_t svhsub[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svhsub[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svhsub[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UHSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UHSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UHSUBR Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) => FusedSubtractHalving(left, right); + + /// + /// svuint64_t svhsub[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svhsub[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svhsub[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UHSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UHSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UHSUBR Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static Vector FusedSubtractHalving(Vector left, Vector right) => FusedSubtractHalving(left, right); + /// Interleaving Xor /// diff --git a/src/runtime/src/libraries/System.Private.DataContractSerialization/System.Private.DataContractSerialization.slnx b/src/runtime/src/libraries/System.Private.DataContractSerialization/System.Private.DataContractSerialization.slnx index 6816b9480f5..05932b6adc7 100644 --- a/src/runtime/src/libraries/System.Private.DataContractSerialization/System.Private.DataContractSerialization.slnx +++ b/src/runtime/src/libraries/System.Private.DataContractSerialization/System.Private.DataContractSerialization.slnx @@ -1,22 +1,1088 @@ + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Private.Xml.Linq/System.Private.Xml.Linq.slnx b/src/runtime/src/libraries/System.Private.Xml.Linq/System.Private.Xml.Linq.slnx index c46f0f84004..e3792121cd0 100644 --- a/src/runtime/src/libraries/System.Private.Xml.Linq/System.Private.Xml.Linq.slnx +++ b/src/runtime/src/libraries/System.Private.Xml.Linq/System.Private.Xml.Linq.slnx @@ -1,43 +1,1130 @@ + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Private.Xml/System.Private.Xml.slnx b/src/runtime/src/libraries/System.Private.Xml/System.Private.Xml.slnx index d3a8fb09abd..ffc743e1732 100644 --- a/src/runtime/src/libraries/System.Private.Xml/System.Private.Xml.slnx +++ b/src/runtime/src/libraries/System.Private.Xml/System.Private.Xml.slnx @@ -1,35 +1,1066 @@ + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Reflection.DispatchProxy/System.Reflection.DispatchProxy.slnx b/src/runtime/src/libraries/System.Reflection.DispatchProxy/System.Reflection.DispatchProxy.slnx index d6ed42fdf97..2ed97c462fd 100644 --- a/src/runtime/src/libraries/System.Reflection.DispatchProxy/System.Reflection.DispatchProxy.slnx +++ b/src/runtime/src/libraries/System.Reflection.DispatchProxy/System.Reflection.DispatchProxy.slnx @@ -1,30 +1,498 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Reflection.Emit/System.Reflection.Emit.slnx b/src/runtime/src/libraries/System.Reflection.Emit/System.Reflection.Emit.slnx index b640fc67602..5a8c2c3121c 100644 --- a/src/runtime/src/libraries/System.Reflection.Emit/System.Reflection.Emit.slnx +++ b/src/runtime/src/libraries/System.Reflection.Emit/System.Reflection.Emit.slnx @@ -52,6 +52,14 @@ + + + + + + + + @@ -76,6 +84,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -124,6 +180,14 @@ + + + + + + + + @@ -132,6 +196,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -149,6 +237,14 @@ + + + + + + + + @@ -157,6 +253,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -181,6 +333,22 @@ + + + + + + + + + + + + + + + + @@ -189,6 +357,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Reflection.Metadata/System.Reflection.Metadata.slnx b/src/runtime/src/libraries/System.Reflection.Metadata/System.Reflection.Metadata.slnx index 5def1af5edc..80d6cea7e7e 100644 --- a/src/runtime/src/libraries/System.Reflection.Metadata/System.Reflection.Metadata.slnx +++ b/src/runtime/src/libraries/System.Reflection.Metadata/System.Reflection.Metadata.slnx @@ -92,6 +92,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -100,6 +140,22 @@ + + + + + + + + + + + + + + + + @@ -116,6 +172,22 @@ + + + + + + + + + + + + + + + + @@ -181,6 +253,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -189,6 +301,22 @@ + + + + + + + + + + + + + + + + @@ -205,6 +333,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Reflection.MetadataLoadContext/System.Reflection.MetadataLoadContext.slnx b/src/runtime/src/libraries/System.Reflection.MetadataLoadContext/System.Reflection.MetadataLoadContext.slnx index 8a8acb6ee5f..c62b8a444a6 100644 --- a/src/runtime/src/libraries/System.Reflection.MetadataLoadContext/System.Reflection.MetadataLoadContext.slnx +++ b/src/runtime/src/libraries/System.Reflection.MetadataLoadContext/System.Reflection.MetadataLoadContext.slnx @@ -1,37 +1,426 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Resources.Extensions/System.Resources.Extensions.slnx b/src/runtime/src/libraries/System.Resources.Extensions/System.Resources.Extensions.slnx index 64917d06f2d..709a278c88b 100644 --- a/src/runtime/src/libraries/System.Resources.Extensions/System.Resources.Extensions.slnx +++ b/src/runtime/src/libraries/System.Resources.Extensions/System.Resources.Extensions.slnx @@ -100,6 +100,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -116,6 +156,22 @@ + + + + + + + + + + + + + + + + @@ -132,6 +188,22 @@ + + + + + + + + + + + + + + + + @@ -165,7 +237,7 @@ - + @@ -173,7 +245,7 @@ - + @@ -181,7 +253,7 @@ - + @@ -189,7 +261,7 @@ - + @@ -197,7 +269,7 @@ - + @@ -205,7 +277,7 @@ - + @@ -213,7 +285,39 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -237,6 +341,22 @@ + + + + + + + + + + + + + + + + @@ -253,6 +373,22 @@ + + + + + + + + + + + + + + + + @@ -278,6 +414,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Resources.Writer/System.Resources.Writer.slnx b/src/runtime/src/libraries/System.Resources.Writer/System.Resources.Writer.slnx index fd96f4b93ab..cc39b89226b 100644 --- a/src/runtime/src/libraries/System.Resources.Writer/System.Resources.Writer.slnx +++ b/src/runtime/src/libraries/System.Resources.Writer/System.Resources.Writer.slnx @@ -1,29 +1,202 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Runtime.Caching/System.Runtime.Caching.slnx b/src/runtime/src/libraries/System.Runtime.Caching/System.Runtime.Caching.slnx index 4af3ab6e623..c41fb61d631 100644 --- a/src/runtime/src/libraries/System.Runtime.Caching/System.Runtime.Caching.slnx +++ b/src/runtime/src/libraries/System.Runtime.Caching/System.Runtime.Caching.slnx @@ -18,6 +18,14 @@ + + + + + + + + @@ -44,6 +52,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -60,6 +100,22 @@ + + + + + + + + + + + + + + + + @@ -68,6 +124,14 @@ + + + + + + + + @@ -76,6 +140,22 @@ + + + + + + + + + + + + + + + + @@ -92,6 +172,14 @@ + + + + + + + + @@ -100,6 +188,22 @@ + + + + + + + + + + + + + + + + @@ -125,7 +229,31 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -157,6 +285,22 @@ + + + + + + + + + + + + + + + + @@ -165,6 +309,14 @@ + + + + + + + + @@ -173,6 +325,22 @@ + + + + + + + + + + + + + + + + @@ -189,6 +357,14 @@ + + + + + + + + @@ -197,6 +373,22 @@ + + + + + + + + + + + + + + + + @@ -214,6 +406,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Runtime.CompilerServices.VisualC/System.Runtime.CompilerServices.VisualC.slnx b/src/runtime/src/libraries/System.Runtime.CompilerServices.VisualC/System.Runtime.CompilerServices.VisualC.slnx index f3f2915096e..1e9970818f9 100644 --- a/src/runtime/src/libraries/System.Runtime.CompilerServices.VisualC/System.Runtime.CompilerServices.VisualC.slnx +++ b/src/runtime/src/libraries/System.Runtime.CompilerServices.VisualC/System.Runtime.CompilerServices.VisualC.slnx @@ -1,29 +1,170 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.slnx b/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.slnx index 12774d84f69..dcca71173e2 100644 --- a/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.slnx +++ b/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.slnx @@ -52,6 +52,14 @@ + + + + + + + + @@ -60,6 +68,14 @@ + + + + + + + + @@ -92,6 +108,14 @@ + + + + + + + + @@ -100,6 +124,14 @@ + + + + + + + + @@ -133,6 +165,14 @@ + + + + + + + + @@ -141,6 +181,14 @@ + + + + + + + + @@ -181,6 +229,14 @@ + + + + + + + + diff --git a/src/runtime/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/runtime/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 51abff0c198..17378d29ec3 100644 --- a/src/runtime/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/runtime/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -5348,12 +5348,12 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVector128AndReplicateToVector(System.Numerics.Vector mask, ushort* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector128AndReplicateToVector(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector128AndReplicateToVector(System.Numerics.Vector mask, ulong* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToInt16(byte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToInt32(byte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToInt64(byte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToUInt16(byte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToUInt32(byte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToUInt64(byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToInt16(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToInt32(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToInt64(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToUInt16(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToUInt32(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteNonFaultingZeroExtendToUInt64(System.Numerics.Vector mask, byte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendFirstFaulting(System.Numerics.Vector mask, byte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendFirstFaulting(System.Numerics.Vector mask, byte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendFirstFaulting(System.Numerics.Vector mask, byte* address) { throw null; } @@ -5366,10 +5366,10 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToUInt16(System.Numerics.Vector mask, byte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToUInt32(System.Numerics.Vector mask, byte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToUInt64(System.Numerics.Vector mask, byte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorInt16NonFaultingSignExtendToInt32(short* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorInt16NonFaultingSignExtendToInt64(short* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorInt16NonFaultingSignExtendToUInt32(short* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorInt16NonFaultingSignExtendToUInt64(short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16NonFaultingSignExtendToInt32(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16NonFaultingSignExtendToInt64(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16NonFaultingSignExtendToUInt32(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16NonFaultingSignExtendToUInt64(System.Numerics.Vector mask, short* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendFirstFaulting(System.Numerics.Vector mask, short* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendFirstFaulting(System.Numerics.Vector mask, short* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendFirstFaulting(System.Numerics.Vector mask, short* address) { throw null; } @@ -5378,22 +5378,22 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToInt64(System.Numerics.Vector mask, short* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToUInt32(System.Numerics.Vector mask, short* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToUInt64(System.Numerics.Vector mask, short* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorInt32NonFaultingSignExtendToInt64(int* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorInt32NonFaultingSignExtendToUInt64(int* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt32NonFaultingSignExtendToInt64(System.Numerics.Vector mask, int* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt32NonFaultingSignExtendToUInt64(System.Numerics.Vector mask, int* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorInt32SignExtendFirstFaulting(System.Numerics.Vector mask, int* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorInt32SignExtendFirstFaulting(System.Numerics.Vector mask, int* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorInt32SignExtendToInt64(System.Numerics.Vector mask, int* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorInt32SignExtendToUInt64(System.Numerics.Vector mask, int* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(byte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(double* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(short* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(int* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(long* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(sbyte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(float* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(ushort* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(uint* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorNonFaulting(ulong* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, double* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, int* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, long* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, float* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, uint* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorNonFaulting(System.Numerics.Vector mask, ulong* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorNonTemporal(System.Numerics.Vector mask, byte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorNonTemporal(System.Numerics.Vector mask, double* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorNonTemporal(System.Numerics.Vector mask, short* address) { throw null; } @@ -5414,12 +5414,12 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorFirstFaulting(System.Numerics.Vector mask, ushort* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorFirstFaulting(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorFirstFaulting(System.Numerics.Vector mask, ulong* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToInt16(sbyte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToInt32(sbyte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToInt64(sbyte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToUInt16(sbyte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToUInt32(sbyte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToUInt64(sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToInt16(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToInt32(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToInt64(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToUInt16(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToUInt32(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteNonFaultingSignExtendToUInt64(System.Numerics.Vector mask, sbyte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendFirstFaulting(System.Numerics.Vector mask, sbyte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendFirstFaulting(System.Numerics.Vector mask, sbyte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendFirstFaulting(System.Numerics.Vector mask, sbyte* address) { throw null; } @@ -5432,10 +5432,10 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToUInt16(System.Numerics.Vector mask, sbyte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToUInt32(System.Numerics.Vector mask, sbyte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToUInt64(System.Numerics.Vector mask, sbyte* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorUInt16NonFaultingZeroExtendToInt32(ushort* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorUInt16NonFaultingZeroExtendToInt64(ushort* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorUInt16NonFaultingZeroExtendToUInt32(ushort* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorUInt16NonFaultingZeroExtendToUInt64(ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16NonFaultingZeroExtendToInt32(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16NonFaultingZeroExtendToInt64(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16NonFaultingZeroExtendToUInt32(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16NonFaultingZeroExtendToUInt64(System.Numerics.Vector mask, ushort* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendFirstFaulting(System.Numerics.Vector mask, ushort* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendFirstFaulting(System.Numerics.Vector mask, ushort* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendFirstFaulting(System.Numerics.Vector mask, ushort* address) { throw null; } @@ -5444,8 +5444,8 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToInt64(System.Numerics.Vector mask, ushort* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToUInt32(System.Numerics.Vector mask, ushort* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToUInt64(System.Numerics.Vector mask, ushort* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorUInt32NonFaultingZeroExtendToInt64(uint* address) { throw null; } - public static unsafe System.Numerics.Vector LoadVectorUInt32NonFaultingZeroExtendToUInt64(uint* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt32NonFaultingZeroExtendToInt64(System.Numerics.Vector mask, uint* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt32NonFaultingZeroExtendToUInt64(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendFirstFaulting(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendFirstFaulting(System.Numerics.Vector mask, uint* address) { throw null; } public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToInt64(System.Numerics.Vector mask, uint* address) { throw null; } @@ -6171,12 +6171,12 @@ internal Arm64() { } public static System.Numerics.Vector AddPairwise(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AddPairwise(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddPairwiseWidening(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddPairwiseWidening(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddPairwiseWidening(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddPairwiseWidening(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddPairwiseWidening(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddPairwiseWidening(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddPairwiseWideningAndAdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddPairwiseWideningAndAdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddPairwiseWideningAndAdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddPairwiseWideningAndAdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddPairwiseWideningAndAdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddPairwiseWideningAndAdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static new System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static new System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -6194,33 +6194,33 @@ internal Arm64() { } public static System.Numerics.Vector AddSaturateWithUnsignedAddend(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AddSaturateWithUnsignedAddend(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AddSaturateWithUnsignedAddend(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningLower(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningLowerUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningLowerUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningLowerUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningUpper(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEvenOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEvenOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEvenOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector BitwiseClearXor(System.Numerics.Vector xor, System.Numerics.Vector value, System.Numerics.Vector mask) { throw null; } public static System.Numerics.Vector BitwiseClearXor(System.Numerics.Vector xor, System.Numerics.Vector value, System.Numerics.Vector mask) { throw null; } public static System.Numerics.Vector BitwiseClearXor(System.Numerics.Vector xor, System.Numerics.Vector value, System.Numerics.Vector mask) { throw null; } @@ -6253,6 +6253,22 @@ internal Arm64() { } public static System.Numerics.Vector BitwiseSelectRightInverted(System.Numerics.Vector select, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector BitwiseSelectRightInverted(System.Numerics.Vector select, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector BitwiseSelectRightInverted(System.Numerics.Vector select, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedAddHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedAddHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedAddHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedAddHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedAddHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedAddHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedAddHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedAddHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } diff --git a/src/runtime/src/libraries/System.Runtime.Numerics/System.Runtime.Numerics.slnx b/src/runtime/src/libraries/System.Runtime.Numerics/System.Runtime.Numerics.slnx index 75912c18842..6d025293d5c 100644 --- a/src/runtime/src/libraries/System.Runtime.Numerics/System.Runtime.Numerics.slnx +++ b/src/runtime/src/libraries/System.Runtime.Numerics/System.Runtime.Numerics.slnx @@ -1,29 +1,210 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Runtime.Serialization.Formatters/System.Runtime.Serialization.Formatters.slnx b/src/runtime/src/libraries/System.Runtime.Serialization.Formatters/System.Runtime.Serialization.Formatters.slnx index 2739977a659..c1810ab5845 100644 --- a/src/runtime/src/libraries/System.Runtime.Serialization.Formatters/System.Runtime.Serialization.Formatters.slnx +++ b/src/runtime/src/libraries/System.Runtime.Serialization.Formatters/System.Runtime.Serialization.Formatters.slnx @@ -52,6 +52,14 @@ + + + + + + + + @@ -164,6 +172,22 @@ + + + + + + + + + + + + + + + + @@ -172,6 +196,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -188,6 +236,22 @@ + + + + + + + + + + + + + + + + @@ -204,6 +268,22 @@ + + + + + + + + + + + + + + + + @@ -220,6 +300,22 @@ + + + + + + + + + + + + + + + + @@ -236,6 +332,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -285,7 +405,7 @@ - + @@ -413,6 +533,22 @@ + + + + + + + + + + + + + + + + @@ -421,6 +557,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -437,6 +597,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -445,6 +629,22 @@ + + + + + + + + + + + + + + + + @@ -461,6 +661,22 @@ + + + + + + + + + + + + + + + + @@ -477,6 +693,22 @@ + + + + + + + + + + + + + + + + @@ -502,6 +734,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Runtime.Serialization.Json/System.Runtime.Serialization.Json.slnx b/src/runtime/src/libraries/System.Runtime.Serialization.Json/System.Runtime.Serialization.Json.slnx index f1987ebcbe4..6268fc44f00 100644 --- a/src/runtime/src/libraries/System.Runtime.Serialization.Json/System.Runtime.Serialization.Json.slnx +++ b/src/runtime/src/libraries/System.Runtime.Serialization.Json/System.Runtime.Serialization.Json.slnx @@ -1,40 +1,1138 @@ + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Runtime.Serialization.Primitives/System.Runtime.Serialization.Primitives.slnx b/src/runtime/src/libraries/System.Runtime.Serialization.Primitives/System.Runtime.Serialization.Primitives.slnx index 1573fe00854..ea035a6ac62 100644 --- a/src/runtime/src/libraries/System.Runtime.Serialization.Primitives/System.Runtime.Serialization.Primitives.slnx +++ b/src/runtime/src/libraries/System.Runtime.Serialization.Primitives/System.Runtime.Serialization.Primitives.slnx @@ -76,6 +76,14 @@ + + + + + + + + @@ -157,6 +165,14 @@ + + + + + + + + diff --git a/src/runtime/src/libraries/System.Runtime.Serialization.Xml/System.Runtime.Serialization.Xml.slnx b/src/runtime/src/libraries/System.Runtime.Serialization.Xml/System.Runtime.Serialization.Xml.slnx index 108a9881a0b..7037559f50f 100644 --- a/src/runtime/src/libraries/System.Runtime.Serialization.Xml/System.Runtime.Serialization.Xml.slnx +++ b/src/runtime/src/libraries/System.Runtime.Serialization.Xml/System.Runtime.Serialization.Xml.slnx @@ -1,43 +1,1162 @@ + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Runtime/System.Runtime.slnx b/src/runtime/src/libraries/System.Runtime/System.Runtime.slnx index b7ef24259dc..542b3f1bdfc 100644 --- a/src/runtime/src/libraries/System.Runtime/System.Runtime.slnx +++ b/src/runtime/src/libraries/System.Runtime/System.Runtime.slnx @@ -52,6 +52,14 @@ + + + + + + + + @@ -108,6 +116,14 @@ + + + + + + + + @@ -116,6 +132,22 @@ + + + + + + + + + + + + + + + + @@ -124,6 +156,14 @@ + + + + + + + + @@ -148,6 +188,22 @@ + + + + + + + + + + + + + + + + @@ -196,6 +252,14 @@ + + + + + + + + @@ -204,6 +268,14 @@ + + + + + + + + @@ -237,7 +309,7 @@ - + @@ -309,6 +381,14 @@ + + + + + + + + @@ -317,6 +397,22 @@ + + + + + + + + + + + + + + + + @@ -325,6 +421,14 @@ + + + + + + + + @@ -349,6 +453,22 @@ + + + + + + + + + + + + + + + + @@ -357,6 +477,22 @@ + + + + + + + + + + + + + + + + @@ -365,6 +501,14 @@ + + + + + + + + @@ -373,6 +517,14 @@ + + + + + + + + @@ -381,6 +533,14 @@ + + + + + + + + @@ -406,6 +566,16 @@ + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Security.AccessControl/System.Security.AccessControl.slnx b/src/runtime/src/libraries/System.Security.AccessControl/System.Security.AccessControl.slnx index de11291d4a4..e7be8297b8c 100644 --- a/src/runtime/src/libraries/System.Security.AccessControl/System.Security.AccessControl.slnx +++ b/src/runtime/src/libraries/System.Security.AccessControl/System.Security.AccessControl.slnx @@ -1,36 +1,370 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Security.Claims/System.Security.Claims.slnx b/src/runtime/src/libraries/System.Security.Claims/System.Security.Claims.slnx index 6c57d2dc102..936f7742d23 100644 --- a/src/runtime/src/libraries/System.Security.Claims/System.Security.Claims.slnx +++ b/src/runtime/src/libraries/System.Security.Claims/System.Security.Claims.slnx @@ -1,29 +1,226 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Security.Cryptography.Cose/System.Security.Cryptography.Cose.slnx b/src/runtime/src/libraries/System.Security.Cryptography.Cose/System.Security.Cryptography.Cose.slnx index 6b383c4c128..c2e42d8a6e4 100644 --- a/src/runtime/src/libraries/System.Security.Cryptography.Cose/System.Security.Cryptography.Cose.slnx +++ b/src/runtime/src/libraries/System.Security.Cryptography.Cose/System.Security.Cryptography.Cose.slnx @@ -1,30 +1,370 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Security.Cryptography.Pkcs/System.Security.Cryptography.Pkcs.slnx b/src/runtime/src/libraries/System.Security.Cryptography.Pkcs/System.Security.Cryptography.Pkcs.slnx index 8a59eb66526..f141f179ebc 100644 --- a/src/runtime/src/libraries/System.Security.Cryptography.Pkcs/System.Security.Cryptography.Pkcs.slnx +++ b/src/runtime/src/libraries/System.Security.Cryptography.Pkcs/System.Security.Cryptography.Pkcs.slnx @@ -1,36 +1,354 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Security.Cryptography.Xml/System.Security.Cryptography.Xml.slnx b/src/runtime/src/libraries/System.Security.Cryptography.Xml/System.Security.Cryptography.Xml.slnx index e589f6cc591..3129be211fd 100644 --- a/src/runtime/src/libraries/System.Security.Cryptography.Xml/System.Security.Cryptography.Xml.slnx +++ b/src/runtime/src/libraries/System.Security.Cryptography.Xml/System.Security.Cryptography.Xml.slnx @@ -1,38 +1,370 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Security.Cryptography/System.Security.Cryptography.slnx b/src/runtime/src/libraries/System.Security.Cryptography/System.Security.Cryptography.slnx index 987a1c3c142..741432d88af 100644 --- a/src/runtime/src/libraries/System.Security.Cryptography/System.Security.Cryptography.slnx +++ b/src/runtime/src/libraries/System.Security.Cryptography/System.Security.Cryptography.slnx @@ -68,6 +68,14 @@ + + + + + + + + @@ -84,6 +92,22 @@ + + + + + + + + + + + + + + + + @@ -100,6 +124,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -108,6 +164,14 @@ + + + + + + + + @@ -116,6 +180,14 @@ + + + + + + + + @@ -124,6 +196,14 @@ + + + + + + + + @@ -156,6 +236,22 @@ + + + + + + + + + + + + + + + + @@ -189,6 +285,14 @@ + + + + + + + + @@ -197,6 +301,14 @@ + + + + + + + + @@ -213,6 +325,22 @@ + + + + + + + + + + + + + + + + @@ -229,6 +357,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -237,6 +413,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -261,6 +469,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Security.Permissions/System.Security.Permissions.slnx b/src/runtime/src/libraries/System.Security.Permissions/System.Security.Permissions.slnx index e9265948767..1faf7851898 100644 --- a/src/runtime/src/libraries/System.Security.Permissions/System.Security.Permissions.slnx +++ b/src/runtime/src/libraries/System.Security.Permissions/System.Security.Permissions.slnx @@ -93,7 +93,7 @@ - + @@ -101,7 +101,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -117,7 +117,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -133,7 +133,9 @@ - + + + diff --git a/src/runtime/src/libraries/System.Security.Principal.Windows/System.Security.Principal.Windows.slnx b/src/runtime/src/libraries/System.Security.Principal.Windows/System.Security.Principal.Windows.slnx index 74b48a9429e..0b5d5476cc7 100644 --- a/src/runtime/src/libraries/System.Security.Principal.Windows/System.Security.Principal.Windows.slnx +++ b/src/runtime/src/libraries/System.Security.Principal.Windows/System.Security.Principal.Windows.slnx @@ -1,32 +1,322 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.ServiceProcess.ServiceController/System.ServiceProcess.ServiceController.slnx b/src/runtime/src/libraries/System.ServiceProcess.ServiceController/System.ServiceProcess.ServiceController.slnx index 22eaa92bfd0..ea5ccb15e09 100644 --- a/src/runtime/src/libraries/System.ServiceProcess.ServiceController/System.ServiceProcess.ServiceController.slnx +++ b/src/runtime/src/libraries/System.ServiceProcess.ServiceController/System.ServiceProcess.ServiceController.slnx @@ -1,34 +1,418 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Text.Encoding.CodePages/System.Text.Encoding.CodePages.slnx b/src/runtime/src/libraries/System.Text.Encoding.CodePages/System.Text.Encoding.CodePages.slnx index 7ec59fd0826..1c420aed94a 100644 --- a/src/runtime/src/libraries/System.Text.Encoding.CodePages/System.Text.Encoding.CodePages.slnx +++ b/src/runtime/src/libraries/System.Text.Encoding.CodePages/System.Text.Encoding.CodePages.slnx @@ -1,31 +1,274 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Text.Encodings.Web/System.Text.Encodings.Web.slnx b/src/runtime/src/libraries/System.Text.Encodings.Web/System.Text.Encodings.Web.slnx index 5ed34628476..cdf191872d2 100644 --- a/src/runtime/src/libraries/System.Text.Encodings.Web/System.Text.Encodings.Web.slnx +++ b/src/runtime/src/libraries/System.Text.Encodings.Web/System.Text.Encodings.Web.slnx @@ -1,29 +1,234 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Text.Json/System.Text.Json.slnx b/src/runtime/src/libraries/System.Text.Json/System.Text.Json.slnx index d9b773c4d63..533699a28b0 100644 --- a/src/runtime/src/libraries/System.Text.Json/System.Text.Json.slnx +++ b/src/runtime/src/libraries/System.Text.Json/System.Text.Json.slnx @@ -1,66 +1,882 @@ + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Text.RegularExpressions/System.Text.RegularExpressions.slnx b/src/runtime/src/libraries/System.Text.RegularExpressions/System.Text.RegularExpressions.slnx index 74c6f8e3f5f..caf98d67833 100644 --- a/src/runtime/src/libraries/System.Text.RegularExpressions/System.Text.RegularExpressions.slnx +++ b/src/runtime/src/libraries/System.Text.RegularExpressions/System.Text.RegularExpressions.slnx @@ -84,6 +84,14 @@ + + + + + + + + @@ -92,6 +100,14 @@ + + + + + + + + @@ -108,6 +124,14 @@ + + + + + + + + @@ -124,6 +148,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -132,6 +180,14 @@ + + + + + + + + @@ -140,6 +196,22 @@ + + + + + + + + + + + + + + + + @@ -156,6 +228,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -172,6 +268,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -188,6 +308,22 @@ + + + + + + + + + + + + + + + + @@ -204,6 +340,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -237,6 +397,14 @@ + + + + + + + + @@ -245,6 +413,14 @@ + + + + + + + + @@ -261,6 +437,22 @@ + + + + + + + + + + + + + + + + @@ -269,6 +461,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -277,6 +493,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -285,6 +533,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -301,6 +621,22 @@ + + + + + + + + + + + + + + + + @@ -317,6 +653,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/runtime/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs index df8858c9813..1314122c953 100644 --- a/src/runtime/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs +++ b/src/runtime/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs @@ -1238,7 +1238,7 @@ private async Task Match_TestThatTimeoutHappens(RegexEngine engine) } string input = new string(chars); - Regex re = await RegexHelpers.GetRegexAsync(engine, @"a.{20}^", RegexOptions.None, TimeSpan.FromMilliseconds(10)); + Regex re = await RegexHelpers.GetRegexAsync(engine, @"a.{20}^", RegexOptions.None, TimeSpan.FromMilliseconds(1)); Assert.Throws(() => { re.Match(input); }); } diff --git a/src/runtime/src/libraries/System.Threading.AccessControl/System.Threading.AccessControl.slnx b/src/runtime/src/libraries/System.Threading.AccessControl/System.Threading.AccessControl.slnx index 0b64336d159..775142e7349 100644 --- a/src/runtime/src/libraries/System.Threading.AccessControl/System.Threading.AccessControl.slnx +++ b/src/runtime/src/libraries/System.Threading.AccessControl/System.Threading.AccessControl.slnx @@ -1,28 +1,370 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Threading.Channels/System.Threading.Channels.slnx b/src/runtime/src/libraries/System.Threading.Channels/System.Threading.Channels.slnx index d2efdf1d8ff..ddebde2143d 100644 --- a/src/runtime/src/libraries/System.Threading.Channels/System.Threading.Channels.slnx +++ b/src/runtime/src/libraries/System.Threading.Channels/System.Threading.Channels.slnx @@ -76,6 +76,14 @@ + + + + + + + + @@ -100,6 +108,22 @@ + + + + + + + + + + + + + + + + @@ -165,6 +189,14 @@ + + + + + + + + @@ -189,6 +221,14 @@ + + + + + + + + diff --git a/src/runtime/src/libraries/System.Threading.Tasks.Dataflow/System.Threading.Tasks.Dataflow.slnx b/src/runtime/src/libraries/System.Threading.Tasks.Dataflow/System.Threading.Tasks.Dataflow.slnx index 36f230ea193..ae6e016c34f 100644 --- a/src/runtime/src/libraries/System.Threading.Tasks.Dataflow/System.Threading.Tasks.Dataflow.slnx +++ b/src/runtime/src/libraries/System.Threading.Tasks.Dataflow/System.Threading.Tasks.Dataflow.slnx @@ -1,37 +1,394 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Threading.Tasks.Parallel/System.Threading.Tasks.Parallel.slnx b/src/runtime/src/libraries/System.Threading.Tasks.Parallel/System.Threading.Tasks.Parallel.slnx index 981d6321d27..a867c7a2766 100644 --- a/src/runtime/src/libraries/System.Threading.Tasks.Parallel/System.Threading.Tasks.Parallel.slnx +++ b/src/runtime/src/libraries/System.Threading.Tasks.Parallel/System.Threading.Tasks.Parallel.slnx @@ -1,30 +1,274 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Transactions.Local/System.Transactions.Local.slnx b/src/runtime/src/libraries/System.Transactions.Local/System.Transactions.Local.slnx index 392e347447f..c6260171db8 100644 --- a/src/runtime/src/libraries/System.Transactions.Local/System.Transactions.Local.slnx +++ b/src/runtime/src/libraries/System.Transactions.Local/System.Transactions.Local.slnx @@ -1,33 +1,1106 @@ + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Web.HttpUtility/System.Web.HttpUtility.slnx b/src/runtime/src/libraries/System.Web.HttpUtility/System.Web.HttpUtility.slnx index bc85167d092..222b9827e56 100644 --- a/src/runtime/src/libraries/System.Web.HttpUtility/System.Web.HttpUtility.slnx +++ b/src/runtime/src/libraries/System.Web.HttpUtility/System.Web.HttpUtility.slnx @@ -1,35 +1,298 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Windows.Extensions/System.Windows.Extensions.slnx b/src/runtime/src/libraries/System.Windows.Extensions/System.Windows.Extensions.slnx index a1ff20ddf35..b67b7ac19b5 100644 --- a/src/runtime/src/libraries/System.Windows.Extensions/System.Windows.Extensions.slnx +++ b/src/runtime/src/libraries/System.Windows.Extensions/System.Windows.Extensions.slnx @@ -77,7 +77,7 @@ - + @@ -85,7 +85,7 @@ - + @@ -93,7 +93,7 @@ - + @@ -101,7 +101,9 @@ - + + + diff --git a/src/runtime/src/libraries/System.Xml.ReaderWriter/System.Xml.ReaderWriter.slnx b/src/runtime/src/libraries/System.Xml.ReaderWriter/System.Xml.ReaderWriter.slnx index 52984cb6636..7acc17fa775 100644 --- a/src/runtime/src/libraries/System.Xml.ReaderWriter/System.Xml.ReaderWriter.slnx +++ b/src/runtime/src/libraries/System.Xml.ReaderWriter/System.Xml.ReaderWriter.slnx @@ -1,34 +1,1008 @@ + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Xml.XDocument/System.Xml.XDocument.slnx b/src/runtime/src/libraries/System.Xml.XDocument/System.Xml.XDocument.slnx index dfd9bd0f8f7..4e10e6a1aeb 100644 --- a/src/runtime/src/libraries/System.Xml.XDocument/System.Xml.XDocument.slnx +++ b/src/runtime/src/libraries/System.Xml.XDocument/System.Xml.XDocument.slnx @@ -1,37 +1,1024 @@ + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Xml.XPath.XDocument/System.Xml.XPath.XDocument.slnx b/src/runtime/src/libraries/System.Xml.XPath.XDocument/System.Xml.XPath.XDocument.slnx index fd1086980a9..5adce387dc2 100644 --- a/src/runtime/src/libraries/System.Xml.XPath.XDocument/System.Xml.XPath.XDocument.slnx +++ b/src/runtime/src/libraries/System.Xml.XPath.XDocument/System.Xml.XPath.XDocument.slnx @@ -1,38 +1,1032 @@ + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Xml.XPath/System.Xml.XPath.slnx b/src/runtime/src/libraries/System.Xml.XPath/System.Xml.XPath.slnx index 62a985e95d1..13095c72020 100644 --- a/src/runtime/src/libraries/System.Xml.XPath/System.Xml.XPath.slnx +++ b/src/runtime/src/libraries/System.Xml.XPath/System.Xml.XPath.slnx @@ -1,35 +1,1016 @@ + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/System.Xml.XmlSerializer/System.Xml.XmlSerializer.slnx b/src/runtime/src/libraries/System.Xml.XmlSerializer/System.Xml.XmlSerializer.slnx index e8869ec061e..d620a0742b2 100644 --- a/src/runtime/src/libraries/System.Xml.XmlSerializer/System.Xml.XmlSerializer.slnx +++ b/src/runtime/src/libraries/System.Xml.XmlSerializer/System.Xml.XmlSerializer.slnx @@ -1,39 +1,1016 @@ + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml b/src/runtime/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml index 4317f49799c..24e10dd2564 100644 --- a/src/runtime/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml +++ b/src/runtime/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml @@ -1,6 +1,210 @@  + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToInt16(System.Byte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToInt32(System.Byte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToInt64(System.Byte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToUInt16(System.Byte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToUInt32(System.Byte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorByteNonFaultingZeroExtendToUInt64(System.Byte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt16NonFaultingSignExtendToInt32(System.Int16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt16NonFaultingSignExtendToInt64(System.Int16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt16NonFaultingSignExtendToUInt32(System.Int16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt16NonFaultingSignExtendToUInt64(System.Int16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt32NonFaultingSignExtendToInt64(System.Int32*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorInt32NonFaultingSignExtendToUInt64(System.Int32*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.Byte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.Double*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.Int16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.Int32*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.Int64*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.SByte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.Single*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.UInt16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.UInt32*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorNonFaulting(System.UInt64*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToInt16(System.SByte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToInt32(System.SByte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToInt64(System.SByte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToUInt16(System.SByte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToUInt32(System.SByte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorSByteNonFaultingSignExtendToUInt64(System.SByte*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt16NonFaultingZeroExtendToInt32(System.UInt16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt16NonFaultingZeroExtendToInt64(System.UInt16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt16NonFaultingZeroExtendToUInt32(System.UInt16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt16NonFaultingZeroExtendToUInt64(System.UInt16*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt32NonFaultingZeroExtendToInt64(System.UInt32*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + + + CP0002 + M:System.Runtime.Intrinsics.Arm.Sve.LoadVectorUInt32NonFaultingZeroExtendToUInt64(System.UInt32*) + net9.0/System.Runtime.Intrinsics.dll + net10.0/System.Runtime.Intrinsics.dll + CP0002 M:System.Runtime.Intrinsics.Arm.Sve.PrefetchBytes(System.Numerics.Vector{System.Byte},System.Void*,System.Runtime.Intrinsics.Arm.SvePrefetchType) diff --git a/src/runtime/src/libraries/sfx-finish.proj b/src/runtime/src/libraries/sfx-finish.proj index 875813ad93a..742bafb2054 100644 --- a/src/runtime/src/libraries/sfx-finish.proj +++ b/src/runtime/src/libraries/sfx-finish.proj @@ -4,6 +4,7 @@ $(NetCoreAppCurrent)-$(TargetOS) + true $(MicrosoftNetCoreAppRefPackDataDir)FrameworkList.xml true diff --git a/src/runtime/src/libraries/sfx-gen.proj b/src/runtime/src/libraries/sfx-gen.proj index 6c3e0143766..1b3bdf6c104 100644 --- a/src/runtime/src/libraries/sfx-gen.proj +++ b/src/runtime/src/libraries/sfx-gen.proj @@ -4,6 +4,7 @@ netstandard2.0 true + true diff --git a/src/runtime/src/libraries/sfx-src.proj b/src/runtime/src/libraries/sfx-src.proj index 934f31e43ff..8da1f3b306c 100644 --- a/src/runtime/src/libraries/sfx-src.proj +++ b/src/runtime/src/libraries/sfx-src.proj @@ -4,6 +4,7 @@ $(NetCoreAppCurrent)-$(TargetOS) true + true diff --git a/src/runtime/src/libraries/sfx.proj b/src/runtime/src/libraries/sfx.proj index 53a43a12252..3b808ecbe7d 100644 --- a/src/runtime/src/libraries/sfx.proj +++ b/src/runtime/src/libraries/sfx.proj @@ -2,6 +2,7 @@ $(NetCoreAppCurrent)-$(TargetOS) + true diff --git a/src/runtime/src/libraries/sfx.slnx b/src/runtime/src/libraries/sfx.slnx new file mode 100644 index 00000000000..b12ca216e1b --- /dev/null +++ b/src/runtime/src/libraries/sfx.slnx @@ -0,0 +1,2612 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/runtime/src/libraries/shims/Directory.Build.props b/src/runtime/src/libraries/shims/Directory.Build.props index f2397697229..6a4bed74569 100644 --- a/src/runtime/src/libraries/shims/Directory.Build.props +++ b/src/runtime/src/libraries/shims/Directory.Build.props @@ -21,7 +21,7 @@ true - shims + \shims diff --git a/src/runtime/src/libraries/slngen.proj b/src/runtime/src/libraries/slngen.proj index c06b8c0e403..aa88a104f26 100644 --- a/src/runtime/src/libraries/slngen.proj +++ b/src/runtime/src/libraries/slngen.proj @@ -1,4 +1,5 @@ + .cmd .sh @@ -10,6 +11,8 @@ + + + + + DestinationFiles="%(SolutionFile.ProjFilePath)" + Condition="'%(SolutionFile.Filename)' != 'sfx'" /> - + @@ -41,4 +48,5 @@ SlnFilePath="%(RelativeDir)%(Filename).sln" /> + diff --git a/src/runtime/src/libraries/tests.proj b/src/runtime/src/libraries/tests.proj index 5641c763c36..a2b63c15130 100644 --- a/src/runtime/src/libraries/tests.proj +++ b/src/runtime/src/libraries/tests.proj @@ -40,11 +40,6 @@ - - - - - @@ -607,7 +602,8 @@ - + + diff --git a/src/runtime/src/mono/mono/component/debugger-agent.c b/src/runtime/src/mono/mono/component/debugger-agent.c index ea283037a11..3cd51abf6f6 100644 --- a/src/runtime/src/mono/mono/component/debugger-agent.c +++ b/src/runtime/src/mono/mono/component/debugger-agent.c @@ -4140,7 +4140,7 @@ jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo) if (assembly) { DebuggerTlsData *tls; tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id); - if (!CHECK_ICORDBG (TRUE) || tls->invoke == NULL) { + if (!CHECK_ICORDBG (TRUE) || !tls || tls->invoke == NULL) { process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly); } else { mono_dbg_assembly_load (prof, assembly); //send later diff --git a/src/runtime/src/native/eventpipe/ds-eventpipe-protocol.c b/src/runtime/src/native/eventpipe/ds-eventpipe-protocol.c index 4f5e6daf299..bac8ee6df99 100644 --- a/src/runtime/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/runtime/src/native/eventpipe/ds-eventpipe-protocol.c @@ -920,7 +920,7 @@ eventpipe_protocol_helper_collect_tracing ( payload->serialization_format, payload->rundown_keyword, payload->stackwalk_requested, - payload->session_type == EP_SESSION_TYPE_IPCSTREAM ? ds_ipc_stream_get_stream_ref (stream) : NULL, + ds_ipc_stream_get_stream_ref (stream), NULL, NULL, user_events_data_fd); diff --git a/src/runtime/src/native/eventpipe/ds-ipc-pal-namedpipe.c b/src/runtime/src/native/eventpipe/ds-ipc-pal-namedpipe.c index 2444cb763c6..0da47f5c772 100644 --- a/src/runtime/src/native/eventpipe/ds-ipc-pal-namedpipe.c +++ b/src/runtime/src/native/eventpipe/ds-ipc-pal-namedpipe.c @@ -213,7 +213,7 @@ ds_ipc_poll ( handles [i] = poll_handles_data [i].ipc->overlap.hEvent; if (handles [i] == INVALID_HANDLE_VALUE) { // Invalid handle, wait will fail. Signal error - poll_handles_data [i].events = DS_IPC_POLL_EVENTS_ERR; + poll_handles_data [i].events = IPC_POLL_EVENTS_ERR; } } else { // CLIENT @@ -238,7 +238,7 @@ ds_ipc_poll ( handles [i] = poll_handles_data [i].stream->overlap.hEvent; break; case ERROR_PIPE_NOT_CONNECTED: - poll_handles_data [i].events = (uint8_t)DS_IPC_POLL_EVENTS_HANGUP; + poll_handles_data [i].events = (uint8_t)IPC_POLL_EVENTS_HANGUP; result = -1; ep_raise_error (); default: @@ -288,7 +288,7 @@ ds_ipc_poll ( // check if we abandoned something DWORD abandonedIndex = wait - WAIT_ABANDONED_0; if (abandonedIndex > 0 || abandonedIndex < (poll_handles_data_len - 1)) { - poll_handles_data [abandonedIndex].events = (uint8_t)DS_IPC_POLL_EVENTS_HANGUP; + poll_handles_data [abandonedIndex].events = (uint8_t)IPC_POLL_EVENTS_HANGUP; result = -1; ep_raise_error (); } else { @@ -325,20 +325,20 @@ ds_ipc_poll ( if (!success) { DWORD error = GetLastError(); if (error == ERROR_PIPE_NOT_CONNECTED || error == ERROR_BROKEN_PIPE) { - poll_handles_data [index].events = (uint8_t)DS_IPC_POLL_EVENTS_HANGUP; + poll_handles_data [index].events = (uint8_t)IPC_POLL_EVENTS_HANGUP; } else { if (callback) callback ("Client connection error", error); - poll_handles_data [index].events = (uint8_t)DS_IPC_POLL_EVENTS_ERR; + poll_handles_data [index].events = (uint8_t)IPC_POLL_EVENTS_ERR; result = -1; ep_raise_error (); } } else { - poll_handles_data [index].events = (uint8_t)DS_IPC_POLL_EVENTS_SIGNALED; + poll_handles_data [index].events = (uint8_t)IPC_POLL_EVENTS_SIGNALED; } } else { // SERVER - poll_handles_data [index].events = (uint8_t)DS_IPC_POLL_EVENTS_SIGNALED; + poll_handles_data [index].events = (uint8_t)IPC_POLL_EVENTS_SIGNALED; } result = 1; @@ -694,7 +694,7 @@ ipc_stream_read_func ( DWORD error = GetLastError (); if (error == ERROR_IO_PENDING) { // if we're waiting infinitely, only make one syscall - if (timeout_ms == DS_IPC_TIMEOUT_INFINITE) { + if (timeout_ms == IPC_TIMEOUT_INFINITE) { DS_ENTER_BLOCKING_PAL_SECTION; success = GetOverlappedResult ( ipc_stream->pipe, // pipe @@ -765,7 +765,7 @@ ipc_stream_write_func ( DWORD error = GetLastError (); if (error == ERROR_IO_PENDING) { // if we're waiting infinitely, only make one syscall - if (timeout_ms == DS_IPC_TIMEOUT_INFINITE) { + if (timeout_ms == IPC_TIMEOUT_INFINITE) { DS_ENTER_BLOCKING_PAL_SECTION; success = GetOverlappedResult ( ipc_stream->pipe, // pipe @@ -834,12 +834,24 @@ ipc_stream_close_func (void *object) return ds_ipc_stream_close (ipc_stream, NULL); } +static +IpcPollEvents +ipc_stream_poll_func ( + void *object, + uint32_t timeout_ms) +{ + EP_ASSERT (!"ipc_stream_poll_func needs to be implemented for NamedPipes"); + // TODO: Implement ipc_stream_poll_func for NamedPipes + return IPC_POLL_EVENTS_UNKNOWN; +} + static IpcStreamVtable ipc_stream_vtable = { ipc_stream_free_func, ipc_stream_read_func, ipc_stream_write_func, ipc_stream_flush_func, - ipc_stream_close_func }; + ipc_stream_close_func, + ipc_stream_poll_func }; static DiagnosticsIpcStream * diff --git a/src/runtime/src/native/eventpipe/ds-ipc-pal-socket.c b/src/runtime/src/native/eventpipe/ds-ipc-pal-socket.c index 89df116e8f6..c668c0851f0 100644 --- a/src/runtime/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/runtime/src/native/eventpipe/ds-ipc-pal-socket.c @@ -586,7 +586,7 @@ ipc_socket_connect ( // the server hasn't called `accept`, so no need to check for timeout or connect error. #if defined(DS_IPC_PAL_AF_INET) || defined(DS_IPC_PAL_AF_INET6) - if (timeout_ms != DS_IPC_TIMEOUT_INFINITE) { + if (timeout_ms != IPC_TIMEOUT_INFINITE) { // Set socket to none blocking. ipc_socket_set_blocking (s, false); } @@ -599,7 +599,7 @@ ipc_socket_connect ( DS_EXIT_BLOCKING_PAL_SECTION; #if defined(DS_IPC_PAL_AF_INET) || defined(DS_IPC_PAL_AF_INET6) - if (timeout_ms != DS_IPC_TIMEOUT_INFINITE) { + if (timeout_ms != IPC_TIMEOUT_INFINITE) { if (result_connect == DS_IPC_SOCKET_ERROR) { if (ipc_get_last_error () == DS_IPC_SOCKET_ERROR_WOULDBLOCK) { ds_ipc_pollfd_t pfd; @@ -625,7 +625,7 @@ ipc_socket_connect ( } } - if (timeout_ms != DS_IPC_TIMEOUT_INFINITE) { + if (timeout_ms != IPC_TIMEOUT_INFINITE) { // Reset socket to blocking. int last_error = ipc_get_last_error (); ipc_socket_set_blocking (s, true); @@ -1144,15 +1144,15 @@ ds_ipc_poll ( // check for hangup first because a closed socket // will technically meet the requirements for POLLIN // i.e., a call to recv/read won't block - poll_handles_data [i].events = (uint8_t)DS_IPC_POLL_EVENTS_HANGUP; + poll_handles_data [i].events = (uint8_t)IPC_POLL_EVENTS_HANGUP; } else if ((poll_fds [i].revents & (POLLERR|POLLNVAL))) { if (callback) callback ("Poll error", (uint32_t)poll_fds [i].revents); - poll_handles_data [i].events = (uint8_t)DS_IPC_POLL_EVENTS_ERR; + poll_handles_data [i].events = (uint8_t)IPC_POLL_EVENTS_ERR; } else if (poll_fds [i].revents & (POLLIN|POLLPRI)) { - poll_handles_data [i].events = (uint8_t)DS_IPC_POLL_EVENTS_SIGNALED; + poll_handles_data [i].events = (uint8_t)IPC_POLL_EVENTS_SIGNALED; } else { - poll_handles_data [i].events = (uint8_t)DS_IPC_POLL_EVENTS_UNKNOWN; + poll_handles_data [i].events = (uint8_t)IPC_POLL_EVENTS_UNKNOWN; if (callback) callback ("unknown poll response", (uint32_t)poll_fds [i].revents); } @@ -1399,7 +1399,7 @@ ipc_stream_read_func ( DiagnosticsIpcStream *ipc_stream = (DiagnosticsIpcStream *)object; ssize_t total_bytes_read = 0; - if (timeout_ms != DS_IPC_TIMEOUT_INFINITE) { + if (timeout_ms != IPC_TIMEOUT_INFINITE) { ds_ipc_pollfd_t pfd; pfd.fd = ipc_stream->client_socket; pfd.events = POLLIN; @@ -1443,7 +1443,7 @@ ipc_stream_write_func ( DiagnosticsIpcStream *ipc_stream = (DiagnosticsIpcStream *)object; ssize_t total_bytes_written = 0; - if (timeout_ms != DS_IPC_TIMEOUT_INFINITE) { + if (timeout_ms != IPC_TIMEOUT_INFINITE) { ds_ipc_pollfd_t pfd; pfd.fd = ipc_stream->client_socket; pfd.events = POLLOUT; @@ -1487,12 +1487,24 @@ ipc_stream_close_func (void *object) return ds_ipc_stream_close (ipc_stream, NULL); } +static +IpcPollEvents +ipc_stream_poll_func ( + void *object, + uint32_t timeout_ms) +{ + EP_ASSERT (object != NULL); + DiagnosticsIpcStream *ipc_stream = (DiagnosticsIpcStream *)object; + return ds_ipc_stream_poll (ipc_stream, timeout_ms); +} + static IpcStreamVtable ipc_stream_vtable = { ipc_stream_free_func, ipc_stream_read_func, ipc_stream_write_func, ipc_stream_flush_func, - ipc_stream_close_func }; + ipc_stream_close_func, + ipc_stream_poll_func }; static DiagnosticsIpcStream * @@ -1666,6 +1678,44 @@ ds_ipc_stream_to_string ( return (result > 0 && result < (int32_t)buffer_len) ? result : 0; } +IpcPollEvents +ds_ipc_stream_poll ( + DiagnosticsIpcStream *ipc_stream, + uint32_t timeout_ms) +{ + EP_ASSERT (ipc_stream != NULL); + + if (ipc_stream->client_socket == DS_IPC_INVALID_SOCKET) + return IPC_POLL_EVENTS_HANGUP; + + ds_ipc_pollfd_t pfd; + pfd.fd = ipc_stream->client_socket; + pfd.events = POLLIN | POLLPRI | POLLOUT; + + int result_poll; + result_poll = ipc_poll_fds (&pfd, 1, timeout_ms); + + if (result_poll < 0) + return IPC_POLL_EVENTS_ERR; + + if (result_poll == 0) + return IPC_POLL_EVENTS_NONE; + + if (pfd.revents == 0) + return IPC_POLL_EVENTS_NONE; + + if (pfd.revents & POLLHUP) + return IPC_POLL_EVENTS_HANGUP; + + if (pfd.revents & (POLLERR | POLLNVAL)) + return IPC_POLL_EVENTS_ERR; + + if (pfd.revents & (POLLIN | POLLPRI | POLLOUT)) + return IPC_POLL_EVENTS_SIGNALED; + + return IPC_POLL_EVENTS_UNKNOWN; +} + #endif /* ENABLE_PERFTRACING */ #ifndef DS_INCLUDE_SOURCE_FILES diff --git a/src/runtime/src/native/eventpipe/ds-ipc-pal-types.h b/src/runtime/src/native/eventpipe/ds-ipc-pal-types.h index d623fb22e40..7b75e998b3f 100644 --- a/src/runtime/src/native/eventpipe/ds-ipc-pal-types.h +++ b/src/runtime/src/native/eventpipe/ds-ipc-pal-types.h @@ -22,21 +22,12 @@ typedef struct _DiagnosticsIpcStream DiagnosticsIpcStream; * Diagnostics IPC PAL Enums. */ -typedef enum { - DS_IPC_POLL_EVENTS_NONE = 0x00, // no events - DS_IPC_POLL_EVENTS_SIGNALED = 0x01, // ready for use - DS_IPC_POLL_EVENTS_HANGUP = 0x02, // connection remotely closed - DS_IPC_POLL_EVENTS_ERR = 0x04, // error - DS_IPC_POLL_EVENTS_UNKNOWN = 0x80 // unknown state -} DiagnosticsIpcPollEvents; - typedef enum { DS_IPC_CONNECTION_MODE_CONNECT, DS_IPC_CONNECTION_MODE_LISTEN } DiagnosticsIpcConnectionMode; #define DS_IPC_MAX_TO_STRING_LEN 128 -#define DS_IPC_TIMEOUT_INFINITE (uint32_t)-1 #define DS_IPC_POLL_TIMEOUT_FALLOFF_FACTOR (float)1.25 #define DS_IPC_POLL_TIMEOUT_MIN_MS (uint32_t)10 diff --git a/src/runtime/src/native/eventpipe/ds-ipc-pal-websocket.c b/src/runtime/src/native/eventpipe/ds-ipc-pal-websocket.c index 97eb89025a4..a50fa1bfd4f 100644 --- a/src/runtime/src/native/eventpipe/ds-ipc-pal-websocket.c +++ b/src/runtime/src/native/eventpipe/ds-ipc-pal-websocket.c @@ -248,11 +248,11 @@ ds_ipc_poll ( int client_socket = poll_handles_data [i].stream->client_socket; int pending = ds_rt_websocket_poll (client_socket); if (pending < 0){ - poll_handles_data [i].events = (uint8_t)DS_IPC_POLL_EVENTS_ERR; + poll_handles_data [i].events = (uint8_t)IPC_POLL_EVENTS_ERR; return 1; } if (pending > 0){ - poll_handles_data [i].events = (uint8_t)DS_IPC_POLL_EVENTS_SIGNALED; + poll_handles_data [i].events = (uint8_t)IPC_POLL_EVENTS_SIGNALED; return 1; } } @@ -425,12 +425,24 @@ ipc_stream_close_func (void *object) return ds_ipc_stream_close (ipc_stream, NULL); } +static +IpcPollEvents +ipc_stream_poll_func ( + void *object, + uint32_t timeout_ms) +{ + EP_ASSERT (!"ipc_stream_poll_func needs to be implemented for WebSockets"); + // TODO: Implement ipc_stream_poll_func for WebSockets + return IPC_POLL_EVENTS_UNKNOWN; +} + static IpcStreamVtable ipc_stream_vtable = { ipc_stream_free_func, ipc_stream_read_func, ipc_stream_write_func, ipc_stream_flush_func, - ipc_stream_close_func }; + ipc_stream_close_func, + ipc_stream_poll_func }; static DiagnosticsIpcStream * diff --git a/src/runtime/src/native/eventpipe/ds-ipc-pal.h b/src/runtime/src/native/eventpipe/ds-ipc-pal.h index 362ea3925f9..3761099fb4b 100644 --- a/src/runtime/src/native/eventpipe/ds-ipc-pal.h +++ b/src/runtime/src/native/eventpipe/ds-ipc-pal.h @@ -140,5 +140,10 @@ ds_ipc_stream_to_string ( ep_char8_t *buffer, uint32_t buffer_len); +IpcPollEvents +ds_ipc_stream_poll ( + DiagnosticsIpcStream *ipc_stream, + uint32_t timeout_ms); + #endif /* ENABLE_PERFTRACING */ #endif /* __DIAGNOSTICS_IPC_PAL_H__ */ diff --git a/src/runtime/src/native/eventpipe/ds-ipc.c b/src/runtime/src/native/eventpipe/ds-ipc.c index 6527d5bbce7..cb2b051cb9e 100644 --- a/src/runtime/src/native/eventpipe/ds-ipc.c +++ b/src/runtime/src/native/eventpipe/ds-ipc.c @@ -122,7 +122,7 @@ inline uint32_t ipc_stream_factory_get_next_timeout (uint32_t current_timeout_ms) { - if (current_timeout_ms == DS_IPC_TIMEOUT_INFINITE) + if (current_timeout_ms == IPC_TIMEOUT_INFINITE) return DS_IPC_POLL_TIMEOUT_MIN_MS; else return (current_timeout_ms >= DS_IPC_POLL_TIMEOUT_MAX_MS) ? @@ -361,7 +361,7 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call DiagnosticsIpcStream *stream = NULL; - uint32_t poll_timeout_ms = DS_IPC_TIMEOUT_INFINITE; + uint32_t poll_timeout_ms = IPC_TIMEOUT_INFINITE; bool connect_success = true; uint32_t poll_attempts = 0; @@ -382,7 +382,7 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call } DN_VECTOR_PTR_FOREACH_END; poll_timeout_ms = connect_success ? - DS_IPC_TIMEOUT_INFINITE : + IPC_TIMEOUT_INFINITE : ipc_stream_factory_get_next_timeout (poll_timeout_ms); int32_t ret_val; @@ -392,7 +392,7 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call ipc_log_poll_handles (&ipc_poll_handles); ret_val = ds_ipc_poll (dn_vector_data_t (&ipc_poll_handles, DiagnosticsIpcPollHandle), dn_vector_size (&ipc_poll_handles), poll_timeout_ms, callback); } else { - if (poll_timeout_ms == DS_IPC_TIMEOUT_INFINITE) + if (poll_timeout_ms == IPC_TIMEOUT_INFINITE) poll_timeout_ms = DS_IPC_POLL_TIMEOUT_MAX_MS; DS_LOG_DEBUG_1 ("ds_ipc_stream_factory_get_next_available_stream - Nothing to poll, sleeping using timeout: %dms.", poll_timeout_ms); ep_rt_thread_sleep ((uint64_t)poll_timeout_ms * NUM_NANOSECONDS_IN_1_MS); @@ -406,13 +406,13 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call DN_VECTOR_FOREACH_BEGIN (DiagnosticsIpcPollHandle, ipc_poll_handle, &ipc_poll_handles) { DiagnosticsPort *port = (DiagnosticsPort *)ipc_poll_handle.user_data; switch (ipc_poll_handle.events) { - case DS_IPC_POLL_EVENTS_HANGUP: + case IPC_POLL_EVENTS_HANGUP: EP_ASSERT (port != NULL); ds_port_reset_vcall (port, callback); DS_LOG_INFO_2 ("ds_ipc_stream_factory_get_next_available_stream - HUP :: Poll attempt: %d, connection %d hung up. Connect is reset.", poll_attempts, connection_id); poll_timeout_ms = DS_IPC_POLL_TIMEOUT_MIN_MS; break; - case DS_IPC_POLL_EVENTS_SIGNALED: + case IPC_POLL_EVENTS_SIGNALED: EP_ASSERT (port != NULL); if (!stream) { // only use first signaled stream; will get others on subsequent calls stream = ds_port_get_connected_stream_vcall (port, callback); @@ -422,12 +422,12 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call } DS_LOG_DEBUG_2 ("ds_ipc_stream_factory_get_next_available_stream - SIG :: Poll attempt: %d, connection %d signalled.", poll_attempts, connection_id); break; - case DS_IPC_POLL_EVENTS_ERR: + case IPC_POLL_EVENTS_ERR: ds_port_reset_vcall ((DiagnosticsPort *)ipc_poll_handle.user_data, callback); DS_LOG_INFO_2 ("ds_ipc_stream_factory_get_next_available_stream - ERR :: Poll attempt: %d, connection %d errored. Connection is reset.", poll_attempts, connection_id); saw_error = true; break; - case DS_IPC_POLL_EVENTS_NONE: + case IPC_POLL_EVENTS_NONE: DS_LOG_INFO_2 ("ds_ipc_stream_factory_get_next_available_stream - NON :: Poll attempt: %d, connection %d had no events.", poll_attempts, connection_id); break; default: @@ -444,7 +444,7 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call if (!stream && saw_error) { // Some errors can cause the poll to return instantly, we want to delay if we see an error to avoid // runaway CPU usage. - if (poll_timeout_ms == DS_IPC_TIMEOUT_INFINITE) + if (poll_timeout_ms == IPC_TIMEOUT_INFINITE) poll_timeout_ms = DS_IPC_POLL_TIMEOUT_MAX_MS; DS_LOG_DEBUG_1 ("ds_ipc_stream_factory_get_next_available_stream - Saw error, sleeping using timeout: %dms.", poll_timeout_ms); ep_rt_thread_sleep ((uint64_t)poll_timeout_ms * NUM_NANOSECONDS_IN_1_MS); diff --git a/src/runtime/src/native/eventpipe/ep-ipc-pal-types.h b/src/runtime/src/native/eventpipe/ep-ipc-pal-types.h index a353b8a3c10..574654fd64b 100644 --- a/src/runtime/src/native/eventpipe/ep-ipc-pal-types.h +++ b/src/runtime/src/native/eventpipe/ep-ipc-pal-types.h @@ -11,5 +11,19 @@ #include "ep-ipc-pal-types-forward.h" +/* + * Shared Diagnostics/EventPipe IPC PAL Enums. + */ + +typedef enum { + IPC_POLL_EVENTS_NONE = 0x00, // no events + IPC_POLL_EVENTS_SIGNALED = 0x01, // ready for use + IPC_POLL_EVENTS_HANGUP = 0x02, // connection remotely closed + IPC_POLL_EVENTS_ERR = 0x04, // error + IPC_POLL_EVENTS_UNKNOWN = 0x80 // unknown state +} IpcPollEvents; + +#define IPC_TIMEOUT_INFINITE (uint32_t)-1 + #endif /* ENABLE_PERFTRACING */ #endif /* __EVENTPIPE_IPC_PAL_TYPES_H__ */ diff --git a/src/runtime/src/native/eventpipe/ep-ipc-stream.h b/src/runtime/src/native/eventpipe/ep-ipc-stream.h index eeb615675de..633edfa976d 100644 --- a/src/runtime/src/native/eventpipe/ep-ipc-stream.h +++ b/src/runtime/src/native/eventpipe/ep-ipc-stream.h @@ -21,6 +21,7 @@ typedef bool (*IpcStreamReadFunc)(void *object, uint8_t *buffer, uint32_t bytes_ typedef bool (*IpcStreamWriteFunc)(void *object, const uint8_t *buffer, uint32_t bytes_to_write, uint32_t *bytes_written, uint32_t timeout_ms); typedef bool (*IpcStreamFlushFunc)(void *object); typedef bool (*IpcStreamCloseFunc)(void *object); +typedef IpcPollEvents (*IpcStreamPollFunc)(void *object, uint32_t timeout_ms); struct _IpcStreamVtable { IpcStreamFreeFunc free_func; @@ -28,6 +29,7 @@ struct _IpcStreamVtable { IpcStreamWriteFunc write_func; IpcStreamFlushFunc flush_func; IpcStreamCloseFunc close_func; + IpcStreamPollFunc poll_func; }; #if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_IPC_STREAM_GETTER_SETTER) || defined(DS_IMPL_IPC_PAL_NAMEDPIPE_GETTER_SETTER) || defined(DS_IMPL_IPC_PAL_SOCKET_GETTER_SETTER) @@ -77,5 +79,8 @@ ep_ipc_stream_flush_vcall (IpcStream *ipc_stream); bool ep_ipc_stream_close_vcall (IpcStream *ipc_stream); +IpcPollEvents +ep_ipc_stream_poll_vcall (IpcStream *ipc_stream, uint32_t timeout_ms); + #endif /* ENABLE_PERFTRACING */ #endif /* __EVENTPIPE_IPC_STREAM_H__ */ diff --git a/src/runtime/src/native/eventpipe/ep-session.c b/src/runtime/src/native/eventpipe/ep-session.c index ac9cf1d7e36..56786d0e6f2 100644 --- a/src/runtime/src/native/eventpipe/ep-session.c +++ b/src/runtime/src/native/eventpipe/ep-session.c @@ -9,7 +9,9 @@ #include "ep-config.h" #include "ep-event.h" #include "ep-file.h" +#include "ep-ipc-stream.h" #include "ep-session.h" +#include "ep-stream.h" #include "ep-event-payload.h" #include "ep-rt.h" @@ -76,6 +78,10 @@ session_tracepoint_write_event ( ep_rt_thread_handle_t event_thread, EventPipeStackContents *stack); +static +bool +session_is_stream_connection_closed (IpcStream *stream); + /* * EventPipeSession. */ @@ -91,7 +97,7 @@ EP_RT_DEFINE_THREAD_FUNC (streaming_thread) ep_rt_thread_params_t *thread_params = (ep_rt_thread_params_t *)data; EventPipeSession *const session = (EventPipeSession *)thread_params->thread_params; - if (session->session_type != EP_SESSION_TYPE_IPCSTREAM && session->session_type != EP_SESSION_TYPE_FILESTREAM) + if (!ep_session_type_uses_streaming_thread (session->session_type)) return 1; if (!thread_params->thread || !ep_rt_thread_has_started (thread_params->thread)) @@ -100,28 +106,44 @@ EP_RT_DEFINE_THREAD_FUNC (streaming_thread) session->streaming_thread = thread_params->thread; bool success = true; - ep_rt_wait_event_handle_t *wait_event = ep_session_get_wait_event (session); ep_rt_volatile_store_uint32_t (&session->started, 1); EP_GCX_PREEMP_ENTER - while (ep_session_get_streaming_enabled (session)) { - bool events_written = false; - if (!ep_session_write_all_buffers_to_file (session, &events_written)) { - success = false; - break; - } + if (ep_session_type_uses_buffer_manager (session->session_type)) { + ep_rt_wait_event_handle_t *wait_event = ep_session_get_wait_event (session); + while (ep_session_get_streaming_enabled (session)) { + bool events_written = false; + if (!ep_session_write_all_buffers_to_file (session, &events_written)) { + success = false; + break; + } - if (!events_written) { - // No events were available, sleep until more are available - ep_rt_wait_event_wait (wait_event, EP_INFINITE_WAIT, false); + if (!events_written) { + // No events were available, sleep until more are available + ep_rt_wait_event_wait (wait_event, EP_INFINITE_WAIT, false); + } + + // Wait until it's time to sample again. + const uint32_t timeout_ns = 100000000; // 100 msec. + ep_rt_thread_sleep (timeout_ns); } + } else if (session->session_type == EP_SESSION_TYPE_USEREVENTS) { + // In a user events session we only monitor the stream to stop the session if it closes. + while (ep_session_get_streaming_enabled (session)) { + EP_ASSERT (session->stream != NULL); + if (session_is_stream_connection_closed (session->stream)) { + success = false; + break; + } - // Wait until it's time to sample again. - const uint32_t timeout_ns = 100000000; // 100 msec. - ep_rt_thread_sleep (timeout_ns); + // Wait until it's time to poll again. + const uint32_t timeout_ns = 100000000; // 100 msec. + ep_rt_thread_sleep (timeout_ns); + } + } else { + EP_UNREACHABLE ("Unsupported session type for streaming thread."); } - session->streaming_thread = NULL; ep_rt_wait_event_set (&session->rt_thread_shutdown_event); EP_GCX_PREEMP_EXIT @@ -159,19 +181,19 @@ void session_create_streaming_thread (EventPipeSession *session) { EP_ASSERT (session != NULL); - EP_ASSERT (session->session_type == EP_SESSION_TYPE_IPCSTREAM || session->session_type == EP_SESSION_TYPE_FILESTREAM); + EP_ASSERT (ep_session_type_uses_streaming_thread (session->session_type)); ep_requires_lock_held (); ep_session_set_streaming_enabled (session, true); ep_rt_wait_event_alloc (&session->rt_thread_shutdown_event, true, false); if (!ep_rt_wait_event_is_valid (&session->rt_thread_shutdown_event)) - EP_UNREACHABLE ("Unable to create stream flushing thread shutdown event."); + EP_UNREACHABLE ("Unable to create streaming thread shutdown event."); #ifndef PERFTRACING_DISABLE_THREADS ep_rt_thread_id_t thread_id = ep_rt_uint64_t_to_thread_id_t (0); if (!ep_rt_thread_create ((void *)streaming_thread, (void *)session, EP_THREAD_TYPE_SESSION, &thread_id)) - EP_UNREACHABLE ("Unable to create stream flushing thread."); + EP_UNREACHABLE ("Unable to create streaming thread."); #else ep_session_inc_ref (session); ep_rt_volatile_store_uint32_t (&session->started, 1); @@ -183,18 +205,19 @@ static void session_disable_streaming_thread (EventPipeSession *session) { - EP_ASSERT (session->session_type == EP_SESSION_TYPE_IPCSTREAM || session->session_type == EP_SESSION_TYPE_FILESTREAM); + EP_ASSERT (ep_session_type_uses_streaming_thread (session->session_type)); EP_ASSERT (ep_session_get_streaming_enabled (session)); EP_ASSERT (!ep_rt_process_detach ()); - EP_ASSERT (session->buffer_manager != NULL); + EP_ASSERT (!ep_session_type_uses_buffer_manager (session->session_type) || session->buffer_manager != NULL); // The streaming thread will watch this value and exit // when profiling is disabled. ep_session_set_streaming_enabled (session, false); // Thread could be waiting on the event that there is new data to read. - ep_rt_wait_event_set (ep_buffer_manager_get_rt_wait_event_ref (session->buffer_manager)); + if (ep_session_type_uses_buffer_manager (session->session_type)) + ep_rt_wait_event_set (ep_buffer_manager_get_rt_wait_event_ref (session->buffer_manager)); // Wait for the streaming thread to clean itself up. ep_rt_wait_event_handle_t *rt_thread_shutdown_event = &session->rt_thread_shutdown_event; @@ -202,6 +225,15 @@ session_disable_streaming_thread (EventPipeSession *session) ep_rt_wait_event_free (rt_thread_shutdown_event); } +static +bool +session_is_stream_connection_closed (IpcStream *stream) +{ + EP_ASSERT (stream != NULL); + IpcPollEvents poll_event = ep_ipc_stream_poll_vcall (stream, IPC_TIMEOUT_INFINITE); + return poll_event == IPC_POLL_EVENTS_HANGUP || poll_event == IPC_POLL_EVENTS_ERR; +} + /* * session_user_events_tracepoints_init * @@ -282,6 +314,8 @@ ep_session_alloc ( instance->rundown_keyword = rundown_keyword; instance->synchronous_callback = sync_callback; instance->callback_additional_data = callback_additional_data; + instance->user_events_data_fd = -1; + instance->stream = NULL; // Hard coded 10MB for now, we'll probably want to make // this configurable later. @@ -320,6 +354,7 @@ ep_session_alloc ( case EP_SESSION_TYPE_USEREVENTS: // With the user_events_data file, register tracepoints for each provider's tracepoint configurations ep_raise_error_if_nok (session_user_events_tracepoints_init (instance, user_events_data_fd)); + instance->stream = stream; break; default: @@ -550,7 +585,7 @@ ep_session_start_streaming (EventPipeSession *session) if (session->file != NULL) ep_file_initialize_file (session->file); - if (session->session_type == EP_SESSION_TYPE_IPCSTREAM || session->session_type == EP_SESSION_TYPE_FILESTREAM) + if (ep_session_type_uses_streaming_thread (session->session_type)) session_create_streaming_thread (session); if (session->session_type == EP_SESSION_TYPE_SYNCHRONOUS) { @@ -558,7 +593,7 @@ ep_session_start_streaming (EventPipeSession *session) EP_ASSERT (!ep_session_get_streaming_enabled (session)); } - if (session->session_type != EP_SESSION_TYPE_IPCSTREAM && session->session_type != EP_SESSION_TYPE_FILESTREAM) + if (!ep_session_type_uses_streaming_thread (session->session_type)) ep_rt_volatile_store_uint32_t_without_barrier (&session->started, 1); ep_requires_lock_held (); @@ -590,7 +625,7 @@ ep_session_disable (EventPipeSession *session) { EP_ASSERT (session != NULL); - if ((session->session_type == EP_SESSION_TYPE_IPCSTREAM || session->session_type == EP_SESSION_TYPE_FILESTREAM) && ep_session_get_streaming_enabled (session)) + if ((ep_session_type_uses_streaming_thread (session->session_type)) && ep_session_get_streaming_enabled (session)) session_disable_streaming_thread (session); if (session->session_type == EP_SESSION_TYPE_USEREVENTS) @@ -945,8 +980,8 @@ ep_session_get_next_event (EventPipeSession *session) EP_ASSERT (session != NULL); ep_requires_lock_not_held (); - if (!session->buffer_manager) { - EP_ASSERT (!"Shouldn't call get_next_event on a synchronous session."); + if (!ep_session_type_uses_buffer_manager (session->session_type)) { + EP_ASSERT (!"Shouldn't call get_next_event on a session that doesn't use the buffer manager."); return NULL; } @@ -958,8 +993,8 @@ ep_session_get_wait_event (EventPipeSession *session) { EP_ASSERT (session != NULL); - if (!session->buffer_manager) { - EP_ASSERT (!"Shouldn't call get_wait_event on a synchronous session."); + if (!ep_session_type_uses_buffer_manager (session->session_type)) { + EP_ASSERT (!"Shouldn't call get_wait_event on a session that doesn't use the buffer manager."); return NULL; } @@ -1032,6 +1067,12 @@ ep_session_type_uses_buffer_manager (EventPipeSessionType session_type) return (session_type != EP_SESSION_TYPE_SYNCHRONOUS && session_type != EP_SESSION_TYPE_USEREVENTS); } +bool +ep_session_type_uses_streaming_thread (EventPipeSessionType session_type) +{ + return (session_type == EP_SESSION_TYPE_IPCSTREAM || session_type == EP_SESSION_TYPE_FILESTREAM || session_type == EP_SESSION_TYPE_USEREVENTS); +} + #endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ #endif /* ENABLE_PERFTRACING */ diff --git a/src/runtime/src/native/eventpipe/ep-session.h b/src/runtime/src/native/eventpipe/ep-session.h index 56af80bf343..0617a876287 100644 --- a/src/runtime/src/native/eventpipe/ep-session.h +++ b/src/runtime/src/native/eventpipe/ep-session.h @@ -71,6 +71,9 @@ struct _EventPipeSession_Internal { volatile uint32_t ref_count; // The user_events_data file descriptor to register Tracepoints and write user_events to. int user_events_data_fd; + // The IPC continuation stream from initializing the session through the diagnostic server + // Currently only initialized for user_events sessions. + IpcStream *stream; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_SESSION_GETTER_SETTER) @@ -220,5 +223,8 @@ ep_session_has_started (EventPipeSession *session); bool ep_session_type_uses_buffer_manager (EventPipeSessionType session_type); +bool +ep_session_type_uses_streaming_thread (EventPipeSessionType session_type); + #endif /* ENABLE_PERFTRACING */ #endif /* __EVENTPIPE_SESSION_H__ */ diff --git a/src/runtime/src/native/eventpipe/ep-stream.c b/src/runtime/src/native/eventpipe/ep-stream.c index 76b0c3f0db2..cb31ddccef8 100644 --- a/src/runtime/src/native/eventpipe/ep-stream.c +++ b/src/runtime/src/native/eventpipe/ep-stream.c @@ -538,6 +538,18 @@ ep_ipc_stream_close_vcall (IpcStream *ipc_stream) return vtable->close_func (ipc_stream); } +IpcPollEvents +ep_ipc_stream_poll_vcall (IpcStream *ipc_stream, uint32_t timeout_ms) +{ + EP_ASSERT (ipc_stream != NULL); + + EP_ASSERT (ipc_stream->vtable != NULL); + IpcStreamVtable *vtable = ipc_stream->vtable; + + EP_ASSERT (vtable->poll_func != NULL); + return vtable->poll_func (ipc_stream, timeout_ms); +} + /* * IpcStreamWriter. */ diff --git a/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ILoader.cs b/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ILoader.cs index cda96efcddd..ea748dffda1 100644 --- a/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ILoader.cs +++ b/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ILoader.cs @@ -75,10 +75,11 @@ public interface ILoader : IContract { static string IContract.Name => nameof(Loader); - ModuleHandle GetModuleHandle(TargetPointer modulePointer) => throw new NotImplementedException(); - - IEnumerable GetModules(TargetPointer appDomain, AssemblyIterationFlags iterationFlags) => throw new NotImplementedException(); + ModuleHandle GetModuleHandleFromModulePtr(TargetPointer modulePointer) => throw new NotImplementedException(); + ModuleHandle GetModuleHandleFromAssemblyPtr(TargetPointer assemblyPointer) => throw new NotImplementedException(); + IEnumerable GetModuleHandles(TargetPointer appDomain, AssemblyIterationFlags iterationFlags) => throw new NotImplementedException(); TargetPointer GetRootAssembly() => throw new NotImplementedException(); + TargetPointer GetModule(ModuleHandle handle) => throw new NotImplementedException(); TargetPointer GetAssembly(ModuleHandle handle) => throw new NotImplementedException(); TargetPointer GetPEAssembly(ModuleHandle handle) => throw new NotImplementedException(); bool TryGetLoadedImageContents(ModuleHandle handle, out TargetPointer baseAddress, out uint size, out uint imageFlags) => throw new NotImplementedException(); diff --git a/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs b/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs index 70fec695684..9f0211efc7b 100644 --- a/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs +++ b/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs @@ -128,7 +128,7 @@ bool ICodeVersions.CodeVersionManagerSupportsMethod(TargetPointer methodDescAddr TypeHandle mt = rts.GetTypeHandle(mtAddr); TargetPointer modAddr = rts.GetModule(mt); ILoader loader = _target.Contracts.Loader; - ModuleHandle mod = loader.GetModuleHandle(modAddr); + ModuleHandle mod = loader.GetModuleHandleFromModulePtr(modAddr); ModuleFlags modFlags = loader.GetFlags(mod); if (modFlags.HasFlag(ModuleFlags.EditAndContinue)) return false; @@ -324,7 +324,7 @@ private TargetPointer GetILVersionStateAddress(TargetPointer module, uint method if (methodDefToken == (uint)EcmaMetadataUtils.TokenType.mdtMethodDef) return TargetPointer.Null; - ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandle(module); + ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(module); TargetPointer ilCodeVersionTable = _target.Contracts.Loader.GetLookupTables(moduleHandle).MethodDefToILCodeVersioningState; TargetPointer ilVersionStateAddress = _target.Contracts.Loader.GetModuleLookupMapElement(ilCodeVersionTable, methodDefToken, out var _); return ilVersionStateAddress; diff --git a/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Loader_1.cs b/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Loader_1.cs index 1f51583b9e6..c03a42e840c 100644 --- a/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Loader_1.cs +++ b/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Loader_1.cs @@ -43,15 +43,26 @@ internal Loader_1(Target target) _target = target; } - ModuleHandle ILoader.GetModuleHandle(TargetPointer modulePointer) + ModuleHandle ILoader.GetModuleHandleFromModulePtr(TargetPointer modulePointer) { if (modulePointer == TargetPointer.Null) throw new ArgumentNullException(nameof(modulePointer)); return new ModuleHandle(modulePointer); } + ModuleHandle ILoader.GetModuleHandleFromAssemblyPtr(TargetPointer assemblyPointer) + { + if (assemblyPointer == TargetPointer.Null) + throw new ArgumentNullException(nameof(assemblyPointer)); + + Data.Assembly assembly = _target.ProcessedData.GetOrAdd(assemblyPointer); + if (assembly.Module == TargetPointer.Null) + throw new InvalidOperationException("Assembly does not have a module associated with it."); + + return new ModuleHandle(assembly.Module); + } - IEnumerable ILoader.GetModules(TargetPointer appDomain, AssemblyIterationFlags iterationFlags) + IEnumerable ILoader.GetModuleHandles(TargetPointer appDomain, AssemblyIterationFlags iterationFlags) { if (appDomain == TargetPointer.Null) throw new ArgumentNullException(nameof(appDomain)); @@ -128,7 +139,10 @@ TargetPointer ILoader.GetRootAssembly() Data.AppDomain appDomain = _target.ProcessedData.GetOrAdd(_target.ReadPointer(appDomainPointer)); return appDomain.RootAssembly; } - + TargetPointer ILoader.GetModule(ModuleHandle handle) + { + return handle.Address; + } TargetPointer ILoader.GetAssembly(ModuleHandle handle) { Data.Module module = _target.ProcessedData.GetOrAdd(handle.Address); diff --git a/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index 1225c281df7..91c10bc2466 100644 --- a/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/runtime/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -917,7 +917,7 @@ bool IRuntimeTypeSystem.IsCollectibleMethod(MethodDescHandle methodDesc) { MethodDesc md = _methodDescs[methodDesc.Address]; TargetPointer loaderModuleAddr = GetLoaderModule(md); - ModuleHandle mod = _target.Contracts.Loader.GetModuleHandle(loaderModuleAddr); + ModuleHandle mod = _target.Contracts.Loader.GetModuleHandleFromModulePtr(loaderModuleAddr); return _target.Contracts.Loader.IsCollectible(mod); } diff --git a/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/ClrDataModule.cs b/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/ClrDataModule.cs index 9f87ccf6774..56eca6885f0 100644 --- a/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/ClrDataModule.cs +++ b/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/ClrDataModule.cs @@ -129,7 +129,7 @@ int IXCLRDataModule.GetFileName(uint bufLen, uint* nameLen, char* name) try { Contracts.ILoader contract = _target.Contracts.Loader; - Contracts.ModuleHandle handle = contract.GetModuleHandle(_address); + Contracts.ModuleHandle handle = contract.GetModuleHandleFromModulePtr(_address); string result = string.Empty; try { @@ -180,7 +180,7 @@ int IXCLRDataModule.GetFlags(uint* flags) try { Contracts.ILoader contract = _target.Contracts.Loader; - Contracts.ModuleHandle handle = contract.GetModuleHandle(_address); + Contracts.ModuleHandle handle = contract.GetModuleHandleFromModulePtr(_address); ModuleFlags moduleFlags = contract.GetFlags(handle); if ((moduleFlags & ModuleFlags.ReflectionEmit) != 0) @@ -222,7 +222,7 @@ int IXCLRDataModule.StartEnumExtents(ulong* handle) if (!_extentsSet) { Contracts.ILoader contract = _target.Contracts.Loader; - Contracts.ModuleHandle moduleHandle = contract.GetModuleHandle(_address); + Contracts.ModuleHandle moduleHandle = contract.GetModuleHandleFromModulePtr(_address); TargetPointer peAssembly = contract.GetPEAssembly(moduleHandle); if (peAssembly == 0) @@ -268,7 +268,7 @@ int IXCLRDataModule.EnumExtent(ulong* handle, /*CLRDATA_MODULE_EXTENT*/ void* ex try { Contracts.ILoader contract = _target.Contracts.Loader; - Contracts.ModuleHandle moduleHandle = contract.GetModuleHandle(_address); + Contracts.ModuleHandle moduleHandle = contract.GetModuleHandleFromModulePtr(_address); if (!_extentsSet) { @@ -344,7 +344,7 @@ private int DacPrivateRequestGetModuleData(uint inBufferSize, byte* inBuffer, ui Unsafe.InitBlock(getModuleData, 0, (uint)sizeof(DacpGetModuleData)); Contracts.ILoader contract = _target.Contracts.Loader; - Contracts.ModuleHandle moduleHandle = contract.GetModuleHandle(_address); + Contracts.ModuleHandle moduleHandle = contract.GetModuleHandleFromModulePtr(_address); TargetPointer peAssembly = contract.GetPEAssembly(moduleHandle); bool isReflectionEmit = (contract.GetFlags(moduleHandle) & ModuleFlags.ReflectionEmit) != 0; diff --git a/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs b/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs index 4a07701f68d..2104fb43970 100644 --- a/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs +++ b/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs @@ -157,7 +157,7 @@ int ISOSDacInterface.GetAssemblyList(ClrDataAddress addr, int count, [In, Marsha else { ILoader loader = _target.Contracts.Loader; - List modules = loader.GetModules( + List modules = loader.GetModuleHandles( appDomain, AssemblyIterationFlags.IncludeLoading | AssemblyIterationFlags.IncludeLoaded | @@ -225,8 +225,54 @@ int ISOSDacInterface.GetAssemblyList(ClrDataAddress addr, int count, [In, Marsha } int ISOSDacInterface.GetAssemblyLocation(ClrDataAddress assembly, int count, char* location, uint* pNeeded) => _legacyImpl is not null ? _legacyImpl.GetAssemblyLocation(assembly, count, location, pNeeded) : HResults.E_NOTIMPL; - int ISOSDacInterface.GetAssemblyModuleList(ClrDataAddress assembly, uint count, [In, MarshalUsing(CountElementName = "count"), Out] ClrDataAddress[] modules, uint* pNeeded) - => _legacyImpl is not null ? _legacyImpl.GetAssemblyModuleList(assembly, count, modules, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAssemblyModuleList(ClrDataAddress assembly, uint count, [In, MarshalUsing(CountElementName = "count"), Out] ClrDataAddress[]? modules, uint* pNeeded) + { + if (assembly == 0) + { + return HResults.E_INVALIDARG; + } + int hr = HResults.S_OK; + try + { + if (modules is not null && modules.Length > 0 && count > 0) + { + TargetPointer addr = assembly.ToTargetPointer(_target); + Contracts.ILoader loader = _target.Contracts.Loader; + Contracts.ModuleHandle handle = loader.GetModuleHandleFromAssemblyPtr(addr); + TargetPointer modulePointer = loader.GetModule(handle); + modules[0] = modulePointer.ToClrDataAddress(_target); + } + + if (pNeeded is not null) + { + *pNeeded = 1; + } + } + catch (System.Exception ex) + { + hr = ex.HResult; + } + +#if DEBUG + if (_legacyImpl is not null) + { + ClrDataAddress[] modulesLocal = new ClrDataAddress[count]; + uint neededLocal; + int hrLocal = _legacyImpl.GetAssemblyModuleList(assembly, count, modulesLocal, &neededLocal); + Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}"); + if (hr == HResults.S_OK) + { + Debug.Assert(pNeeded == null || *pNeeded == neededLocal); + if (modules is not null && modules.Length > 0) + { + Debug.Assert(modules[0] == modulesLocal[0], $"cDAC: {modules[0]:x}, DAC: {modulesLocal[0]:x}"); + } + } + } +#endif + return hr; + + } int ISOSDacInterface.GetAssemblyName(ClrDataAddress assembly, uint count, char* name, uint* pNeeded) => _legacyImpl is not null ? _legacyImpl.GetAssemblyName(assembly, count, name, pNeeded) : HResults.E_NOTIMPL; int ISOSDacInterface.GetCCWData(ClrDataAddress ccw, void* data) @@ -262,7 +308,10 @@ int ISOSDacInterface.GetDomainFromContext(ClrDataAddress context, ClrDataAddress ClrDataAddress domainLocal; int hrLocal = _legacyImpl.GetDomainFromContext(context, &domainLocal); Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}"); - Debug.Assert(domainLocal == context, $"cDAC: {context:x}, DAC: {domainLocal:x}"); + if (hr == HResults.S_OK) + { + Debug.Assert(domainLocal == context, $"cDAC: {context:x}, DAC: {domainLocal:x}"); + } } #endif return hr; @@ -767,7 +816,7 @@ int ISOSDacInterface.GetMethodDescName(ClrDataAddress addr, uint count, char* na else { TargetPointer modulePtr = rtsContract.GetModule(rtsContract.GetTypeHandle(rtsContract.GetMethodTable(methodDescHandle))); - Contracts.ModuleHandle module = _target.Contracts.Loader.GetModuleHandle(modulePtr); + Contracts.ModuleHandle module = _target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); string modulePath = _target.Contracts.Loader.GetPath(module); ReadOnlySpan moduleSpan = modulePath.AsSpan(); char directorySeparator = (char)_target.ReadGlobal(Constants.Globals.DirectorySeparator); @@ -1076,7 +1125,7 @@ int ISOSDacInterface.GetModuleData(ClrDataAddress moduleAddr, DacpModuleData* da try { Contracts.ILoader contract = _target.Contracts.Loader; - Contracts.ModuleHandle handle = contract.GetModuleHandle(moduleAddr.ToTargetPointer(_target)); + Contracts.ModuleHandle handle = contract.GetModuleHandleFromModulePtr(moduleAddr.ToTargetPointer(_target)); data->Address = moduleAddr; data->PEAssembly = moduleAddr; // Module address in .NET 9+ - correspondingly, SOS-DAC APIs for PE assemblies expect a module address @@ -1366,7 +1415,7 @@ int ISOSDacInterface.GetPEFileBase(ClrDataAddress addr, ClrDataAddress* peBase) try { Contracts.ILoader contract = _target.Contracts.Loader; - Contracts.ModuleHandle handle = contract.GetModuleHandle(addr.ToTargetPointer(_target)); + Contracts.ModuleHandle handle = contract.GetModuleHandleFromModulePtr(addr.ToTargetPointer(_target)); Contracts.ModuleFlags flags = contract.GetFlags(handle); if (!flags.HasFlag(Contracts.ModuleFlags.ReflectionEmit)) @@ -1405,7 +1454,7 @@ int ISOSDacInterface.GetPEFileName(ClrDataAddress addr, uint count, char* fileNa try { Contracts.ILoader contract = _target.Contracts.Loader; - Contracts.ModuleHandle handle = contract.GetModuleHandle(addr.ToTargetPointer(_target)); + Contracts.ModuleHandle handle = contract.GetModuleHandleFromModulePtr(addr.ToTargetPointer(_target)); string path = contract.GetPath(handle); // Return not implemented for empty paths for non-reflection emit assemblies (for example, loaded from memory) @@ -1789,7 +1838,46 @@ int ISOSDacInterface6.GetMethodTableCollectibleData(ClrDataAddress mt, /*struct #region ISOSDacInterface7 int ISOSDacInterface7.GetPendingReJITID(ClrDataAddress methodDesc, int* pRejitId) - => _legacyImpl7 is not null ? _legacyImpl7.GetPendingReJITID(methodDesc, pRejitId) : HResults.E_NOTIMPL; + { + if (methodDesc == 0 || pRejitId == null) + return HResults.E_INVALIDARG; + + int hr = HResults.S_OK; + try + { + Contracts.IReJIT rejitContract = _target.Contracts.ReJIT; + Contracts.ICodeVersions codeVersionsContract = _target.Contracts.CodeVersions; + TargetPointer methodDescPtr = methodDesc.ToTargetPointer(_target); + Contracts.ILCodeVersionHandle activeILCodeVersion = codeVersionsContract.GetActiveILCodeVersion(methodDescPtr); + + if (rejitContract.GetRejitState(activeILCodeVersion) == Contracts.RejitState.Requested) + { + *pRejitId = (int)rejitContract.GetRejitId(activeILCodeVersion).Value; + } + else + { + hr = HResults.S_FALSE; + } + } + catch (System.Exception ex) + { + hr = ex.HResult; + } +#if DEBUG + if (_legacyImpl7 is not null) + { + int rejitIdLocal; + int hrLocal = _legacyImpl7.GetPendingReJITID(methodDesc, &rejitIdLocal); + Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}"); + if (hr == HResults.S_OK) + { + Debug.Assert(*pRejitId == rejitIdLocal); + } + } + +#endif + return hr; + } int ISOSDacInterface7.GetReJITInformation(ClrDataAddress methodDesc, int rejitId, /*struct DacpReJitData2*/ void* pRejitData) => _legacyImpl7 is not null ? _legacyImpl7.GetReJITInformation(methodDesc, rejitId, pRejitData) : HResults.E_NOTIMPL; int ISOSDacInterface7.GetProfilerModifiedILInformation(ClrDataAddress methodDesc, /*struct DacpProfilerILData*/ void* pILData) diff --git a/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/SigFormat.cs b/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/SigFormat.cs index 69246f6b1e8..98ac68d98d0 100644 --- a/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/SigFormat.cs +++ b/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/SigFormat.cs @@ -179,7 +179,7 @@ private static unsafe void AddTypeString(Target target, uint typeDefToken = runtimeTypeSystem.GetTypeDefToken(th); TargetPointer modulePointer = target.Contracts.RuntimeTypeSystem.GetModule(th); - Contracts.ModuleHandle module = target.Contracts.Loader.GetModuleHandle(modulePointer); + Contracts.ModuleHandle module = target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePointer); MetadataReader internalTypeMetadata = target.Contracts.EcmaMetadata.GetMetadata(module)!; TypeDefinition internalTypeDef = internalTypeMetadata.GetTypeDefinition((TypeDefinitionHandle)MetadataTokens.Handle((int)typeDefToken)); @@ -345,7 +345,7 @@ private static void AddType(Target target, StringBuilder stringBuilder, TypeHand case CorElementType.Class: uint typeDefToken = runtimeTypeSystem.GetTypeDefToken(typeHandle); TargetPointer modulePointer = target.Contracts.RuntimeTypeSystem.GetModule(typeHandle); - Contracts.ModuleHandle module = target.Contracts.Loader.GetModuleHandle(modulePointer); + Contracts.ModuleHandle module = target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePointer); MetadataReader metadata = target.Contracts.EcmaMetadata.GetMetadata(module)!; TypeDefinition typeDef = metadata.GetTypeDefinition((TypeDefinitionHandle)MetadataTokens.Handle((int)typeDefToken)); string _namespace = metadata.GetString(typeDef.Namespace); @@ -390,7 +390,7 @@ private static void AddType(Target target, StringBuilder stringBuilder, TypeHand case CorElementType.MVar: case CorElementType.Var: runtimeTypeSystem.IsGenericVariable(typeHandle, out TargetPointer genericVariableModulePointer, out uint typeVarToken); - Contracts.ModuleHandle genericVariableModule = target.Contracts.Loader.GetModuleHandle(genericVariableModulePointer); + Contracts.ModuleHandle genericVariableModule = target.Contracts.Loader.GetModuleHandleFromModulePtr(genericVariableModulePointer); MetadataReader generatedVariableMetadata = target.Contracts.EcmaMetadata.GetMetadata(genericVariableModule)!; GenericParameter genericVariable = generatedVariableMetadata.GetGenericParameter((GenericParameterHandle)MetadataTokens.Handle((int)typeVarToken)); stringBuilder.Append(generatedVariableMetadata.GetString(genericVariable.Name)); diff --git a/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/TypeNameBuilder.cs b/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/TypeNameBuilder.cs index 1688f34db24..d05f14803d5 100644 --- a/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/TypeNameBuilder.cs +++ b/src/runtime/src/native/managed/cdac/mscordaccore_universal/Legacy/TypeNameBuilder.cs @@ -119,7 +119,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, } else { - module = loader.GetModuleHandle(runtimeTypeSystem.GetModule(th)); + module = loader.GetModuleHandleFromModulePtr(runtimeTypeSystem.GetModule(th)); MetadataReader reader = target.Contracts.EcmaMetadata.GetMetadata(module)!; MethodDefinition methodDef = reader.GetMethodDefinition(MetadataTokens.MethodDefinitionHandle((int)runtimeTypeSystem.GetMethodToken(method))); stringBuilder.Append(reader.GetString(methodDef.Name)); @@ -226,7 +226,7 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.TypeHandle } else if (typeSystemContract.IsGenericVariable(typeHandle, out TargetPointer modulePointer, out uint genericParamToken)) { - Contracts.ModuleHandle module = tnb.Target.Contracts.Loader.GetModuleHandle(modulePointer); + Contracts.ModuleHandle module = tnb.Target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePointer); MetadataReader reader = tnb.Target.Contracts.EcmaMetadata.GetMetadata(module)!; var handle = (GenericParameterHandle)MetadataTokens.Handle((int)genericParamToken); GenericParameter genericParam = reader.GetGenericParameter(handle); @@ -280,7 +280,7 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.TypeHandle { // ...otherwise it's just a plain type def or an instantiated type uint typeDefToken = typeSystemContract.GetTypeDefToken(typeHandle); - Contracts.ModuleHandle moduleHandle = tnb.Target.Contracts.Loader.GetModuleHandle(typeSystemContract.GetModule(typeHandle)); + Contracts.ModuleHandle moduleHandle = tnb.Target.Contracts.Loader.GetModuleHandleFromModulePtr(typeSystemContract.GetModule(typeHandle)); if (MetadataTokens.EntityHandle((int)typeDefToken).IsNil) { tnb.AddName("(dynamicClass)"); @@ -311,7 +311,7 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.TypeHandle { TargetPointer modulePtr = typeSystemContract.GetModule(typeHandle); - Contracts.ModuleHandle module = tnb.Target.Contracts.Loader.GetModuleHandle(modulePtr); + Contracts.ModuleHandle module = tnb.Target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); // NOTE: The DAC variant of assembly name generation is different than the runtime version. The DAC variant is simpler, and only uses SimpleName MetadataReader mr = tnb.Target.Contracts.EcmaMetadata.GetMetadata(module)!; diff --git a/src/runtime/src/native/managed/cdac/tests/CodeVersionsTests.cs b/src/runtime/src/native/managed/cdac/tests/CodeVersionsTests.cs index 570fa878270..1b7619349cd 100644 --- a/src/runtime/src/native/managed/cdac/tests/CodeVersionsTests.cs +++ b/src/runtime/src/native/managed/cdac/tests/CodeVersionsTests.cs @@ -85,7 +85,7 @@ public static void AddCodeBlock(this Mock mock, MockCodeBlock public static void AddModule(this Mock mock, MockModule module) { Contracts.ModuleHandle handle = new Contracts.ModuleHandle(module.Address); - mock.Setup(l => l.GetModuleHandle(module.Address)).Returns(handle); + mock.Setup(l => l.GetModuleHandleFromModulePtr(module.Address)).Returns(handle); mock.Setup(l => l.GetLookupTables(handle)).Returns(new ModuleLookupTables() { MethodDefToILCodeVersioningState = module.MethodDefToILCodeVersioningStateAddress, }); diff --git a/src/runtime/src/native/managed/cdac/tests/LoaderTests.cs b/src/runtime/src/native/managed/cdac/tests/LoaderTests.cs index 2e13e784dcc..da7198d353a 100644 --- a/src/runtime/src/native/managed/cdac/tests/LoaderTests.cs +++ b/src/runtime/src/native/managed/cdac/tests/LoaderTests.cs @@ -36,12 +36,12 @@ public void GetPath(MockTarget.Architecture arch) ILoader contract = target.Contracts.Loader; Assert.NotNull(contract); { - Contracts.ModuleHandle handle = contract.GetModuleHandle(moduleAddr); + Contracts.ModuleHandle handle = contract.GetModuleHandleFromModulePtr(moduleAddr); string actual = contract.GetPath(handle); Assert.Equal(expected, actual); } { - Contracts.ModuleHandle handle = contract.GetModuleHandle(moduleAddrEmptyPath); + Contracts.ModuleHandle handle = contract.GetModuleHandleFromModulePtr(moduleAddrEmptyPath); string actual = contract.GetFileName(handle); Assert.Equal(string.Empty, actual); } @@ -70,12 +70,12 @@ public void GetFileName(MockTarget.Architecture arch) Contracts.ILoader contract = target.Contracts.Loader; Assert.NotNull(contract); { - Contracts.ModuleHandle handle = contract.GetModuleHandle(moduleAddr); + Contracts.ModuleHandle handle = contract.GetModuleHandleFromModulePtr(moduleAddr); string actual = contract.GetFileName(handle); Assert.Equal(expected, actual); } { - Contracts.ModuleHandle handle = contract.GetModuleHandle(moduleAddrEmptyName); + Contracts.ModuleHandle handle = contract.GetModuleHandleFromModulePtr(moduleAddrEmptyName); string actual = contract.GetFileName(handle); Assert.Equal(string.Empty, actual); } diff --git a/src/runtime/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/runtime/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 1dcde7f2655..00d9e45ae2a 100644 --- a/src/runtime/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/runtime/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -3907,16 +3907,16 @@ ("SveLoadVectorMaskedTest.template", new Dictionary { ["TestName"] = "Sve_LoadVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()"}), ("SveLoadVectorMaskedTest.template", new Dictionary { ["TestName"] = "Sve_LoadVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_float", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["Cast"] = "(float*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_double", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["Cast"] = "(double*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_sbyte", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["GetFfrType"] = "SByte", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Cast"] = "(sbyte*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_short", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["GetFfrType"] = "Int16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Cast"] = "(short*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_int", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["GetFfrType"] = "Int32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Cast"] = "(int*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_long", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["GetFfrType"] = "Int64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Cast"] = "(long*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_byte", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["GetFfrType"] = "Byte", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Cast"] = "(byte*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_ushort", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Cast"] = "(ushort*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_uint", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Cast"] = "(uint*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Cast"] = "(ulong*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_float", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt32", ["NextValueOp1"] = "Helpers.getMaskSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["Cast"] = "(float*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_double", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt64", ["NextValueOp1"] = "Helpers.getMaskDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["Cast"] = "(double*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_sbyte", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["GetFfrType"] = "SByte", ["NextValueOp1"] = "Helpers.getMaskSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["Cast"] = "(sbyte*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_short", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["GetFfrType"] = "Int16", ["NextValueOp1"] = "Helpers.getMaskInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Cast"] = "(short*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_int", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["GetFfrType"] = "Int32", ["NextValueOp1"] = "Helpers.getMaskInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Cast"] = "(int*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_long", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["GetFfrType"] = "Int64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Cast"] = "(long*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_byte", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["GetFfrType"] = "Byte", ["NextValueOp1"] = "Helpers.getMaskByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["Cast"] = "(byte*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_ushort", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt16", ["NextValueOp1"] = "Helpers.getMaskUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Cast"] = "(ushort*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_uint", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt32", ["NextValueOp1"] = "Helpers.getMaskUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Cast"] = "(uint*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorNonFaulting_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVectorNonFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["GetFfrType"] = "UInt64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Cast"] = "(ulong*)", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoadVectorFirstFaultingTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteZeroExtendFirstFaulting_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendFirstFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["GetFfrType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()"}), ("SveLoadVectorFirstFaultingTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteZeroExtendFirstFaulting_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendFirstFaulting", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["GetFfrType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()"}), @@ -3981,18 +3981,18 @@ ("SveLoadVectorMaskedTest.template", new Dictionary { ["TestName"] = "Sve_LoadVector128AndReplicateToVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector128AndReplicateToVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()"}), ("SveLoadVectorMaskedTest.template", new Dictionary { ["TestName"] = "Sve_LoadVector128AndReplicateToVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector128AndReplicateToVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()"}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt16NonFaultingSignExtendToInt32_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt16NonFaultingSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["GetFfrType"] = "Int32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt16NonFaultingSignExtendToInt64_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt16NonFaultingSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt16NonFaultingSignExtendToUInt32_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt16NonFaultingSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["GetFfrType"] = "UInt32", ["Cast"] = "", ["ValidateIterResult"] = "((uint)firstOp[i]) != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt16NonFaultingSignExtendToUInt64_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt16NonFaultingSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "((ulong)firstOp[i]) != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt32NonFaultingSignExtendToInt64_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt32NonFaultingSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt32NonFaultingSignExtendToUInt64_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt32NonFaultingSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "((ulong)firstOp[i]) != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToInt16_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "Int16", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToInt32_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "Int32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToInt64_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToUInt16_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "UInt16", ["Cast"] = "", ["ValidateIterResult"] = "((ushort)firstOp[i]) != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToUInt32_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "UInt32", ["Cast"] = "", ["ValidateIterResult"] = "((uint)firstOp[i]) != result[i]",}), - ("SveLoadNonFaultingUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToUInt64_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "((ulong)firstOp[i]) != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt16NonFaultingSignExtendToInt32_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt16NonFaultingSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["GetFfrType"] = "Int32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt16NonFaultingSignExtendToInt64_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt16NonFaultingSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt16NonFaultingSignExtendToUInt32_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt16NonFaultingSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["GetFfrType"] = "UInt32", ["Cast"] = "", ["ValidateIterResult"] = "((uint)firstOp[i]) != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt16NonFaultingSignExtendToUInt64_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt16NonFaultingSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "((ulong)firstOp[i]) != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt32NonFaultingSignExtendToInt64_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt32NonFaultingSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorInt32NonFaultingSignExtendToUInt64_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorInt32NonFaultingSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "((ulong)firstOp[i]) != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToInt16_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "Int16", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToInt32_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "Int32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToInt64_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToUInt16_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "UInt16", ["Cast"] = "", ["ValidateIterResult"] = "((ushort)firstOp[i]) != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToUInt32_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "UInt32", ["Cast"] = "", ["ValidateIterResult"] = "((uint)firstOp[i]) != result[i]",}), + ("SveLoadNonFaultingMaskedUnOpTest.template",new Dictionary {["TestName"] = "Sve_LoadVectorSByteNonFaultingSignExtendToUInt64_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "LoadVectorSByteNonFaultingSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "((ulong)firstOp[i]) != result[i]",}), ("SveLoadVectorMaskedTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorInt16SignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()"}), ("SveLoadVectorMaskedTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorInt16SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()"}), @@ -4019,18 +4019,18 @@ ("SveLoadVectorMaskedTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt32ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()"}), ("SveLoadVectorMaskedTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt32ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "Int16", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "Int32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "UInt16", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "UInt32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt16NonFaultingZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16NonFaultingZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["GetFfrType"] = "Int32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt16NonFaultingZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16NonFaultingZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt16NonFaultingZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16NonFaultingZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["GetFfrType"] = "UInt32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt16NonFaultingZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16NonFaultingZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt32NonFaultingZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32NonFaultingZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadNonFaultingUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt32NonFaultingZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32NonFaultingZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "Int16", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "Int32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "UInt16", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "UInt32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorByteNonFaultingZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteNonFaultingZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt16NonFaultingZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16NonFaultingZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["GetFfrType"] = "Int32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt16NonFaultingZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16NonFaultingZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt16NonFaultingZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16NonFaultingZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["GetFfrType"] = "UInt32", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt16NonFaultingZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16NonFaultingZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt32NonFaultingZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32NonFaultingZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["GetFfrType"] = "Int64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadNonFaultingMaskedUnOpTest.template", new Dictionary { ["TestName"] = "Sve_LoadVectorUInt32NonFaultingZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32NonFaultingZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["GetFfrType"] = "UInt64", ["Cast"] = "", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("SveLoad2xVectorAndUnzipTest.template", new Dictionary { ["TestName"] = "Sve_Load2xVectorAndUnzip_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Load2xVectorAndUnzip", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "result1[i] != input[i * 2] || result2[i] != input[i * 2 + 1]"}), ("SveLoad2xVectorAndUnzipTest.template", new Dictionary { ["TestName"] = "Sve_Load2xVectorAndUnzip_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Load2xVectorAndUnzip", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "result1[i] != input[i * 2] || result2[i] != input[i * 2 + 1]"}), @@ -4889,12 +4889,12 @@ ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_AddPairwise_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseSve(left, right, i) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddPairwiseSve(left, right, i)"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_AddPairwise_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseSve(left, right, i) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddPairwiseSve(left, right, i)"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWidening_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddPairwiseWidening(left, right, i)"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWidening_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddPairwiseWidening(left, right, i)"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWidening_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddPairwiseWidening(left, right, i)"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWidening_ushort_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddPairwiseWidening(left, right, i)"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWidening_uint_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddPairwiseWidening(left, right, i)"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWidening_ulong_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddPairwiseWidening(left, right, i)"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWideningAndAdd_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddPairwiseWidening(left, right, i)"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWideningAndAdd_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddPairwiseWidening(left, right, i)"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWideningAndAdd_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddPairwiseWidening(left, right, i)"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWideningAndAdd_ushort_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddPairwiseWidening(left, right, i)"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWideningAndAdd_uint_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddPairwiseWidening(left, right, i)"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddPairwiseWideningAndAdd_ulong_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(left, right, i) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddPairwiseWidening(left, right, i)"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_AddSaturate_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "(SByte) Helpers.AddSaturate(left[i], right[i])"}), ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_AddSaturate_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddSaturate(left[i], right[i])"}), @@ -4915,37 +4915,37 @@ ("SveVecBinOpDifferentRetType.template", new Dictionary {["TestName"] = "Sve2_AddSaturateWithUnsignedAddend_int_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddSaturateWithUnsignedAddend", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddSaturate(left[i], right[i])"}), ("SveVecBinOpDifferentRetType.template", new Dictionary {["TestName"] = "Sve2_AddSaturateWithUnsignedAddend_long_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddSaturateWithUnsignedAddend", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddSaturate(left[i], right[i])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideLower_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i], right[i * 2])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideLower_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i], right[i * 2])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideLower_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i], right[i * 2])",}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideLower_ushort_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2])!= result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddWidening(left[i], right[i * 2])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideLower_uint_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddWidening(left[i], right[i * 2])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideLower_ulong_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddWidening(left[i], right[i * 2])"}), - - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideUpper_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideUpper_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideUpper_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideUpper_ushort_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideUpper_uint_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideUpper_ulong_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), - - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningLower_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i * 2], right[i * 2])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningLower_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i * 2], right[i * 2])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningLower_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i * 2], right[i * 2])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningLower_ushort_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddWidening(left[i * 2], right[i * 2])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningLower_uint_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddWidening(left[i * 2], right[i * 2])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningLower_ulong_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddWidening(left[i * 2], right[i * 2])"}), - - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningLowerUpper_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningLowerUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i * 2], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningLowerUpper_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningLowerUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i * 2], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningLowerUpper_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningLowerUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i * 2], right[i * 2 + 1])"}), - - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningUpper_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningUpper_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningUpper_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningUpper_ushort_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningUpper_uint_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), - ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningUpper_ulong_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_short_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i], right[i * 2])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_int_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i], right[i * 2])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_long_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i], right[i * 2])",}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_ushort_ushort_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2])!= result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddWidening(left[i], right[i * 2])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_uint_uint_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddWidening(left[i], right[i * 2])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_ulong_ulong_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddWidening(left[i], right[i * 2])"}), + + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_short_sbyte_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i * 2], right[i * 2])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_int_short_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i * 2], right[i * 2])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_long_int_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i * 2], right[i * 2])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_ushort_byte_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddWidening(left[i * 2], right[i * 2])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_uint_ushort_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddWidening(left[i * 2], right[i * 2])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEven_ulong_uint_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2]) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddWidening(left[i * 2], right[i * 2])"}), + + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEvenOdd_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEvenOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i * 2], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEvenOdd_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEvenOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i * 2], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningEvenOdd_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningEvenOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i * 2], right[i * 2 + 1])"}), + + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_short_short_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_int_int_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_long_long_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_ushort_ushort_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_uint_uint_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_ulong_ulong_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddWidening(left[i], right[i * 2 + 1])"}), + + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_short_sbyte_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int16) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_int_short_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int32) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_long_int_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(Int64) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_ushort_byte_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt16) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_uint_ushort_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt32) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), + ("SveVecBinOpDifferentRetType.template", new Dictionary { ["TestName"] = "Sve2_AddWideningOdd_ulong_uint_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "AddWideningOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1]) != result[i]", ["GetIterResult"] = "(UInt64) Helpers.AddWidening(left[i * 2 + 1], right[i * 2 + 1])"}), ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_BitwiseClearXor_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "BitwiseClearXor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != (firstOp[i] ^ (secondOp[i] &~ thirdOp[i]))", ["GetIterResult"] = "(SByte) (firstOp[i] ^ (secondOp[i] &~ thirdOp[i]))"}), ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_BitwiseClearXor_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "BitwiseClearXor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != (firstOp[i] ^ (secondOp[i] &~ thirdOp[i]))", ["GetIterResult"] = "(Int16) (firstOp[i] ^ (secondOp[i] &~ thirdOp[i]))"}), @@ -4981,6 +4981,24 @@ ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_BitwiseSelectRightInverted_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "BitwiseSelectRightInverted", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.BitwiseSelectRightInverted(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.BitwiseSelectRightInverted(firstOp[i], secondOp[i], thirdOp[i])"}), ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_BitwiseSelectRightInverted_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "BitwiseSelectRightInverted", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.BitwiseSelectRightInverted(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.BitwiseSelectRightInverted(firstOp[i], secondOp[i], thirdOp[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedAddHalving_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedAddHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedAddHalving_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedAddHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedAddHalving_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedAddHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedAddHalving_long", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedAddHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedAddHalving_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedAddHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedAddHalving_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedAddHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedAddHalving_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedAddHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedAddHalving_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedAddHalving(left[i], right[i])"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedSubtractHalving_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedSubtractHalving_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedSubtractHalving_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedSubtractHalving_long", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedSubtractHalving_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedSubtractHalving_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedSubtractHalving_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_FusedSubtractHalving_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i])"}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_InterleavingXorEvenOdd_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "InterleavingXorEvenOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.InterleavingXorEvenOdd(firstOp, secondOp, thirdOp)[i]", ["GetIterResult"] = "Helpers.InterleavingXorEvenOdd(first, second, third)[i]"}), ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_InterleavingXorEvenOdd_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "InterleavingXorEvenOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.InterleavingXorEvenOdd(firstOp, secondOp, thirdOp)[i]", ["GetIterResult"] = "Helpers.InterleavingXorEvenOdd(first, second, third)[i]"}), ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_InterleavingXorEvenOdd_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "InterleavingXorEvenOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.InterleavingXorEvenOdd(firstOp, secondOp, thirdOp)[i]", ["GetIterResult"] = "Helpers.InterleavingXorEvenOdd(first, second, third)[i]"}), diff --git a/src/runtime/src/tests/Interop/COM/NETClients/IDispatch/Program.cs b/src/runtime/src/tests/Interop/COM/NETClients/IDispatch/Program.cs index 90a6ea994eb..4324913a5a1 100644 --- a/src/runtime/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/runtime/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -108,7 +108,7 @@ static void Validate_Double_In_ReturnAndUpdateByRef() static int GetErrorCodeFromHResult(int hresult) { - // https://msdn.microsoft.com/en-us/library/cc231198.aspx + // https://msdn.microsoft.com/library/cc231198.aspx return hresult & 0xffff; } @@ -116,7 +116,7 @@ static void Validate_Exception() { var dispatchTesting = (DispatchTesting)new DispatchTestingClass(); - int errorCode = 127; + int errorCode = 1127; string resultString = errorCode.ToString("x"); try { @@ -130,6 +130,19 @@ static void Validate_Exception() Assert.Equal(e.Message, resultString); } + try + { + Console.WriteLine($"Calling {nameof(DispatchTesting.TriggerException)} with {nameof(IDispatchTesting_Exception.DispLegacy)} {errorCode}..."); + dispatchTesting.TriggerException(IDispatchTesting_Exception.DispLegacy, errorCode); + Assert.Fail("DISP exception not thrown properly"); + } + catch (COMException e) + { + Assert.Equal(e.ErrorCode, errorCode); // The legacy DISP exception returns the error code unmodified. + Assert.Equal(e.HResult, errorCode); + Assert.Equal(e.Message, resultString); + } + try { Console.WriteLine($"Calling {nameof(DispatchTesting.TriggerException)} with {nameof(IDispatchTesting_Exception.HResult)} {errorCode}..."); diff --git a/src/runtime/src/tests/Interop/COM/NETServer/DispatchTesting.cs b/src/runtime/src/tests/Interop/COM/NETServer/DispatchTesting.cs index 66461b8c7e4..bf9b9d740e9 100644 --- a/src/runtime/src/tests/Interop/COM/NETServer/DispatchTesting.cs +++ b/src/runtime/src/tests/Interop/COM/NETServer/DispatchTesting.cs @@ -55,6 +55,7 @@ public void TriggerException(IDispatchTesting_Exception excep, int errorCode) switch (excep) { case IDispatchTesting_Exception.Disp: + case IDispatchTesting_Exception.DispLegacy: throw new Exception(); case IDispatchTesting_Exception.HResult: case IDispatchTesting_Exception.Int: diff --git a/src/runtime/src/tests/Interop/COM/NativeServer/DispatchTesting.h b/src/runtime/src/tests/Interop/COM/NativeServer/DispatchTesting.h index b4ee769ed8c..4c69174eec7 100644 --- a/src/runtime/src/tests/Interop/COM/NativeServer/DispatchTesting.h +++ b/src/runtime/src/tests/Interop/COM/NativeServer/DispatchTesting.h @@ -240,6 +240,7 @@ class DispatchTesting : public UnknownImpl, public IDispatchTesting switch (excep) { case IDispatchTesting_Exception_Disp: + case IDispatchTesting_Exception_Disp_Legacy: return DISP_E_EXCEPTION; case IDispatchTesting_Exception_HResult: return HRESULT_FROM_WIN32(errorCode); @@ -457,11 +458,22 @@ class DispatchTesting : public UnknownImpl, public IDispatchTesting args[1] = &currArg->intVal; } - hr = TriggerException(static_cast(*args[0]), *args[1]); + IDispatchTesting_Exception kind = static_cast(*args[0]); + hr = TriggerException(kind, *args[1]); if (hr == DISP_E_EXCEPTION) { *puArgErr = 1; - pExcepInfo->scode = HRESULT_FROM_WIN32(*args[1]); + if (kind == IDispatchTesting_Exception_Disp_Legacy) + { + pExcepInfo->wCode = *args[1]; // Legacy exception code + pExcepInfo->scode = 0; + } + else + { + assert(kind == IDispatchTesting_Exception_Disp); + pExcepInfo->wCode = 0; + pExcepInfo->scode = HRESULT_FROM_WIN32(*args[1]); + } WCHAR buffer[ARRAY_SIZE(W("4294967295"))]; _snwprintf_s(buffer, ARRAY_SIZE(buffer), _TRUNCATE, W("%x"), *args[1]); diff --git a/src/runtime/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs b/src/runtime/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs index ae68bcf34a0..a697d0359a2 100644 --- a/src/runtime/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/runtime/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -237,7 +237,8 @@ public interface IErrorMarshalTesting public enum IDispatchTesting_Exception { - Disp, + Disp, // scode + DispLegacy, // wCode HResult, Int, } diff --git a/src/runtime/src/tests/Interop/COM/ServerContracts/Server.Contracts.h b/src/runtime/src/tests/Interop/COM/ServerContracts/Server.Contracts.h index 9e8b256a73d..b73c0c54b8b 100644 --- a/src/runtime/src/tests/Interop/COM/ServerContracts/Server.Contracts.h +++ b/src/runtime/src/tests/Interop/COM/ServerContracts/Server.Contracts.h @@ -413,7 +413,8 @@ IErrorMarshalTesting : IUnknown enum IDispatchTesting_Exception { - IDispatchTesting_Exception_Disp, + IDispatchTesting_Exception_Disp, // scode + IDispatchTesting_Exception_Disp_Legacy, // wCode IDispatchTesting_Exception_HResult, IDispatchTesting_Exception_Int, }; diff --git a/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index 1234c422959..e1ddb8238d1 100644 --- a/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -3124,6 +3124,38 @@ public static uint AddHighNarrowingOdd(uint[] even, ulong[] op1, ulong[] op2, in public static uint FusedAddHalving(uint op1, uint op2) => (uint)((ulong)((ulong)op1 + (ulong)op2) >> 1); + public static ulong FusedAddHalving(ulong op1, ulong op2) + { + ulong sum = op1 + op2; + bool carry = sum < op1; + return (sum >> 1) + (carry ? 1UL << 63 : 0); + } + public static long FusedAddHalving(long op1, long op2) + { + long sum = op1 + op2; + bool carry = sum < op1; + return (sum >> 1) + (carry ? 1L << 63 : 0); + } + + public static long FusedSubtractHalving(long op1, long op2) + { + ulong uop1 = (ulong)op1; + ulong uop2 = (ulong)op2; + + ulong udiff = uop1 - uop2; + long sdiff = unchecked((long)udiff); + + return sdiff >> 1; + } + + public static ulong FusedSubtractHalving(ulong op1, ulong op2) + { + ulong diff = op1 - op2; + bool overflow = op1 < op2; + return (diff >> 1) + (overflow ? 1UL << 63 : 0); + } + + public static uint FusedAddRoundedHalving(uint op1, uint op2) => (uint)((ulong)((ulong)op1 + (ulong)op2 + 1) >> 1); public static uint FusedSubtractHalving(uint op1, uint op2) => (uint)((ulong)((ulong)op1 - (ulong)op2) >> 1); diff --git a/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadNonFaultingMaskedUnOpTest.template b/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadNonFaultingMaskedUnOpTest.template new file mode 100644 index 00000000000..ad454ae481a --- /dev/null +++ b/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadNonFaultingMaskedUnOpTest.template @@ -0,0 +1,350 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Buffers; +using System.Numerics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new LoadVectorFaultingMaskedUnOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario_Load(); + + // Validates basic non faulting functionality + test.RunBasicScenario_LoadNonFaulting(); + + // Validates calling via reflection works + test.RunReflectionScenario_Load(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class LoadVectorFaultingMaskedUnOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op2BaseType}[] inArray1, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + int sizeOfInBounded = {RetVectorType}<{RetBaseType}>.Count / 2; + + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfoutArray: {sizeOfoutArray}"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + this.inBounded = BoundedMemory.Allocate(sizeOfInBounded, PoisonPagePlacement.After); + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref inBounded.Span.GetPinnableReference(), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray1[0]), (uint)sizeOfInBounded); + } + + public BoundedMemory inBounded; + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {RetVectorType}<{RetBaseType}> _fld1; + public {RetBaseType}[] _outData; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._outData= new {RetBaseType}[RetElementCount]; + + // Randomise the output buffer to ensure that after the load operation, expected data is populated. + for (var i = 0; i < RetElementCount; i++) { testStruct._outData[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetVectorType}<{RetBaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{RetBaseType}, byte>(ref testStruct._outData[0]), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(LoadVectorFaultingMaskedUnOpTest__{TestName} testClass) + { + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}(loadMask, ({Op2BaseType}*)testClass._dataTable.inArray1Ptr); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(loadMask, testClass._dataTable.inArray1Ptr, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{RetVectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + private static readonly int Op2ElementCount = RetElementCount; + + private static {Op2BaseType}[] _data = new {Op2BaseType}[Op2ElementCount]; + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + + private {Op1VectorType}<{RetBaseType}> _fld1; + + private {Op1VectorType}<{Op1BaseType}> _mask; + + private DataTable _dataTable; + + public LoadVectorFaultingMaskedUnOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1}); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op2ElementCount; i++) { _data[i] = {NextValueOp2}; } + _dataTable = new DataTable(_data, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + loadMask, + ({Op2BaseType}*)(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(loadMask, _dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadNonFaulting() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadNonFaulting)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + ref var op2Ref = ref _dataTable.inBounded.Span.GetPinnableReference(); + + Sve.SetFfr(Sve.CreateTrueMaskByte(SveMaskPattern.All)); + + var result = {Isa}.{Method}( + loadMask, + ({Op2BaseType}*)(Unsafe.AsPointer(ref op2Ref)) + ); + + var faultResult = Sve.GetFfr{GetFfrType}(); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateNonFaultingResult(loadMask, Unsafe.AsPointer(ref op2Ref), _dataTable.outArrayPtr, faultResult); + } + + public void RunBasicScenario_LoadMasked() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = {Isa}.{Method}( + _mask, + ({Op2BaseType}*)(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_mask, _dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof(Vector<{Op1BaseType}>), typeof({Op2BaseType}*) }) + .Invoke(null, new object[] { + loadMask, + Pointer.Box(_dataTable.inArray1Ptr, typeof({Op2BaseType}*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(loadMask, _dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + _fld1 = {Isa}.{Method}(loadMask, ({Op2BaseType}*)_dataTable.inArray1Ptr); + + Unsafe.Write(_dataTable.outArrayPtr, _fld1); + ValidateResult(loadMask, _dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var test = TestStruct.Create(); + test._fld1 = {Isa}.{Method}(loadMask, ({Op2BaseType}*)_dataTable.inArray1Ptr); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld1); + ValidateResult(loadMask, _dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_Load(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> firstOp, void * secondOp, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] maskArray = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref maskArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray[0]), ref Unsafe.AsRef(secondOp), (uint)(sizeof({Op2BaseType}) * Op2ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(sizeof({RetBaseType}) * RetElementCount)); + + ValidateResult(maskArray, inArray, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = Helpers.CheckLoadVectorBehavior(firstOp, secondOp, result); + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2BaseType}): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + + private void ValidateNonFaultingResult({Op1VectorType}<{Op1BaseType}> firstOp, void* secondOp, void* result, Vector<{GetFfrType}> faultResult, [CallerMemberName] string method = "") + { + {Op1BaseType}[] maskArray = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + {GetFfrType}[] faultArray = new {GetFfrType}[RetElementCount]; + + // Only read bytes mapping to half of the destination vector. The remaining elements are in the poison page. + // It would make inArray to contain elements that could read without a fault followed by zeros. + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref maskArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray[0]), ref Unsafe.AsRef(secondOp), ((uint){RetVectorType}<{RetBaseType}>.Count / 2) ); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + fixed({GetFfrType}* faultArrayPtr = &faultArray[0]) + { + Unsafe.Write(faultArrayPtr, faultResult); + } + + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + var expectedOut = ({RetBaseType})((i < (RetElementCount / 2)) ? inArray[i] : 0); + var expectedFault = ({GetFfrType}) ((i < (RetElementCount / 2)) ? 1 : 0); + + if ((outArray[i] != expectedOut) && (faultArray[i] != expectedFault) ) + { + succeeded = false; + break; + } + } + } + } +} diff --git a/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadNonFaultingUnOpTest.template b/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadNonFaultingUnOpTest.template deleted file mode 100644 index db2416974cd..00000000000 --- a/src/runtime/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadNonFaultingUnOpTest.template +++ /dev/null @@ -1,521 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/****************************************************************************** - * This file is auto-generated from a template file by the GenerateTests.csx * - * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * - * changes, please update the corresponding template and run according to the * - * directions listed in the file. * - ******************************************************************************/ - -using System; -using System.Buffers; -using System.Numerics; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.Arm; -using Xunit; - -namespace JIT.HardwareIntrinsics.Arm -{ - public static partial class Program - { - [Fact] - public static void {TestName}() - { - var test = new LoadNonFaultingUnaryOpTest__{TestName}(); - - if (test.IsSupported) - { - // Validates basic functionality works - test.RunBasicScenario_Load(); - - // Validates basic functionality - test.RunBasicScenario_LoadNonFaulting(); - - // Validates calling via reflection works - test.RunReflectionScenario_Load(); - - // Validates passing an instance member of a class works - test.RunClassFldScenario(); - - // Validates passing the field of a local struct works - test.RunStructLclFldScenario(); - - // Validates passing an instance member of a struct works - test.RunStructFldScenario(); - - // Validates using inside ConditionalSelect with value falseValue - test.ConditionalSelect_FalseOp(); - - // Validates using inside ConditionalSelect with zero falseValue - test.ConditionalSelect_ZeroOp(); - } - else - { - // Validates we throw on unsupported hardware - test.RunUnsupportedScenario(); - } - - if (!test.Succeeded) - { - throw new Exception("One or more scenarios did not complete as expected."); - } - } - } - - public sealed unsafe class LoadNonFaultingUnaryOpTest__{TestName} - { - private struct DataTable - { - private byte[] inArray1; - private byte[] outArray; - - private GCHandle inHandle1; - private GCHandle outHandle; - - private ulong alignment; - - public DataTable({Op1BaseType}[] inArray1, {RetBaseType}[] outArray, int alignment) - { - int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); - int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); - // Choose size of bounded memory such that half of the vector would fall in accessible memory while the rest would in non-accessible one. - int sizeOfInBounded = {RetVectorType}<{RetBaseType}>.Count / 2; - - if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) - { - throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfoutArray: {sizeOfoutArray}"); - } - - this.inArray1 = new byte[alignment * 2]; - this.outArray = new byte[alignment * 2]; - - this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); - this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); - - this.alignment = (ulong)alignment; - this.inBounded = BoundedMemory.Allocate(sizeOfInBounded, PoisonPagePlacement.After); - - Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); - Unsafe.CopyBlockUnaligned(ref inBounded.Span.GetPinnableReference(), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfInBounded); - } - - public BoundedMemory inBounded; - - public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); - public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); - - public void Dispose() - { - inHandle1.Free(); - outHandle.Free(); - } - - private static unsafe void* Align(byte* buffer, ulong expectedAlignment) - { - return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); - } - } - - private struct TestStruct - { - public {Op1VectorType}<{RetBaseType}> _fld1; - - public static TestStruct Create() - { - var testStruct = new TestStruct(); - - for (var i = 0; i < Op1ElementCount; i++) { _data[i] = {NextValueOp1}; } - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{RetBaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{RetBaseType}>>()); - - return testStruct; - } - - public void RunStructFldScenario(LoadNonFaultingUnaryOpTest__{TestName} testClass) - { - var result = {Isa}.{Method}(({Op1BaseType}*)testClass._dataTable.inArray1Ptr); - - Unsafe.Write(testClass._dataTable.outArrayPtr, result); - testClass.ValidateResult(testClass._dataTable.inArray1Ptr, testClass._dataTable.outArrayPtr); - } - } - - private static readonly int LargestVectorSize = {LargestVectorSize}; - - private static readonly int Op1ElementCount = Unsafe.SizeOf<{RetVectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); - private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); - - private static {RetBaseType}[] _maskData = new {RetBaseType}[RetElementCount]; - private static {RetBaseType}[] _falseData = new {RetBaseType}[RetElementCount]; - private static {Op1BaseType}[] _data = new {Op1BaseType}[Op1ElementCount]; - - private {Op1VectorType}<{RetBaseType}> _fld1; - private {Op1VectorType}<{RetBaseType}> _mask; - private {Op1VectorType}<{RetBaseType}> _falseFld; - - private DataTable _dataTable; - - public LoadNonFaultingUnaryOpTest__{TestName}() - { - Succeeded = true; - - for (var i = 0; i < RetElementCount; i++) { _maskData[i] = ({RetBaseType})({NextValueOp1} % 2); } - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{RetBaseType}>, byte>(ref _mask), ref Unsafe.As<{RetBaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{RetBaseType}>>()); - - for (var i = 0; i < RetElementCount; i++) { _falseData[i] = ({RetBaseType})({NextValueOp1} % 50); } - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{RetBaseType}>, byte>(ref _falseFld), ref Unsafe.As<{RetBaseType}, byte>(ref _falseData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{RetBaseType}>>()); - - for (var i = 0; i < Op1ElementCount; i++) { _data[i] = {NextValueOp1}; } - _dataTable = new DataTable(_data, new {RetBaseType}[RetElementCount], LargestVectorSize); - } - - public bool IsSupported => {Isa}.IsSupported; - - public bool Succeeded { get; set; } - - public void RunBasicScenario_Load() - { - TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - - var result = {Isa}.{Method}( - ({Op1BaseType}*)(_dataTable.inArray1Ptr) - ); - - Unsafe.Write(_dataTable.outArrayPtr, result); - ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); - } - - public void RunBasicScenario_LoadNonFaulting() - { - TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadNonFaulting)); - - ref var op1Ref = ref _dataTable.inBounded.Span.GetPinnableReference(); - - Sve.SetFfr(Sve.CreateTrueMaskByte(SveMaskPattern.All)); - var result = {Isa}.{Method}(({Op1BaseType}*)(Unsafe.AsPointer(ref op1Ref))); - var faultResult = Sve.GetFfr{GetFfrType}(); - - Unsafe.Write(_dataTable.outArrayPtr, result); - ValidateNonFaultingResult(Unsafe.AsPointer(ref op1Ref), _dataTable.outArrayPtr, faultResult); - } - - public void RunReflectionScenario_Load() - { - TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - - var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}*) }) - .Invoke(null, new object[] { - Pointer.Box(_dataTable.inArray1Ptr, typeof({Op1BaseType}*)) - }); - - Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); - ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); - } - - public void RunClassFldScenario() - { - TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - - _fld1 = {Isa}.{Method}(({Op1BaseType}*)_dataTable.inArray1Ptr); - - Unsafe.Write(_dataTable.outArrayPtr, _fld1); - ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); - } - - public void RunStructLclFldScenario() - { - TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); - - var test = TestStruct.Create(); - test._fld1 = {Isa}.{Method}(({Op1BaseType}*)_dataTable.inArray1Ptr); - - Unsafe.Write(_dataTable.outArrayPtr, test._fld1); - ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); - } - - public void RunStructFldScenario() - { - TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); - - var test = TestStruct.Create(); - test.RunStructFldScenario(this); - } - - public void ConditionalSelect_FalseOp() - { - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_mask - operation in TrueValue"); - ConditionalSelectScenario_TrueValue(_mask, _dataTable.inArray1Ptr, _falseFld); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero - operation in TrueValue"); - ConditionalSelectScenario_TrueValue({Op1VectorType}<{RetBaseType}>.Zero, _dataTable.inArray1Ptr, _falseFld); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all - operation in TrueValue"); - ConditionalSelectScenario_TrueValue({Op1VectorType}<{RetBaseType}>.AllBitsSet, _dataTable.inArray1Ptr, _falseFld); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_mask - operation in FalseValue"); - ConditionalSelectScenario_FalseValue(_mask, _dataTable.inArray1Ptr, _falseFld); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero - operation in FalseValue"); - ConditionalSelectScenario_FalseValue({Op1VectorType}<{RetBaseType}>.Zero, _dataTable.inArray1Ptr, _falseFld); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all - operation in FalseValue"); - ConditionalSelectScenario_FalseValue({Op1VectorType}<{RetBaseType}>.AllBitsSet, _dataTable.inArray1Ptr, _falseFld); - } - - public void ConditionalSelect_ZeroOp() - { - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_mask - operation in TrueValue"); - ConditionalSelectScenario_TrueValue(_mask, _dataTable.inArray1Ptr, {Op1VectorType}<{RetBaseType}>.Zero); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero - operation in TrueValue"); - ConditionalSelectScenario_TrueValue({Op1VectorType}<{RetBaseType}>.Zero, _dataTable.inArray1Ptr, {Op1VectorType}<{RetBaseType}>.Zero); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all - operation in TrueValue"); - ConditionalSelectScenario_TrueValue({Op1VectorType}<{RetBaseType}>.AllBitsSet, _dataTable.inArray1Ptr, {Op1VectorType}<{RetBaseType}>.Zero); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_mask - operation in FalseValue"); - ConditionalSelectScenario_FalseValue(_mask, _dataTable.inArray1Ptr, {Op1VectorType}<{RetBaseType}>.Zero); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero - operation in FalseValue"); - ConditionalSelectScenario_FalseValue({Op1VectorType}<{RetBaseType}>.Zero, _dataTable.inArray1Ptr, {Op1VectorType}<{RetBaseType}>.Zero); - - TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all - operation in FalseValue"); - ConditionalSelectScenario_FalseValue({Op1VectorType}<{RetBaseType}>.AllBitsSet, _dataTable.inArray1Ptr, {Op1VectorType}<{RetBaseType}>.Zero); - } - - [method: MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ConditionalSelectScenario_TrueValue({Op1VectorType}<{RetBaseType}> mask, void* address, {Op1VectorType}<{RetBaseType}> falseOp) - { - var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(({Op1BaseType}*)address), falseOp); - - Unsafe.Write(_dataTable.outArrayPtr, result); - ValidateConditionalSelectResult_TrueValue(mask, address, falseOp, _dataTable.outArrayPtr); - } - - [method: MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ConditionalSelectScenario_FalseValue({Op1VectorType}<{RetBaseType}> mask, void* address, {Op1VectorType}<{RetBaseType}> trueOp) - { - var result = Sve.ConditionalSelect(mask, trueOp, {Isa}.{Method}(({Op1BaseType}*)address)); - - Unsafe.Write(_dataTable.outArrayPtr, result); - ValidateConditionalSelectResult_FalseValue(mask, address, trueOp, _dataTable.outArrayPtr); - } - - public void RunUnsupportedScenario() - { - TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); - - Succeeded = false; - - try - { - RunBasicScenario_Load(); - } - catch (PlatformNotSupportedException) - { - Succeeded = true; - } - } - - private void ValidateConditionalSelectResult_TrueValue({Op1VectorType}<{RetBaseType}> maskOp, void* leftOp, {Op1VectorType}<{RetBaseType}> falseOp, void* output, [CallerMemberName] string method = "") - { - {RetBaseType}[] mask = new {RetBaseType}[RetElementCount]; - {Op1BaseType}[] left = new {Op1BaseType}[Op1ElementCount]; - {RetBaseType}[] falseVal = new {RetBaseType}[RetElementCount]; - {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; - - Unsafe.WriteUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref mask[0]), maskOp); - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref left[0]), ref Unsafe.AsRef(leftOp), (uint)Unsafe.SizeOf<{RetVectorType}<{Op1BaseType}>>()); - Unsafe.WriteUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref falseVal[0]), falseOp); - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - - bool succeeded = true; - - for (var i = 0; i < RetElementCount; i++) - { - {RetBaseType} iterResult = (mask[i] != 0) ? (({RetBaseType})left[i]) : falseVal[i]; - if (iterResult != result[i]) - { - succeeded = false; - break; - } - } - - if (!succeeded) - { - TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}*): {method} failed:"); - TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); - TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); - TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); - TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); - TestLibrary.TestFramework.LogInformation(string.Empty); - - Succeeded = false; - } - } - - private void ValidateConditionalSelectResult_FalseValue({Op1VectorType}<{RetBaseType}> maskOp, void* leftOp, {Op1VectorType}<{RetBaseType}> trueOp, void* output, [CallerMemberName] string method = "") - { - {RetBaseType}[] mask = new {RetBaseType}[RetElementCount]; - {Op1BaseType}[] left = new {Op1BaseType}[Op1ElementCount]; - {RetBaseType}[] trueVal = new {RetBaseType}[RetElementCount]; - {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; - - Unsafe.WriteUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref mask[0]), maskOp); - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref left[0]), ref Unsafe.AsRef(leftOp), (uint)Unsafe.SizeOf<{RetVectorType}<{Op1BaseType}>>()); - Unsafe.WriteUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref trueVal[0]), trueOp); - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - - bool succeeded = true; - - for (var i = 0; i < RetElementCount; i++) - { - {RetBaseType} iterResult = (mask[i] != 0) ? trueVal[i] : (({RetBaseType})left[i]); - if (mask[i] != 0) - { - if (iterResult != result[i]) - { - succeeded = false; - break; - } - } - } - - if (!succeeded) - { - TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}*): {method} failed:"); - TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); - TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); - TestLibrary.TestFramework.LogInformation($" trueOp: ({string.Join(", ", trueVal)})"); - TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); - TestLibrary.TestFramework.LogInformation(string.Empty); - - Succeeded = false; - } - } - - private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") - { - {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; - {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; - - Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - - ValidateResult(inArray1, outArray, method); - } - - private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") - { - {Op1BaseType}[] inArray = new {Op1BaseType}[Op1ElementCount]; - {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; - - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf<{RetVectorType}<{Op1BaseType}>>()); - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - - ValidateResult(inArray, outArray, method); - } - - private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") - { - bool succeeded = true; - - for (var i = 0; i < RetElementCount; i++) - { - if ({ValidateIterResult}) - { - succeeded = false; - break; - } - } - - if (!succeeded) - { - TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}): {method} failed:"); - TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); - TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); - TestLibrary.TestFramework.LogInformation(string.Empty); - - Succeeded = false; - } - } - - private void ValidateZeroResult(void* firstOp, void* result, [CallerMemberName] string method = "") - { - {Op1BaseType}[] inArray = new {Op1BaseType}[Op1ElementCount]; - {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; - - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf<{RetVectorType}<{Op1BaseType}>>()); - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - - ValidateZeroResult(inArray, outArray, method); - } - - private void ValidateNonFaultingResult(void* firstOp, void* result, Vector<{GetFfrType}> faultResult, [CallerMemberName] string method = "") - { - {Op1BaseType}[] inArray = new {Op1BaseType}[Op1ElementCount]; - {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; - {GetFfrType}[] faultArray = new {GetFfrType}[RetElementCount]; - - // Only read bytes mapping to half of the destination vector. The remaining elements are in the poison page. - // It would make inArray to contain elements that could read without a fault followed by zeros. - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray[0]), ref Unsafe.AsRef(firstOp), ((uint){RetVectorType}<{RetBaseType}>.Count / 2) ); - Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - - fixed({GetFfrType}* faultArrayPtr = &faultArray[0]) - { - Unsafe.Write(faultArrayPtr, faultResult); - } - - bool succeeded = true; - - for (var i = 0; i < RetElementCount; i++) - { - var expectedOut = ({RetBaseType})((i < (RetElementCount / 2)) ? inArray[i] : 0); - var expectedFault = ({GetFfrType}) ((i < (RetElementCount / 2)) ? 1 : 0); - - if ((outArray[i] != expectedOut) && (faultArray[i] != expectedFault) ) - { - succeeded = false; - break; - } - } - - if (!succeeded) - { - TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}): {method} failed:"); - TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", inArray)})"); - TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", outArray)})"); - TestLibrary.TestFramework.LogInformation(string.Empty); - Succeeded = false; - } - } - - private void ValidateZeroResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") - { - bool succeeded = true; - - for (var i = 0; i < RetElementCount; i++) - { - if (result[i] != 0) - { - succeeded = false; - break; - } - } - - if (!succeeded) - { - TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}): {method} failed:"); - TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); - TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); - TestLibrary.TestFramework.LogInformation(string.Empty); - - Succeeded = false; - } - } - } -} \ No newline at end of file diff --git a/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_106338/Runtime_106338.cs b/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_106338/Runtime_106338.cs index 450c002a5d9..b3d4667c075 100644 --- a/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_106338/Runtime_106338.cs +++ b/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_106338/Runtime_106338.cs @@ -8,21 +8,74 @@ // Debug: Outputs 1600094603 // Release: Outputs 1600094604 using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics.X86; using Xunit; public class Runtime_106338 { + [MethodImpl(MethodImplOptions.NoInlining)] + static float CastToFloatDirect(long val) => (float)val; + + [MethodImpl(MethodImplOptions.NoInlining)] + static float CastToFloatDirect(ulong val) => (float)val; + + [MethodImpl(MethodImplOptions.NoInlining)] + static float CastToFloatThroughDouble(long val) => (float)(double)val; + + [MethodImpl(MethodImplOptions.NoInlining)] + static float CastToFloatThroughDouble(ulong val) => (float)(double)val; + [Fact] [SkipOnMono("https://github.com/dotnet/runtime/issues/100368", TestPlatforms.Any)] public static void TestEntryPoint() { - ulong vr10 = 16105307123914158031UL; - float vr11 = 4294967295U | vr10; - uint result = BitConverter.SingleToUInt32Bits(vr11); + ulong vr10 = 0xDF818B7F_FFFFFFFF; + float vr11 = vr10; + float vr12 = (float)(double)vr10; + + // These results will be const folded + uint resultDirect = BitConverter.SingleToUInt32Bits(vr11); + uint resultIntermediate = BitConverter.SingleToUInt32Bits(vr12); // Expected to cast ulong -> float directly - Assert.Equal(1600094603U, result); + Assert.Equal(1600094603U, resultDirect); + + // Expected to preserve ulong -> double intermediate cast + Assert.Equal(1600094604U, resultIntermediate); + + // Check that run-time computed values match + resultDirect = BitConverter.SingleToUInt32Bits(CastToFloatDirect(vr10)); + resultIntermediate = BitConverter.SingleToUInt32Bits(CastToFloatThroughDouble(vr10)); + + Assert.Equal(1600094603U, resultDirect); + Assert.Equal(1600094604U, resultIntermediate); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368", TestPlatforms.Any)] + public static void TestEntryPointSigned() + { + long vr10 = 0x002FFFFF_DFFFFFFF; + float vr11 = vr10; + float vr12 = (float)(double)vr10; + + // These results will be const folded + uint resultDirect = BitConverter.SingleToUInt32Bits(vr11); + uint resultIntermediate = BitConverter.SingleToUInt32Bits(vr12); + + // Expected to cast long -> float directly + Assert.Equal(1514143743U, resultDirect); + + // Expected to preserve long -> double intermediate cast + Assert.Equal(1514143744U, resultIntermediate); + + // Check that run-time computed values match + resultDirect = BitConverter.SingleToUInt32Bits(CastToFloatDirect(vr10)); + resultIntermediate = BitConverter.SingleToUInt32Bits(CastToFloatThroughDouble(vr10)); + + Assert.Equal(1514143743U, resultDirect); + Assert.Equal(1514143744U, resultIntermediate); } } \ No newline at end of file diff --git a/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_116888/Runtime_116888.cs b/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_116888/Runtime_116888.cs new file mode 100644 index 00000000000..2094e08f0a0 --- /dev/null +++ b/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_116888/Runtime_116888.cs @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Found by Antigen +// Reduced from 342.86 KB to 1.33 KB. + +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; +using System.Numerics; +using Xunit; + +public class TestClass +{ + public struct S1 + { + } + public struct S2 + { + } + static Vector s_v_ulong_45 = Vector.AllBitsSet; + static S1 s_s1_51 = new S1(); + S1 s1_101 = new S1(); + S2 s2_102 = new S2(); + private static List toPrint = new List(); + public S2 Method14(ref S1 p_s1_448, S2 p_s2_449, out S2 p_s2_450, S1 p_s1_451, out S1 p_s1_452, Vector p_v_ulong_453, out S1 p_s1_454) + { + unchecked + { + return s2_102; + } + } + + private void Method0() + { + unchecked + { + S1 s1_2842 = new S1(); + S2 s2_2843 = new S2(); + s2_2843 = Method14(ref s_s1_51, s2_102, out s2_102, s1_101, out s_s1_51, Sve.CreateTrueMaskUInt64(SveMaskPattern.LargestMultipleOf4) + s_v_ulong_45 + s_v_ulong_45- s_v_ulong_45 * s_v_ulong_45, out s1_2842); + return; + } + } + + [Fact] + public static void TestEntryPoint() + { + if (Sve.IsSupported) + { + new TestClass().Method0(); + } + return; + } +} diff --git a/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_116888/Runtime_116888.csproj b/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_116888/Runtime_116888.csproj new file mode 100644 index 00000000000..532bf97e961 --- /dev/null +++ b/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_116888/Runtime_116888.csproj @@ -0,0 +1,14 @@ + + + + true + None + True + $(NoWarn);SYSLIB5003 + + + + + + + diff --git a/src/runtime/src/tests/JIT/interpreter/CMakeLists.txt b/src/runtime/src/tests/JIT/interpreter/CMakeLists.txt new file mode 100644 index 00000000000..8370c4824a5 --- /dev/null +++ b/src/runtime/src/tests/JIT/interpreter/CMakeLists.txt @@ -0,0 +1,11 @@ +project (pinvoke) + +include_directories(${INC_PLATFORM_DIR}) + +set(SOURCES pinvoke.cpp) + +# add the executable +add_library (pinvoke SHARED ${SOURCES}) + +# add the install targets +install (TARGETS pinvoke DESTINATION bin) diff --git a/src/runtime/src/tests/JIT/interpreter/Interpreter.cs b/src/runtime/src/tests/JIT/interpreter/Interpreter.cs index 71a419cfdff..61c02d4bb61 100644 --- a/src/runtime/src/tests/JIT/interpreter/Interpreter.cs +++ b/src/runtime/src/tests/JIT/interpreter/Interpreter.cs @@ -5,6 +5,8 @@ using System.Numerics; using System.Runtime.Intrinsics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; public interface ITest { @@ -949,12 +951,29 @@ public static void RunInterpreterTests() if (!TestPreciseInitCctors()) Environment.FailFast(null); - Console.WriteLine("Empty string length: {0}", string.Empty.Length); + Console.WriteLine("TestThreading_Interlocked_CompareExchange"); + if (!TestThreading_Interlocked_CompareExchange()) + Environment.FailFast(null); + + Console.WriteLine("TestRuntimeHelpers_IsReferenceOrContainsReferences"); + if (!TestRuntimeHelpers_IsReferenceOrContainsReferences()) + Environment.FailFast(null); + + Console.WriteLine("TestMemoryMarshal_GetArrayDataReference"); + if (!TestMemoryMarshal_GetArrayDataReference()) + Environment.FailFast(null); - Console.WriteLine("BitConverter.IsLittleEndian: {0}", BitConverter.IsLittleEndian); + Console.WriteLine("Empty string length: {0}", string.Empty.Length); - Console.WriteLine("IntPtr.Zero: {0}, UIntPtr.Zero: {1}", IntPtr.Zero, UIntPtr.Zero); + Console.WriteLine("BitConverter.IsLittleEndian: {0}", BitConverter.IsLittleEndian); + Console.WriteLine("IntPtr.Zero: {0}, UIntPtr.Zero: {1}", IntPtr.Zero, UIntPtr.Zero); + + Console.WriteLine("TestPInvoke"); + if (!TestPInvoke()) + Environment.FailFast(null); + + // For stackwalking validation System.GC.Collect(); Console.WriteLine("All tests passed successfully!"); @@ -2040,7 +2059,7 @@ public static T[] TestNewArr(int len) public static T[,,] TestNewMDArr(int len) { - return new T[len,len-1,len-2]; + return new T[len, len - 1, len - 2]; } public static object Box(T value) @@ -2072,7 +2091,7 @@ public static void TriggerCctorClass() } public static void TriggerCctorMethod() - {} + { } } class MyClass @@ -2369,6 +2388,99 @@ static object BoxedSubtraction(object lhs, object rhs) return (int)lhs - (int)rhs; } + [DllImport("pinvoke", CallingConvention = CallingConvention.Cdecl)] + public static extern int sumTwoInts(int x, int y); + [DllImport("pinvoke", CallingConvention = CallingConvention.Cdecl)] + public static extern double sumTwoDoubles(double x, double y); + [DllImport("pinvoke", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern int writeToStdout(string s); + [DllImport("missingLibrary", CallingConvention = CallingConvention.Cdecl)] + public static extern void missingPInvoke(); + [DllImport("missingLibrary", CallingConvention = CallingConvention.Cdecl)] + public static extern void missingPInvokeWithMarshaling(string s); + + public static bool TestPInvoke() + { + if (sumTwoInts(1, 2) != 3) + return false; + + double summed = sumTwoDoubles(1, 2); + if (summed != 3) + return false; + + // Test marshaling wrappers + writeToStdout("Hello world from pinvoke.dll!writeToStdout\n"); + + /* fails, with output: + Assert failure(PID 32748 [0x00007fec], Thread: 24256 [0x5ec0]): pMD == codeInfo.GetMethodDesc() + + CORECLR! AppendExceptionStackFrame + 0x331 (0x00007ff9`85879b71) + SYSTEM.PRIVATE.CORELIB! + 0x0 (0x00007ff9`80d91f30) + SYSTEM.PRIVATE.CORELIB! + 0x0 (0x00007ff9`80d926b7) + SYSTEM.PRIVATE.CORELIB! + 0x0 (0x00007ff9`80d92289) + CORECLR! CallDescrWorkerInternal + 0x83 (0x00007ff9`859811c3) + CORECLR! CallDescrWorkerWithHandler + 0x130 (0x00007ff9`854755c0) + CORECLR! DispatchCallSimple + 0x26C (0x00007ff9`8547655c) + CORECLR! DispatchManagedException + 0x388 (0x00007ff9`85872998) + CORECLR! DispatchManagedException + 0x67 (0x00007ff9`858725a7) + CORECLR! UnwindAndContinueRethrowHelperAfterCatch + 0x1F8 (0x00007ff9`851be5e8) + File: Z:\runtime\src\coreclr\vm\exceptionhandling.cpp:3032 + Image: Z:\runtime\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root\corerun.exe + + pMD is TestPInvoke (correct) and codeInfo.GetMethodDesc() is Main (wrong) + */ + /* + bool caught = false; + try { + Console.WriteLine("calling missingPInvoke"); + missingPInvoke(); + return false; + } catch (DllNotFoundException) { + Console.WriteLine("caught #1"); + caught = true; + } + + if (!caught) + return false; + */ + + /* fails, with output: + calling missingPInvokeWithMarshaling + caught #2 + + Assert failure(PID 59772 [0x0000e97c], Thread: 24864 [0x6120]): ohThrowable + + CORECLR! PreStubWorker$catch$10 + 0x93 (0x00007ff9`580972b3) + CORECLR! CallSettingFrame_LookupContinuationIndex + 0x20 (0x00007ff9`57f32e70) + CORECLR! _FrameHandler4::CxxCallCatchBlock + 0x1DE (0x00007ff9`57f1e83e) + NTDLL! RtlCaptureContext2 + 0x4A6 (0x00007ffa`b7e46606) + CORECLR! PreStubWorker + 0x4F8 (0x00007ff9`5789dd78) + CORECLR! ThePreStub + 0x55 (0x00007ff9`57ec29c5) + CORECLR! CallJittedMethodRetVoid + 0x14 (0x00007ff9`57ec0f34) + CORECLR! InvokeCompiledMethod + 0x5D7 (0x00007ff9`57afaf67) + CORECLR! InterpExecMethod + 0x84BB (0x00007ff9`57af68cb) + CORECLR! ExecuteInterpretedMethod + 0x11B (0x00007ff9`5789c77b) + File: Z:\runtime\src\coreclr\vm\prestub.cpp:1965 + Image: Z:\runtime\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root\corerun.exe + */ + /* + bool caught2 = false; + try { + Console.WriteLine("calling missingPInvokeWithMarshaling"); + missingPInvokeWithMarshaling("test"); + return false; + } catch (DllNotFoundException) { + Console.WriteLine("caught #2"); + caught2 = true; + } + + if (!caught2) + return false; + */ + + return true; + } + public static bool TestArray() { // sbyte @@ -2906,4 +3018,72 @@ public static bool TestStaticVirtualGeneric_CodePointerCase() return true; } + + public static bool TestThreading_Interlocked_CompareExchange() + { + // Value type test + int location = 1; + int value = 2; + int comparand = 1; + int result = System.Threading.Interlocked.CompareExchange(ref location, value, comparand); + if (!(result == 1 && location == 2)) + return false; + + // Reference type test + object objLocation = "a"; + object objValue = "b"; + object objComparand = "a"; + object objResult = System.Threading.Interlocked.CompareExchange(ref objLocation, objValue, objComparand); + if (!(object.ReferenceEquals(objResult, objComparand) && object.ReferenceEquals(objLocation, objValue))) + return false; + + // Reference type test (fail) + objLocation = "a"; + objValue = "b"; + objComparand = "c"; + objResult = System.Threading.Interlocked.CompareExchange(ref objLocation, objValue, objComparand); + if (!(object.ReferenceEquals(objResult, objLocation) && object.ReferenceEquals(objLocation, "a"))) + return false; + + // Null reference test + objLocation = null; + objValue = "b"; + objComparand = null; + objResult = System.Threading.Interlocked.CompareExchange(ref objLocation, objValue, objComparand); + if (!(objResult is null && object.ReferenceEquals(objLocation, objValue))) + return false; + + return true; + } + + public static bool TestRuntimeHelpers_IsReferenceOrContainsReferences() + { + if (!RuntimeHelpers.IsReferenceOrContainsReferences()) + return false; + if (RuntimeHelpers.IsReferenceOrContainsReferences()) + return false; + if (!RuntimeHelpers.IsReferenceOrContainsReferences()) + return false; + return true; + } + + public static bool TestMemoryMarshal_GetArrayDataReference() + { + int[] arr = new int[1]; + ref int dataRef = ref MemoryMarshal.GetArrayDataReference(arr); + dataRef = 42; + if (arr[0] != 42) + return false; + + arr = null; + try + { + MemoryMarshal.GetArrayDataReference(arr); + return false; + } + catch (NullReferenceException) + { + return true; + } + } } diff --git a/src/runtime/src/tests/JIT/interpreter/Interpreter.csproj b/src/runtime/src/tests/JIT/interpreter/Interpreter.csproj index 98b0af809b2..567503852c6 100644 --- a/src/runtime/src/tests/JIT/interpreter/Interpreter.csproj +++ b/src/runtime/src/tests/JIT/interpreter/Interpreter.csproj @@ -8,4 +8,7 @@ + + + diff --git a/src/runtime/src/tests/JIT/interpreter/InterpreterTester.csproj b/src/runtime/src/tests/JIT/interpreter/InterpreterTester.csproj index 4bb141749f2..e654b46510b 100644 --- a/src/runtime/src/tests/JIT/interpreter/InterpreterTester.csproj +++ b/src/runtime/src/tests/JIT/interpreter/InterpreterTester.csproj @@ -13,6 +13,9 @@ + + + diff --git a/src/runtime/src/tests/JIT/interpreter/pinvoke.cpp b/src/runtime/src/tests/JIT/interpreter/pinvoke.cpp new file mode 100644 index 00000000000..149a902e611 --- /dev/null +++ b/src/runtime/src/tests/JIT/interpreter/pinvoke.cpp @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "stdio.h" +#include +#include + +#define EXPORT_IT extern "C" DLL_EXPORT + +EXPORT_IT void writeToStdout (const char *str) +{ + puts(str); +} + +EXPORT_IT int sumTwoInts (int x, int y) +{ + return x + y; +} + +EXPORT_IT double sumTwoDoubles (double x, double y) +{ + return x + y; +} diff --git a/src/runtime/src/tests/JIT/opt/Compares/conditionalSimpleOps.cs b/src/runtime/src/tests/JIT/opt/Compares/conditionalSimpleOps.cs new file mode 100644 index 00000000000..547962c693c --- /dev/null +++ b/src/runtime/src/tests/JIT/opt/Compares/conditionalSimpleOps.cs @@ -0,0 +1,291 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// unit test for the full range comparison optimization + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public class ConditionalSimpleOpConstantTest +{ + [Theory] + [InlineData(12, 10)] + [InlineData(45, 5)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_left(byte op1, int expected) + { + int result = op1 < 42 ? 10 : 5; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(12, -13)] + [InlineData(45, -25)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_right_arithmetic(byte op1, int expected) + { + int result = op1 > 42 ? -25 : -13; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(12, 0x7FFF_FFF3)] + [InlineData(45, -25)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_right_logic(byte op1, int expected) + { + int result = op1 < 42 ? 0x7FFF_FFF3 : -25; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(12, 0x7FFF_FFFF_FFFF_FFF3ul)] + [InlineData(45, 0xFFFF_FFFF_FFFF_FFE7ul)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_right_logic_ulong(byte op1, ulong expected) + { + ulong result = op1 < 42 ? 0x7FFF_FFFF_FFFF_FFF3ul : 0xFFFF_FFFF_FFFF_FFE7ul; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(12, 0x7FFF_FFF3)] + [InlineData(45, 0xFFFF_FFE7)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_right_logic_long_32(byte op1, long expected) + { + long result = op1 > 42 ? 0xFFFF_FFE7 : 0x7FFF_FFF3; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(12, 64)] + [InlineData(45, 0)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void pow2_or_zero(byte op1, int expected) + { + int result = op1 < 42 ? 64 : 0; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(12, long.MinValue)] + [InlineData(45, 0)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void pow2_or_zero_long(byte op1, long expected) + { + long result = op1 >= 42 ? 0 : long.MinValue; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(12, 0xFFFF_FFFF_8000_0000ul)] + [InlineData(45, 0ul)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void pow2_or_zero_ulong_32(byte op1, ulong expected) + { + ulong result = op1 < 42 ? 0xFFFF_FFFF_8000_0000ul : 0ul; + Assert.Equal(expected, result); + } +} + +public class ConditionalSimpleOpVariableTest +{ + [Theory] + [InlineData(11, 12)] + [InlineData(12, 13)] + [InlineData(45, 45)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void add_var(int a, int expected) + { + a = a < 42 ? a + 1 : a; + Assert.Equal(expected, a); + } + + [Theory] + [InlineData(11, 12)] + [InlineData(12, 13)] + [InlineData(45, 45)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void add_var_no_else(int a, int expected) + { + if (a < 42) + a++; + Assert.Equal(expected, a); + } + + [Theory] + [InlineData(11, 12)] + [InlineData(12, 13)] + [InlineData(45, 45)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void add_var_reversed(int a, int expected) + { + a = a > 42 ? a : ++a; + Assert.Equal(expected, a); + } + + [Theory] + [InlineData(12, 13)] + [InlineData(13, 13)] + [InlineData(45, 45)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void or_var(int a, int expected) + { + a = a < 42 ? a | 1 : a; + Assert.Equal(expected, a); + } + + [Theory] + [InlineData(12, 13)] + [InlineData(13, 13)] + [InlineData(45, 45)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void or_var_no_else(int a, int expected) + { + if (a < 42) + a = a | 1; + Assert.Equal(expected, a); + } + + [Theory] + [InlineData(11, 10)] + [InlineData(12, 11)] + [InlineData(45, 45)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void sub_var(int a, int expected) + { + a = a < 42 ? a - 1 : a; + Assert.Equal(expected, a); + } + + public static int globVar = 0; + [Theory] + [InlineData(11, 10)] + [InlineData(12, 11)] + [InlineData(45, 45)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void sub_var_globref(int a, int expected) + { + a = (a + globVar) < 42 ? a - 1 : a; + Assert.Equal(expected, a); + } + + [Theory] + [InlineData(11, 10)] + [InlineData(12, 11)] + [InlineData(45, 45)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void sub_var_globref_no_else(int a, int expected) + { + if ((a + globVar) < 42) + --a; + Assert.Equal(expected, a); + } + + [Theory] + [InlineData(12, 13)] + [InlineData(13, 12)] + [InlineData(45, 45)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void xor_var(int a, int expected) + { + a = a < 42 ? a ^ 1 : a; + Assert.Equal(expected, a); + } + + [Theory] + [InlineData(-12, -24)] + [InlineData(12, 24)] + [InlineData(43, 43)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_left_var(int a, int expected) + { + long result = a > 42 ? a : a * 2; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(-12, -24)] + [InlineData(12, 24)] + [InlineData(43, 43)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_left_var_no_else(int a, int expected) + { + long result = a; + if (a <= 42) + result *= 2; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(-12, -24)] + [InlineData(12, 24)] + [InlineData(43, 3)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_left_var_no_else_different_var(long a, long expected) + { + long result = 3; + if (a <= 42) + result = a * 2; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(12, 6)] + [InlineData(-25, -13)] + [InlineData(45, 45)] + [InlineData(-4000_000_000_000l, -2000_000_000_000l)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_right_arithmetic_var(long a, long expected) + { + long result = a > 42 ? a : a >> 1; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(43, 21)] + [InlineData(0x8000_0000, 0x4000_0000)] + [InlineData(12, 12)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void shift_right_logic_var(uint a, uint expected) + { + uint result = a > 42 ? a >> 1 : a; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(44, 0)] + [InlineData(43, 1)] + [InlineData(11, 0)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void and_or_zero_var(int a, int expected) + { + int result = a > 42 ? a & 1 : 0; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(44, 0)] + [InlineData(43, 0)] + [InlineData(11, 1)] + [InlineData(10, 0)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void and_or_zero_var_globref_reversed(uint a, uint expected) + { + uint result = (a ^ globVar) > 42 ? 0 : a & 1; + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(4, 16)] + [InlineData(6, 64)] + [InlineData(43, 0)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void pow2_or_zero_var(int a, int expected) + { + int result = a > 42 ? 0 : 1 << a; + Assert.Equal(expected, result); + } +} diff --git a/src/runtime/src/tests/JIT/opt/Compares/conditionalSimpleOps.csproj b/src/runtime/src/tests/JIT/opt/Compares/conditionalSimpleOps.csproj new file mode 100644 index 00000000000..b042a45bea9 --- /dev/null +++ b/src/runtime/src/tests/JIT/opt/Compares/conditionalSimpleOps.csproj @@ -0,0 +1,15 @@ + + + + true + + + None + True + + + + + + + diff --git a/src/runtime/src/tests/JIT/opt/SVE/EmbeddedLoads.cs b/src/runtime/src/tests/JIT/opt/SVE/EmbeddedLoads.cs index 45de9c21b8a..6573ae86e28 100644 --- a/src/runtime/src/tests/JIT/opt/SVE/EmbeddedLoads.cs +++ b/src/runtime/src/tests/JIT/opt/SVE/EmbeddedLoads.cs @@ -46,7 +46,7 @@ static unsafe void CndSelectEmbeddedOp3LoadTrueMask(int[] array, Vector op1 //ARM6-FULL-LINE: ldnf1w { {{z[0-9]+}}.s }, {{p[0-9]+}}/m, [{{x[0-9]+}}] fixed (int* arr_ptr = array) { - var result = Sve.ConditionalSelect(Sve.CreateTrueMaskInt32(), op1, Sve.LoadVectorNonFaulting(arr_ptr)); + var result = Sve.ConditionalSelect(Sve.CreateTrueMaskInt32(), op1, Sve.LoadVectorNonFaulting(Sve.CreateTrueMaskInt32(), arr_ptr)); Consume(result); } } @@ -56,7 +56,7 @@ static unsafe void CndSelectEmbeddedOp3LoadAllBits(int[] array, Vector op1) //ARM6-FULL-LINE: ldnf1w { {{z[0-9]+}}.s }, {{p[0-9]+}}/m, [{{x[0-9]+}}] fixed (int* arr_ptr = array) { - var result = Sve.ConditionalSelect(Vector.AllBitsSet, op1, Sve.LoadVectorNonFaulting(arr_ptr)); + var result = Sve.ConditionalSelect(Vector.AllBitsSet, op1, Sve.LoadVectorNonFaulting(Vector.AllBitsSet, arr_ptr)); Consume(result); } } @@ -66,7 +66,7 @@ static unsafe void CndSelectEmbeddedOp3LoadFalseMask(int[] array, Vector op //ARM6-FULL-LINE: ldnf1w { {{z[0-9]+}}.s }, {{p[0-9]+}}/m, [{{x[0-9]+}}] fixed (int* arr_ptr = array) { - var result = Sve.ConditionalSelect(Sve.CreateFalseMaskInt32(), op1, Sve.LoadVectorNonFaulting(arr_ptr)); + var result = Sve.ConditionalSelect(Sve.CreateFalseMaskInt32(), op1, Sve.LoadVectorNonFaulting(Sve.CreateFalseMaskInt32(), arr_ptr)); Consume(result); } } @@ -76,7 +76,7 @@ static unsafe void CndSelectEmbeddedOp3LoadZero(int[] array, Vector op1) { //ARM6-FULL-LINE: ldnf1w { {{z[0-9]+}}.s }, {{p[0-9]+}}/m, [{{x[0-9]+}}] fixed (int* arr_ptr = array) { - var result = Sve.ConditionalSelect(Vector.Zero, op1, Sve.LoadVectorNonFaulting(arr_ptr)); + var result = Sve.ConditionalSelect(Vector.Zero, op1, Sve.LoadVectorNonFaulting(Vector.Zero, arr_ptr)); Consume(result); } } diff --git a/src/runtime/src/tests/async/synchronization-context/synchronization-context.cs b/src/runtime/src/tests/async/synchronization-context/synchronization-context.cs new file mode 100644 index 00000000000..e028ee09c9b --- /dev/null +++ b/src/runtime/src/tests/async/synchronization-context/synchronization-context.cs @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +public class Async2SynchronizationContext +{ + [Fact] + public static void TestSyncContexts() + { + SynchronizationContext prevContext = SynchronizationContext.Current; + try + { + SynchronizationContext.SetSynchronizationContext(new MySyncContext()); + TestSyncContext().GetAwaiter().GetResult(); + } + finally + { + SynchronizationContext.SetSynchronizationContext(prevContext); + } + } + + private static async Task TestSyncContext() + { + MySyncContext context = (MySyncContext)SynchronizationContext.Current; + await WrappedYieldToThreadPool(suspend: false); + Assert.Same(context, SynchronizationContext.Current); + + await WrappedYieldToThreadPool(suspend: true); + Assert.Same(context, SynchronizationContext.Current); + + await WrappedYieldToThreadPool(suspend: true).ConfigureAwait(true); + Assert.Same(context, SynchronizationContext.Current); + + await WrappedYieldToThreadPool(suspend: false).ConfigureAwait(false); + Assert.Same(context, SynchronizationContext.Current); + + await WrappedYieldToThreadPool(suspend: true).ConfigureAwait(false); + Assert.Null(SynchronizationContext.Current); + + await WrappedYieldToThreadWithCustomSyncContext(); + Assert.Null(SynchronizationContext.Current); + } + + private static async Task WrappedYieldToThreadPool(bool suspend) + { + if (suspend) + { + await Task.Yield(); + } + } + + private static async Task WrappedYieldToThreadWithCustomSyncContext() + { + Assert.Null(SynchronizationContext.Current); + await new YieldToThreadWithCustomSyncContext(); + Assert.True(SynchronizationContext.Current is MySyncContext { }); + } + + private class MySyncContext : SynchronizationContext + { + public override void Post(SendOrPostCallback d, object state) + { + ThreadPool.UnsafeQueueUserWorkItem(_ => + { + SynchronizationContext prevContext = Current; + try + { + SetSynchronizationContext(this); + d(state); + } + finally + { + SetSynchronizationContext(prevContext); + } + }, null); + } + } + + private struct YieldToThreadWithCustomSyncContext : ICriticalNotifyCompletion + { + public YieldToThreadWithCustomSyncContext GetAwaiter() => this; + + public void UnsafeOnCompleted(Action continuation) + { + new Thread(state => + { + SynchronizationContext.SetSynchronizationContext(new MySyncContext()); + continuation(); + }).Start(); + } + + public void OnCompleted(Action continuation) + { + throw new NotImplementedException(); + } + + public bool IsCompleted => false; + + public void GetResult() { } + } +} diff --git a/src/runtime/src/tests/async/synchronization-context/synchronization-context.csproj b/src/runtime/src/tests/async/synchronization-context/synchronization-context.csproj new file mode 100644 index 00000000000..1ae294349c3 --- /dev/null +++ b/src/runtime/src/tests/async/synchronization-context/synchronization-context.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/source-build-reference-packages/eng/Version.Details.xml b/src/source-build-reference-packages/eng/Version.Details.xml index 87c410a6f98..7ba434d6d24 100644 --- a/src/source-build-reference-packages/eng/Version.Details.xml +++ b/src/source-build-reference-packages/eng/Version.Details.xml @@ -1,30 +1,30 @@ - + - + https://github.com/dotnet/dotnet - 0b032b9f942c1ae8de535a434c4f4a9206fd3339 + 78061f4bcc414fa2054be6237b1fd3813d8edf6b - + https://github.com/dotnet/dotnet - 0b032b9f942c1ae8de535a434c4f4a9206fd3339 + 78061f4bcc414fa2054be6237b1fd3813d8edf6b - + https://github.com/dotnet/dotnet - 0b032b9f942c1ae8de535a434c4f4a9206fd3339 + 78061f4bcc414fa2054be6237b1fd3813d8edf6b - + https://github.com/dotnet/dotnet - 0b032b9f942c1ae8de535a434c4f4a9206fd3339 + 78061f4bcc414fa2054be6237b1fd3813d8edf6b - + https://github.com/dotnet/dotnet - 0b032b9f942c1ae8de535a434c4f4a9206fd3339 + 78061f4bcc414fa2054be6237b1fd3813d8edf6b - + https://github.com/dotnet/dotnet - 0b032b9f942c1ae8de535a434c4f4a9206fd3339 + 78061f4bcc414fa2054be6237b1fd3813d8edf6b diff --git a/src/source-build-reference-packages/eng/Versions.props b/src/source-build-reference-packages/eng/Versions.props index 2029c674fad..3348de36656 100644 --- a/src/source-build-reference-packages/eng/Versions.props +++ b/src/source-build-reference-packages/eng/Versions.props @@ -21,15 +21,15 @@ $(HumanizerReleaseVersion) - 17.15.0-preview-25363-101 - 17.15.0-preview-25363-101 + 17.15.0-preview-25365-101 + 17.15.0-preview-25365-101 6.11.0 - 10.0.0-preview.7.25363.101 - 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25365.101 + 10.0.0-preview.7.25365.101 - 10.0.100-preview.7.25363.101 + 10.0.100-preview.7.25365.101 1.4.13 diff --git a/src/source-build-reference-packages/global.json b/src/source-build-reference-packages/global.json index dd2dbdbb36d..1ce7dc5f847 100644 --- a/src/source-build-reference-packages/global.json +++ b/src/source-build-reference-packages/global.json @@ -15,6 +15,6 @@ "msbuild-sdks": { "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25363.101" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25365.101" } } diff --git a/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/System.Collections.Immutable.9.0.0.csproj b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/System.Collections.Immutable.9.0.0.csproj new file mode 100644 index 00000000000..44da48a5018 --- /dev/null +++ b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/System.Collections.Immutable.9.0.0.csproj @@ -0,0 +1,14 @@ + + + + net8.0;net9.0;netstandard2.0 + 9.0.0 + System.Collections.Immutable + + + + + + + + diff --git a/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/lib/net8.0/System.Collections.Immutable.cs b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/lib/net8.0/System.Collections.Immutable.cs new file mode 100644 index 00000000000..03a15690654 --- /dev/null +++ b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/lib/net8.0/System.Collections.Immutable.cs @@ -0,0 +1,1455 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the http://aka.ms/api-review process. +// ------------------------------------------------------------------------------ +[assembly: System.Runtime.CompilerServices.CompilationRelaxations(8)] +[assembly: System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = true)] +[assembly: System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Collections.Immutable.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")] +[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")] +[assembly: System.Reflection.AssemblyMetadata("Serviceable", "True")] +[assembly: System.Reflection.AssemblyMetadata("PreferInbox", "True")] +[assembly: System.Reflection.AssemblyDefaultAlias("System.Collections.Immutable")] +[assembly: System.Resources.NeutralResourcesLanguage("en-US")] +[assembly: System.CLSCompliant(true)] +[assembly: System.Reflection.AssemblyMetadata("IsTrimmable", "True")] +[assembly: System.Runtime.InteropServices.DefaultDllImportSearchPaths(System.Runtime.InteropServices.DllImportSearchPath.AssemblyDirectory | System.Runtime.InteropServices.DllImportSearchPath.System32)] +[assembly: System.Reflection.AssemblyCompany("Microsoft Corporation")] +[assembly: System.Reflection.AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: System.Reflection.AssemblyDescription("This package provides collections that are thread safe and guaranteed to never change their contents, also known as immutable collections. Like strings, any methods that perform modifications will not change the existing instance but instead return a new instance. For efficiency reasons, the implementation uses a sharing mechanism to ensure that newly created instances share as much data as possible with the previous instance while ensuring that operations have a predictable time complexity.\r\n\r\nThe System.Collections.Immutable library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks.")] +[assembly: System.Reflection.AssemblyFileVersion("9.0.24.52809")] +[assembly: System.Reflection.AssemblyInformationalVersion("9.0.0+9d5a6a9aa463d6d10b0b0ba6d5982cc82f363dc3")] +[assembly: System.Reflection.AssemblyProduct("Microsoft® .NET")] +[assembly: System.Reflection.AssemblyTitle("System.Collections.Immutable")] +[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")] +[assembly: System.Reflection.AssemblyVersionAttribute("9.0.0.0")] +[assembly: System.Runtime.CompilerServices.ReferenceAssembly] +[assembly: System.Reflection.AssemblyFlagsAttribute((System.Reflection.AssemblyNameFlags)0x70)] +namespace System.Collections.Frozen +{ + public static partial class FrozenDictionary + { + public static FrozenDictionary ToFrozenDictionary(this Generic.IEnumerable source, Func keySelector, Generic.IEqualityComparer? comparer = null) { throw null; } + public static FrozenDictionary ToFrozenDictionary(this Generic.IEnumerable> source, Generic.IEqualityComparer? comparer = null) { throw null; } + public static FrozenDictionary ToFrozenDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IEqualityComparer? comparer = null) { throw null; } + } + public abstract partial class FrozenDictionary : Generic.IDictionary, Generic.ICollection>, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyDictionary, Generic.IReadOnlyCollection>, IDictionary, ICollection + { + internal FrozenDictionary() { } + public Generic.IEqualityComparer Comparer { get { throw null; } } + public int Count { get { throw null; } } + public static FrozenDictionary Empty { get { throw null; } } + + public ref readonly TValue this[TKey key] { get { throw null; } } + + public Immutable.ImmutableArray Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + TValue Generic.IDictionary.this[TKey key] { get { throw null; } set { } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + TValue Generic.IReadOnlyDictionary.this[TKey key] { get { throw null; } } + + Generic.IEnumerable Generic.IReadOnlyDictionary.Keys { get { throw null; } } + + Generic.IEnumerable Generic.IReadOnlyDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Immutable.ImmutableArray Values { get { throw null; } } + + public bool ContainsKey(TKey key) { throw null; } + public void CopyTo(Generic.KeyValuePair[] destination, int destinationIndex) { } + public void CopyTo(Span> destination) { } + public Enumerator GetEnumerator() { throw null; } + public ref readonly TValue GetValueRefOrNullRef(TKey key) { throw null; } + void Generic.ICollection>.Add(Generic.KeyValuePair item) { } + void Generic.ICollection>.Clear() { } + bool Generic.ICollection>.Contains(Generic.KeyValuePair item) { throw null; } + bool Generic.ICollection>.Remove(Generic.KeyValuePair item) { throw null; } + void Generic.IDictionary.Add(TKey key, TValue value) { } + bool Generic.IDictionary.Remove(TKey key) { throw null; } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int index) { } + void IDictionary.Add(object key, object value) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public partial struct Enumerator : Generic.IEnumerator>, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public Generic.KeyValuePair Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public bool MoveNext() { throw null; } + void IEnumerator.Reset() { } + void IDisposable.Dispose() { } + } + } + + public static partial class FrozenSet + { + public static FrozenSet Create(Generic.IEqualityComparer? equalityComparer, params scoped ReadOnlySpan source) { throw null; } + public static FrozenSet Create(params scoped ReadOnlySpan source) { throw null; } + public static FrozenSet ToFrozenSet(this Generic.IEnumerable source, Generic.IEqualityComparer? comparer = null) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(FrozenSet), "Create")] + public abstract partial class FrozenSet : Generic.ISet, Generic.ICollection, Generic.IEnumerable, IEnumerable, Generic.IReadOnlySet, Generic.IReadOnlyCollection, ICollection + { + internal FrozenSet() { } + public Generic.IEqualityComparer Comparer { get { throw null; } } + public int Count { get { throw null; } } + public static FrozenSet Empty { get { throw null; } } + public Immutable.ImmutableArray Items { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + public bool Contains(T item) { throw null; } + public void CopyTo(T[] destination, int destinationIndex) { } + public void CopyTo(Span destination) { } + public Enumerator GetEnumerator() { throw null; } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + bool Generic.ISet.Add(T item) { throw null; } + void Generic.ISet.ExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.IntersectWith(Generic.IEnumerable other) { } + void Generic.ISet.SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.UnionWith(Generic.IEnumerable other) { } + void ICollection.CopyTo(Array array, int index) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public bool MoveNext() { throw null; } + void IEnumerator.Reset() { } + void IDisposable.Dispose() { } + } + } +} + +namespace System.Collections.Immutable +{ + public partial interface IImmutableDictionary : Generic.IReadOnlyDictionary, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyCollection> + { + IImmutableDictionary Add(TKey key, TValue value); + IImmutableDictionary AddRange(Generic.IEnumerable> pairs); + IImmutableDictionary Clear(); + bool Contains(Generic.KeyValuePair pair); + IImmutableDictionary Remove(TKey key); + IImmutableDictionary RemoveRange(Generic.IEnumerable keys); + IImmutableDictionary SetItem(TKey key, TValue value); + IImmutableDictionary SetItems(Generic.IEnumerable> items); + bool TryGetKey(TKey equalKey, out TKey actualKey); + } + + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableList), "Create")] + public partial interface IImmutableList : Generic.IReadOnlyList, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection + { + IImmutableList Add(T value); + IImmutableList AddRange(Generic.IEnumerable items); + IImmutableList Clear(); + int IndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer); + IImmutableList Insert(int index, T element); + IImmutableList InsertRange(int index, Generic.IEnumerable items); + int LastIndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer); + IImmutableList Remove(T value, Generic.IEqualityComparer? equalityComparer); + IImmutableList RemoveAll(Predicate match); + IImmutableList RemoveAt(int index); + IImmutableList RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer); + IImmutableList RemoveRange(int index, int count); + IImmutableList Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer); + IImmutableList SetItem(int index, T value); + } + + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableQueue), "Create")] + public partial interface IImmutableQueue : Generic.IEnumerable, IEnumerable + { + bool IsEmpty { get; } + + IImmutableQueue Clear(); + IImmutableQueue Dequeue(); + IImmutableQueue Enqueue(T value); + T Peek(); + } + + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableHashSet), "Create")] + public partial interface IImmutableSet : Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable + { + IImmutableSet Add(T value); + IImmutableSet Clear(); + bool Contains(T value); + IImmutableSet Except(Generic.IEnumerable other); + IImmutableSet Intersect(Generic.IEnumerable other); + bool IsProperSubsetOf(Generic.IEnumerable other); + bool IsProperSupersetOf(Generic.IEnumerable other); + bool IsSubsetOf(Generic.IEnumerable other); + bool IsSupersetOf(Generic.IEnumerable other); + bool Overlaps(Generic.IEnumerable other); + IImmutableSet Remove(T value); + bool SetEquals(Generic.IEnumerable other); + IImmutableSet SymmetricExcept(Generic.IEnumerable other); + bool TryGetValue(T equalValue, out T actualValue); + IImmutableSet Union(Generic.IEnumerable other); + } + + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableStack), "Create")] + public partial interface IImmutableStack : Generic.IEnumerable, IEnumerable + { + bool IsEmpty { get; } + + IImmutableStack Clear(); + T Peek(); + IImmutableStack Pop(); + IImmutableStack Push(T value); + } + + public static partial class ImmutableArray + { + public static int BinarySearch(this ImmutableArray array, T value, Generic.IComparer? comparer) { throw null; } + public static int BinarySearch(this ImmutableArray array, T value) { throw null; } + public static int BinarySearch(this ImmutableArray array, int index, int length, T value, Generic.IComparer? comparer) { throw null; } + public static int BinarySearch(this ImmutableArray array, int index, int length, T value) { throw null; } + public static ImmutableArray Create() { throw null; } + public static ImmutableArray Create(T item1, T item2, T item3, T item4) { throw null; } + public static ImmutableArray Create(T item1, T item2, T item3) { throw null; } + public static ImmutableArray Create(T item1, T item2) { throw null; } + public static ImmutableArray Create(T item) { throw null; } + public static ImmutableArray Create(T[] items, int start, int length) { throw null; } + public static ImmutableArray Create(params T[]? items) { throw null; } + public static ImmutableArray Create(ImmutableArray items, int start, int length) { throw null; } + public static ImmutableArray Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableArray Create(Span items) { throw null; } + public static ImmutableArray.Builder CreateBuilder() { throw null; } + public static ImmutableArray.Builder CreateBuilder(int initialCapacity) { throw null; } + public static ImmutableArray CreateRange(Generic.IEnumerable items) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, Func selector) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, int start, int length, Func selector) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, Func selector, TArg arg) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, int start, int length, Func selector, TArg arg) { throw null; } + public static ImmutableArray ToImmutableArray(this Generic.IEnumerable items) { throw null; } + public static ImmutableArray ToImmutableArray(this ImmutableArray.Builder builder) { throw null; } + public static ImmutableArray ToImmutableArray(this ReadOnlySpan items) { throw null; } + public static ImmutableArray ToImmutableArray(this Span items) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableArray), "Create")] + public readonly partial struct ImmutableArray : Generic.IReadOnlyList, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection, Generic.IList, Generic.ICollection, IEquatable>, IList, ICollection, IStructuralComparable, IStructuralEquatable, IImmutableList + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly ImmutableArray Empty; + public bool IsDefault { get { throw null; } } + public bool IsDefaultOrEmpty { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public T this[int index] { get { throw null; } } + + public int Length { get { throw null; } } + + int Generic.ICollection.Count { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + T Generic.IList.this[int index] { get { throw null; } set { } } + + int Generic.IReadOnlyCollection.Count { get { throw null; } } + + T Generic.IReadOnlyList.this[int index] { get { throw null; } } + + int ICollection.Count { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public readonly ImmutableArray Add(T item) { throw null; } + public readonly ImmutableArray AddRange(T[] items, int length) { throw null; } + public readonly ImmutableArray AddRange(params T[] items) { throw null; } + public readonly ImmutableArray AddRange(Generic.IEnumerable items) { throw null; } + public readonly ImmutableArray AddRange(ImmutableArray items, int length) { throw null; } + public readonly ImmutableArray AddRange(ImmutableArray items) { throw null; } + public readonly ImmutableArray AddRange(params scoped ReadOnlySpan items) { throw null; } + public readonly ImmutableArray AddRange(TDerived[] items) where TDerived : T { throw null; } + public readonly ImmutableArray AddRange(ImmutableArray items) where TDerived : T { throw null; } + public readonly ImmutableArray As() where TOther : class { throw null; } + public readonly ReadOnlyMemory AsMemory() { throw null; } + public readonly ReadOnlySpan AsSpan() { throw null; } + public readonly ReadOnlySpan AsSpan(int start, int length) { throw null; } + public readonly ReadOnlySpan AsSpan(Range range) { throw null; } + public readonly ImmutableArray CastArray() where TOther : class { throw null; } + public static ImmutableArray CastUp(ImmutableArray items) where TDerived : class, T { throw null; } + public readonly ImmutableArray Clear() { throw null; } + public readonly bool Contains(T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly bool Contains(T item) { throw null; } + public readonly void CopyTo(T[] destination, int destinationIndex) { } + public readonly void CopyTo(T[] destination) { } + public readonly void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { } + public readonly void CopyTo(Span destination) { } + public readonly bool Equals(ImmutableArray other) { throw null; } + public override readonly bool Equals(object? obj) { throw null; } + public readonly Enumerator GetEnumerator() { throw null; } + public override readonly int GetHashCode() { throw null; } + public readonly int IndexOf(T item, int startIndex, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly int IndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly int IndexOf(T item, int startIndex, int count) { throw null; } + public readonly int IndexOf(T item, int startIndex) { throw null; } + public readonly int IndexOf(T item) { throw null; } + public readonly ImmutableArray Insert(int index, T item) { throw null; } + public readonly ImmutableArray InsertRange(int index, T[] items) { throw null; } + public readonly ImmutableArray InsertRange(int index, Generic.IEnumerable items) { throw null; } + public readonly ImmutableArray InsertRange(int index, ImmutableArray items) { throw null; } + public readonly ImmutableArray InsertRange(int index, params scoped ReadOnlySpan items) { throw null; } + public readonly ref readonly T ItemRef(int index) { throw null; } + public readonly int LastIndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly int LastIndexOf(T item, int startIndex, int count) { throw null; } + public readonly int LastIndexOf(T item, int startIndex) { throw null; } + public readonly int LastIndexOf(T item) { throw null; } + public readonly Generic.IEnumerable OfType() { throw null; } + public static bool operator ==(ImmutableArray left, ImmutableArray right) { throw null; } + public static bool operator ==(ImmutableArray? left, ImmutableArray? right) { throw null; } + public static bool operator !=(ImmutableArray left, ImmutableArray right) { throw null; } + public static bool operator !=(ImmutableArray? left, ImmutableArray? right) { throw null; } + public readonly ImmutableArray Remove(T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray Remove(T item) { throw null; } + public readonly ImmutableArray RemoveAll(Predicate match) { throw null; } + public readonly ImmutableArray RemoveAt(int index) { throw null; } + public readonly ImmutableArray RemoveRange(T[] items, Generic.IEqualityComparer? equalityComparer = null) { throw null; } + public readonly ImmutableArray RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray RemoveRange(Generic.IEnumerable items) { throw null; } + public readonly ImmutableArray RemoveRange(ImmutableArray items, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray RemoveRange(ImmutableArray items) { throw null; } + public readonly ImmutableArray RemoveRange(int index, int length) { throw null; } + public readonly ImmutableArray RemoveRange(ReadOnlySpan items, Generic.IEqualityComparer? equalityComparer = null) { throw null; } + public readonly ImmutableArray Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray Replace(T oldValue, T newValue) { throw null; } + public readonly ImmutableArray SetItem(int index, T item) { throw null; } + public readonly ImmutableArray Slice(int start, int length) { throw null; } + public readonly ImmutableArray Sort() { throw null; } + public readonly ImmutableArray Sort(Generic.IComparer? comparer) { throw null; } + public readonly ImmutableArray Sort(Comparison comparison) { throw null; } + public readonly ImmutableArray Sort(int index, int count, Generic.IComparer? comparer) { throw null; } + readonly void Generic.ICollection.Add(T item) { } + readonly void Generic.ICollection.Clear() { } + readonly bool Generic.ICollection.Remove(T item) { throw null; } + readonly Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + readonly void Generic.IList.Insert(int index, T item) { } + readonly void Generic.IList.RemoveAt(int index) { } + readonly void ICollection.CopyTo(Array array, int index) { } + readonly IEnumerator IEnumerable.GetEnumerator() { throw null; } + readonly int IList.Add(object value) { throw null; } + readonly void IList.Clear() { } + readonly bool IList.Contains(object value) { throw null; } + readonly int IList.IndexOf(object value) { throw null; } + readonly void IList.Insert(int index, object value) { } + readonly void IList.Remove(object value) { } + readonly void IList.RemoveAt(int index) { } + readonly IImmutableList IImmutableList.Add(T value) { throw null; } + readonly IImmutableList IImmutableList.AddRange(Generic.IEnumerable items) { throw null; } + readonly IImmutableList IImmutableList.Clear() { throw null; } + readonly IImmutableList IImmutableList.Insert(int index, T element) { throw null; } + readonly IImmutableList IImmutableList.InsertRange(int index, Generic.IEnumerable items) { throw null; } + readonly IImmutableList IImmutableList.Remove(T value, Generic.IEqualityComparer equalityComparer) { throw null; } + readonly IImmutableList IImmutableList.RemoveAll(Predicate match) { throw null; } + readonly IImmutableList IImmutableList.RemoveAt(int index) { throw null; } + readonly IImmutableList IImmutableList.RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer equalityComparer) { throw null; } + readonly IImmutableList IImmutableList.RemoveRange(int index, int count) { throw null; } + readonly IImmutableList IImmutableList.Replace(T oldValue, T newValue, Generic.IEqualityComparer equalityComparer) { throw null; } + readonly IImmutableList IImmutableList.SetItem(int index, T value) { throw null; } + readonly int IStructuralComparable.CompareTo(object other, IComparer comparer) { throw null; } + readonly bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) { throw null; } + readonly int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { throw null; } + public readonly Builder ToBuilder() { throw null; } + public sealed partial class Builder : Generic.IList, Generic.ICollection, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyList, Generic.IReadOnlyCollection + { + internal Builder() { } + public int Capacity { get { throw null; } set { } } + public int Count { get { throw null; } set { } } + + public T this[int index] { get { throw null; } set { } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + public void Add(T item) { } + public void AddRange(T[] items, int length) { } + public void AddRange(params T[] items) { } + public void AddRange(Generic.IEnumerable items) { } + public void AddRange(ImmutableArray items, int length) { } + public void AddRange(Builder items) { } + public void AddRange(ImmutableArray items) { } + public void AddRange(params scoped ReadOnlySpan items) { } + public void AddRange(TDerived[] items) where TDerived : T { } + public void AddRange(ImmutableArray.Builder items) where TDerived : T { } + public void AddRange(ImmutableArray items) where TDerived : T { } + public void AddRange(params scoped ReadOnlySpan items) where TDerived : T { } + public void Clear() { } + public bool Contains(T item) { throw null; } + public void CopyTo(T[] array, int index) { } + public void CopyTo(T[] destination) { } + public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { } + public void CopyTo(Span destination) { } + public ImmutableArray DrainToImmutable() { throw null; } + public Generic.IEnumerator GetEnumerator() { throw null; } + public int IndexOf(T item, int startIndex, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T item, int startIndex, int count) { throw null; } + public int IndexOf(T item, int startIndex) { throw null; } + public int IndexOf(T item) { throw null; } + public void Insert(int index, T item) { } + public void InsertRange(int index, Generic.IEnumerable items) { } + public void InsertRange(int index, ImmutableArray items) { } + public ref readonly T ItemRef(int index) { throw null; } + public int LastIndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int LastIndexOf(T item, int startIndex, int count) { throw null; } + public int LastIndexOf(T item, int startIndex) { throw null; } + public int LastIndexOf(T item) { throw null; } + public ImmutableArray MoveToImmutable() { throw null; } + public bool Remove(T element, Generic.IEqualityComparer? equalityComparer) { throw null; } + public bool Remove(T element) { throw null; } + public void RemoveAll(Predicate match) { } + public void RemoveAt(int index) { } + public void RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { } + public void RemoveRange(Generic.IEnumerable items) { } + public void RemoveRange(int index, int length) { } + public void Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { } + public void Replace(T oldValue, T newValue) { } + public void Reverse() { } + public void Sort() { } + public void Sort(Generic.IComparer? comparer) { } + public void Sort(Comparison comparison) { } + public void Sort(int index, int count, Generic.IComparer? comparer) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public T[] ToArray() { throw null; } + public ImmutableArray ToImmutable() { throw null; } + } + + public partial struct Enumerator + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + public bool MoveNext() { throw null; } + } + } + + public static partial class ImmutableDictionary + { + public static bool Contains(this IImmutableDictionary map, TKey key, TValue value) { throw null; } + public static ImmutableDictionary Create() { throw null; } + public static ImmutableDictionary Create(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary Create(Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary.Builder CreateBuilder() { throw null; } + public static ImmutableDictionary.Builder CreateBuilder(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary.Builder CreateBuilder(Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary CreateRange(Generic.IEnumerable> items) { throw null; } + public static ImmutableDictionary CreateRange(Generic.IEqualityComparer? keyComparer, Generic.IEnumerable> items) { throw null; } + public static ImmutableDictionary CreateRange(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer, Generic.IEnumerable> items) { throw null; } + public static TValue GetValueOrDefault(this IImmutableDictionary dictionary, TKey key, TValue defaultValue) { throw null; } + public static TValue? GetValueOrDefault(this IImmutableDictionary dictionary, TKey key) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable> source, Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable> source, Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable> source) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this ImmutableDictionary.Builder builder) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector) { throw null; } + } + public sealed partial class ImmutableDictionary : IImmutableDictionary, Generic.IReadOnlyDictionary, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyCollection>, Generic.IDictionary, Generic.ICollection>, IDictionary, ICollection + { + internal ImmutableDictionary() { } + public static readonly ImmutableDictionary Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } } + + public Generic.IEqualityComparer KeyComparer { get { throw null; } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + TValue Generic.IDictionary.this[TKey key] { get { throw null; } set { } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } } + public Generic.IEnumerable Values { get { throw null; } } + + public ImmutableDictionary Add(TKey key, TValue value) { throw null; } + public ImmutableDictionary AddRange(Generic.IEnumerable> pairs) { throw null; } + public ImmutableDictionary Clear() { throw null; } + public bool Contains(Generic.KeyValuePair pair) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ImmutableDictionary Remove(TKey key) { throw null; } + public ImmutableDictionary RemoveRange(Generic.IEnumerable keys) { throw null; } + public ImmutableDictionary SetItem(TKey key, TValue value) { throw null; } + public ImmutableDictionary SetItems(Generic.IEnumerable> items) { throw null; } + void Generic.ICollection>.Add(Generic.KeyValuePair item) { } + void Generic.ICollection>.Clear() { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + bool Generic.ICollection>.Remove(Generic.KeyValuePair item) { throw null; } + void Generic.IDictionary.Add(TKey key, TValue value) { } + bool Generic.IDictionary.Remove(TKey key) { throw null; } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + void IDictionary.Add(object key, object value) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.AddRange(Generic.IEnumerable> pairs) { throw null; } + IImmutableDictionary IImmutableDictionary.Clear() { throw null; } + IImmutableDictionary IImmutableDictionary.Remove(TKey key) { throw null; } + IImmutableDictionary IImmutableDictionary.RemoveRange(Generic.IEnumerable keys) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItems(Generic.IEnumerable> items) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public ImmutableDictionary WithComparers(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public ImmutableDictionary WithComparers(Generic.IEqualityComparer? keyComparer) { throw null; } + public sealed partial class Builder : Generic.IDictionary, Generic.ICollection>, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyDictionary, Generic.IReadOnlyCollection>, IDictionary, ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } set { } } + + public Generic.IEqualityComparer KeyComparer { get { throw null; } set { } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } set { } } + public Generic.IEnumerable Values { get { throw null; } } + + public void Add(TKey key, TValue value) { } + public void Add(Generic.KeyValuePair item) { } + public void AddRange(Generic.IEnumerable> items) { } + public void Clear() { } + public bool Contains(Generic.KeyValuePair item) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public TValue GetValueOrDefault(TKey key, TValue defaultValue) { throw null; } + public TValue? GetValueOrDefault(TKey key) { throw null; } + public bool Remove(TKey key) { throw null; } + public bool Remove(Generic.KeyValuePair item) { throw null; } + public void RemoveRange(Generic.IEnumerable keys) { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + void IDictionary.Add(object key, object value) { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableDictionary ToImmutable() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator>, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public Generic.KeyValuePair Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableHashSet + { + public static ImmutableHashSet Create() { throw null; } + public static ImmutableHashSet Create(T item) { throw null; } + public static ImmutableHashSet Create(params T[] items) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer, T item) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer, params T[] items) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer, params scoped ReadOnlySpan items) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer) { throw null; } + public static ImmutableHashSet Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableHashSet.Builder CreateBuilder() { throw null; } + public static ImmutableHashSet.Builder CreateBuilder(Generic.IEqualityComparer? equalityComparer) { throw null; } + public static ImmutableHashSet CreateRange(Generic.IEnumerable items) { throw null; } + public static ImmutableHashSet CreateRange(Generic.IEqualityComparer? equalityComparer, Generic.IEnumerable items) { throw null; } + public static ImmutableHashSet ToImmutableHashSet(this Generic.IEnumerable source, Generic.IEqualityComparer? equalityComparer) { throw null; } + public static ImmutableHashSet ToImmutableHashSet(this Generic.IEnumerable source) { throw null; } + public static ImmutableHashSet ToImmutableHashSet(this ImmutableHashSet.Builder builder) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableHashSet), "Create")] + public sealed partial class ImmutableHashSet : IImmutableSet, Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.ICollection, Generic.ISet, ICollection, Generic.IReadOnlySet + { + internal ImmutableHashSet() { } + public static readonly ImmutableHashSet Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + public Generic.IEqualityComparer KeyComparer { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + public ImmutableHashSet Add(T item) { throw null; } + public ImmutableHashSet Clear() { throw null; } + public bool Contains(T item) { throw null; } + public ImmutableHashSet Except(Generic.IEnumerable other) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ImmutableHashSet Intersect(Generic.IEnumerable other) { throw null; } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public ImmutableHashSet Remove(T item) { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public ImmutableHashSet SymmetricExcept(Generic.IEnumerable other) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + bool Generic.ISet.Add(T item) { throw null; } + void Generic.ISet.ExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.IntersectWith(Generic.IEnumerable other) { } + void Generic.ISet.SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.UnionWith(Generic.IEnumerable other) { } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableSet IImmutableSet.Add(T item) { throw null; } + IImmutableSet IImmutableSet.Clear() { throw null; } + IImmutableSet IImmutableSet.Except(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Intersect(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Remove(T item) { throw null; } + IImmutableSet IImmutableSet.SymmetricExcept(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Union(Generic.IEnumerable other) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public ImmutableHashSet Union(Generic.IEnumerable other) { throw null; } + public ImmutableHashSet WithComparer(Generic.IEqualityComparer? equalityComparer) { throw null; } + public sealed partial class Builder : Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.ISet, Generic.ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + public Generic.IEqualityComparer KeyComparer { get { throw null; } set { } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + public bool Add(T item) { throw null; } + public void Clear() { } + public bool Contains(T item) { throw null; } + public void ExceptWith(Generic.IEnumerable other) { } + public Enumerator GetEnumerator() { throw null; } + public void IntersectWith(Generic.IEnumerable other) { } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public bool Remove(T item) { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public void SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableHashSet ToImmutable() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public void UnionWith(Generic.IEnumerable other) { } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object? IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableInterlocked + { + public static TValue AddOrUpdate(ref ImmutableDictionary location, TKey key, TValue addValue, Func updateValueFactory) { throw null; } + public static TValue AddOrUpdate(ref ImmutableDictionary location, TKey key, Func addValueFactory, Func updateValueFactory) { throw null; } + public static void Enqueue(ref ImmutableQueue location, T value) { } + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, TValue value) { throw null; } + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory) { throw null; } + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory, TArg factoryArgument) { throw null; } + public static ImmutableArray InterlockedCompareExchange(ref ImmutableArray location, ImmutableArray value, ImmutableArray comparand) { throw null; } + public static ImmutableArray InterlockedExchange(ref ImmutableArray location, ImmutableArray value) { throw null; } + public static bool InterlockedInitialize(ref ImmutableArray location, ImmutableArray value) { throw null; } + public static void Push(ref ImmutableStack location, T value) { } + public static bool TryAdd(ref ImmutableDictionary location, TKey key, TValue value) { throw null; } + public static bool TryDequeue(ref ImmutableQueue location, out T value) { throw null; } + public static bool TryPop(ref ImmutableStack location, out T value) { throw null; } + public static bool TryRemove(ref ImmutableDictionary location, TKey key, out TValue value) { throw null; } + public static bool TryUpdate(ref ImmutableDictionary location, TKey key, TValue newValue, TValue comparisonValue) { throw null; } + public static bool Update(ref T location, Func transformer) where T : class { throw null; } + public static bool Update(ref ImmutableArray location, Func, ImmutableArray> transformer) { throw null; } + public static bool Update(ref T location, Func transformer, TArg transformerArgument) where T : class { throw null; } + public static bool Update(ref ImmutableArray location, Func, TArg, ImmutableArray> transformer, TArg transformerArgument) { throw null; } + } + public static partial class ImmutableList + { + public static ImmutableList Create() { throw null; } + public static ImmutableList Create(T item) { throw null; } + public static ImmutableList Create(params T[] items) { throw null; } + public static ImmutableList Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableList.Builder CreateBuilder() { throw null; } + public static ImmutableList CreateRange(Generic.IEnumerable items) { throw null; } + public static int IndexOf(this IImmutableList list, T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public static int IndexOf(this IImmutableList list, T item, int startIndex, int count) { throw null; } + public static int IndexOf(this IImmutableList list, T item, int startIndex) { throw null; } + public static int IndexOf(this IImmutableList list, T item) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item, int startIndex, int count) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item, int startIndex) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item) { throw null; } + public static IImmutableList Remove(this IImmutableList list, T value) { throw null; } + public static IImmutableList RemoveRange(this IImmutableList list, Generic.IEnumerable items) { throw null; } + public static IImmutableList Replace(this IImmutableList list, T oldValue, T newValue) { throw null; } + public static ImmutableList ToImmutableList(this Generic.IEnumerable source) { throw null; } + public static ImmutableList ToImmutableList(this ImmutableList.Builder builder) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableList), "Create")] + public sealed partial class ImmutableList : IImmutableList, Generic.IReadOnlyList, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection, Generic.IList, Generic.ICollection, IList, ICollection + { + internal ImmutableList() { } + public static readonly ImmutableList Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public T this[int index] { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + T Generic.IList.this[int index] { get { throw null; } set { } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public ImmutableList Add(T value) { throw null; } + public ImmutableList AddRange(Generic.IEnumerable items) { throw null; } + public int BinarySearch(T item, Generic.IComparer? comparer) { throw null; } + public int BinarySearch(T item) { throw null; } + public int BinarySearch(int index, int count, T item, Generic.IComparer? comparer) { throw null; } + public ImmutableList Clear() { throw null; } + public bool Contains(T value) { throw null; } + public ImmutableList ConvertAll(Func converter) { throw null; } + public void CopyTo(T[] array, int arrayIndex) { } + public void CopyTo(T[] array) { } + public void CopyTo(int index, T[] array, int arrayIndex, int count) { } + public bool Exists(Predicate match) { throw null; } + public T? Find(Predicate match) { throw null; } + public ImmutableList FindAll(Predicate match) { throw null; } + public int FindIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindIndex(int startIndex, Predicate match) { throw null; } + public int FindIndex(Predicate match) { throw null; } + public T? FindLast(Predicate match) { throw null; } + public int FindLastIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindLastIndex(int startIndex, Predicate match) { throw null; } + public int FindLastIndex(Predicate match) { throw null; } + public void ForEach(Action action) { } + public Enumerator GetEnumerator() { throw null; } + public ImmutableList GetRange(int index, int count) { throw null; } + public int IndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T value) { throw null; } + public ImmutableList Insert(int index, T item) { throw null; } + public ImmutableList InsertRange(int index, Generic.IEnumerable items) { throw null; } + public ref readonly T ItemRef(int index) { throw null; } + public int LastIndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList Remove(T value, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList Remove(T value) { throw null; } + public ImmutableList RemoveAll(Predicate match) { throw null; } + public ImmutableList RemoveAt(int index) { throw null; } + public ImmutableList RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList RemoveRange(Generic.IEnumerable items) { throw null; } + public ImmutableList RemoveRange(int index, int count) { throw null; } + public ImmutableList Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList Replace(T oldValue, T newValue) { throw null; } + public ImmutableList Reverse() { throw null; } + public ImmutableList Reverse(int index, int count) { throw null; } + public ImmutableList SetItem(int index, T value) { throw null; } + public ImmutableList Sort() { throw null; } + public ImmutableList Sort(Generic.IComparer? comparer) { throw null; } + public ImmutableList Sort(Comparison comparison) { throw null; } + public ImmutableList Sort(int index, int count, Generic.IComparer? comparer) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void Generic.IList.Insert(int index, T item) { } + void Generic.IList.RemoveAt(int index) { } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + int IList.Add(object value) { throw null; } + void IList.Clear() { } + bool IList.Contains(object value) { throw null; } + int IList.IndexOf(object value) { throw null; } + void IList.Insert(int index, object value) { } + void IList.Remove(object value) { } + void IList.RemoveAt(int index) { } + IImmutableList IImmutableList.Add(T value) { throw null; } + IImmutableList IImmutableList.AddRange(Generic.IEnumerable items) { throw null; } + IImmutableList IImmutableList.Clear() { throw null; } + IImmutableList IImmutableList.Insert(int index, T item) { throw null; } + IImmutableList IImmutableList.InsertRange(int index, Generic.IEnumerable items) { throw null; } + IImmutableList IImmutableList.Remove(T value, Generic.IEqualityComparer equalityComparer) { throw null; } + IImmutableList IImmutableList.RemoveAll(Predicate match) { throw null; } + IImmutableList IImmutableList.RemoveAt(int index) { throw null; } + IImmutableList IImmutableList.RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer equalityComparer) { throw null; } + IImmutableList IImmutableList.RemoveRange(int index, int count) { throw null; } + IImmutableList IImmutableList.Replace(T oldValue, T newValue, Generic.IEqualityComparer equalityComparer) { throw null; } + IImmutableList IImmutableList.SetItem(int index, T value) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TrueForAll(Predicate match) { throw null; } + public sealed partial class Builder : Generic.IList, Generic.ICollection, Generic.IEnumerable, IEnumerable, IList, ICollection, Generic.IReadOnlyList, Generic.IReadOnlyCollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public T this[int index] { get { throw null; } set { } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public void Add(T item) { } + public void AddRange(Generic.IEnumerable items) { } + public int BinarySearch(T item, Generic.IComparer? comparer) { throw null; } + public int BinarySearch(T item) { throw null; } + public int BinarySearch(int index, int count, T item, Generic.IComparer? comparer) { throw null; } + public void Clear() { } + public bool Contains(T item) { throw null; } + public ImmutableList ConvertAll(Func converter) { throw null; } + public void CopyTo(T[] array, int arrayIndex) { } + public void CopyTo(T[] array) { } + public void CopyTo(int index, T[] array, int arrayIndex, int count) { } + public bool Exists(Predicate match) { throw null; } + public T? Find(Predicate match) { throw null; } + public ImmutableList FindAll(Predicate match) { throw null; } + public int FindIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindIndex(int startIndex, Predicate match) { throw null; } + public int FindIndex(Predicate match) { throw null; } + public T? FindLast(Predicate match) { throw null; } + public int FindLastIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindLastIndex(int startIndex, Predicate match) { throw null; } + public int FindLastIndex(Predicate match) { throw null; } + public void ForEach(Action action) { } + public Enumerator GetEnumerator() { throw null; } + public ImmutableList GetRange(int index, int count) { throw null; } + public int IndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T item, int index, int count) { throw null; } + public int IndexOf(T item, int index) { throw null; } + public int IndexOf(T item) { throw null; } + public void Insert(int index, T item) { } + public void InsertRange(int index, Generic.IEnumerable items) { } + public ref readonly T ItemRef(int index) { throw null; } + public int LastIndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int LastIndexOf(T item, int startIndex, int count) { throw null; } + public int LastIndexOf(T item, int startIndex) { throw null; } + public int LastIndexOf(T item) { throw null; } + public bool Remove(T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public bool Remove(T item) { throw null; } + public int RemoveAll(Predicate match) { throw null; } + public void RemoveAt(int index) { } + public void RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { } + public void RemoveRange(Generic.IEnumerable items) { } + public void RemoveRange(int index, int count) { } + public void Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { } + public void Replace(T oldValue, T newValue) { } + public void Reverse() { } + public void Reverse(int index, int count) { } + public void Sort() { } + public void Sort(Generic.IComparer? comparer) { } + public void Sort(Comparison comparison) { } + public void Sort(int index, int count, Generic.IComparer? comparer) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + int IList.Add(object value) { throw null; } + void IList.Clear() { } + bool IList.Contains(object value) { throw null; } + int IList.IndexOf(object value) { throw null; } + void IList.Insert(int index, object value) { } + void IList.Remove(object value) { } + public ImmutableList ToImmutable() { throw null; } + public bool TrueForAll(Predicate match) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object? IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableQueue + { + public static ImmutableQueue Create() { throw null; } + public static ImmutableQueue Create(T item) { throw null; } + public static ImmutableQueue Create(params T[] items) { throw null; } + public static ImmutableQueue Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableQueue CreateRange(Generic.IEnumerable items) { throw null; } + public static IImmutableQueue Dequeue(this IImmutableQueue queue, out T value) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableQueue), "Create")] + public sealed partial class ImmutableQueue : IImmutableQueue, Generic.IEnumerable, IEnumerable + { + internal ImmutableQueue() { } + public static ImmutableQueue Empty { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public ImmutableQueue Clear() { throw null; } + public ImmutableQueue Dequeue() { throw null; } + public ImmutableQueue Dequeue(out T value) { throw null; } + public ImmutableQueue Enqueue(T value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public T Peek() { throw null; } + public ref readonly T PeekRef() { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableQueue IImmutableQueue.Clear() { throw null; } + IImmutableQueue IImmutableQueue.Dequeue() { throw null; } + IImmutableQueue IImmutableQueue.Enqueue(T value) { throw null; } + public partial struct Enumerator + { + private ImmutableQueue _originalQueue; + private ImmutableStack _remainingForwardsStack; + private ImmutableStack _remainingBackwardsStack; + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + public bool MoveNext() { throw null; } + } + } + + public static partial class ImmutableSortedDictionary + { + public static ImmutableSortedDictionary Create() { throw null; } + public static ImmutableSortedDictionary Create(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary Create(Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary.Builder CreateBuilder() { throw null; } + public static ImmutableSortedDictionary.Builder CreateBuilder(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary.Builder CreateBuilder(Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary CreateRange(Generic.IComparer? keyComparer, Generic.IEnumerable> items) { throw null; } + public static ImmutableSortedDictionary CreateRange(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer, Generic.IEnumerable> items) { throw null; } + public static ImmutableSortedDictionary CreateRange(Generic.IEnumerable> items) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable> source, Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable> source, Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable> source) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this ImmutableSortedDictionary.Builder builder) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector) { throw null; } + } + public sealed partial class ImmutableSortedDictionary : IImmutableDictionary, Generic.IReadOnlyDictionary, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyCollection>, Generic.IDictionary, Generic.ICollection>, IDictionary, ICollection + { + internal ImmutableSortedDictionary() { } + public static readonly ImmutableSortedDictionary Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } } + + public Generic.IComparer KeyComparer { get { throw null; } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + TValue Generic.IDictionary.this[TKey key] { get { throw null; } set { } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } } + public Generic.IEnumerable Values { get { throw null; } } + + public ImmutableSortedDictionary Add(TKey key, TValue value) { throw null; } + public ImmutableSortedDictionary AddRange(Generic.IEnumerable> items) { throw null; } + public ImmutableSortedDictionary Clear() { throw null; } + public bool Contains(Generic.KeyValuePair pair) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ImmutableSortedDictionary Remove(TKey value) { throw null; } + public ImmutableSortedDictionary RemoveRange(Generic.IEnumerable keys) { throw null; } + public ImmutableSortedDictionary SetItem(TKey key, TValue value) { throw null; } + public ImmutableSortedDictionary SetItems(Generic.IEnumerable> items) { throw null; } + void Generic.ICollection>.Add(Generic.KeyValuePair item) { } + void Generic.ICollection>.Clear() { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + bool Generic.ICollection>.Remove(Generic.KeyValuePair item) { throw null; } + void Generic.IDictionary.Add(TKey key, TValue value) { } + bool Generic.IDictionary.Remove(TKey key) { throw null; } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int index) { } + void IDictionary.Add(object key, object value) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.AddRange(Generic.IEnumerable> pairs) { throw null; } + IImmutableDictionary IImmutableDictionary.Clear() { throw null; } + IImmutableDictionary IImmutableDictionary.Remove(TKey key) { throw null; } + IImmutableDictionary IImmutableDictionary.RemoveRange(Generic.IEnumerable keys) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItems(Generic.IEnumerable> items) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public ref readonly TValue ValueRef(TKey key) { throw null; } + public ImmutableSortedDictionary WithComparers(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public ImmutableSortedDictionary WithComparers(Generic.IComparer? keyComparer) { throw null; } + public sealed partial class Builder : Generic.IDictionary, Generic.ICollection>, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyDictionary, Generic.IReadOnlyCollection>, IDictionary, ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } set { } } + + public Generic.IComparer KeyComparer { get { throw null; } set { } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } set { } } + public Generic.IEnumerable Values { get { throw null; } } + + public void Add(TKey key, TValue value) { } + public void Add(Generic.KeyValuePair item) { } + public void AddRange(Generic.IEnumerable> items) { } + public void Clear() { } + public bool Contains(Generic.KeyValuePair item) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public TValue GetValueOrDefault(TKey key, TValue defaultValue) { throw null; } + public TValue? GetValueOrDefault(TKey key) { throw null; } + public bool Remove(TKey key) { throw null; } + public bool Remove(Generic.KeyValuePair item) { throw null; } + public void RemoveRange(Generic.IEnumerable keys) { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int index) { } + void IDictionary.Add(object key, object value) { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableSortedDictionary ToImmutable() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public ref readonly TValue ValueRef(TKey key) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator>, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public Generic.KeyValuePair Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableSortedSet + { + public static ImmutableSortedSet Create() { throw null; } + public static ImmutableSortedSet Create(T item) { throw null; } + public static ImmutableSortedSet Create(params T[] items) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer, T item) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer, params T[] items) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer, params scoped ReadOnlySpan items) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer) { throw null; } + public static ImmutableSortedSet Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableSortedSet.Builder CreateBuilder() { throw null; } + public static ImmutableSortedSet.Builder CreateBuilder(Generic.IComparer? comparer) { throw null; } + public static ImmutableSortedSet CreateRange(Generic.IComparer? comparer, Generic.IEnumerable items) { throw null; } + public static ImmutableSortedSet CreateRange(Generic.IEnumerable items) { throw null; } + public static ImmutableSortedSet ToImmutableSortedSet(this Generic.IEnumerable source, Generic.IComparer? comparer) { throw null; } + public static ImmutableSortedSet ToImmutableSortedSet(this Generic.IEnumerable source) { throw null; } + public static ImmutableSortedSet ToImmutableSortedSet(this ImmutableSortedSet.Builder builder) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableSortedSet), "Create")] + public sealed partial class ImmutableSortedSet : IImmutableSet, Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.IReadOnlySet, Generic.IReadOnlyList, Generic.IList, Generic.ICollection, Generic.ISet, IList, ICollection + { + internal ImmutableSortedSet() { } + public static readonly ImmutableSortedSet Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public T this[int index] { get { throw null; } } + + public Generic.IComparer KeyComparer { get { throw null; } } + public T? Max { get { throw null; } } + public T? Min { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + T Generic.IList.this[int index] { get { throw null; } set { } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public ImmutableSortedSet Add(T value) { throw null; } + public ImmutableSortedSet Clear() { throw null; } + public bool Contains(T value) { throw null; } + public ImmutableSortedSet Except(Generic.IEnumerable other) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public int IndexOf(T item) { throw null; } + public ImmutableSortedSet Intersect(Generic.IEnumerable other) { throw null; } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public ref readonly T ItemRef(int index) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public ImmutableSortedSet Remove(T value) { throw null; } + public Generic.IEnumerable Reverse() { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public ImmutableSortedSet SymmetricExcept(Generic.IEnumerable other) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void Generic.IList.Insert(int index, T item) { } + void Generic.IList.RemoveAt(int index) { } + bool Generic.ISet.Add(T item) { throw null; } + void Generic.ISet.ExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.IntersectWith(Generic.IEnumerable other) { } + void Generic.ISet.SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.UnionWith(Generic.IEnumerable other) { } + void ICollection.CopyTo(Array array, int index) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + int IList.Add(object value) { throw null; } + void IList.Clear() { } + bool IList.Contains(object value) { throw null; } + int IList.IndexOf(object value) { throw null; } + void IList.Insert(int index, object value) { } + void IList.Remove(object value) { } + void IList.RemoveAt(int index) { } + IImmutableSet IImmutableSet.Add(T value) { throw null; } + IImmutableSet IImmutableSet.Clear() { throw null; } + IImmutableSet IImmutableSet.Except(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Intersect(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Remove(T value) { throw null; } + IImmutableSet IImmutableSet.SymmetricExcept(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Union(Generic.IEnumerable other) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public ImmutableSortedSet Union(Generic.IEnumerable other) { throw null; } + public ImmutableSortedSet WithComparer(Generic.IComparer? comparer) { throw null; } + public sealed partial class Builder : Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.ISet, Generic.ICollection, ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public T this[int index] { get { throw null; } } + + public Generic.IComparer KeyComparer { get { throw null; } set { } } + public T? Max { get { throw null; } } + public T? Min { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + public bool Add(T item) { throw null; } + public void Clear() { } + public bool Contains(T item) { throw null; } + public void ExceptWith(Generic.IEnumerable other) { } + public Enumerator GetEnumerator() { throw null; } + public int IndexOf(T item) { throw null; } + public void IntersectWith(Generic.IEnumerable other) { } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public ref readonly T ItemRef(int index) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public bool Remove(T item) { throw null; } + public Generic.IEnumerable Reverse() { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public void SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableSortedSet ToImmutable() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public void UnionWith(Generic.IEnumerable other) { } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object? IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableStack + { + public static ImmutableStack Create() { throw null; } + public static ImmutableStack Create(T item) { throw null; } + public static ImmutableStack Create(params T[] items) { throw null; } + public static ImmutableStack Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableStack CreateRange(Generic.IEnumerable items) { throw null; } + public static IImmutableStack Pop(this IImmutableStack stack, out T value) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableStack), "Create")] + public sealed partial class ImmutableStack : IImmutableStack, Generic.IEnumerable, IEnumerable + { + internal ImmutableStack() { } + public static ImmutableStack Empty { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public ImmutableStack Clear() { throw null; } + public Enumerator GetEnumerator() { throw null; } + public T Peek() { throw null; } + public ref readonly T PeekRef() { throw null; } + public ImmutableStack Pop() { throw null; } + public ImmutableStack Pop(out T value) { throw null; } + public ImmutableStack Push(T value) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableStack IImmutableStack.Clear() { throw null; } + IImmutableStack IImmutableStack.Pop() { throw null; } + IImmutableStack IImmutableStack.Push(T value) { throw null; } + public partial struct Enumerator + { + private ImmutableStack _originalStack; + private ImmutableStack _remainingStack; + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + public bool MoveNext() { throw null; } + } + } +} + +namespace System.Linq +{ + public static partial class ImmutableArrayExtensions + { + public static T? Aggregate(this Collections.Immutable.ImmutableArray immutableArray, Func func) { throw null; } + public static TAccumulate Aggregate(this Collections.Immutable.ImmutableArray immutableArray, TAccumulate seed, Func func) { throw null; } + public static TResult Aggregate(this Collections.Immutable.ImmutableArray immutableArray, TAccumulate seed, Func func, Func resultSelector) { throw null; } + public static bool All(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static bool Any(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static bool Any(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static bool Any(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T ElementAt(this Collections.Immutable.ImmutableArray immutableArray, int index) { throw null; } + public static T? ElementAtOrDefault(this Collections.Immutable.ImmutableArray immutableArray, int index) { throw null; } + public static T First(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T First(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T First(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T? FirstOrDefault(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T? FirstOrDefault(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T? FirstOrDefault(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T Last(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T Last(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T Last(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T? LastOrDefault(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T? LastOrDefault(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T? LastOrDefault(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static Collections.Generic.IEnumerable Select(this Collections.Immutable.ImmutableArray immutableArray, Func selector) { throw null; } + public static Collections.Generic.IEnumerable SelectMany(this Collections.Immutable.ImmutableArray immutableArray, Func> collectionSelector, Func resultSelector) { throw null; } + public static bool SequenceEqual(this Collections.Immutable.ImmutableArray immutableArray, Collections.Generic.IEnumerable items, Collections.Generic.IEqualityComparer? comparer = null) where TDerived : TBase { throw null; } + public static bool SequenceEqual(this Collections.Immutable.ImmutableArray immutableArray, Collections.Immutable.ImmutableArray items, Collections.Generic.IEqualityComparer? comparer = null) where TDerived : TBase { throw null; } + public static bool SequenceEqual(this Collections.Immutable.ImmutableArray immutableArray, Collections.Immutable.ImmutableArray items, Func predicate) where TDerived : TBase { throw null; } + public static T Single(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T Single(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T? SingleOrDefault(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T? SingleOrDefault(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T[] ToArray(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector, Collections.Generic.IEqualityComparer? comparer) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector, Func elementSelector, Collections.Generic.IEqualityComparer? comparer) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector, Func elementSelector) { throw null; } + public static Collections.Generic.IEnumerable Where(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + } +} + +namespace System.Runtime.InteropServices +{ + public static partial class ImmutableCollectionsMarshal + { + public static T[]? AsArray(Collections.Immutable.ImmutableArray array) { throw null; } + public static Collections.Immutable.ImmutableArray AsImmutableArray(T[]? array) { throw null; } + } +} \ No newline at end of file diff --git a/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/lib/net9.0/System.Collections.Immutable.cs b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/lib/net9.0/System.Collections.Immutable.cs new file mode 100644 index 00000000000..7e7af54619d --- /dev/null +++ b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/lib/net9.0/System.Collections.Immutable.cs @@ -0,0 +1,1483 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the http://aka.ms/api-review process. +// ------------------------------------------------------------------------------ +[assembly: System.Runtime.CompilerServices.CompilationRelaxations(8)] +[assembly: System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = true)] +[assembly: System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Collections.Immutable.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")] +[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")] +[assembly: System.Reflection.AssemblyMetadata("Serviceable", "True")] +[assembly: System.Reflection.AssemblyMetadata("PreferInbox", "True")] +[assembly: System.Reflection.AssemblyDefaultAlias("System.Collections.Immutable")] +[assembly: System.Resources.NeutralResourcesLanguage("en-US")] +[assembly: System.CLSCompliant(true)] +[assembly: System.Reflection.AssemblyMetadata("IsTrimmable", "True")] +[assembly: System.Runtime.InteropServices.DefaultDllImportSearchPaths(System.Runtime.InteropServices.DllImportSearchPath.AssemblyDirectory | System.Runtime.InteropServices.DllImportSearchPath.System32)] +[assembly: System.Reflection.AssemblyCompany("Microsoft Corporation")] +[assembly: System.Reflection.AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: System.Reflection.AssemblyDescription("This package provides collections that are thread safe and guaranteed to never change their contents, also known as immutable collections. Like strings, any methods that perform modifications will not change the existing instance but instead return a new instance. For efficiency reasons, the implementation uses a sharing mechanism to ensure that newly created instances share as much data as possible with the previous instance while ensuring that operations have a predictable time complexity.\r\n\r\nThe System.Collections.Immutable library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks.")] +[assembly: System.Reflection.AssemblyFileVersion("9.0.24.52809")] +[assembly: System.Reflection.AssemblyInformationalVersion("9.0.0+9d5a6a9aa463d6d10b0b0ba6d5982cc82f363dc3")] +[assembly: System.Reflection.AssemblyProduct("Microsoft® .NET")] +[assembly: System.Reflection.AssemblyTitle("System.Collections.Immutable")] +[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")] +[assembly: System.Reflection.AssemblyVersionAttribute("9.0.0.0")] +[assembly: System.Runtime.CompilerServices.ReferenceAssembly] +[assembly: System.Reflection.AssemblyFlagsAttribute((System.Reflection.AssemblyNameFlags)0x70)] +namespace System.Collections.Frozen +{ + public static partial class FrozenDictionary + { + public static FrozenDictionary ToFrozenDictionary(this Generic.IEnumerable source, Func keySelector, Generic.IEqualityComparer? comparer = null) { throw null; } + public static FrozenDictionary ToFrozenDictionary(this Generic.IEnumerable> source, Generic.IEqualityComparer? comparer = null) { throw null; } + public static FrozenDictionary ToFrozenDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IEqualityComparer? comparer = null) { throw null; } + } + public abstract partial class FrozenDictionary : Generic.IDictionary, Generic.ICollection>, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyDictionary, Generic.IReadOnlyCollection>, IDictionary, ICollection + { + internal FrozenDictionary() { } + public Generic.IEqualityComparer Comparer { get { throw null; } } + public int Count { get { throw null; } } + public static FrozenDictionary Empty { get { throw null; } } + + public ref readonly TValue this[TKey key] { get { throw null; } } + + public Immutable.ImmutableArray Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + TValue Generic.IDictionary.this[TKey key] { get { throw null; } set { } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + TValue Generic.IReadOnlyDictionary.this[TKey key] { get { throw null; } } + + Generic.IEnumerable Generic.IReadOnlyDictionary.Keys { get { throw null; } } + + Generic.IEnumerable Generic.IReadOnlyDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Immutable.ImmutableArray Values { get { throw null; } } + + public bool ContainsKey(TKey key) { throw null; } + public void CopyTo(Generic.KeyValuePair[] destination, int destinationIndex) { } + public void CopyTo(Span> destination) { } + public AlternateLookup GetAlternateLookup() { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ref readonly TValue GetValueRefOrNullRef(TKey key) { throw null; } + void Generic.ICollection>.Add(Generic.KeyValuePair item) { } + void Generic.ICollection>.Clear() { } + bool Generic.ICollection>.Contains(Generic.KeyValuePair item) { throw null; } + bool Generic.ICollection>.Remove(Generic.KeyValuePair item) { throw null; } + void Generic.IDictionary.Add(TKey key, TValue value) { } + bool Generic.IDictionary.Remove(TKey key) { throw null; } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int index) { } + void IDictionary.Add(object key, object value) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public bool TryGetAlternateLookup(out AlternateLookup lookup) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public readonly partial struct AlternateLookup + { + private readonly FrozenDictionary _Dictionary_k__BackingField; + private readonly object _dummy; + private readonly int _dummyPrimitive; + public FrozenDictionary Dictionary { get { throw null; } } + + public TValue this[TAlternateKey key] { get { throw null; } } + + public readonly bool ContainsKey(TAlternateKey key) { throw null; } + public readonly bool TryGetValue(TAlternateKey key, out TValue value) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator>, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public Generic.KeyValuePair Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public bool MoveNext() { throw null; } + void IEnumerator.Reset() { } + void IDisposable.Dispose() { } + } + } + + public static partial class FrozenSet + { + public static FrozenSet Create(Generic.IEqualityComparer? equalityComparer, params scoped ReadOnlySpan source) { throw null; } + public static FrozenSet Create(params scoped ReadOnlySpan source) { throw null; } + public static FrozenSet ToFrozenSet(this Generic.IEnumerable source, Generic.IEqualityComparer? comparer = null) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(FrozenSet), "Create")] + public abstract partial class FrozenSet : Generic.ISet, Generic.ICollection, Generic.IEnumerable, IEnumerable, Generic.IReadOnlySet, Generic.IReadOnlyCollection, ICollection + { + internal FrozenSet() { } + public Generic.IEqualityComparer Comparer { get { throw null; } } + public int Count { get { throw null; } } + public static FrozenSet Empty { get { throw null; } } + public Immutable.ImmutableArray Items { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + public bool Contains(T item) { throw null; } + public void CopyTo(T[] destination, int destinationIndex) { } + public void CopyTo(Span destination) { } + public AlternateLookup GetAlternateLookup() { throw null; } + public Enumerator GetEnumerator() { throw null; } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + bool Generic.ISet.Add(T item) { throw null; } + void Generic.ISet.ExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.IntersectWith(Generic.IEnumerable other) { } + void Generic.ISet.SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.UnionWith(Generic.IEnumerable other) { } + void ICollection.CopyTo(Array array, int index) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public bool TryGetAlternateLookup(out AlternateLookup lookup) { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public readonly partial struct AlternateLookup + { + private readonly FrozenSet _Set_k__BackingField; + private readonly object _dummy; + private readonly int _dummyPrimitive; + public FrozenSet Set { get { throw null; } } + + public readonly bool Contains(TAlternate item) { throw null; } + public readonly bool TryGetValue(TAlternate equalValue, out T actualValue) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public bool MoveNext() { throw null; } + void IEnumerator.Reset() { } + void IDisposable.Dispose() { } + } + } +} + +namespace System.Collections.Immutable +{ + public partial interface IImmutableDictionary : Generic.IReadOnlyDictionary, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyCollection> + { + IImmutableDictionary Add(TKey key, TValue value); + IImmutableDictionary AddRange(Generic.IEnumerable> pairs); + IImmutableDictionary Clear(); + bool Contains(Generic.KeyValuePair pair); + IImmutableDictionary Remove(TKey key); + IImmutableDictionary RemoveRange(Generic.IEnumerable keys); + IImmutableDictionary SetItem(TKey key, TValue value); + IImmutableDictionary SetItems(Generic.IEnumerable> items); + bool TryGetKey(TKey equalKey, out TKey actualKey); + } + + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableList), "Create")] + public partial interface IImmutableList : Generic.IReadOnlyList, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection + { + IImmutableList Add(T value); + IImmutableList AddRange(Generic.IEnumerable items); + IImmutableList Clear(); + int IndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer); + IImmutableList Insert(int index, T element); + IImmutableList InsertRange(int index, Generic.IEnumerable items); + int LastIndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer); + IImmutableList Remove(T value, Generic.IEqualityComparer? equalityComparer); + IImmutableList RemoveAll(Predicate match); + IImmutableList RemoveAt(int index); + IImmutableList RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer); + IImmutableList RemoveRange(int index, int count); + IImmutableList Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer); + IImmutableList SetItem(int index, T value); + } + + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableQueue), "Create")] + public partial interface IImmutableQueue : Generic.IEnumerable, IEnumerable + { + bool IsEmpty { get; } + + IImmutableQueue Clear(); + IImmutableQueue Dequeue(); + IImmutableQueue Enqueue(T value); + T Peek(); + } + + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableHashSet), "Create")] + public partial interface IImmutableSet : Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable + { + IImmutableSet Add(T value); + IImmutableSet Clear(); + bool Contains(T value); + IImmutableSet Except(Generic.IEnumerable other); + IImmutableSet Intersect(Generic.IEnumerable other); + bool IsProperSubsetOf(Generic.IEnumerable other); + bool IsProperSupersetOf(Generic.IEnumerable other); + bool IsSubsetOf(Generic.IEnumerable other); + bool IsSupersetOf(Generic.IEnumerable other); + bool Overlaps(Generic.IEnumerable other); + IImmutableSet Remove(T value); + bool SetEquals(Generic.IEnumerable other); + IImmutableSet SymmetricExcept(Generic.IEnumerable other); + bool TryGetValue(T equalValue, out T actualValue); + IImmutableSet Union(Generic.IEnumerable other); + } + + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableStack), "Create")] + public partial interface IImmutableStack : Generic.IEnumerable, IEnumerable + { + bool IsEmpty { get; } + + IImmutableStack Clear(); + T Peek(); + IImmutableStack Pop(); + IImmutableStack Push(T value); + } + + public static partial class ImmutableArray + { + public static int BinarySearch(this ImmutableArray array, T value, Generic.IComparer? comparer) { throw null; } + public static int BinarySearch(this ImmutableArray array, T value) { throw null; } + public static int BinarySearch(this ImmutableArray array, int index, int length, T value, Generic.IComparer? comparer) { throw null; } + public static int BinarySearch(this ImmutableArray array, int index, int length, T value) { throw null; } + public static ImmutableArray Create() { throw null; } + public static ImmutableArray Create(T item1, T item2, T item3, T item4) { throw null; } + public static ImmutableArray Create(T item1, T item2, T item3) { throw null; } + public static ImmutableArray Create(T item1, T item2) { throw null; } + public static ImmutableArray Create(T item) { throw null; } + public static ImmutableArray Create(T[] items, int start, int length) { throw null; } + public static ImmutableArray Create(params T[]? items) { throw null; } + public static ImmutableArray Create(ImmutableArray items, int start, int length) { throw null; } + public static ImmutableArray Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableArray Create(Span items) { throw null; } + public static ImmutableArray.Builder CreateBuilder() { throw null; } + public static ImmutableArray.Builder CreateBuilder(int initialCapacity) { throw null; } + public static ImmutableArray CreateRange(Generic.IEnumerable items) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, Func selector) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, int start, int length, Func selector) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, Func selector, TArg arg) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, int start, int length, Func selector, TArg arg) { throw null; } + public static ImmutableArray ToImmutableArray(this Generic.IEnumerable items) { throw null; } + public static ImmutableArray ToImmutableArray(this ImmutableArray.Builder builder) { throw null; } + public static ImmutableArray ToImmutableArray(this ReadOnlySpan items) { throw null; } + public static ImmutableArray ToImmutableArray(this Span items) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableArray), "Create")] + public readonly partial struct ImmutableArray : Generic.IReadOnlyList, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection, Generic.IList, Generic.ICollection, IEquatable>, IList, ICollection, IStructuralComparable, IStructuralEquatable, IImmutableList + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly ImmutableArray Empty; + public bool IsDefault { get { throw null; } } + public bool IsDefaultOrEmpty { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public T this[int index] { get { throw null; } } + + public int Length { get { throw null; } } + + int Generic.ICollection.Count { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + T Generic.IList.this[int index] { get { throw null; } set { } } + + int Generic.IReadOnlyCollection.Count { get { throw null; } } + + T Generic.IReadOnlyList.this[int index] { get { throw null; } } + + int ICollection.Count { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public readonly ImmutableArray Add(T item) { throw null; } + public readonly ImmutableArray AddRange(T[] items, int length) { throw null; } + public readonly ImmutableArray AddRange(params T[] items) { throw null; } + public readonly ImmutableArray AddRange(Generic.IEnumerable items) { throw null; } + public readonly ImmutableArray AddRange(ImmutableArray items, int length) { throw null; } + public readonly ImmutableArray AddRange(ImmutableArray items) { throw null; } + public readonly ImmutableArray AddRange(params scoped ReadOnlySpan items) { throw null; } + public readonly ImmutableArray AddRange(TDerived[] items) where TDerived : T { throw null; } + public readonly ImmutableArray AddRange(ImmutableArray items) where TDerived : T { throw null; } + public readonly ImmutableArray As() where TOther : class { throw null; } + public readonly ReadOnlyMemory AsMemory() { throw null; } + public readonly ReadOnlySpan AsSpan() { throw null; } + public readonly ReadOnlySpan AsSpan(int start, int length) { throw null; } + public readonly ReadOnlySpan AsSpan(Range range) { throw null; } + public readonly ImmutableArray CastArray() where TOther : class { throw null; } + public static ImmutableArray CastUp(ImmutableArray items) where TDerived : class, T { throw null; } + public readonly ImmutableArray Clear() { throw null; } + public readonly bool Contains(T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly bool Contains(T item) { throw null; } + public readonly void CopyTo(T[] destination, int destinationIndex) { } + public readonly void CopyTo(T[] destination) { } + public readonly void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { } + public readonly void CopyTo(Span destination) { } + public readonly bool Equals(ImmutableArray other) { throw null; } + public override readonly bool Equals(object? obj) { throw null; } + public readonly Enumerator GetEnumerator() { throw null; } + public override readonly int GetHashCode() { throw null; } + public readonly int IndexOf(T item, int startIndex, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly int IndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly int IndexOf(T item, int startIndex, int count) { throw null; } + public readonly int IndexOf(T item, int startIndex) { throw null; } + public readonly int IndexOf(T item) { throw null; } + public readonly ImmutableArray Insert(int index, T item) { throw null; } + public readonly ImmutableArray InsertRange(int index, T[] items) { throw null; } + public readonly ImmutableArray InsertRange(int index, Generic.IEnumerable items) { throw null; } + public readonly ImmutableArray InsertRange(int index, ImmutableArray items) { throw null; } + public readonly ImmutableArray InsertRange(int index, params scoped ReadOnlySpan items) { throw null; } + public readonly ref readonly T ItemRef(int index) { throw null; } + public readonly int LastIndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly int LastIndexOf(T item, int startIndex, int count) { throw null; } + public readonly int LastIndexOf(T item, int startIndex) { throw null; } + public readonly int LastIndexOf(T item) { throw null; } + public readonly Generic.IEnumerable OfType() { throw null; } + public static bool operator ==(ImmutableArray left, ImmutableArray right) { throw null; } + public static bool operator ==(ImmutableArray? left, ImmutableArray? right) { throw null; } + public static bool operator !=(ImmutableArray left, ImmutableArray right) { throw null; } + public static bool operator !=(ImmutableArray? left, ImmutableArray? right) { throw null; } + public readonly ImmutableArray Remove(T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray Remove(T item) { throw null; } + public readonly ImmutableArray RemoveAll(Predicate match) { throw null; } + public readonly ImmutableArray RemoveAt(int index) { throw null; } + public readonly ImmutableArray RemoveRange(T[] items, Generic.IEqualityComparer? equalityComparer = null) { throw null; } + public readonly ImmutableArray RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray RemoveRange(Generic.IEnumerable items) { throw null; } + public readonly ImmutableArray RemoveRange(ImmutableArray items, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray RemoveRange(ImmutableArray items) { throw null; } + public readonly ImmutableArray RemoveRange(int index, int length) { throw null; } + public readonly ImmutableArray RemoveRange(ReadOnlySpan items, Generic.IEqualityComparer? equalityComparer = null) { throw null; } + public readonly ImmutableArray Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray Replace(T oldValue, T newValue) { throw null; } + public readonly ImmutableArray SetItem(int index, T item) { throw null; } + public readonly ImmutableArray Slice(int start, int length) { throw null; } + public readonly ImmutableArray Sort() { throw null; } + public readonly ImmutableArray Sort(Generic.IComparer? comparer) { throw null; } + public readonly ImmutableArray Sort(Comparison comparison) { throw null; } + public readonly ImmutableArray Sort(int index, int count, Generic.IComparer? comparer) { throw null; } + readonly void Generic.ICollection.Add(T item) { } + readonly void Generic.ICollection.Clear() { } + readonly bool Generic.ICollection.Remove(T item) { throw null; } + readonly Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + readonly void Generic.IList.Insert(int index, T item) { } + readonly void Generic.IList.RemoveAt(int index) { } + readonly void ICollection.CopyTo(Array array, int index) { } + readonly IEnumerator IEnumerable.GetEnumerator() { throw null; } + readonly int IList.Add(object value) { throw null; } + readonly void IList.Clear() { } + readonly bool IList.Contains(object value) { throw null; } + readonly int IList.IndexOf(object value) { throw null; } + readonly void IList.Insert(int index, object value) { } + readonly void IList.Remove(object value) { } + readonly void IList.RemoveAt(int index) { } + readonly IImmutableList IImmutableList.Add(T value) { throw null; } + readonly IImmutableList IImmutableList.AddRange(Generic.IEnumerable items) { throw null; } + readonly IImmutableList IImmutableList.Clear() { throw null; } + readonly IImmutableList IImmutableList.Insert(int index, T element) { throw null; } + readonly IImmutableList IImmutableList.InsertRange(int index, Generic.IEnumerable items) { throw null; } + readonly IImmutableList IImmutableList.Remove(T value, Generic.IEqualityComparer equalityComparer) { throw null; } + readonly IImmutableList IImmutableList.RemoveAll(Predicate match) { throw null; } + readonly IImmutableList IImmutableList.RemoveAt(int index) { throw null; } + readonly IImmutableList IImmutableList.RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer equalityComparer) { throw null; } + readonly IImmutableList IImmutableList.RemoveRange(int index, int count) { throw null; } + readonly IImmutableList IImmutableList.Replace(T oldValue, T newValue, Generic.IEqualityComparer equalityComparer) { throw null; } + readonly IImmutableList IImmutableList.SetItem(int index, T value) { throw null; } + readonly int IStructuralComparable.CompareTo(object other, IComparer comparer) { throw null; } + readonly bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) { throw null; } + readonly int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { throw null; } + public readonly Builder ToBuilder() { throw null; } + public sealed partial class Builder : Generic.IList, Generic.ICollection, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyList, Generic.IReadOnlyCollection + { + internal Builder() { } + public int Capacity { get { throw null; } set { } } + public int Count { get { throw null; } set { } } + + public T this[int index] { get { throw null; } set { } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + public void Add(T item) { } + public void AddRange(T[] items, int length) { } + public void AddRange(params T[] items) { } + public void AddRange(Generic.IEnumerable items) { } + public void AddRange(ImmutableArray items, int length) { } + public void AddRange(Builder items) { } + public void AddRange(ImmutableArray items) { } + public void AddRange(params scoped ReadOnlySpan items) { } + public void AddRange(TDerived[] items) where TDerived : T { } + public void AddRange(ImmutableArray.Builder items) where TDerived : T { } + public void AddRange(ImmutableArray items) where TDerived : T { } + public void AddRange(params scoped ReadOnlySpan items) where TDerived : T { } + public void Clear() { } + public bool Contains(T item) { throw null; } + public void CopyTo(T[] array, int index) { } + public void CopyTo(T[] destination) { } + public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { } + public void CopyTo(Span destination) { } + public ImmutableArray DrainToImmutable() { throw null; } + public Generic.IEnumerator GetEnumerator() { throw null; } + public int IndexOf(T item, int startIndex, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T item, int startIndex, int count) { throw null; } + public int IndexOf(T item, int startIndex) { throw null; } + public int IndexOf(T item) { throw null; } + public void Insert(int index, T item) { } + public void InsertRange(int index, Generic.IEnumerable items) { } + public void InsertRange(int index, ImmutableArray items) { } + public ref readonly T ItemRef(int index) { throw null; } + public int LastIndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int LastIndexOf(T item, int startIndex, int count) { throw null; } + public int LastIndexOf(T item, int startIndex) { throw null; } + public int LastIndexOf(T item) { throw null; } + public ImmutableArray MoveToImmutable() { throw null; } + public bool Remove(T element, Generic.IEqualityComparer? equalityComparer) { throw null; } + public bool Remove(T element) { throw null; } + public void RemoveAll(Predicate match) { } + public void RemoveAt(int index) { } + public void RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { } + public void RemoveRange(Generic.IEnumerable items) { } + public void RemoveRange(int index, int length) { } + public void Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { } + public void Replace(T oldValue, T newValue) { } + public void Reverse() { } + public void Sort() { } + public void Sort(Generic.IComparer? comparer) { } + public void Sort(Comparison comparison) { } + public void Sort(int index, int count, Generic.IComparer? comparer) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public T[] ToArray() { throw null; } + public ImmutableArray ToImmutable() { throw null; } + } + + public partial struct Enumerator + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + public bool MoveNext() { throw null; } + } + } + + public static partial class ImmutableDictionary + { + public static bool Contains(this IImmutableDictionary map, TKey key, TValue value) { throw null; } + public static ImmutableDictionary Create() { throw null; } + public static ImmutableDictionary Create(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary Create(Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary.Builder CreateBuilder() { throw null; } + public static ImmutableDictionary.Builder CreateBuilder(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary.Builder CreateBuilder(Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary CreateRange(Generic.IEnumerable> items) { throw null; } + public static ImmutableDictionary CreateRange(Generic.IEqualityComparer? keyComparer, Generic.IEnumerable> items) { throw null; } + public static ImmutableDictionary CreateRange(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer, Generic.IEnumerable> items) { throw null; } + public static TValue GetValueOrDefault(this IImmutableDictionary dictionary, TKey key, TValue defaultValue) { throw null; } + public static TValue? GetValueOrDefault(this IImmutableDictionary dictionary, TKey key) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable> source, Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable> source, Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable> source) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this ImmutableDictionary.Builder builder) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector) { throw null; } + } + public sealed partial class ImmutableDictionary : IImmutableDictionary, Generic.IReadOnlyDictionary, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyCollection>, Generic.IDictionary, Generic.ICollection>, IDictionary, ICollection + { + internal ImmutableDictionary() { } + public static readonly ImmutableDictionary Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } } + + public Generic.IEqualityComparer KeyComparer { get { throw null; } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + TValue Generic.IDictionary.this[TKey key] { get { throw null; } set { } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } } + public Generic.IEnumerable Values { get { throw null; } } + + public ImmutableDictionary Add(TKey key, TValue value) { throw null; } + public ImmutableDictionary AddRange(Generic.IEnumerable> pairs) { throw null; } + public ImmutableDictionary Clear() { throw null; } + public bool Contains(Generic.KeyValuePair pair) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ImmutableDictionary Remove(TKey key) { throw null; } + public ImmutableDictionary RemoveRange(Generic.IEnumerable keys) { throw null; } + public ImmutableDictionary SetItem(TKey key, TValue value) { throw null; } + public ImmutableDictionary SetItems(Generic.IEnumerable> items) { throw null; } + void Generic.ICollection>.Add(Generic.KeyValuePair item) { } + void Generic.ICollection>.Clear() { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + bool Generic.ICollection>.Remove(Generic.KeyValuePair item) { throw null; } + void Generic.IDictionary.Add(TKey key, TValue value) { } + bool Generic.IDictionary.Remove(TKey key) { throw null; } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + void IDictionary.Add(object key, object value) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.AddRange(Generic.IEnumerable> pairs) { throw null; } + IImmutableDictionary IImmutableDictionary.Clear() { throw null; } + IImmutableDictionary IImmutableDictionary.Remove(TKey key) { throw null; } + IImmutableDictionary IImmutableDictionary.RemoveRange(Generic.IEnumerable keys) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItems(Generic.IEnumerable> items) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public ImmutableDictionary WithComparers(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public ImmutableDictionary WithComparers(Generic.IEqualityComparer? keyComparer) { throw null; } + public sealed partial class Builder : Generic.IDictionary, Generic.ICollection>, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyDictionary, Generic.IReadOnlyCollection>, IDictionary, ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } set { } } + + public Generic.IEqualityComparer KeyComparer { get { throw null; } set { } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } set { } } + public Generic.IEnumerable Values { get { throw null; } } + + public void Add(TKey key, TValue value) { } + public void Add(Generic.KeyValuePair item) { } + public void AddRange(Generic.IEnumerable> items) { } + public void Clear() { } + public bool Contains(Generic.KeyValuePair item) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public TValue GetValueOrDefault(TKey key, TValue defaultValue) { throw null; } + public TValue? GetValueOrDefault(TKey key) { throw null; } + public bool Remove(TKey key) { throw null; } + public bool Remove(Generic.KeyValuePair item) { throw null; } + public void RemoveRange(Generic.IEnumerable keys) { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + void IDictionary.Add(object key, object value) { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableDictionary ToImmutable() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator>, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public Generic.KeyValuePair Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableHashSet + { + public static ImmutableHashSet Create() { throw null; } + public static ImmutableHashSet Create(T item) { throw null; } + public static ImmutableHashSet Create(params T[] items) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer, T item) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer, params T[] items) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer, params scoped ReadOnlySpan items) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer) { throw null; } + public static ImmutableHashSet Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableHashSet.Builder CreateBuilder() { throw null; } + public static ImmutableHashSet.Builder CreateBuilder(Generic.IEqualityComparer? equalityComparer) { throw null; } + public static ImmutableHashSet CreateRange(Generic.IEnumerable items) { throw null; } + public static ImmutableHashSet CreateRange(Generic.IEqualityComparer? equalityComparer, Generic.IEnumerable items) { throw null; } + public static ImmutableHashSet ToImmutableHashSet(this Generic.IEnumerable source, Generic.IEqualityComparer? equalityComparer) { throw null; } + public static ImmutableHashSet ToImmutableHashSet(this Generic.IEnumerable source) { throw null; } + public static ImmutableHashSet ToImmutableHashSet(this ImmutableHashSet.Builder builder) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableHashSet), "Create")] + public sealed partial class ImmutableHashSet : IImmutableSet, Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.ICollection, Generic.ISet, ICollection, Generic.IReadOnlySet + { + internal ImmutableHashSet() { } + public static readonly ImmutableHashSet Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + public Generic.IEqualityComparer KeyComparer { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + public ImmutableHashSet Add(T item) { throw null; } + public ImmutableHashSet Clear() { throw null; } + public bool Contains(T item) { throw null; } + public ImmutableHashSet Except(Generic.IEnumerable other) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ImmutableHashSet Intersect(Generic.IEnumerable other) { throw null; } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public ImmutableHashSet Remove(T item) { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public ImmutableHashSet SymmetricExcept(Generic.IEnumerable other) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + bool Generic.ISet.Add(T item) { throw null; } + void Generic.ISet.ExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.IntersectWith(Generic.IEnumerable other) { } + void Generic.ISet.SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.UnionWith(Generic.IEnumerable other) { } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableSet IImmutableSet.Add(T item) { throw null; } + IImmutableSet IImmutableSet.Clear() { throw null; } + IImmutableSet IImmutableSet.Except(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Intersect(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Remove(T item) { throw null; } + IImmutableSet IImmutableSet.SymmetricExcept(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Union(Generic.IEnumerable other) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public ImmutableHashSet Union(Generic.IEnumerable other) { throw null; } + public ImmutableHashSet WithComparer(Generic.IEqualityComparer? equalityComparer) { throw null; } + public sealed partial class Builder : Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.ISet, Generic.ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + public Generic.IEqualityComparer KeyComparer { get { throw null; } set { } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + public bool Add(T item) { throw null; } + public void Clear() { } + public bool Contains(T item) { throw null; } + public void ExceptWith(Generic.IEnumerable other) { } + public Enumerator GetEnumerator() { throw null; } + public void IntersectWith(Generic.IEnumerable other) { } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public bool Remove(T item) { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public void SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableHashSet ToImmutable() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public void UnionWith(Generic.IEnumerable other) { } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object? IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableInterlocked + { + public static TValue AddOrUpdate(ref ImmutableDictionary location, TKey key, TValue addValue, Func updateValueFactory) { throw null; } + public static TValue AddOrUpdate(ref ImmutableDictionary location, TKey key, Func addValueFactory, Func updateValueFactory) { throw null; } + public static void Enqueue(ref ImmutableQueue location, T value) { } + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, TValue value) { throw null; } + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory) { throw null; } + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory, TArg factoryArgument) { throw null; } + public static ImmutableArray InterlockedCompareExchange(ref ImmutableArray location, ImmutableArray value, ImmutableArray comparand) { throw null; } + public static ImmutableArray InterlockedExchange(ref ImmutableArray location, ImmutableArray value) { throw null; } + public static bool InterlockedInitialize(ref ImmutableArray location, ImmutableArray value) { throw null; } + public static void Push(ref ImmutableStack location, T value) { } + public static bool TryAdd(ref ImmutableDictionary location, TKey key, TValue value) { throw null; } + public static bool TryDequeue(ref ImmutableQueue location, out T value) { throw null; } + public static bool TryPop(ref ImmutableStack location, out T value) { throw null; } + public static bool TryRemove(ref ImmutableDictionary location, TKey key, out TValue value) { throw null; } + public static bool TryUpdate(ref ImmutableDictionary location, TKey key, TValue newValue, TValue comparisonValue) { throw null; } + public static bool Update(ref T location, Func transformer) where T : class { throw null; } + public static bool Update(ref ImmutableArray location, Func, ImmutableArray> transformer) { throw null; } + public static bool Update(ref T location, Func transformer, TArg transformerArgument) where T : class { throw null; } + public static bool Update(ref ImmutableArray location, Func, TArg, ImmutableArray> transformer, TArg transformerArgument) { throw null; } + } + public static partial class ImmutableList + { + public static ImmutableList Create() { throw null; } + public static ImmutableList Create(T item) { throw null; } + public static ImmutableList Create(params T[] items) { throw null; } + public static ImmutableList Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableList.Builder CreateBuilder() { throw null; } + public static ImmutableList CreateRange(Generic.IEnumerable items) { throw null; } + public static int IndexOf(this IImmutableList list, T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public static int IndexOf(this IImmutableList list, T item, int startIndex, int count) { throw null; } + public static int IndexOf(this IImmutableList list, T item, int startIndex) { throw null; } + public static int IndexOf(this IImmutableList list, T item) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item, int startIndex, int count) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item, int startIndex) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item) { throw null; } + public static IImmutableList Remove(this IImmutableList list, T value) { throw null; } + public static IImmutableList RemoveRange(this IImmutableList list, Generic.IEnumerable items) { throw null; } + public static IImmutableList Replace(this IImmutableList list, T oldValue, T newValue) { throw null; } + public static ImmutableList ToImmutableList(this Generic.IEnumerable source) { throw null; } + public static ImmutableList ToImmutableList(this ImmutableList.Builder builder) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableList), "Create")] + public sealed partial class ImmutableList : IImmutableList, Generic.IReadOnlyList, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection, Generic.IList, Generic.ICollection, IList, ICollection + { + internal ImmutableList() { } + public static readonly ImmutableList Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public T this[int index] { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + T Generic.IList.this[int index] { get { throw null; } set { } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public ImmutableList Add(T value) { throw null; } + public ImmutableList AddRange(Generic.IEnumerable items) { throw null; } + public int BinarySearch(T item, Generic.IComparer? comparer) { throw null; } + public int BinarySearch(T item) { throw null; } + public int BinarySearch(int index, int count, T item, Generic.IComparer? comparer) { throw null; } + public ImmutableList Clear() { throw null; } + public bool Contains(T value) { throw null; } + public ImmutableList ConvertAll(Func converter) { throw null; } + public void CopyTo(T[] array, int arrayIndex) { } + public void CopyTo(T[] array) { } + public void CopyTo(int index, T[] array, int arrayIndex, int count) { } + public bool Exists(Predicate match) { throw null; } + public T? Find(Predicate match) { throw null; } + public ImmutableList FindAll(Predicate match) { throw null; } + public int FindIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindIndex(int startIndex, Predicate match) { throw null; } + public int FindIndex(Predicate match) { throw null; } + public T? FindLast(Predicate match) { throw null; } + public int FindLastIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindLastIndex(int startIndex, Predicate match) { throw null; } + public int FindLastIndex(Predicate match) { throw null; } + public void ForEach(Action action) { } + public Enumerator GetEnumerator() { throw null; } + public ImmutableList GetRange(int index, int count) { throw null; } + public int IndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T value) { throw null; } + public ImmutableList Insert(int index, T item) { throw null; } + public ImmutableList InsertRange(int index, Generic.IEnumerable items) { throw null; } + public ref readonly T ItemRef(int index) { throw null; } + public int LastIndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList Remove(T value, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList Remove(T value) { throw null; } + public ImmutableList RemoveAll(Predicate match) { throw null; } + public ImmutableList RemoveAt(int index) { throw null; } + public ImmutableList RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList RemoveRange(Generic.IEnumerable items) { throw null; } + public ImmutableList RemoveRange(int index, int count) { throw null; } + public ImmutableList Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList Replace(T oldValue, T newValue) { throw null; } + public ImmutableList Reverse() { throw null; } + public ImmutableList Reverse(int index, int count) { throw null; } + public ImmutableList SetItem(int index, T value) { throw null; } + public ImmutableList Sort() { throw null; } + public ImmutableList Sort(Generic.IComparer? comparer) { throw null; } + public ImmutableList Sort(Comparison comparison) { throw null; } + public ImmutableList Sort(int index, int count, Generic.IComparer? comparer) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void Generic.IList.Insert(int index, T item) { } + void Generic.IList.RemoveAt(int index) { } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + int IList.Add(object value) { throw null; } + void IList.Clear() { } + bool IList.Contains(object value) { throw null; } + int IList.IndexOf(object value) { throw null; } + void IList.Insert(int index, object value) { } + void IList.Remove(object value) { } + void IList.RemoveAt(int index) { } + IImmutableList IImmutableList.Add(T value) { throw null; } + IImmutableList IImmutableList.AddRange(Generic.IEnumerable items) { throw null; } + IImmutableList IImmutableList.Clear() { throw null; } + IImmutableList IImmutableList.Insert(int index, T item) { throw null; } + IImmutableList IImmutableList.InsertRange(int index, Generic.IEnumerable items) { throw null; } + IImmutableList IImmutableList.Remove(T value, Generic.IEqualityComparer equalityComparer) { throw null; } + IImmutableList IImmutableList.RemoveAll(Predicate match) { throw null; } + IImmutableList IImmutableList.RemoveAt(int index) { throw null; } + IImmutableList IImmutableList.RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer equalityComparer) { throw null; } + IImmutableList IImmutableList.RemoveRange(int index, int count) { throw null; } + IImmutableList IImmutableList.Replace(T oldValue, T newValue, Generic.IEqualityComparer equalityComparer) { throw null; } + IImmutableList IImmutableList.SetItem(int index, T value) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TrueForAll(Predicate match) { throw null; } + public sealed partial class Builder : Generic.IList, Generic.ICollection, Generic.IEnumerable, IEnumerable, IList, ICollection, Generic.IReadOnlyList, Generic.IReadOnlyCollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public T this[int index] { get { throw null; } set { } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public void Add(T item) { } + public void AddRange(Generic.IEnumerable items) { } + public int BinarySearch(T item, Generic.IComparer? comparer) { throw null; } + public int BinarySearch(T item) { throw null; } + public int BinarySearch(int index, int count, T item, Generic.IComparer? comparer) { throw null; } + public void Clear() { } + public bool Contains(T item) { throw null; } + public ImmutableList ConvertAll(Func converter) { throw null; } + public void CopyTo(T[] array, int arrayIndex) { } + public void CopyTo(T[] array) { } + public void CopyTo(int index, T[] array, int arrayIndex, int count) { } + public bool Exists(Predicate match) { throw null; } + public T? Find(Predicate match) { throw null; } + public ImmutableList FindAll(Predicate match) { throw null; } + public int FindIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindIndex(int startIndex, Predicate match) { throw null; } + public int FindIndex(Predicate match) { throw null; } + public T? FindLast(Predicate match) { throw null; } + public int FindLastIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindLastIndex(int startIndex, Predicate match) { throw null; } + public int FindLastIndex(Predicate match) { throw null; } + public void ForEach(Action action) { } + public Enumerator GetEnumerator() { throw null; } + public ImmutableList GetRange(int index, int count) { throw null; } + public int IndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T item, int index, int count) { throw null; } + public int IndexOf(T item, int index) { throw null; } + public int IndexOf(T item) { throw null; } + public void Insert(int index, T item) { } + public void InsertRange(int index, Generic.IEnumerable items) { } + public ref readonly T ItemRef(int index) { throw null; } + public int LastIndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int LastIndexOf(T item, int startIndex, int count) { throw null; } + public int LastIndexOf(T item, int startIndex) { throw null; } + public int LastIndexOf(T item) { throw null; } + public bool Remove(T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public bool Remove(T item) { throw null; } + public int RemoveAll(Predicate match) { throw null; } + public void RemoveAt(int index) { } + public void RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { } + public void RemoveRange(Generic.IEnumerable items) { } + public void RemoveRange(int index, int count) { } + public void Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { } + public void Replace(T oldValue, T newValue) { } + public void Reverse() { } + public void Reverse(int index, int count) { } + public void Sort() { } + public void Sort(Generic.IComparer? comparer) { } + public void Sort(Comparison comparison) { } + public void Sort(int index, int count, Generic.IComparer? comparer) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + int IList.Add(object value) { throw null; } + void IList.Clear() { } + bool IList.Contains(object value) { throw null; } + int IList.IndexOf(object value) { throw null; } + void IList.Insert(int index, object value) { } + void IList.Remove(object value) { } + public ImmutableList ToImmutable() { throw null; } + public bool TrueForAll(Predicate match) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object? IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableQueue + { + public static ImmutableQueue Create() { throw null; } + public static ImmutableQueue Create(T item) { throw null; } + public static ImmutableQueue Create(params T[] items) { throw null; } + public static ImmutableQueue Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableQueue CreateRange(Generic.IEnumerable items) { throw null; } + public static IImmutableQueue Dequeue(this IImmutableQueue queue, out T value) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableQueue), "Create")] + public sealed partial class ImmutableQueue : IImmutableQueue, Generic.IEnumerable, IEnumerable + { + internal ImmutableQueue() { } + public static ImmutableQueue Empty { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public ImmutableQueue Clear() { throw null; } + public ImmutableQueue Dequeue() { throw null; } + public ImmutableQueue Dequeue(out T value) { throw null; } + public ImmutableQueue Enqueue(T value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public T Peek() { throw null; } + public ref readonly T PeekRef() { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableQueue IImmutableQueue.Clear() { throw null; } + IImmutableQueue IImmutableQueue.Dequeue() { throw null; } + IImmutableQueue IImmutableQueue.Enqueue(T value) { throw null; } + public partial struct Enumerator + { + private ImmutableQueue _originalQueue; + private ImmutableStack _remainingForwardsStack; + private ImmutableStack _remainingBackwardsStack; + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + public bool MoveNext() { throw null; } + } + } + + public static partial class ImmutableSortedDictionary + { + public static ImmutableSortedDictionary Create() { throw null; } + public static ImmutableSortedDictionary Create(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary Create(Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary.Builder CreateBuilder() { throw null; } + public static ImmutableSortedDictionary.Builder CreateBuilder(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary.Builder CreateBuilder(Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary CreateRange(Generic.IComparer? keyComparer, Generic.IEnumerable> items) { throw null; } + public static ImmutableSortedDictionary CreateRange(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer, Generic.IEnumerable> items) { throw null; } + public static ImmutableSortedDictionary CreateRange(Generic.IEnumerable> items) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable> source, Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable> source, Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable> source) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this ImmutableSortedDictionary.Builder builder) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector) { throw null; } + } + public sealed partial class ImmutableSortedDictionary : IImmutableDictionary, Generic.IReadOnlyDictionary, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyCollection>, Generic.IDictionary, Generic.ICollection>, IDictionary, ICollection + { + internal ImmutableSortedDictionary() { } + public static readonly ImmutableSortedDictionary Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } } + + public Generic.IComparer KeyComparer { get { throw null; } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + TValue Generic.IDictionary.this[TKey key] { get { throw null; } set { } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } } + public Generic.IEnumerable Values { get { throw null; } } + + public ImmutableSortedDictionary Add(TKey key, TValue value) { throw null; } + public ImmutableSortedDictionary AddRange(Generic.IEnumerable> items) { throw null; } + public ImmutableSortedDictionary Clear() { throw null; } + public bool Contains(Generic.KeyValuePair pair) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ImmutableSortedDictionary Remove(TKey value) { throw null; } + public ImmutableSortedDictionary RemoveRange(Generic.IEnumerable keys) { throw null; } + public ImmutableSortedDictionary SetItem(TKey key, TValue value) { throw null; } + public ImmutableSortedDictionary SetItems(Generic.IEnumerable> items) { throw null; } + void Generic.ICollection>.Add(Generic.KeyValuePair item) { } + void Generic.ICollection>.Clear() { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + bool Generic.ICollection>.Remove(Generic.KeyValuePair item) { throw null; } + void Generic.IDictionary.Add(TKey key, TValue value) { } + bool Generic.IDictionary.Remove(TKey key) { throw null; } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int index) { } + void IDictionary.Add(object key, object value) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.AddRange(Generic.IEnumerable> pairs) { throw null; } + IImmutableDictionary IImmutableDictionary.Clear() { throw null; } + IImmutableDictionary IImmutableDictionary.Remove(TKey key) { throw null; } + IImmutableDictionary IImmutableDictionary.RemoveRange(Generic.IEnumerable keys) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItems(Generic.IEnumerable> items) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public ref readonly TValue ValueRef(TKey key) { throw null; } + public ImmutableSortedDictionary WithComparers(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public ImmutableSortedDictionary WithComparers(Generic.IComparer? keyComparer) { throw null; } + public sealed partial class Builder : Generic.IDictionary, Generic.ICollection>, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyDictionary, Generic.IReadOnlyCollection>, IDictionary, ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } set { } } + + public Generic.IComparer KeyComparer { get { throw null; } set { } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } set { } } + public Generic.IEnumerable Values { get { throw null; } } + + public void Add(TKey key, TValue value) { } + public void Add(Generic.KeyValuePair item) { } + public void AddRange(Generic.IEnumerable> items) { } + public void Clear() { } + public bool Contains(Generic.KeyValuePair item) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public TValue GetValueOrDefault(TKey key, TValue defaultValue) { throw null; } + public TValue? GetValueOrDefault(TKey key) { throw null; } + public bool Remove(TKey key) { throw null; } + public bool Remove(Generic.KeyValuePair item) { throw null; } + public void RemoveRange(Generic.IEnumerable keys) { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int index) { } + void IDictionary.Add(object key, object value) { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableSortedDictionary ToImmutable() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public ref readonly TValue ValueRef(TKey key) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator>, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public Generic.KeyValuePair Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableSortedSet + { + public static ImmutableSortedSet Create() { throw null; } + public static ImmutableSortedSet Create(T item) { throw null; } + public static ImmutableSortedSet Create(params T[] items) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer, T item) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer, params T[] items) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer, params scoped ReadOnlySpan items) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer) { throw null; } + public static ImmutableSortedSet Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableSortedSet.Builder CreateBuilder() { throw null; } + public static ImmutableSortedSet.Builder CreateBuilder(Generic.IComparer? comparer) { throw null; } + public static ImmutableSortedSet CreateRange(Generic.IComparer? comparer, Generic.IEnumerable items) { throw null; } + public static ImmutableSortedSet CreateRange(Generic.IEnumerable items) { throw null; } + public static ImmutableSortedSet ToImmutableSortedSet(this Generic.IEnumerable source, Generic.IComparer? comparer) { throw null; } + public static ImmutableSortedSet ToImmutableSortedSet(this Generic.IEnumerable source) { throw null; } + public static ImmutableSortedSet ToImmutableSortedSet(this ImmutableSortedSet.Builder builder) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableSortedSet), "Create")] + public sealed partial class ImmutableSortedSet : IImmutableSet, Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.IReadOnlySet, Generic.IReadOnlyList, Generic.IList, Generic.ICollection, Generic.ISet, IList, ICollection + { + internal ImmutableSortedSet() { } + public static readonly ImmutableSortedSet Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public T this[int index] { get { throw null; } } + + public Generic.IComparer KeyComparer { get { throw null; } } + public T? Max { get { throw null; } } + public T? Min { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + T Generic.IList.this[int index] { get { throw null; } set { } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public ImmutableSortedSet Add(T value) { throw null; } + public ImmutableSortedSet Clear() { throw null; } + public bool Contains(T value) { throw null; } + public ImmutableSortedSet Except(Generic.IEnumerable other) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public int IndexOf(T item) { throw null; } + public ImmutableSortedSet Intersect(Generic.IEnumerable other) { throw null; } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public ref readonly T ItemRef(int index) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public ImmutableSortedSet Remove(T value) { throw null; } + public Generic.IEnumerable Reverse() { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public ImmutableSortedSet SymmetricExcept(Generic.IEnumerable other) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void Generic.IList.Insert(int index, T item) { } + void Generic.IList.RemoveAt(int index) { } + bool Generic.ISet.Add(T item) { throw null; } + void Generic.ISet.ExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.IntersectWith(Generic.IEnumerable other) { } + void Generic.ISet.SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.UnionWith(Generic.IEnumerable other) { } + void ICollection.CopyTo(Array array, int index) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + int IList.Add(object value) { throw null; } + void IList.Clear() { } + bool IList.Contains(object value) { throw null; } + int IList.IndexOf(object value) { throw null; } + void IList.Insert(int index, object value) { } + void IList.Remove(object value) { } + void IList.RemoveAt(int index) { } + IImmutableSet IImmutableSet.Add(T value) { throw null; } + IImmutableSet IImmutableSet.Clear() { throw null; } + IImmutableSet IImmutableSet.Except(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Intersect(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Remove(T value) { throw null; } + IImmutableSet IImmutableSet.SymmetricExcept(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Union(Generic.IEnumerable other) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public ImmutableSortedSet Union(Generic.IEnumerable other) { throw null; } + public ImmutableSortedSet WithComparer(Generic.IComparer? comparer) { throw null; } + public sealed partial class Builder : Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.ISet, Generic.ICollection, ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public T this[int index] { get { throw null; } } + + public Generic.IComparer KeyComparer { get { throw null; } set { } } + public T? Max { get { throw null; } } + public T? Min { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + public bool Add(T item) { throw null; } + public void Clear() { } + public bool Contains(T item) { throw null; } + public void ExceptWith(Generic.IEnumerable other) { } + public Enumerator GetEnumerator() { throw null; } + public int IndexOf(T item) { throw null; } + public void IntersectWith(Generic.IEnumerable other) { } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public ref readonly T ItemRef(int index) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public bool Remove(T item) { throw null; } + public Generic.IEnumerable Reverse() { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public void SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableSortedSet ToImmutable() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public void UnionWith(Generic.IEnumerable other) { } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object? IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableStack + { + public static ImmutableStack Create() { throw null; } + public static ImmutableStack Create(T item) { throw null; } + public static ImmutableStack Create(params T[] items) { throw null; } + public static ImmutableStack Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableStack CreateRange(Generic.IEnumerable items) { throw null; } + public static IImmutableStack Pop(this IImmutableStack stack, out T value) { throw null; } + } + [Runtime.CompilerServices.CollectionBuilder(typeof(ImmutableStack), "Create")] + public sealed partial class ImmutableStack : IImmutableStack, Generic.IEnumerable, IEnumerable + { + internal ImmutableStack() { } + public static ImmutableStack Empty { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public ImmutableStack Clear() { throw null; } + public Enumerator GetEnumerator() { throw null; } + public T Peek() { throw null; } + public ref readonly T PeekRef() { throw null; } + public ImmutableStack Pop() { throw null; } + public ImmutableStack Pop(out T value) { throw null; } + public ImmutableStack Push(T value) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableStack IImmutableStack.Clear() { throw null; } + IImmutableStack IImmutableStack.Pop() { throw null; } + IImmutableStack IImmutableStack.Push(T value) { throw null; } + public partial struct Enumerator + { + private ImmutableStack _originalStack; + private ImmutableStack _remainingStack; + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + public bool MoveNext() { throw null; } + } + } +} + +namespace System.Linq +{ + public static partial class ImmutableArrayExtensions + { + public static T? Aggregate(this Collections.Immutable.ImmutableArray immutableArray, Func func) { throw null; } + public static TAccumulate Aggregate(this Collections.Immutable.ImmutableArray immutableArray, TAccumulate seed, Func func) { throw null; } + public static TResult Aggregate(this Collections.Immutable.ImmutableArray immutableArray, TAccumulate seed, Func func, Func resultSelector) { throw null; } + public static bool All(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static bool Any(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static bool Any(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static bool Any(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T ElementAt(this Collections.Immutable.ImmutableArray immutableArray, int index) { throw null; } + public static T? ElementAtOrDefault(this Collections.Immutable.ImmutableArray immutableArray, int index) { throw null; } + public static T First(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T First(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T First(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T? FirstOrDefault(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T? FirstOrDefault(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T? FirstOrDefault(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T Last(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T Last(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T Last(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T? LastOrDefault(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T? LastOrDefault(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T? LastOrDefault(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static Collections.Generic.IEnumerable Select(this Collections.Immutable.ImmutableArray immutableArray, Func selector) { throw null; } + public static Collections.Generic.IEnumerable SelectMany(this Collections.Immutable.ImmutableArray immutableArray, Func> collectionSelector, Func resultSelector) { throw null; } + public static bool SequenceEqual(this Collections.Immutable.ImmutableArray immutableArray, Collections.Generic.IEnumerable items, Collections.Generic.IEqualityComparer? comparer = null) where TDerived : TBase { throw null; } + public static bool SequenceEqual(this Collections.Immutable.ImmutableArray immutableArray, Collections.Immutable.ImmutableArray items, Collections.Generic.IEqualityComparer? comparer = null) where TDerived : TBase { throw null; } + public static bool SequenceEqual(this Collections.Immutable.ImmutableArray immutableArray, Collections.Immutable.ImmutableArray items, Func predicate) where TDerived : TBase { throw null; } + public static T Single(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T Single(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T? SingleOrDefault(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T? SingleOrDefault(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T[] ToArray(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector, Collections.Generic.IEqualityComparer? comparer) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector, Func elementSelector, Collections.Generic.IEqualityComparer? comparer) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector, Func elementSelector) { throw null; } + public static Collections.Generic.IEnumerable Where(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + } +} + +namespace System.Runtime.InteropServices +{ + public static partial class ImmutableCollectionsMarshal + { + public static T[]? AsArray(Collections.Immutable.ImmutableArray array) { throw null; } + public static Collections.Immutable.ImmutableArray AsImmutableArray(T[]? array) { throw null; } + } +} \ No newline at end of file diff --git a/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/lib/netstandard2.0/System.Collections.Immutable.cs b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/lib/netstandard2.0/System.Collections.Immutable.cs new file mode 100644 index 00000000000..a56a8835078 --- /dev/null +++ b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/lib/netstandard2.0/System.Collections.Immutable.cs @@ -0,0 +1,1443 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the http://aka.ms/api-review process. +// ------------------------------------------------------------------------------ +[assembly: System.Runtime.CompilerServices.CompilationRelaxations(8)] +[assembly: System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = true)] +[assembly: System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Collections.Immutable.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")] +[assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] +[assembly: System.Reflection.AssemblyMetadata("Serviceable", "True")] +[assembly: System.Reflection.AssemblyMetadata("PreferInbox", "True")] +[assembly: System.Reflection.AssemblyDefaultAlias("System.Collections.Immutable")] +[assembly: System.Resources.NeutralResourcesLanguage("en-US")] +[assembly: System.CLSCompliant(true)] +[assembly: System.Reflection.AssemblyMetadata("IsTrimmable", "True")] +[assembly: System.Runtime.InteropServices.DefaultDllImportSearchPaths(System.Runtime.InteropServices.DllImportSearchPath.AssemblyDirectory | System.Runtime.InteropServices.DllImportSearchPath.System32)] +[assembly: System.Reflection.AssemblyCompany("Microsoft Corporation")] +[assembly: System.Reflection.AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: System.Reflection.AssemblyDescription("This package provides collections that are thread safe and guaranteed to never change their contents, also known as immutable collections. Like strings, any methods that perform modifications will not change the existing instance but instead return a new instance. For efficiency reasons, the implementation uses a sharing mechanism to ensure that newly created instances share as much data as possible with the previous instance while ensuring that operations have a predictable time complexity.\r\n\r\nThe System.Collections.Immutable library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks.")] +[assembly: System.Reflection.AssemblyFileVersion("9.0.24.52809")] +[assembly: System.Reflection.AssemblyInformationalVersion("9.0.0+9d5a6a9aa463d6d10b0b0ba6d5982cc82f363dc3")] +[assembly: System.Reflection.AssemblyProduct("Microsoft® .NET")] +[assembly: System.Reflection.AssemblyTitle("System.Collections.Immutable")] +[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")] +[assembly: System.Reflection.AssemblyVersionAttribute("9.0.0.0")] +[assembly: System.Runtime.CompilerServices.ReferenceAssembly] +[assembly: System.Reflection.AssemblyFlagsAttribute((System.Reflection.AssemblyNameFlags)0x70)] +namespace System.Collections.Frozen +{ + public static partial class FrozenDictionary + { + public static FrozenDictionary ToFrozenDictionary(this Generic.IEnumerable source, Func keySelector, Generic.IEqualityComparer? comparer = null) { throw null; } + public static FrozenDictionary ToFrozenDictionary(this Generic.IEnumerable> source, Generic.IEqualityComparer? comparer = null) { throw null; } + public static FrozenDictionary ToFrozenDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IEqualityComparer? comparer = null) { throw null; } + } + public abstract partial class FrozenDictionary : Generic.IDictionary, Generic.ICollection>, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyDictionary, Generic.IReadOnlyCollection>, IDictionary, ICollection + { + internal FrozenDictionary() { } + public Generic.IEqualityComparer Comparer { get { throw null; } } + public int Count { get { throw null; } } + public static FrozenDictionary Empty { get { throw null; } } + + public ref readonly TValue this[TKey key] { get { throw null; } } + + public Immutable.ImmutableArray Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + TValue Generic.IDictionary.this[TKey key] { get { throw null; } set { } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + TValue Generic.IReadOnlyDictionary.this[TKey key] { get { throw null; } } + + Generic.IEnumerable Generic.IReadOnlyDictionary.Keys { get { throw null; } } + + Generic.IEnumerable Generic.IReadOnlyDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Immutable.ImmutableArray Values { get { throw null; } } + + public bool ContainsKey(TKey key) { throw null; } + public void CopyTo(Generic.KeyValuePair[] destination, int destinationIndex) { } + public void CopyTo(Span> destination) { } + public Enumerator GetEnumerator() { throw null; } + public ref readonly TValue GetValueRefOrNullRef(TKey key) { throw null; } + void Generic.ICollection>.Add(Generic.KeyValuePair item) { } + void Generic.ICollection>.Clear() { } + bool Generic.ICollection>.Contains(Generic.KeyValuePair item) { throw null; } + bool Generic.ICollection>.Remove(Generic.KeyValuePair item) { throw null; } + void Generic.IDictionary.Add(TKey key, TValue value) { } + bool Generic.IDictionary.Remove(TKey key) { throw null; } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int index) { } + void IDictionary.Add(object key, object value) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public partial struct Enumerator : Generic.IEnumerator>, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public Generic.KeyValuePair Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public bool MoveNext() { throw null; } + void IEnumerator.Reset() { } + void IDisposable.Dispose() { } + } + } + + public static partial class FrozenSet + { + public static FrozenSet Create(Generic.IEqualityComparer? equalityComparer, params scoped ReadOnlySpan source) { throw null; } + public static FrozenSet Create(params scoped ReadOnlySpan source) { throw null; } + public static FrozenSet ToFrozenSet(this Generic.IEnumerable source, Generic.IEqualityComparer? comparer = null) { throw null; } + } + public abstract partial class FrozenSet : Generic.ISet, Generic.ICollection, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection, ICollection + { + internal FrozenSet() { } + public Generic.IEqualityComparer Comparer { get { throw null; } } + public int Count { get { throw null; } } + public static FrozenSet Empty { get { throw null; } } + public Immutable.ImmutableArray Items { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + public bool Contains(T item) { throw null; } + public void CopyTo(T[] destination, int destinationIndex) { } + public void CopyTo(Span destination) { } + public Enumerator GetEnumerator() { throw null; } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + bool Generic.ISet.Add(T item) { throw null; } + void Generic.ISet.ExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.IntersectWith(Generic.IEnumerable other) { } + void Generic.ISet.SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.UnionWith(Generic.IEnumerable other) { } + void ICollection.CopyTo(Array array, int index) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public bool MoveNext() { throw null; } + void IEnumerator.Reset() { } + void IDisposable.Dispose() { } + } + } +} + +namespace System.Collections.Immutable +{ + public partial interface IImmutableDictionary : Generic.IReadOnlyDictionary, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyCollection> + { + IImmutableDictionary Add(TKey key, TValue value); + IImmutableDictionary AddRange(Generic.IEnumerable> pairs); + IImmutableDictionary Clear(); + bool Contains(Generic.KeyValuePair pair); + IImmutableDictionary Remove(TKey key); + IImmutableDictionary RemoveRange(Generic.IEnumerable keys); + IImmutableDictionary SetItem(TKey key, TValue value); + IImmutableDictionary SetItems(Generic.IEnumerable> items); + bool TryGetKey(TKey equalKey, out TKey actualKey); + } + + public partial interface IImmutableList : Generic.IReadOnlyList, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection + { + IImmutableList Add(T value); + IImmutableList AddRange(Generic.IEnumerable items); + IImmutableList Clear(); + int IndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer); + IImmutableList Insert(int index, T element); + IImmutableList InsertRange(int index, Generic.IEnumerable items); + int LastIndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer); + IImmutableList Remove(T value, Generic.IEqualityComparer? equalityComparer); + IImmutableList RemoveAll(Predicate match); + IImmutableList RemoveAt(int index); + IImmutableList RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer); + IImmutableList RemoveRange(int index, int count); + IImmutableList Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer); + IImmutableList SetItem(int index, T value); + } + + public partial interface IImmutableQueue : Generic.IEnumerable, IEnumerable + { + bool IsEmpty { get; } + + IImmutableQueue Clear(); + IImmutableQueue Dequeue(); + IImmutableQueue Enqueue(T value); + T Peek(); + } + + public partial interface IImmutableSet : Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable + { + IImmutableSet Add(T value); + IImmutableSet Clear(); + bool Contains(T value); + IImmutableSet Except(Generic.IEnumerable other); + IImmutableSet Intersect(Generic.IEnumerable other); + bool IsProperSubsetOf(Generic.IEnumerable other); + bool IsProperSupersetOf(Generic.IEnumerable other); + bool IsSubsetOf(Generic.IEnumerable other); + bool IsSupersetOf(Generic.IEnumerable other); + bool Overlaps(Generic.IEnumerable other); + IImmutableSet Remove(T value); + bool SetEquals(Generic.IEnumerable other); + IImmutableSet SymmetricExcept(Generic.IEnumerable other); + bool TryGetValue(T equalValue, out T actualValue); + IImmutableSet Union(Generic.IEnumerable other); + } + + public partial interface IImmutableStack : Generic.IEnumerable, IEnumerable + { + bool IsEmpty { get; } + + IImmutableStack Clear(); + T Peek(); + IImmutableStack Pop(); + IImmutableStack Push(T value); + } + + public static partial class ImmutableArray + { + public static int BinarySearch(this ImmutableArray array, T value, Generic.IComparer? comparer) { throw null; } + public static int BinarySearch(this ImmutableArray array, T value) { throw null; } + public static int BinarySearch(this ImmutableArray array, int index, int length, T value, Generic.IComparer? comparer) { throw null; } + public static int BinarySearch(this ImmutableArray array, int index, int length, T value) { throw null; } + public static ImmutableArray Create() { throw null; } + public static ImmutableArray Create(T item1, T item2, T item3, T item4) { throw null; } + public static ImmutableArray Create(T item1, T item2, T item3) { throw null; } + public static ImmutableArray Create(T item1, T item2) { throw null; } + public static ImmutableArray Create(T item) { throw null; } + public static ImmutableArray Create(T[] items, int start, int length) { throw null; } + public static ImmutableArray Create(params T[]? items) { throw null; } + public static ImmutableArray Create(ImmutableArray items, int start, int length) { throw null; } + public static ImmutableArray Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableArray Create(Span items) { throw null; } + public static ImmutableArray.Builder CreateBuilder() { throw null; } + public static ImmutableArray.Builder CreateBuilder(int initialCapacity) { throw null; } + public static ImmutableArray CreateRange(Generic.IEnumerable items) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, Func selector) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, int start, int length, Func selector) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, Func selector, TArg arg) { throw null; } + public static ImmutableArray CreateRange(ImmutableArray items, int start, int length, Func selector, TArg arg) { throw null; } + public static ImmutableArray ToImmutableArray(this Generic.IEnumerable items) { throw null; } + public static ImmutableArray ToImmutableArray(this ImmutableArray.Builder builder) { throw null; } + public static ImmutableArray ToImmutableArray(this ReadOnlySpan items) { throw null; } + public static ImmutableArray ToImmutableArray(this Span items) { throw null; } + } + public readonly partial struct ImmutableArray : Generic.IReadOnlyList, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection, Generic.IList, Generic.ICollection, IEquatable>, IList, ICollection, IStructuralComparable, IStructuralEquatable, IImmutableList + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly ImmutableArray Empty; + public bool IsDefault { get { throw null; } } + public bool IsDefaultOrEmpty { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public T this[int index] { get { throw null; } } + + public int Length { get { throw null; } } + + int Generic.ICollection.Count { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + T Generic.IList.this[int index] { get { throw null; } set { } } + + int Generic.IReadOnlyCollection.Count { get { throw null; } } + + T Generic.IReadOnlyList.this[int index] { get { throw null; } } + + int ICollection.Count { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public readonly ImmutableArray Add(T item) { throw null; } + public readonly ImmutableArray AddRange(T[] items, int length) { throw null; } + public readonly ImmutableArray AddRange(params T[] items) { throw null; } + public readonly ImmutableArray AddRange(Generic.IEnumerable items) { throw null; } + public readonly ImmutableArray AddRange(ImmutableArray items, int length) { throw null; } + public readonly ImmutableArray AddRange(ImmutableArray items) { throw null; } + public readonly ImmutableArray AddRange(params scoped ReadOnlySpan items) { throw null; } + public readonly ImmutableArray AddRange(TDerived[] items) where TDerived : T { throw null; } + public readonly ImmutableArray AddRange(ImmutableArray items) where TDerived : T { throw null; } + public readonly ImmutableArray As() where TOther : class { throw null; } + public readonly ReadOnlyMemory AsMemory() { throw null; } + public readonly ReadOnlySpan AsSpan() { throw null; } + public readonly ReadOnlySpan AsSpan(int start, int length) { throw null; } + public readonly ImmutableArray CastArray() where TOther : class { throw null; } + public static ImmutableArray CastUp(ImmutableArray items) where TDerived : class, T { throw null; } + public readonly ImmutableArray Clear() { throw null; } + public readonly bool Contains(T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly bool Contains(T item) { throw null; } + public readonly void CopyTo(T[] destination, int destinationIndex) { } + public readonly void CopyTo(T[] destination) { } + public readonly void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { } + public readonly void CopyTo(Span destination) { } + public readonly bool Equals(ImmutableArray other) { throw null; } + public override readonly bool Equals(object? obj) { throw null; } + public readonly Enumerator GetEnumerator() { throw null; } + public override readonly int GetHashCode() { throw null; } + public readonly int IndexOf(T item, int startIndex, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly int IndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly int IndexOf(T item, int startIndex, int count) { throw null; } + public readonly int IndexOf(T item, int startIndex) { throw null; } + public readonly int IndexOf(T item) { throw null; } + public readonly ImmutableArray Insert(int index, T item) { throw null; } + public readonly ImmutableArray InsertRange(int index, T[] items) { throw null; } + public readonly ImmutableArray InsertRange(int index, Generic.IEnumerable items) { throw null; } + public readonly ImmutableArray InsertRange(int index, ImmutableArray items) { throw null; } + public readonly ImmutableArray InsertRange(int index, params scoped ReadOnlySpan items) { throw null; } + public readonly ref readonly T ItemRef(int index) { throw null; } + public readonly int LastIndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly int LastIndexOf(T item, int startIndex, int count) { throw null; } + public readonly int LastIndexOf(T item, int startIndex) { throw null; } + public readonly int LastIndexOf(T item) { throw null; } + public readonly Generic.IEnumerable OfType() { throw null; } + public static bool operator ==(ImmutableArray left, ImmutableArray right) { throw null; } + public static bool operator ==(ImmutableArray? left, ImmutableArray? right) { throw null; } + public static bool operator !=(ImmutableArray left, ImmutableArray right) { throw null; } + public static bool operator !=(ImmutableArray? left, ImmutableArray? right) { throw null; } + public readonly ImmutableArray Remove(T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray Remove(T item) { throw null; } + public readonly ImmutableArray RemoveAll(Predicate match) { throw null; } + public readonly ImmutableArray RemoveAt(int index) { throw null; } + public readonly ImmutableArray RemoveRange(T[] items, Generic.IEqualityComparer? equalityComparer = null) { throw null; } + public readonly ImmutableArray RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray RemoveRange(Generic.IEnumerable items) { throw null; } + public readonly ImmutableArray RemoveRange(ImmutableArray items, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray RemoveRange(ImmutableArray items) { throw null; } + public readonly ImmutableArray RemoveRange(int index, int length) { throw null; } + public readonly ImmutableArray RemoveRange(ReadOnlySpan items, Generic.IEqualityComparer? equalityComparer = null) { throw null; } + public readonly ImmutableArray Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { throw null; } + public readonly ImmutableArray Replace(T oldValue, T newValue) { throw null; } + public readonly ImmutableArray SetItem(int index, T item) { throw null; } + public readonly ImmutableArray Slice(int start, int length) { throw null; } + public readonly ImmutableArray Sort() { throw null; } + public readonly ImmutableArray Sort(Generic.IComparer? comparer) { throw null; } + public readonly ImmutableArray Sort(Comparison comparison) { throw null; } + public readonly ImmutableArray Sort(int index, int count, Generic.IComparer? comparer) { throw null; } + readonly void Generic.ICollection.Add(T item) { } + readonly void Generic.ICollection.Clear() { } + readonly bool Generic.ICollection.Remove(T item) { throw null; } + readonly Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + readonly void Generic.IList.Insert(int index, T item) { } + readonly void Generic.IList.RemoveAt(int index) { } + readonly void ICollection.CopyTo(Array array, int index) { } + readonly IEnumerator IEnumerable.GetEnumerator() { throw null; } + readonly int IList.Add(object value) { throw null; } + readonly void IList.Clear() { } + readonly bool IList.Contains(object value) { throw null; } + readonly int IList.IndexOf(object value) { throw null; } + readonly void IList.Insert(int index, object value) { } + readonly void IList.Remove(object value) { } + readonly void IList.RemoveAt(int index) { } + readonly IImmutableList IImmutableList.Add(T value) { throw null; } + readonly IImmutableList IImmutableList.AddRange(Generic.IEnumerable items) { throw null; } + readonly IImmutableList IImmutableList.Clear() { throw null; } + readonly IImmutableList IImmutableList.Insert(int index, T element) { throw null; } + readonly IImmutableList IImmutableList.InsertRange(int index, Generic.IEnumerable items) { throw null; } + readonly IImmutableList IImmutableList.Remove(T value, Generic.IEqualityComparer equalityComparer) { throw null; } + readonly IImmutableList IImmutableList.RemoveAll(Predicate match) { throw null; } + readonly IImmutableList IImmutableList.RemoveAt(int index) { throw null; } + readonly IImmutableList IImmutableList.RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer equalityComparer) { throw null; } + readonly IImmutableList IImmutableList.RemoveRange(int index, int count) { throw null; } + readonly IImmutableList IImmutableList.Replace(T oldValue, T newValue, Generic.IEqualityComparer equalityComparer) { throw null; } + readonly IImmutableList IImmutableList.SetItem(int index, T value) { throw null; } + readonly int IStructuralComparable.CompareTo(object other, IComparer comparer) { throw null; } + readonly bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) { throw null; } + readonly int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { throw null; } + public readonly Builder ToBuilder() { throw null; } + public sealed partial class Builder : Generic.IList, Generic.ICollection, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyList, Generic.IReadOnlyCollection + { + internal Builder() { } + public int Capacity { get { throw null; } set { } } + public int Count { get { throw null; } set { } } + + public T this[int index] { get { throw null; } set { } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + public void Add(T item) { } + public void AddRange(T[] items, int length) { } + public void AddRange(params T[] items) { } + public void AddRange(Generic.IEnumerable items) { } + public void AddRange(ImmutableArray items, int length) { } + public void AddRange(Builder items) { } + public void AddRange(ImmutableArray items) { } + public void AddRange(params scoped ReadOnlySpan items) { } + public void AddRange(TDerived[] items) where TDerived : T { } + public void AddRange(ImmutableArray.Builder items) where TDerived : T { } + public void AddRange(ImmutableArray items) where TDerived : T { } + public void AddRange(params scoped ReadOnlySpan items) where TDerived : T { } + public void Clear() { } + public bool Contains(T item) { throw null; } + public void CopyTo(T[] array, int index) { } + public void CopyTo(T[] destination) { } + public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { } + public void CopyTo(Span destination) { } + public ImmutableArray DrainToImmutable() { throw null; } + public Generic.IEnumerator GetEnumerator() { throw null; } + public int IndexOf(T item, int startIndex, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T item, int startIndex, int count) { throw null; } + public int IndexOf(T item, int startIndex) { throw null; } + public int IndexOf(T item) { throw null; } + public void Insert(int index, T item) { } + public void InsertRange(int index, Generic.IEnumerable items) { } + public void InsertRange(int index, ImmutableArray items) { } + public ref readonly T ItemRef(int index) { throw null; } + public int LastIndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int LastIndexOf(T item, int startIndex, int count) { throw null; } + public int LastIndexOf(T item, int startIndex) { throw null; } + public int LastIndexOf(T item) { throw null; } + public ImmutableArray MoveToImmutable() { throw null; } + public bool Remove(T element, Generic.IEqualityComparer? equalityComparer) { throw null; } + public bool Remove(T element) { throw null; } + public void RemoveAll(Predicate match) { } + public void RemoveAt(int index) { } + public void RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { } + public void RemoveRange(Generic.IEnumerable items) { } + public void RemoveRange(int index, int length) { } + public void Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { } + public void Replace(T oldValue, T newValue) { } + public void Reverse() { } + public void Sort() { } + public void Sort(Generic.IComparer? comparer) { } + public void Sort(Comparison comparison) { } + public void Sort(int index, int count, Generic.IComparer? comparer) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public T[] ToArray() { throw null; } + public ImmutableArray ToImmutable() { throw null; } + } + + public partial struct Enumerator + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + public bool MoveNext() { throw null; } + } + } + + public static partial class ImmutableDictionary + { + public static bool Contains(this IImmutableDictionary map, TKey key, TValue value) { throw null; } + public static ImmutableDictionary Create() { throw null; } + public static ImmutableDictionary Create(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary Create(Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary.Builder CreateBuilder() { throw null; } + public static ImmutableDictionary.Builder CreateBuilder(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary.Builder CreateBuilder(Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary CreateRange(Generic.IEnumerable> items) { throw null; } + public static ImmutableDictionary CreateRange(Generic.IEqualityComparer? keyComparer, Generic.IEnumerable> items) { throw null; } + public static ImmutableDictionary CreateRange(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer, Generic.IEnumerable> items) { throw null; } + public static TValue GetValueOrDefault(this IImmutableDictionary dictionary, TKey key, TValue defaultValue) { throw null; } + public static TValue? GetValueOrDefault(this IImmutableDictionary dictionary, TKey key) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable> source, Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable> source, Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable> source) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this ImmutableDictionary.Builder builder) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IEqualityComparer? keyComparer) { throw null; } + public static ImmutableDictionary ToImmutableDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector) { throw null; } + } + public sealed partial class ImmutableDictionary : IImmutableDictionary, Generic.IReadOnlyDictionary, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyCollection>, Generic.IDictionary, Generic.ICollection>, IDictionary, ICollection + { + internal ImmutableDictionary() { } + public static readonly ImmutableDictionary Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } } + + public Generic.IEqualityComparer KeyComparer { get { throw null; } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + TValue Generic.IDictionary.this[TKey key] { get { throw null; } set { } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } } + public Generic.IEnumerable Values { get { throw null; } } + + public ImmutableDictionary Add(TKey key, TValue value) { throw null; } + public ImmutableDictionary AddRange(Generic.IEnumerable> pairs) { throw null; } + public ImmutableDictionary Clear() { throw null; } + public bool Contains(Generic.KeyValuePair pair) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ImmutableDictionary Remove(TKey key) { throw null; } + public ImmutableDictionary RemoveRange(Generic.IEnumerable keys) { throw null; } + public ImmutableDictionary SetItem(TKey key, TValue value) { throw null; } + public ImmutableDictionary SetItems(Generic.IEnumerable> items) { throw null; } + void Generic.ICollection>.Add(Generic.KeyValuePair item) { } + void Generic.ICollection>.Clear() { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + bool Generic.ICollection>.Remove(Generic.KeyValuePair item) { throw null; } + void Generic.IDictionary.Add(TKey key, TValue value) { } + bool Generic.IDictionary.Remove(TKey key) { throw null; } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + void IDictionary.Add(object key, object value) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.AddRange(Generic.IEnumerable> pairs) { throw null; } + IImmutableDictionary IImmutableDictionary.Clear() { throw null; } + IImmutableDictionary IImmutableDictionary.Remove(TKey key) { throw null; } + IImmutableDictionary IImmutableDictionary.RemoveRange(Generic.IEnumerable keys) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItems(Generic.IEnumerable> items) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public ImmutableDictionary WithComparers(Generic.IEqualityComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public ImmutableDictionary WithComparers(Generic.IEqualityComparer? keyComparer) { throw null; } + public sealed partial class Builder : Generic.IDictionary, Generic.ICollection>, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyDictionary, Generic.IReadOnlyCollection>, IDictionary, ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } set { } } + + public Generic.IEqualityComparer KeyComparer { get { throw null; } set { } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } set { } } + public Generic.IEnumerable Values { get { throw null; } } + + public void Add(TKey key, TValue value) { } + public void Add(Generic.KeyValuePair item) { } + public void AddRange(Generic.IEnumerable> items) { } + public void Clear() { } + public bool Contains(Generic.KeyValuePair item) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public TValue GetValueOrDefault(TKey key, TValue defaultValue) { throw null; } + public TValue? GetValueOrDefault(TKey key) { throw null; } + public bool Remove(TKey key) { throw null; } + public bool Remove(Generic.KeyValuePair item) { throw null; } + public void RemoveRange(Generic.IEnumerable keys) { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + void IDictionary.Add(object key, object value) { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableDictionary ToImmutable() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator>, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public Generic.KeyValuePair Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableHashSet + { + public static ImmutableHashSet Create() { throw null; } + public static ImmutableHashSet Create(T item) { throw null; } + public static ImmutableHashSet Create(params T[] items) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer, T item) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer, params T[] items) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer, params scoped ReadOnlySpan items) { throw null; } + public static ImmutableHashSet Create(Generic.IEqualityComparer? equalityComparer) { throw null; } + public static ImmutableHashSet Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableHashSet.Builder CreateBuilder() { throw null; } + public static ImmutableHashSet.Builder CreateBuilder(Generic.IEqualityComparer? equalityComparer) { throw null; } + public static ImmutableHashSet CreateRange(Generic.IEnumerable items) { throw null; } + public static ImmutableHashSet CreateRange(Generic.IEqualityComparer? equalityComparer, Generic.IEnumerable items) { throw null; } + public static ImmutableHashSet ToImmutableHashSet(this Generic.IEnumerable source, Generic.IEqualityComparer? equalityComparer) { throw null; } + public static ImmutableHashSet ToImmutableHashSet(this Generic.IEnumerable source) { throw null; } + public static ImmutableHashSet ToImmutableHashSet(this ImmutableHashSet.Builder builder) { throw null; } + } + public sealed partial class ImmutableHashSet : IImmutableSet, Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.ICollection, Generic.ISet, ICollection + { + internal ImmutableHashSet() { } + public static readonly ImmutableHashSet Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + public Generic.IEqualityComparer KeyComparer { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + public ImmutableHashSet Add(T item) { throw null; } + public ImmutableHashSet Clear() { throw null; } + public bool Contains(T item) { throw null; } + public ImmutableHashSet Except(Generic.IEnumerable other) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ImmutableHashSet Intersect(Generic.IEnumerable other) { throw null; } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public ImmutableHashSet Remove(T item) { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public ImmutableHashSet SymmetricExcept(Generic.IEnumerable other) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + bool Generic.ISet.Add(T item) { throw null; } + void Generic.ISet.ExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.IntersectWith(Generic.IEnumerable other) { } + void Generic.ISet.SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.UnionWith(Generic.IEnumerable other) { } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableSet IImmutableSet.Add(T item) { throw null; } + IImmutableSet IImmutableSet.Clear() { throw null; } + IImmutableSet IImmutableSet.Except(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Intersect(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Remove(T item) { throw null; } + IImmutableSet IImmutableSet.SymmetricExcept(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Union(Generic.IEnumerable other) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public ImmutableHashSet Union(Generic.IEnumerable other) { throw null; } + public ImmutableHashSet WithComparer(Generic.IEqualityComparer? equalityComparer) { throw null; } + public sealed partial class Builder : Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.ISet, Generic.ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + public Generic.IEqualityComparer KeyComparer { get { throw null; } set { } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + public bool Add(T item) { throw null; } + public void Clear() { } + public bool Contains(T item) { throw null; } + public void ExceptWith(Generic.IEnumerable other) { } + public Enumerator GetEnumerator() { throw null; } + public void IntersectWith(Generic.IEnumerable other) { } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public bool Remove(T item) { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public void SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableHashSet ToImmutable() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public void UnionWith(Generic.IEnumerable other) { } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object? IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableInterlocked + { + public static TValue AddOrUpdate(ref ImmutableDictionary location, TKey key, TValue addValue, Func updateValueFactory) { throw null; } + public static TValue AddOrUpdate(ref ImmutableDictionary location, TKey key, Func addValueFactory, Func updateValueFactory) { throw null; } + public static void Enqueue(ref ImmutableQueue location, T value) { } + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, TValue value) { throw null; } + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory) { throw null; } + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory, TArg factoryArgument) { throw null; } + public static ImmutableArray InterlockedCompareExchange(ref ImmutableArray location, ImmutableArray value, ImmutableArray comparand) { throw null; } + public static ImmutableArray InterlockedExchange(ref ImmutableArray location, ImmutableArray value) { throw null; } + public static bool InterlockedInitialize(ref ImmutableArray location, ImmutableArray value) { throw null; } + public static void Push(ref ImmutableStack location, T value) { } + public static bool TryAdd(ref ImmutableDictionary location, TKey key, TValue value) { throw null; } + public static bool TryDequeue(ref ImmutableQueue location, out T value) { throw null; } + public static bool TryPop(ref ImmutableStack location, out T value) { throw null; } + public static bool TryRemove(ref ImmutableDictionary location, TKey key, out TValue value) { throw null; } + public static bool TryUpdate(ref ImmutableDictionary location, TKey key, TValue newValue, TValue comparisonValue) { throw null; } + public static bool Update(ref T location, Func transformer) where T : class { throw null; } + public static bool Update(ref ImmutableArray location, Func, ImmutableArray> transformer) { throw null; } + public static bool Update(ref T location, Func transformer, TArg transformerArgument) where T : class { throw null; } + public static bool Update(ref ImmutableArray location, Func, TArg, ImmutableArray> transformer, TArg transformerArgument) { throw null; } + } + public static partial class ImmutableList + { + public static ImmutableList Create() { throw null; } + public static ImmutableList Create(T item) { throw null; } + public static ImmutableList Create(params T[] items) { throw null; } + public static ImmutableList Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableList.Builder CreateBuilder() { throw null; } + public static ImmutableList CreateRange(Generic.IEnumerable items) { throw null; } + public static int IndexOf(this IImmutableList list, T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public static int IndexOf(this IImmutableList list, T item, int startIndex, int count) { throw null; } + public static int IndexOf(this IImmutableList list, T item, int startIndex) { throw null; } + public static int IndexOf(this IImmutableList list, T item) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item, int startIndex, int count) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item, int startIndex) { throw null; } + public static int LastIndexOf(this IImmutableList list, T item) { throw null; } + public static IImmutableList Remove(this IImmutableList list, T value) { throw null; } + public static IImmutableList RemoveRange(this IImmutableList list, Generic.IEnumerable items) { throw null; } + public static IImmutableList Replace(this IImmutableList list, T oldValue, T newValue) { throw null; } + public static ImmutableList ToImmutableList(this Generic.IEnumerable source) { throw null; } + public static ImmutableList ToImmutableList(this ImmutableList.Builder builder) { throw null; } + } + public sealed partial class ImmutableList : IImmutableList, Generic.IReadOnlyList, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyCollection, Generic.IList, Generic.ICollection, IList, ICollection + { + internal ImmutableList() { } + public static readonly ImmutableList Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public T this[int index] { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + T Generic.IList.this[int index] { get { throw null; } set { } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public ImmutableList Add(T value) { throw null; } + public ImmutableList AddRange(Generic.IEnumerable items) { throw null; } + public int BinarySearch(T item, Generic.IComparer? comparer) { throw null; } + public int BinarySearch(T item) { throw null; } + public int BinarySearch(int index, int count, T item, Generic.IComparer? comparer) { throw null; } + public ImmutableList Clear() { throw null; } + public bool Contains(T value) { throw null; } + public ImmutableList ConvertAll(Func converter) { throw null; } + public void CopyTo(T[] array, int arrayIndex) { } + public void CopyTo(T[] array) { } + public void CopyTo(int index, T[] array, int arrayIndex, int count) { } + public bool Exists(Predicate match) { throw null; } + public T? Find(Predicate match) { throw null; } + public ImmutableList FindAll(Predicate match) { throw null; } + public int FindIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindIndex(int startIndex, Predicate match) { throw null; } + public int FindIndex(Predicate match) { throw null; } + public T? FindLast(Predicate match) { throw null; } + public int FindLastIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindLastIndex(int startIndex, Predicate match) { throw null; } + public int FindLastIndex(Predicate match) { throw null; } + public void ForEach(Action action) { } + public Enumerator GetEnumerator() { throw null; } + public ImmutableList GetRange(int index, int count) { throw null; } + public int IndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T value) { throw null; } + public ImmutableList Insert(int index, T item) { throw null; } + public ImmutableList InsertRange(int index, Generic.IEnumerable items) { throw null; } + public ref readonly T ItemRef(int index) { throw null; } + public int LastIndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList Remove(T value, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList Remove(T value) { throw null; } + public ImmutableList RemoveAll(Predicate match) { throw null; } + public ImmutableList RemoveAt(int index) { throw null; } + public ImmutableList RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList RemoveRange(Generic.IEnumerable items) { throw null; } + public ImmutableList RemoveRange(int index, int count) { throw null; } + public ImmutableList Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { throw null; } + public ImmutableList Replace(T oldValue, T newValue) { throw null; } + public ImmutableList Reverse() { throw null; } + public ImmutableList Reverse(int index, int count) { throw null; } + public ImmutableList SetItem(int index, T value) { throw null; } + public ImmutableList Sort() { throw null; } + public ImmutableList Sort(Generic.IComparer? comparer) { throw null; } + public ImmutableList Sort(Comparison comparison) { throw null; } + public ImmutableList Sort(int index, int count, Generic.IComparer? comparer) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void Generic.IList.Insert(int index, T item) { } + void Generic.IList.RemoveAt(int index) { } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + int IList.Add(object value) { throw null; } + void IList.Clear() { } + bool IList.Contains(object value) { throw null; } + int IList.IndexOf(object value) { throw null; } + void IList.Insert(int index, object value) { } + void IList.Remove(object value) { } + void IList.RemoveAt(int index) { } + IImmutableList IImmutableList.Add(T value) { throw null; } + IImmutableList IImmutableList.AddRange(Generic.IEnumerable items) { throw null; } + IImmutableList IImmutableList.Clear() { throw null; } + IImmutableList IImmutableList.Insert(int index, T item) { throw null; } + IImmutableList IImmutableList.InsertRange(int index, Generic.IEnumerable items) { throw null; } + IImmutableList IImmutableList.Remove(T value, Generic.IEqualityComparer equalityComparer) { throw null; } + IImmutableList IImmutableList.RemoveAll(Predicate match) { throw null; } + IImmutableList IImmutableList.RemoveAt(int index) { throw null; } + IImmutableList IImmutableList.RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer equalityComparer) { throw null; } + IImmutableList IImmutableList.RemoveRange(int index, int count) { throw null; } + IImmutableList IImmutableList.Replace(T oldValue, T newValue, Generic.IEqualityComparer equalityComparer) { throw null; } + IImmutableList IImmutableList.SetItem(int index, T value) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TrueForAll(Predicate match) { throw null; } + public sealed partial class Builder : Generic.IList, Generic.ICollection, Generic.IEnumerable, IEnumerable, IList, ICollection, Generic.IReadOnlyList, Generic.IReadOnlyCollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public T this[int index] { get { throw null; } set { } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public void Add(T item) { } + public void AddRange(Generic.IEnumerable items) { } + public int BinarySearch(T item, Generic.IComparer? comparer) { throw null; } + public int BinarySearch(T item) { throw null; } + public int BinarySearch(int index, int count, T item, Generic.IComparer? comparer) { throw null; } + public void Clear() { } + public bool Contains(T item) { throw null; } + public ImmutableList ConvertAll(Func converter) { throw null; } + public void CopyTo(T[] array, int arrayIndex) { } + public void CopyTo(T[] array) { } + public void CopyTo(int index, T[] array, int arrayIndex, int count) { } + public bool Exists(Predicate match) { throw null; } + public T? Find(Predicate match) { throw null; } + public ImmutableList FindAll(Predicate match) { throw null; } + public int FindIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindIndex(int startIndex, Predicate match) { throw null; } + public int FindIndex(Predicate match) { throw null; } + public T? FindLast(Predicate match) { throw null; } + public int FindLastIndex(int startIndex, int count, Predicate match) { throw null; } + public int FindLastIndex(int startIndex, Predicate match) { throw null; } + public int FindLastIndex(Predicate match) { throw null; } + public void ForEach(Action action) { } + public Enumerator GetEnumerator() { throw null; } + public ImmutableList GetRange(int index, int count) { throw null; } + public int IndexOf(T item, int index, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int IndexOf(T item, int index, int count) { throw null; } + public int IndexOf(T item, int index) { throw null; } + public int IndexOf(T item) { throw null; } + public void Insert(int index, T item) { } + public void InsertRange(int index, Generic.IEnumerable items) { } + public ref readonly T ItemRef(int index) { throw null; } + public int LastIndexOf(T item, int startIndex, int count, Generic.IEqualityComparer? equalityComparer) { throw null; } + public int LastIndexOf(T item, int startIndex, int count) { throw null; } + public int LastIndexOf(T item, int startIndex) { throw null; } + public int LastIndexOf(T item) { throw null; } + public bool Remove(T item, Generic.IEqualityComparer? equalityComparer) { throw null; } + public bool Remove(T item) { throw null; } + public int RemoveAll(Predicate match) { throw null; } + public void RemoveAt(int index) { } + public void RemoveRange(Generic.IEnumerable items, Generic.IEqualityComparer? equalityComparer) { } + public void RemoveRange(Generic.IEnumerable items) { } + public void RemoveRange(int index, int count) { } + public void Replace(T oldValue, T newValue, Generic.IEqualityComparer? equalityComparer) { } + public void Replace(T oldValue, T newValue) { } + public void Reverse() { } + public void Reverse(int index, int count) { } + public void Sort() { } + public void Sort(Generic.IComparer? comparer) { } + public void Sort(Comparison comparison) { } + public void Sort(int index, int count, Generic.IComparer? comparer) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + int IList.Add(object value) { throw null; } + void IList.Clear() { } + bool IList.Contains(object value) { throw null; } + int IList.IndexOf(object value) { throw null; } + void IList.Insert(int index, object value) { } + void IList.Remove(object value) { } + public ImmutableList ToImmutable() { throw null; } + public bool TrueForAll(Predicate match) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object? IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableQueue + { + public static ImmutableQueue Create() { throw null; } + public static ImmutableQueue Create(T item) { throw null; } + public static ImmutableQueue Create(params T[] items) { throw null; } + public static ImmutableQueue Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableQueue CreateRange(Generic.IEnumerable items) { throw null; } + public static IImmutableQueue Dequeue(this IImmutableQueue queue, out T value) { throw null; } + } + public sealed partial class ImmutableQueue : IImmutableQueue, Generic.IEnumerable, IEnumerable + { + internal ImmutableQueue() { } + public static ImmutableQueue Empty { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public ImmutableQueue Clear() { throw null; } + public ImmutableQueue Dequeue() { throw null; } + public ImmutableQueue Dequeue(out T value) { throw null; } + public ImmutableQueue Enqueue(T value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public T Peek() { throw null; } + public ref readonly T PeekRef() { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableQueue IImmutableQueue.Clear() { throw null; } + IImmutableQueue IImmutableQueue.Dequeue() { throw null; } + IImmutableQueue IImmutableQueue.Enqueue(T value) { throw null; } + public partial struct Enumerator + { + private ImmutableQueue _originalQueue; + private ImmutableStack _remainingForwardsStack; + private ImmutableStack _remainingBackwardsStack; + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + public bool MoveNext() { throw null; } + } + } + + public static partial class ImmutableSortedDictionary + { + public static ImmutableSortedDictionary Create() { throw null; } + public static ImmutableSortedDictionary Create(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary Create(Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary.Builder CreateBuilder() { throw null; } + public static ImmutableSortedDictionary.Builder CreateBuilder(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary.Builder CreateBuilder(Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary CreateRange(Generic.IComparer? keyComparer, Generic.IEnumerable> items) { throw null; } + public static ImmutableSortedDictionary CreateRange(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer, Generic.IEnumerable> items) { throw null; } + public static ImmutableSortedDictionary CreateRange(Generic.IEnumerable> items) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable> source, Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable> source, Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable> source) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this ImmutableSortedDictionary.Builder builder) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector, Generic.IComparer? keyComparer) { throw null; } + public static ImmutableSortedDictionary ToImmutableSortedDictionary(this Generic.IEnumerable source, Func keySelector, Func elementSelector) { throw null; } + } + public sealed partial class ImmutableSortedDictionary : IImmutableDictionary, Generic.IReadOnlyDictionary, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyCollection>, Generic.IDictionary, Generic.ICollection>, IDictionary, ICollection + { + internal ImmutableSortedDictionary() { } + public static readonly ImmutableSortedDictionary Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } } + + public Generic.IComparer KeyComparer { get { throw null; } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + TValue Generic.IDictionary.this[TKey key] { get { throw null; } set { } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } } + public Generic.IEnumerable Values { get { throw null; } } + + public ImmutableSortedDictionary Add(TKey key, TValue value) { throw null; } + public ImmutableSortedDictionary AddRange(Generic.IEnumerable> items) { throw null; } + public ImmutableSortedDictionary Clear() { throw null; } + public bool Contains(Generic.KeyValuePair pair) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public ImmutableSortedDictionary Remove(TKey value) { throw null; } + public ImmutableSortedDictionary RemoveRange(Generic.IEnumerable keys) { throw null; } + public ImmutableSortedDictionary SetItem(TKey key, TValue value) { throw null; } + public ImmutableSortedDictionary SetItems(Generic.IEnumerable> items) { throw null; } + void Generic.ICollection>.Add(Generic.KeyValuePair item) { } + void Generic.ICollection>.Clear() { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + bool Generic.ICollection>.Remove(Generic.KeyValuePair item) { throw null; } + void Generic.IDictionary.Add(TKey key, TValue value) { } + bool Generic.IDictionary.Remove(TKey key) { throw null; } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int index) { } + void IDictionary.Add(object key, object value) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.AddRange(Generic.IEnumerable> pairs) { throw null; } + IImmutableDictionary IImmutableDictionary.Clear() { throw null; } + IImmutableDictionary IImmutableDictionary.Remove(TKey key) { throw null; } + IImmutableDictionary IImmutableDictionary.RemoveRange(Generic.IEnumerable keys) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) { throw null; } + IImmutableDictionary IImmutableDictionary.SetItems(Generic.IEnumerable> items) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public ref readonly TValue ValueRef(TKey key) { throw null; } + public ImmutableSortedDictionary WithComparers(Generic.IComparer? keyComparer, Generic.IEqualityComparer? valueComparer) { throw null; } + public ImmutableSortedDictionary WithComparers(Generic.IComparer? keyComparer) { throw null; } + public sealed partial class Builder : Generic.IDictionary, Generic.ICollection>, Generic.IEnumerable>, IEnumerable, Generic.IReadOnlyDictionary, Generic.IReadOnlyCollection>, IDictionary, ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public TValue this[TKey key] { get { throw null; } set { } } + + public Generic.IComparer KeyComparer { get { throw null; } set { } } + public Generic.IEnumerable Keys { get { throw null; } } + + bool Generic.ICollection>.IsReadOnly { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Keys { get { throw null; } } + + Generic.ICollection Generic.IDictionary.Values { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IDictionary.IsFixedSize { get { throw null; } } + + bool IDictionary.IsReadOnly { get { throw null; } } + + object? IDictionary.this[object key] { get { throw null; } set { } } + + ICollection IDictionary.Keys { get { throw null; } } + + ICollection IDictionary.Values { get { throw null; } } + public Generic.IEqualityComparer ValueComparer { get { throw null; } set { } } + public Generic.IEnumerable Values { get { throw null; } } + + public void Add(TKey key, TValue value) { } + public void Add(Generic.KeyValuePair item) { } + public void AddRange(Generic.IEnumerable> items) { } + public void Clear() { } + public bool Contains(Generic.KeyValuePair item) { throw null; } + public bool ContainsKey(TKey key) { throw null; } + public bool ContainsValue(TValue value) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public TValue GetValueOrDefault(TKey key, TValue defaultValue) { throw null; } + public TValue? GetValueOrDefault(TKey key) { throw null; } + public bool Remove(TKey key) { throw null; } + public bool Remove(Generic.KeyValuePair item) { throw null; } + public void RemoveRange(Generic.IEnumerable keys) { } + void Generic.ICollection>.CopyTo(Generic.KeyValuePair[] array, int arrayIndex) { } + Generic.IEnumerator> Generic.IEnumerable>.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int index) { } + void IDictionary.Add(object key, object value) { } + bool IDictionary.Contains(object key) { throw null; } + IDictionaryEnumerator IDictionary.GetEnumerator() { throw null; } + void IDictionary.Remove(object key) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableSortedDictionary ToImmutable() { throw null; } + public bool TryGetKey(TKey equalKey, out TKey actualKey) { throw null; } + public bool TryGetValue(TKey key, out TValue value) { throw null; } + public ref readonly TValue ValueRef(TKey key) { throw null; } + } + + public partial struct Enumerator : Generic.IEnumerator>, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public Generic.KeyValuePair Current { get { throw null; } } + + object IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableSortedSet + { + public static ImmutableSortedSet Create() { throw null; } + public static ImmutableSortedSet Create(T item) { throw null; } + public static ImmutableSortedSet Create(params T[] items) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer, T item) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer, params T[] items) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer, params scoped ReadOnlySpan items) { throw null; } + public static ImmutableSortedSet Create(Generic.IComparer? comparer) { throw null; } + public static ImmutableSortedSet Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableSortedSet.Builder CreateBuilder() { throw null; } + public static ImmutableSortedSet.Builder CreateBuilder(Generic.IComparer? comparer) { throw null; } + public static ImmutableSortedSet CreateRange(Generic.IComparer? comparer, Generic.IEnumerable items) { throw null; } + public static ImmutableSortedSet CreateRange(Generic.IEnumerable items) { throw null; } + public static ImmutableSortedSet ToImmutableSortedSet(this Generic.IEnumerable source, Generic.IComparer? comparer) { throw null; } + public static ImmutableSortedSet ToImmutableSortedSet(this Generic.IEnumerable source) { throw null; } + public static ImmutableSortedSet ToImmutableSortedSet(this ImmutableSortedSet.Builder builder) { throw null; } + } + public sealed partial class ImmutableSortedSet : IImmutableSet, Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.IReadOnlyList, Generic.IList, Generic.ICollection, Generic.ISet, IList, ICollection + { + internal ImmutableSortedSet() { } + public static readonly ImmutableSortedSet Empty; + public int Count { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public T this[int index] { get { throw null; } } + + public Generic.IComparer KeyComparer { get { throw null; } } + public T? Max { get { throw null; } } + public T? Min { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + T Generic.IList.this[int index] { get { throw null; } set { } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + bool IList.IsFixedSize { get { throw null; } } + + bool IList.IsReadOnly { get { throw null; } } + + object? IList.this[int index] { get { throw null; } set { } } + + public ImmutableSortedSet Add(T value) { throw null; } + public ImmutableSortedSet Clear() { throw null; } + public bool Contains(T value) { throw null; } + public ImmutableSortedSet Except(Generic.IEnumerable other) { throw null; } + public Enumerator GetEnumerator() { throw null; } + public int IndexOf(T item) { throw null; } + public ImmutableSortedSet Intersect(Generic.IEnumerable other) { throw null; } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public ref readonly T ItemRef(int index) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public ImmutableSortedSet Remove(T value) { throw null; } + public Generic.IEnumerable Reverse() { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public ImmutableSortedSet SymmetricExcept(Generic.IEnumerable other) { throw null; } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.Clear() { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + bool Generic.ICollection.Remove(T item) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void Generic.IList.Insert(int index, T item) { } + void Generic.IList.RemoveAt(int index) { } + bool Generic.ISet.Add(T item) { throw null; } + void Generic.ISet.ExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.IntersectWith(Generic.IEnumerable other) { } + void Generic.ISet.SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ISet.UnionWith(Generic.IEnumerable other) { } + void ICollection.CopyTo(Array array, int index) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + int IList.Add(object value) { throw null; } + void IList.Clear() { } + bool IList.Contains(object value) { throw null; } + int IList.IndexOf(object value) { throw null; } + void IList.Insert(int index, object value) { } + void IList.Remove(object value) { } + void IList.RemoveAt(int index) { } + IImmutableSet IImmutableSet.Add(T value) { throw null; } + IImmutableSet IImmutableSet.Clear() { throw null; } + IImmutableSet IImmutableSet.Except(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Intersect(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Remove(T value) { throw null; } + IImmutableSet IImmutableSet.SymmetricExcept(Generic.IEnumerable other) { throw null; } + IImmutableSet IImmutableSet.Union(Generic.IEnumerable other) { throw null; } + public Builder ToBuilder() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public ImmutableSortedSet Union(Generic.IEnumerable other) { throw null; } + public ImmutableSortedSet WithComparer(Generic.IComparer? comparer) { throw null; } + public sealed partial class Builder : Generic.IReadOnlyCollection, Generic.IEnumerable, IEnumerable, Generic.ISet, Generic.ICollection, ICollection + { + internal Builder() { } + public int Count { get { throw null; } } + + public T this[int index] { get { throw null; } } + + public Generic.IComparer KeyComparer { get { throw null; } set { } } + public T? Max { get { throw null; } } + public T? Min { get { throw null; } } + + bool Generic.ICollection.IsReadOnly { get { throw null; } } + + bool ICollection.IsSynchronized { get { throw null; } } + + object ICollection.SyncRoot { get { throw null; } } + + public bool Add(T item) { throw null; } + public void Clear() { } + public bool Contains(T item) { throw null; } + public void ExceptWith(Generic.IEnumerable other) { } + public Enumerator GetEnumerator() { throw null; } + public int IndexOf(T item) { throw null; } + public void IntersectWith(Generic.IEnumerable other) { } + public bool IsProperSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsProperSupersetOf(Generic.IEnumerable other) { throw null; } + public bool IsSubsetOf(Generic.IEnumerable other) { throw null; } + public bool IsSupersetOf(Generic.IEnumerable other) { throw null; } + public ref readonly T ItemRef(int index) { throw null; } + public bool Overlaps(Generic.IEnumerable other) { throw null; } + public bool Remove(T item) { throw null; } + public Generic.IEnumerable Reverse() { throw null; } + public bool SetEquals(Generic.IEnumerable other) { throw null; } + public void SymmetricExceptWith(Generic.IEnumerable other) { } + void Generic.ICollection.Add(T item) { } + void Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + void ICollection.CopyTo(Array array, int arrayIndex) { } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + public ImmutableSortedSet ToImmutable() { throw null; } + public bool TryGetValue(T equalValue, out T actualValue) { throw null; } + public void UnionWith(Generic.IEnumerable other) { } + } + + public partial struct Enumerator : Generic.IEnumerator, IEnumerator, IDisposable + { + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + object? IEnumerator.Current { get { throw null; } } + + public void Dispose() { } + public bool MoveNext() { throw null; } + public void Reset() { } + } + } + + public static partial class ImmutableStack + { + public static ImmutableStack Create() { throw null; } + public static ImmutableStack Create(T item) { throw null; } + public static ImmutableStack Create(params T[] items) { throw null; } + public static ImmutableStack Create(params scoped ReadOnlySpan items) { throw null; } + public static ImmutableStack CreateRange(Generic.IEnumerable items) { throw null; } + public static IImmutableStack Pop(this IImmutableStack stack, out T value) { throw null; } + } + public sealed partial class ImmutableStack : IImmutableStack, Generic.IEnumerable, IEnumerable + { + internal ImmutableStack() { } + public static ImmutableStack Empty { get { throw null; } } + public bool IsEmpty { get { throw null; } } + + public ImmutableStack Clear() { throw null; } + public Enumerator GetEnumerator() { throw null; } + public T Peek() { throw null; } + public ref readonly T PeekRef() { throw null; } + public ImmutableStack Pop() { throw null; } + public ImmutableStack Pop(out T value) { throw null; } + public ImmutableStack Push(T value) { throw null; } + Generic.IEnumerator Generic.IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IImmutableStack IImmutableStack.Clear() { throw null; } + IImmutableStack IImmutableStack.Pop() { throw null; } + IImmutableStack IImmutableStack.Push(T value) { throw null; } + public partial struct Enumerator + { + private ImmutableStack _originalStack; + private ImmutableStack _remainingStack; + private object _dummy; + private int _dummyPrimitive; + public T Current { get { throw null; } } + + public bool MoveNext() { throw null; } + } + } +} + +namespace System.Linq +{ + public static partial class ImmutableArrayExtensions + { + public static T? Aggregate(this Collections.Immutable.ImmutableArray immutableArray, Func func) { throw null; } + public static TAccumulate Aggregate(this Collections.Immutable.ImmutableArray immutableArray, TAccumulate seed, Func func) { throw null; } + public static TResult Aggregate(this Collections.Immutable.ImmutableArray immutableArray, TAccumulate seed, Func func, Func resultSelector) { throw null; } + public static bool All(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static bool Any(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static bool Any(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static bool Any(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T ElementAt(this Collections.Immutable.ImmutableArray immutableArray, int index) { throw null; } + public static T? ElementAtOrDefault(this Collections.Immutable.ImmutableArray immutableArray, int index) { throw null; } + public static T First(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T First(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T First(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T? FirstOrDefault(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T? FirstOrDefault(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T? FirstOrDefault(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T Last(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T Last(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T Last(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T? LastOrDefault(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T? LastOrDefault(this Collections.Immutable.ImmutableArray.Builder builder) { throw null; } + public static T? LastOrDefault(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static Collections.Generic.IEnumerable Select(this Collections.Immutable.ImmutableArray immutableArray, Func selector) { throw null; } + public static Collections.Generic.IEnumerable SelectMany(this Collections.Immutable.ImmutableArray immutableArray, Func> collectionSelector, Func resultSelector) { throw null; } + public static bool SequenceEqual(this Collections.Immutable.ImmutableArray immutableArray, Collections.Generic.IEnumerable items, Collections.Generic.IEqualityComparer? comparer = null) where TDerived : TBase { throw null; } + public static bool SequenceEqual(this Collections.Immutable.ImmutableArray immutableArray, Collections.Immutable.ImmutableArray items, Collections.Generic.IEqualityComparer? comparer = null) where TDerived : TBase { throw null; } + public static bool SequenceEqual(this Collections.Immutable.ImmutableArray immutableArray, Collections.Immutable.ImmutableArray items, Func predicate) where TDerived : TBase { throw null; } + public static T Single(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T Single(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T? SingleOrDefault(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + public static T? SingleOrDefault(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static T[] ToArray(this Collections.Immutable.ImmutableArray immutableArray) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector, Collections.Generic.IEqualityComparer? comparer) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector, Func elementSelector, Collections.Generic.IEqualityComparer? comparer) { throw null; } + public static Collections.Generic.Dictionary ToDictionary(this Collections.Immutable.ImmutableArray immutableArray, Func keySelector, Func elementSelector) { throw null; } + public static Collections.Generic.IEnumerable Where(this Collections.Immutable.ImmutableArray immutableArray, Func predicate) { throw null; } + } +} + +namespace System.Runtime.InteropServices +{ + public static partial class ImmutableCollectionsMarshal + { + public static T[]? AsArray(Collections.Immutable.ImmutableArray array) { throw null; } + public static Collections.Immutable.ImmutableArray AsImmutableArray(T[]? array) { throw null; } + } +} \ No newline at end of file diff --git a/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/system.collections.immutable.nuspec b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/system.collections.immutable.nuspec new file mode 100644 index 00000000000..440f56bd005 --- /dev/null +++ b/src/source-build-reference-packages/src/referencePackages/src/system.collections.immutable/9.0.0/system.collections.immutable.nuspec @@ -0,0 +1,26 @@ + + + + System.Collections.Immutable + 9.0.0 + Microsoft + MIT + https://licenses.nuget.org/MIT + https://dot.net/ + This package provides collections that are thread safe and guaranteed to never change their contents, also known as immutable collections. Like strings, any methods that perform modifications will not change the existing instance but instead return a new instance. For efficiency reasons, the implementation uses a sharing mechanism to ensure that newly created instances share as much data as possible with the previous instance while ensuring that operations have a predictable time complexity. + +The System.Collections.Immutable library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks. + https://go.microsoft.com/fwlink/?LinkID=799421 + © Microsoft Corporation. All rights reserved. + true + + + + + + + + + + + \ No newline at end of file diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/Icon.png b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/Icon.png new file mode 100755 index 00000000000..fb00ecf91e4 Binary files /dev/null and b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/Icon.png differ diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/ThirdPartyNotices.rtf b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/ThirdPartyNotices.rtf new file mode 100755 index 00000000000..1e4323dea60 Binary files /dev/null and b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/ThirdPartyNotices.rtf differ diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/build/Microsoft.CodeAnalysis.Collections.targets b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/build/Microsoft.CodeAnalysis.Collections.targets new file mode 100755 index 00000000000..f236d98df9f --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/build/Microsoft.CodeAnalysis.Collections.targets @@ -0,0 +1,19 @@ + + + + + <_PackageCompileItems Remove="@(_PackageCompileItems)"/> + <_PackageCompileItems Include="%(Compile.RootDir)%(Compile.Directory)" Condition="'%(Compile.NuGetPackageId)' == 'Microsoft.CodeAnalysis.Collections'" /> + + + + <_PackageCompileItem>@(_PackageCompileItems) + <_PackageCompileItem Condition="'$(_PackageCompileItem)' != ''">$(_PackageCompileItem.Split(';')[0]) + + + + + + + diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/.editorconfig b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/.editorconfig new file mode 100755 index 00000000000..e10491047f5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/.editorconfig @@ -0,0 +1,18 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +# We don't want any analyzer diagnostics to be reported for people consuming this as a source package. +dotnet_analyzer_diagnostic.severity = none + +generated_code = true + +# The above configurations don't apply to compiler warnings. Requiring all params to be documented +# is not something we require for this project, so suppressing it directly here. +dotnet_diagnostic.CS1573.severity = none + +# As above, we need to specifically disable compiler warnings that we don't want to break downstream +# builds +dotnet_diagnostic.IDE0005.severity = none \ No newline at end of file diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Extensions/ICollectionExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Extensions/ICollectionExtensions.cs new file mode 100755 index 00000000000..b6fd40d078d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Extensions/ICollectionExtensions.cs @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.PooledObjects; + +namespace Microsoft.CodeAnalysis; + +internal static class ICollectionExtensions +{ + public static void RemoveRange(this ICollection collection, IEnumerable? items) + { + if (items != null) + { + foreach (var item in items) + { + collection.Remove(item); + } + } + } + + public static void AddIfNotNull(this ICollection collection, T? value) where T : struct + { + if (value != null) + collection.Add(value.Value); + } + + public static void AddIfNotNull(this ICollection collection, T? value) where T : class + { + if (value != null) + collection.Add(value); + } + + public static void AddRange(this ICollection collection, IEnumerable? values) + { + if (values != null) + { + foreach (var item in values) + { + collection.Add(item); + } + } + } + + public static void AddRange(this ICollection collection, ArrayBuilder? values) + { + if (values != null) + { + foreach (var item in values) + collection.Add(item); + } + } + + public static void AddRange(this ICollection collection, HashSet? values) + { + if (values != null) + { + foreach (var item in values) + collection.Add(item); + } + } + + public static void AddRange(this ICollection collection, Dictionary.KeyCollection? keyCollection) where TKey : notnull + { + if (keyCollection != null) + { + foreach (var key in keyCollection) + collection.Add(key); + } + } + + public static void AddRange(this ICollection collection, ImmutableArray values) + { + if (!values.IsDefault) + { + foreach (var item in values) + { + collection.Add(item); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Extensions/IEnumerableExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Extensions/IEnumerableExtensions.cs new file mode 100755 index 00000000000..0e86991e66d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Extensions/IEnumerableExtensions.cs @@ -0,0 +1,1028 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.PooledObjects; + +namespace Roslyn.Utilities +{ + internal static partial class EnumerableExtensions + { + public static int Count(this IEnumerable source, Func predicate, TArg arg) + { + var count = 0; + foreach (var v in source) + { + if (predicate(v, arg)) + count++; + } + + return count; + } + + public static IEnumerable Do(this IEnumerable source, Action action) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + // perf optimization. try to not use enumerator if possible + if (source is IList list) + { + for (int i = 0, count = list.Count; i < count; i++) + { + action(list[i]); + } + } + else + { + foreach (var value in source) + { + action(value); + } + } + + return source; + } + + public static ImmutableArray ToImmutableArrayOrEmpty(this IEnumerable? items) + { + if (items == null) + { + return ImmutableArray.Create(); + } + + if (items is ImmutableArray array) + { + return array.NullToEmpty(); + } + + return ImmutableArray.CreateRange(items); + } + + public static IReadOnlyList ToBoxedImmutableArray(this IEnumerable? items) + { + if (items is null) + { + return SpecializedCollections.EmptyBoxedImmutableArray(); + } + + if (items is ImmutableArray array) + { + return array.IsDefaultOrEmpty ? SpecializedCollections.EmptyBoxedImmutableArray() : (IReadOnlyList)items; + } + + if (items is ICollection collection && collection.Count == 0) + { + return SpecializedCollections.EmptyBoxedImmutableArray(); + } + + return ImmutableArray.CreateRange(items); + } + + public static ReadOnlyCollection ToReadOnlyCollection(this IEnumerable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return new ReadOnlyCollection(source.ToList()); + } + + public static IEnumerable Concat(this IEnumerable source, T value) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.ConcatWorker(value); + } + + private static IEnumerable ConcatWorker(this IEnumerable source, T value) + { + foreach (var v in source) + { + yield return v; + } + + yield return value; + } + + public static bool SetEquals(this IEnumerable source1, IEnumerable source2, IEqualityComparer? comparer) + { + if (source1 == null) + { + throw new ArgumentNullException(nameof(source1)); + } + + if (source2 == null) + { + throw new ArgumentNullException(nameof(source2)); + } + + return source1.ToSet(comparer).SetEquals(source2); + } + + public static bool SetEquals(this IEnumerable source1, IEnumerable source2) + { + if (source1 == null) + { + throw new ArgumentNullException(nameof(source1)); + } + + if (source2 == null) + { + throw new ArgumentNullException(nameof(source2)); + } + + return source1.ToSet().SetEquals(source2); + } + + public static ISet ToSet(this IEnumerable source, IEqualityComparer? comparer) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return new HashSet(source, comparer); + } + + public static ISet ToSet(this IEnumerable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source as ISet ?? new HashSet(source); + } + + public static IReadOnlyCollection ToCollection(this IEnumerable sequence) + => (sequence is IReadOnlyCollection collection) ? collection : sequence.ToList(); + + public static T? FirstOrDefault(this IEnumerable source, Func predicate, TArg arg) + { + foreach (var item in source) + { + if (predicate(item, arg)) + return item; + } + + return default; + } + + public static bool Any(this IEnumerable source, Func predicate, TArg arg) + { + foreach (var item in source) + { + if (predicate(item, arg)) + return true; + } + + return false; + } + + public static T? FirstOrNull(this IEnumerable source) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.Cast().FirstOrDefault(); + } + + public static T? FirstOrNull(this IEnumerable source, Func predicate) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (predicate == null) + { + throw new ArgumentNullException(nameof(predicate)); + } + + return source.Cast().FirstOrDefault(static (v, predicate) => predicate(v!.Value), predicate); + } + + public static T? FirstOrNull(this IEnumerable source, Func predicate, TArg arg) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (predicate == null) + { + throw new ArgumentNullException(nameof(predicate)); + } + + return source.Cast().FirstOrDefault(static (v, arg) => arg.predicate(v!.Value, arg.arg), (predicate, arg)); + } + + public static T? LastOrNull(this IEnumerable source) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.Cast().LastOrDefault(); + } + + public static T? SingleOrNull(this IEnumerable source, Func predicate) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.Cast().SingleOrDefault(v => predicate(v!.Value)); + } + + public static bool IsSingle(this IEnumerable list) + { + using var enumerator = list.GetEnumerator(); + return enumerator.MoveNext() && !enumerator.MoveNext(); + } + + public static bool IsEmpty(this IEnumerable source) + { + if (source is IReadOnlyCollection readOnlyCollection) + { + return readOnlyCollection.Count == 0; + } + + if (source is ICollection genericCollection) + { + return genericCollection.Count == 0; + } + + if (source is ICollection collection) + { + return collection.Count == 0; + } + + if (source is string str) + { + return str.Length == 0; + } + + foreach (var _ in source) + { + return false; + } + + return true; + } + + public static bool IsEmpty(this IReadOnlyCollection source) + { + return source.Count == 0; + } + + public static bool IsEmpty(this ICollection source) + { + return source.Count == 0; + } + + public static bool IsEmpty(this string source) + { + return source.Length == 0; + } + + /// + /// This method is necessary to avoid an ambiguity between and . + /// + public static bool IsEmpty(this T[] source) + { + return source.Length == 0; + } + + /// + /// This method is necessary to avoid an ambiguity between and . + /// + public static bool IsEmpty(this List source) + { + return source.Count == 0; + } + + private static readonly Func s_notNullTest = x => x != null; + + public static IEnumerable WhereNotNull(this IEnumerable source) + where T : class + { + if (source == null) + { + return SpecializedCollections.EmptyEnumerable(); + } + + return source.Where((Func)s_notNullTest)!; + } + + public static ImmutableArray WhereAsArray(this IEnumerable values, Func predicate, TArg arg) + { + var result = ArrayBuilder.GetInstance(); + + foreach (var value in values) + { + if (predicate(value, arg)) + result.Add(value); + } + + return result.ToImmutableAndFree(); + } + + public static T[] AsArray(this IEnumerable source) + => source as T[] ?? source.ToArray(); + + public static ImmutableArray SelectAsArray(this IEnumerable? source, Func selector) + { + if (source == null) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + builder.AddRange(source.Select(selector)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectAsArray(this IEnumerable? source, Func selector) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + + int index = 0; + foreach (var element in source) + { + builder.Add(selector(element, index)); + index++; + } + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectAsArray(this IReadOnlyCollection? source, Func selector) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = new TResult[source.Count]; + var index = 0; + foreach (var item in source) + { + builder[index] = selector(item); + index++; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + public static ImmutableArray SelectAsArray(this IReadOnlyCollection? source, Func selector, TArg arg) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = new TResult[source.Count]; + var index = 0; + foreach (var item in source) + { + builder[index] = selector(item, arg); + index++; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + public static ImmutableArray SelectManyAsArray(this IEnumerable? source, Func> selector) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in source) + builder.AddRange(selector(item)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectManyAsArray(this IEnumerable? source, Func> selector, TArg arg) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in source) + builder.AddRange(selector(item, arg)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectManyAsArray(this IReadOnlyCollection? source, Func> selector) + { + if (source == null) + return ImmutableArray.Empty; + + // Basic heuristic. Assume each element in the source adds one item to the result. + var builder = ArrayBuilder.GetInstance(source.Count); + foreach (var item in source) + builder.AddRange(selector(item)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectManyAsArray(this IReadOnlyCollection? source, Func> selector, TArg arg) + { + if (source == null) + return ImmutableArray.Empty; + + // Basic heuristic. Assume each element in the source adds one item to the result. + var builder = ArrayBuilder.GetInstance(source.Count); + foreach (var item in source) + builder.AddRange(selector(item, arg)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectManyAsArray(this IEnumerable? source, Func> selector) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in source) + selector(item).AddRangeTo(builder); + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps an immutable array through a function that returns ValueTask, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this IEnumerable source, Func> selector) + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.Add(await selector(item).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps an immutable array through a function that returns ValueTask, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this IEnumerable source, Func> selector, CancellationToken cancellationToken) + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.Add(await selector(item, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps an immutable array through a function that returns ValueTask, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this IEnumerable source, Func> selector, TArg arg, CancellationToken cancellationToken) + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.Add(await selector(item, arg, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + + public static async ValueTask> SelectManyAsArrayAsync(this IEnumerable source, Func>> selector, TArg arg, CancellationToken cancellationToken) + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.AddRange(await selector(item, arg, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + + public static async ValueTask> SelectManyInParallelAsync( + this IEnumerable sequence, + Func>> selector, + CancellationToken cancellationToken) + { + return (await Task.WhenAll(sequence.Select(item => selector(item, cancellationToken))).ConfigureAwait(false)).Flatten(); + } + + public static bool All(this IEnumerable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + foreach (var b in source) + { + if (!b) + { + return false; + } + } + + return true; + } + + public static int IndexOf(this IEnumerable sequence, T value) + { + return sequence switch + { + IList list => list.IndexOf(value), + IReadOnlyList readOnlyList => IndexOf(readOnlyList, value, EqualityComparer.Default), + _ => EnumeratingIndexOf(sequence, value, EqualityComparer.Default) + }; + } + + public static int IndexOf(this IEnumerable sequence, T value, IEqualityComparer comparer) + { + return sequence switch + { + IReadOnlyList readOnlyList => IndexOf(readOnlyList, value, comparer), + _ => EnumeratingIndexOf(sequence, value, comparer) + }; + } + + private static int EnumeratingIndexOf(this IEnumerable sequence, T value, IEqualityComparer comparer) + { + int i = 0; + foreach (var item in sequence) + { + if (comparer.Equals(item, value)) + { + return i; + } + + i++; + } + + return -1; + } + + public static int IndexOf(this IReadOnlyList list, T value, IEqualityComparer comparer) + { + for (int i = 0, length = list.Count; i < length; i++) + { + if (comparer.Equals(list[i], value)) + { + return i; + } + } + + return -1; + } + + public static IEnumerable Flatten(this IEnumerable> sequence) + { + if (sequence == null) + { + throw new ArgumentNullException(nameof(sequence)); + } + + return sequence.SelectMany(s => s); + } + + public static IOrderedEnumerable OrderBy(this IEnumerable source, IComparer? comparer) + { + return source.OrderBy(Functions.Identity, comparer); + } + + public static IOrderedEnumerable OrderByDescending(this IEnumerable source, IComparer? comparer) + { + return source.OrderByDescending(Functions.Identity, comparer); + } + + public static IOrderedEnumerable OrderBy(this IEnumerable source, Comparison compare) + { + return source.OrderBy(Comparer.Create(compare)); + } + + public static IOrderedEnumerable OrderByDescending(this IEnumerable source, Comparison compare) + { + return source.OrderByDescending(Comparer.Create(compare)); + } + +#if NET8_0_OR_GREATER + public static IOrderedEnumerable Order(IEnumerable source) where T : IComparable +#else + public static IOrderedEnumerable Order(this IEnumerable source) where T : IComparable +#endif + { + return source.OrderBy(Comparer.Default); + } + + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, IComparer? comparer) + { + return source.ThenBy(Functions.Identity, comparer); + } + + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, Comparison compare) + { + return source.ThenBy(Comparer.Create(compare)); + } + + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source) where T : IComparable + { + return source.ThenBy(Comparer.Default); + } + + public static bool IsSorted(this IEnumerable enumerable, IComparer? comparer = null) + { + using var e = enumerable.GetEnumerator(); + if (!e.MoveNext()) + { + return true; + } + + comparer ??= Comparer.Default; + + var previous = e.Current; + while (e.MoveNext()) + { + if (comparer.Compare(previous, e.Current) > 0) + { + return false; + } + + previous = e.Current; + } + + return true; + } + + public static bool Contains(this IEnumerable sequence, Func predicate) + { + return sequence.Any(predicate); + } + + public static bool Contains(this IEnumerable sequence, string? s) + { + foreach (var item in sequence) + { + if (item == s) + { + return true; + } + } + + return false; + } + + public static IComparer ToComparer(this Comparison comparison) + { + return Comparer.Create(comparison); + } + + public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this IEnumerable>? items) + where K : notnull + { + if (items == null) + { + return ImmutableDictionary.Create(); + } + + return ImmutableDictionary.CreateRange(items); + } + + public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this IEnumerable>? items, IEqualityComparer? keyComparer) + where K : notnull + { + if (items == null) + { + return ImmutableDictionary.Create(keyComparer); + } + + return ImmutableDictionary.CreateRange(keyComparer, items); + } + +#nullable disable // Transpose doesn't handle empty arrays. Needs to be updated as appropriate. + internal static IList> Transpose(this IEnumerable> data) + { +#if DEBUG + var count = data.First().Count(); + Debug.Assert(data.All(d => d.Count() == count)); +#endif + return TransposeInternal(data).ToArray(); + } + + private static IEnumerable> TransposeInternal(this IEnumerable> data) + { + List> enumerators = new List>(); + + var width = 0; + foreach (var e in data) + { + enumerators.Add(e.GetEnumerator()); + width += 1; + } + + try + { + while (true) + { + T[] line = null; + for (int i = 0; i < width; i++) + { + var e = enumerators[i]; + if (!e.MoveNext()) + { + yield break; + } + + if (line == null) + { + line = new T[width]; + } + + line[i] = e.Current; + } + + yield return line; + } + } + finally + { + foreach (var enumerator in enumerators) + { + enumerator.Dispose(); + } + } + } +#nullable enable + + internal static Dictionary> ToMultiDictionary(this IEnumerable data, Func keySelector, IEqualityComparer? comparer = null) + where K : notnull + { + var dictionary = new Dictionary>(comparer); + var groups = data.GroupBy(keySelector, comparer); + foreach (var grouping in groups) + { + dictionary.Add(grouping.Key, [.. grouping]); + } + + return dictionary; + } + + /// + /// Returns the only element of specified sequence if it has exactly one, and default(TSource) otherwise. + /// Unlike doesn't throw if there is more than one element in the sequence. + /// + internal static TSource? AsSingleton(this IEnumerable? source) + { + if (source == null) + { + return default; + } + + if (source is IList list) + { + return (list.Count == 1) ? list[0] : default; + } + + using IEnumerator e = source.GetEnumerator(); + if (!e.MoveNext()) + { + return default; + } + + TSource result = e.Current; + if (e.MoveNext()) + { + return default; + } + + return result; + } + } + + /// + /// Cached versions of commonly used delegates. + /// + /// + internal static class Functions + { + public static readonly Func Identity = t => t; + public static readonly Func True = t => true; + } + + /// + /// Cached versions of commonly used delegates. + /// + /// + internal static class Predicates + { + public static readonly Predicate True = t => true; + } +} + +namespace System.Linq +{ + /// + /// Declare the following extension methods in System.Linq namespace to avoid accidental boxing of ImmutableArray{T} that implements IEnumerable{T}. + /// The boxing would occur if the methods were defined in Roslyn.Utilities and the file calling these methods has using Roslyn.Utilities + /// but not using System.Linq. + /// + internal static class EnumerableExtensions + { + public static bool SequenceEqual(this IEnumerable? first, IEnumerable? second, Func comparer) + { + if (first == second) + { + return true; + } + + if (first == null || second == null) + { + return false; + } + + using (var enumerator = first.GetEnumerator()) + using (var enumerator2 = second.GetEnumerator()) + { + while (enumerator.MoveNext()) + { + if (!enumerator2.MoveNext() || !comparer(enumerator.Current, enumerator2.Current)) + { + return false; + } + } + + if (enumerator2.MoveNext()) + { + return false; + } + } + + return true; + } + + public static T? AggregateOrDefault(this IEnumerable source, Func func) + { + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + { + return default; + } + + var result = e.Current; + while (e.MoveNext()) + { + result = func(result, e.Current); + } + + return result; + } + } + + // https://github.com/dotnet/runtime/issues/107723 +#if NET10_0_OR_GREATER + public static IEnumerable Reverse(T[] source) => Enumerable.Reverse(source); +#else + public static IEnumerable Reverse(this T[] source) => Enumerable.Reverse(source); +#endif + +#if NETSTANDARD + + // Copied from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Linq/src/System/Linq/Chunk.cs + public static IEnumerable Chunk(this IEnumerable source, int size) + { + if (source is null) + throw new ArgumentNullException(nameof(source)); + + if (size < 1) + throw new ArgumentOutOfRangeException(nameof(size)); + + if (source is TSource[] array) + { + // Special-case arrays, which have an immutable length. This enables us to not only do an + // empty check and avoid allocating an iterator object when empty, it enables us to have a + // much more efficient (and simpler) implementation for chunking up the array. + return array.Length != 0 ? + ArrayChunkIterator(array, size) : + []; + } + + return EnumerableChunkIterator(source, size); + } + + private static IEnumerable ArrayChunkIterator(TSource[] source, int size) + { + int index = 0; + while (index < source.Length) + { + TSource[] chunk = new ReadOnlySpan(source, index, Math.Min(size, source.Length - index)).ToArray(); + index += chunk.Length; + yield return chunk; + } + } + + private static IEnumerable EnumerableChunkIterator(IEnumerable source, int size) + { + using IEnumerator e = source.GetEnumerator(); + + // Before allocating anything, make sure there's at least one element. + if (e.MoveNext()) + { + // Now that we know we have at least one item, allocate an initial storage array. This is not + // the array we'll yield. It starts out small in order to avoid significantly overallocating + // when the source has many fewer elements than the chunk size. + int arraySize = Math.Min(size, 4); + int i; + do + { + var array = new TSource[arraySize]; + + // Store the first item. + array[0] = e.Current; + i = 1; + + if (size != array.Length) + { + // This is the first chunk. As we fill the array, grow it as needed. + for (; i < size && e.MoveNext(); i++) + { + if (i >= array.Length) + { + arraySize = (int)Math.Min((uint)size, 2 * (uint)array.Length); + Array.Resize(ref array, arraySize); + } + + array[i] = e.Current; + } + } + else + { + // For all but the first chunk, the array will already be correctly sized. + // We can just store into it until either it's full or MoveNext returns false. + TSource[] local = array; // avoid bounds checks by using cached local (`array` is lifted to iterator object as a field) + Debug.Assert(local.Length == size); + for (; (uint)i < (uint)local.Length && e.MoveNext(); i++) + { + local[i] = e.Current; + } + } + + if (i != array.Length) + { + Array.Resize(ref array, i); + } + + yield return array; + } + while (i >= size && e.MoveNext()); + } + } + +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Extensions/ImmutableArrayExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Extensions/ImmutableArrayExtensions.cs new file mode 100755 index 00000000000..06227b65bc8 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Extensions/ImmutableArrayExtensions.cs @@ -0,0 +1,1416 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Collections; +using Roslyn.Utilities; +using Microsoft.CodeAnalysis.Shared.Collections; + +#if DEBUG +using System.Linq; +#endif + +namespace Microsoft.CodeAnalysis +{ + /// + /// The collection of extension methods for the type + /// + internal static class ImmutableArrayExtensions + { + /// + /// Converts a sequence to an immutable array. + /// + /// Elemental type of the sequence. + /// The sequence to convert. + /// An immutable copy of the contents of the sequence. + /// If items is null (default) + /// If the sequence is null, this will throw + public static ImmutableArray AsImmutable(this IEnumerable items) + { + return ImmutableArray.CreateRange(items); + } + + /// + /// Converts a sequence to an immutable array. + /// + /// Elemental type of the sequence. + /// The sequence to convert. + /// An immutable copy of the contents of the sequence. + /// If the sequence is null, this will return an empty array. + public static ImmutableArray AsImmutableOrEmpty(this IEnumerable? items) + { + if (items == null) + { + return ImmutableArray.Empty; + } + + return ImmutableArray.CreateRange(items); + } + + /// + /// Converts a sequence to an immutable array. + /// + /// Elemental type of the sequence. + /// The sequence to convert. + /// An immutable copy of the contents of the sequence. + /// If the sequence is null, this will return the default (null) array. + public static ImmutableArray AsImmutableOrNull(this IEnumerable? items) + { + if (items == null) + { + return default; + } + + return ImmutableArray.CreateRange(items); + } + + /// + /// Converts an array to an immutable array. The array must not be null. + /// + /// + /// The sequence to convert + /// + public static ImmutableArray AsImmutable(this T[] items) + { + Debug.Assert(items != null); + return ImmutableArray.Create(items); + } + + /// + /// Converts a array to an immutable array. + /// + /// + /// The sequence to convert + /// + /// If the sequence is null, this will return the default (null) array. + public static ImmutableArray AsImmutableOrNull(this T[]? items) + { + if (items == null) + { + return default; + } + + return ImmutableArray.Create(items); + } + + /// + /// Converts an array to an immutable array. + /// + /// + /// The sequence to convert + /// If the array is null, this will return an empty immutable array. + public static ImmutableArray AsImmutableOrEmpty(this T[]? items) + { + if (items == null) + { + return ImmutableArray.Empty; + } + + return ImmutableArray.Create(items); + } + + /// + /// Reads bytes from specified . + /// + /// The stream. + /// Read-only content of the stream. + public static ImmutableArray ToImmutable(this MemoryStream stream) + { + return ImmutableArray.Create(stream.ToArray()); + } + + /// + /// Maps an immutable array to another immutable array. + /// + /// + /// + /// The array to map + /// The mapping delegate + /// If the items's length is 0, this will return an empty immutable array + public static ImmutableArray SelectAsArray(this ImmutableArray items, Func map) + { + return ImmutableArray.CreateRange(items, map); + } + + /// + /// Maps an immutable array to another immutable array. + /// + /// + /// + /// + /// The sequence to map + /// The mapping delegate + /// The extra input used by mapping delegate + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectAsArray(this ImmutableArray items, Func map, TArg arg) + { + return ImmutableArray.CreateRange(items, map, arg); + } + + /// + /// Maps an immutable array to another immutable array. + /// + /// + /// + /// + /// The sequence to map + /// The mapping delegate + /// The extra input used by mapping delegate + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectAsArray(this ImmutableArray items, Func map, TArg arg) + { + switch (items.Length) + { + case 0: + return ImmutableArray.Empty; + + case 1: + return ImmutableArray.Create(map(items[0], 0, arg)); + + case 2: + return ImmutableArray.Create(map(items[0], 0, arg), map(items[1], 1, arg)); + + case 3: + return ImmutableArray.Create(map(items[0], 0, arg), map(items[1], 1, arg), map(items[2], 2, arg)); + + case 4: + return ImmutableArray.Create(map(items[0], 0, arg), map(items[1], 1, arg), map(items[2], 2, arg), map(items[3], 3, arg)); + + default: + var builder = ArrayBuilder.GetInstance(items.Length); + for (int i = 0; i < items.Length; i++) + { + builder.Add(map(items[i], i, arg)); + } + + return builder.ToImmutableAndFree(); + } + } + + /// + /// Maps a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectAsArray(this ImmutableArray array, Func predicate, Func selector) + { + if (array.Length == 0) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item)) + { + builder.Add(selector(item)); + } + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// Type of the extra argument + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// The extra input used by and . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectAsArray(this ImmutableArray array, Func predicate, Func selector, TArg arg) + { + if (array.Length == 0) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item, arg)) + { + builder.Add(selector(item, arg)); + } + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// A transform function to apply to each element. + /// If the array's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + builder.AddRange(selector(item)); + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// A transform function to apply to each element. + /// If the array's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + builder.AddRange(selector(item)); + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// A transform function to apply to each element. + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + selector(item).AddRangeTo(builder); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func predicate, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item)) + builder.AddRange(selector(item)); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func predicate, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item)) + builder.AddRange(selector(item)); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func predicate, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item)) + selector(item).AddRangeTo(builder); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the argument to pass to the predicate and selector + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func predicate, Func> selector, TArg arg) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item, arg)) + selector(item, arg).AddRangeTo(builder); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps an immutable array through a function that returns ValueTasks, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this ImmutableArray array, Func> selector, CancellationToken cancellationToken) + { + if (array.IsEmpty) + return ImmutableArray.Empty; + + var builder = new TResult[array.Length]; + + for (var i = 0; i < array.Length; i++) + { + builder[i] = await selector(array[i], cancellationToken).ConfigureAwait(false); + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + /// + /// Maps an immutable array through a function that returns ValueTasks, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this ImmutableArray array, Func> selector, TArg arg, CancellationToken cancellationToken) + { + if (array.IsEmpty) + return ImmutableArray.Empty; + + var builder = new TResult[array.Length]; + + for (var i = 0; i < array.Length; i++) + { + builder[i] = await selector(array[i], arg, cancellationToken).ConfigureAwait(false); + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + public static ValueTask> SelectManyAsArrayAsync(this ImmutableArray source, Func>> selector, TArg arg, CancellationToken cancellationToken) + { + if (source.Length == 0) + { + return new ValueTask>(ImmutableArray.Empty); + } + + if (source.Length == 1) + { + return selector(source[0], arg, cancellationToken); + } + + return CreateTaskAsync(); + + async ValueTask> CreateTaskAsync() + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.AddRange(await selector(item, arg, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + } + + /// + /// Zips two immutable arrays together through a mapping function, producing another immutable array. + /// + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray ZipAsArray(this ImmutableArray self, ImmutableArray other, Func map) + { + Debug.Assert(self.Length == other.Length); + switch (self.Length) + { + case 0: + return ImmutableArray.Empty; + + case 1: + return ImmutableArray.Create(map(self[0], other[0])); + + case 2: + return ImmutableArray.Create(map(self[0], other[0]), map(self[1], other[1])); + + case 3: + return ImmutableArray.Create(map(self[0], other[0]), map(self[1], other[1]), map(self[2], other[2])); + + case 4: + return ImmutableArray.Create(map(self[0], other[0]), map(self[1], other[1]), map(self[2], other[2]), map(self[3], other[3])); + + default: + var builder = new TResult[self.Length]; + for (int i = 0; i < self.Length; i++) + { + builder[i] = map(self[i], other[i]); + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + } + + public static ImmutableArray ZipAsArray(this ImmutableArray self, ImmutableArray other, TArg arg, Func map) + { + Debug.Assert(self.Length == other.Length); + if (self.IsEmpty) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(self.Length); + for (int i = 0; i < self.Length; i++) + { + builder.Add(map(self[i], other[i], i, arg)); + } + return builder.ToImmutableAndFree(); + } + + /// + /// Creates a new immutable array based on filtered elements by the predicate. The array must not be null. + /// + /// The array to process + /// The delegate that defines the conditions of the element to search for. + public static ImmutableArray WhereAsArray(this ImmutableArray array, Func predicate) + => WhereAsArrayImpl(array, predicate, predicateWithArg: null, arg: null); + + /// + /// Creates a new immutable array based on filtered elements by the predicate. The array must not be null. + /// + /// The array to process + /// The delegate that defines the conditions of the element to search for. + public static ImmutableArray WhereAsArray(this ImmutableArray array, Func predicate, TArg arg) + => WhereAsArrayImpl(array, predicateWithoutArg: null, predicate, arg); + + private static ImmutableArray WhereAsArrayImpl(ImmutableArray array, Func? predicateWithoutArg, Func? predicateWithArg, TArg arg) + { + Debug.Assert(!array.IsDefault); + Debug.Assert(predicateWithArg != null ^ predicateWithoutArg != null); + + ArrayBuilder? builder = null; + bool none = true; + bool all = true; + + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if ((predicateWithoutArg != null) ? predicateWithoutArg(a) : predicateWithArg!(a, arg)) + { + none = false; + if (all) + { + continue; + } + + Debug.Assert(i > 0); + if (builder == null) + { + builder = ArrayBuilder.GetInstance(); + } + + builder.Add(a); + } + else + { + if (none) + { + all = false; + continue; + } + + Debug.Assert(i > 0); + if (all) + { + Debug.Assert(builder == null); + all = false; + builder = ArrayBuilder.GetInstance(); + for (int j = 0; j < i; j++) + { + builder.Add(array[j]); + } + } + } + } + + if (builder != null) + { + Debug.Assert(!all); + Debug.Assert(!none); + return builder.ToImmutableAndFree(); + } + else if (all) + { + return array; + } + else + { + Debug.Assert(none); + return ImmutableArray.Empty; + } + } + + public static bool Any(this ImmutableArray array, Func predicate, TArg arg) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (predicate(a, arg)) + { + return true; + } + } + + return false; + } + + public static bool All(this ImmutableArray array, Func predicate, TArg arg) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (!predicate(a, arg)) + { + return false; + } + } + + return true; + } + + public static async Task AnyAsync(this ImmutableArray array, Func> predicateAsync) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (await predicateAsync(a).ConfigureAwait(false)) + { + return true; + } + } + + return false; + } + + public static async Task AnyAsync(this ImmutableArray array, Func> predicateAsync, TArg arg) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (await predicateAsync(a, arg).ConfigureAwait(false)) + { + return true; + } + } + + return false; + } + + public static async ValueTask FirstOrDefaultAsync(this ImmutableArray array, Func> predicateAsync) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (await predicateAsync(a).ConfigureAwait(false)) + { + return a; + } + } + + return default; + } + + public static TValue? FirstOrDefault(this ImmutableArray array, Func predicate, TArg arg) + { + foreach (var val in array) + { + if (predicate(val, arg)) + { + return val; + } + } + + return default; + } + + public static TValue Single(this ImmutableArray array, Func predicate, TArg arg) + { + var hasValue = false; + TValue? value = default; + foreach (var item in array) + { + if (predicate(item, arg)) + { + if (hasValue) + { + throw ExceptionUtilities.Unreachable(); + } + + value = item; + hasValue = true; + } + } + + if (!hasValue) + { + throw ExceptionUtilities.Unreachable(); + } + + return value!; + } + + /// + /// Casts the immutable array of a Type to an immutable array of its base type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ImmutableArray Cast(this ImmutableArray items) + where TDerived : class, TBase + { + return ImmutableArray.CastUp(items); + } + + /// + /// Determines whether this instance and another immutable array are equal. + /// + /// + /// + /// + /// The comparer to determine if the two arrays are equal. + /// True if the two arrays are equal + public static bool SetEquals(this ImmutableArray array1, ImmutableArray array2, IEqualityComparer comparer) + { + if (array1.IsDefault) + { + return array2.IsDefault; + } + else if (array2.IsDefault) + { + return false; + } + + var count1 = array1.Length; + var count2 = array2.Length; + + // avoid constructing HashSets in these common cases + if (count1 == 0) + { + return count2 == 0; + } + else if (count2 == 0) + { + return false; + } + else if (count1 == 1 && count2 == 1) + { + var item1 = array1[0]; + var item2 = array2[0]; + + return comparer.Equals(item1, item2); + } + + var set1 = new HashSet(array1, comparer); + var set2 = new HashSet(array2, comparer); + + // internally recognizes that set2 is a HashSet with the same comparer (http://msdn.microsoft.com/en-us/library/bb346516.aspx) + return set1.SetEquals(set2); + } + + /// + /// Returns an empty array if the input array is null (default) + /// + public static ImmutableArray NullToEmpty(this ImmutableArray array) + { + return array.IsDefault ? ImmutableArray.Empty : array; + } + + /// + /// Returns an empty array if the input nullable value type is null or the underlying array is null (default) + /// + public static ImmutableArray NullToEmpty(this ImmutableArray? array) + => array switch + { + null or { IsDefault: true } => ImmutableArray.Empty, + { } underlying => underlying + }; + + /// + /// Returns an array of distinct elements, preserving the order in the original array. + /// If the array has no duplicates, the original array is returned. The original array must not be null. + /// + public static ImmutableArray Distinct(this ImmutableArray array, IEqualityComparer? comparer = null) + { + Debug.Assert(!array.IsDefault); + + if (array.Length < 2) + { + return array; + } + + var set = new HashSet(comparer); + var builder = ArrayBuilder.GetInstance(); + foreach (var a in array) + { + if (set.Add(a)) + { + builder.Add(a); + } + } + + var result = (builder.Count == array.Length) ? array : builder.ToImmutable(); + builder.Free(); + return result; + } + + // In DEBUG, swap the first and last elements of a read-only array, yielding a new read only array. + // This helps to avoid depending on accidentally sorted arrays. + internal static ImmutableArray ConditionallyDeOrder(this ImmutableArray array) + { +#if DEBUG + if (!array.IsDefault && array.Length >= 2) + { + T[] copy = array.ToArray(); + int last = copy.Length - 1; + var temp = copy[0]; + copy[0] = copy[last]; + copy[last] = temp; + + return ImmutableCollectionsMarshal.AsImmutableArray(copy); + } +#endif + return array; + } + + internal static ImmutableArray Flatten( + this Dictionary> dictionary, + IComparer? comparer = null) + where TKey : notnull + { + if (dictionary.Count == 0) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + + foreach (var kvp in dictionary) + { + builder.AddRange(kvp.Value); + } + + if (comparer != null && builder.Count > 1) + { + // PERF: Beware ImmutableArray.Builder.Sort allocates a Comparer wrapper object + builder.Sort(comparer); + } + + return builder.ToImmutableAndFree(); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second) + { + return first.AddRange(second); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second, ImmutableArray third) + { + var builder = new T[first.Length + second.Length + third.Length]; + var index = 0; + + foreach (var item in first) + { + builder[index++] = item; + } + + foreach (var item in second) + { + builder[index++] = item; + } + + foreach (var item in third) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second, ImmutableArray third, ImmutableArray fourth) + { + var builder = new T[first.Length + second.Length + third.Length + fourth.Length]; + var index = 0; + + foreach (var item in first) + { + builder[index++] = item; + } + + foreach (var item in second) + { + builder[index++] = item; + } + + foreach (var item in third) + { + builder[index++] = item; + } + + foreach (var item in fourth) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second, ImmutableArray third, ImmutableArray fourth, ImmutableArray fifth) + { + var builder = new T[first.Length + second.Length + third.Length + fourth.Length + fifth.Length]; + var index = 0; + + foreach (var item in first) + { + builder[index++] = item; + } + + foreach (var item in second) + { + builder[index++] = item; + } + + foreach (var item in third) + { + builder[index++] = item; + } + + foreach (var item in fourth) + { + builder[index++] = item; + } + + foreach (var item in fifth) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second, ImmutableArray third, ImmutableArray fourth, ImmutableArray fifth, ImmutableArray sixth) + { + var builder = new T[first.Length + second.Length + third.Length + fourth.Length + fifth.Length + sixth.Length]; + var index = 0; + + foreach (var item in first) + { + builder[index++] = item; + } + + foreach (var item in second) + { + builder[index++] = item; + } + + foreach (var item in third) + { + builder[index++] = item; + } + + foreach (var item in fourth) + { + builder[index++] = item; + } + + foreach (var item in fifth) + { + builder[index++] = item; + } + + foreach (var item in sixth) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + internal static ImmutableArray Concat(this ImmutableArray first, T second) + { + return first.Add(second); + } + + internal static ImmutableArray AddRange(this ImmutableArray self, in TemporaryArray items) + { + if (items.Count == 0) + { + return self; + } + + if (items.Count == 1) + { + return self.Add(items[0]); + } + + var builder = new T[self.Length + items.Count]; + var index = 0; + + foreach (var item in self) + { + builder[index++] = item; + } + + foreach (var item in items) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + /// + /// Determines whether duplicates exist using default equality comparer. + /// + /// Array to search for duplicates + /// Whether duplicates were found + internal static bool HasDuplicates(this ImmutableArray array) + { + switch (array.Length) + { + case 0: + case 1: + return false; + + case 2: + return EqualityComparer.Default.Equals(array[0], array[1]); + + default: + var set = PooledHashSet.GetInstance(); + var foundDuplicate = false; + + foreach (var element in array) + { + if (!set.Add(element)) + { + foundDuplicate = true; + break; + } + } + + set.Free(); + return foundDuplicate; + } + } + + /// + /// Determines whether duplicates exist using . Use other override + /// if you don't need a custom comparer. + /// + /// Array to search for duplicates + /// Comparer to use in search + /// Whether duplicates were found + internal static bool HasDuplicates(this ImmutableArray array, IEqualityComparer comparer) + { + switch (array.Length) + { + case 0: + case 1: + return false; + + case 2: + comparer ??= EqualityComparer.Default; + return comparer.Equals(array[0], array[1]); + + default: + var set = new HashSet(comparer); + foreach (var element in array) + { + if (!set.Add(element)) + { + return true; + } + } + + return false; + } + } + + public static int Count(this ImmutableArray items, Func predicate) + { + if (items.IsEmpty) + { + return 0; + } + + int count = 0; + for (int i = 0; i < items.Length; ++i) + { + if (predicate(items[i])) + { + ++count; + } + } + + return count; + } + + public static int Sum(this ImmutableArray items, Func selector) + { + var sum = 0; + foreach (var item in items) + sum += selector(item); + + return sum; + } + + public static int Sum(this ImmutableArray items, Func selector) + { + var sum = 0; + for (var i = 0; i < items.Length; i++) + sum += selector(items[i], i); + + return sum; + } + + internal static void AddToMultiValueDictionaryBuilder(Dictionary accumulator, K key, T item) + where K : notnull + where T : notnull + { + if (accumulator.TryGetValue(key, out var existingValueOrArray)) + { + if (existingValueOrArray is ArrayBuilder arrayBuilder) + { + // Already a builder in the accumulator, just add to that. + } + else + { + // Just a single value in the accumulator so far. Convert to using a builder. + arrayBuilder = ArrayBuilder.GetInstance(capacity: 2); + arrayBuilder.Add((T)existingValueOrArray); + accumulator[key] = arrayBuilder; + } + + arrayBuilder.Add(item); + } + else + { + // Nothing in the dictionary so far. Add the item directly. + accumulator.Add(key, item); + } + } + + internal static void CreateNameToMembersMap + (Dictionary dictionary, Dictionary> result) + where TKey : notnull + where TNamespaceOrTypeSymbol : class + where TNamedTypeSymbol : class, TNamespaceOrTypeSymbol + where TNamespaceSymbol : class, TNamespaceOrTypeSymbol + { + foreach (var entry in dictionary) + result.Add(entry.Key, createMembers(entry.Value)); + + return; + + static ImmutableArray createMembers(object value) + { + if (value is ArrayBuilder builder) + { + Debug.Assert(builder.Count > 1); + foreach (var item in builder) + { + if (item is TNamespaceSymbol) + return builder.ToImmutableAndFree(); + } + + return ImmutableArray.CastUp(builder.ToDowncastedImmutableAndFree()); + } + else + { + TNamespaceOrTypeSymbol symbol = (TNamespaceOrTypeSymbol)value; + return symbol is TNamespaceSymbol + ? ImmutableArray.Create(symbol) + : ImmutableArray.CastUp(ImmutableArray.Create((TNamedTypeSymbol)symbol)); + } + } + } + + internal static Dictionary> GetTypesFromMemberMap + (Dictionary> map, IEqualityComparer comparer) + where TKey : notnull + where TNamespaceOrTypeSymbol : class + where TNamedTypeSymbol : class, TNamespaceOrTypeSymbol + { + // Initialize dictionary capacity to avoid resize allocations during Add calls. + // Most iterations through the loop add an entry. If map is smaller than the + // smallest capacity dictionary will use, we'll let it grow organically as + // it's possible we might not add anything to the dictionary. + var capacity = map.Count > 3 ? map.Count : 0; + + var dictionary = new Dictionary>(capacity, comparer); + + foreach (var entry in map) + { + var namedTypes = getOrCreateNamedTypes(entry.Value); + if (namedTypes.Length > 0) + dictionary.Add(entry.Key, namedTypes); + } + + return dictionary; + + static ImmutableArray getOrCreateNamedTypes(ImmutableArray members) + { + Debug.Assert(members.Length > 0); + + // See if creator 'map' put a downcasted ImmutableArray in it. If so, we can just directly + // downcast to that and trivially reuse it. If not, that means the array must have contained at least one + // TNamespaceSymbol and we'll need to filter that out. + var membersAsNamedTypes = members.As(); + + if (!membersAsNamedTypes.IsDefault) + return membersAsNamedTypes; + + // Preallocate the right amount so we can avoid garbage reallocs. + var count = members.Count(static s => s is TNamedTypeSymbol); + + // Must have less items than in the original array. Otherwise, the .As() cast would + // have succeeded. + Debug.Assert(count < members.Length); + + if (count == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(count); + foreach (var member in members) + { + if (member is TNamedTypeSymbol namedType) + builder.Add(namedType); + } + + Debug.Assert(builder.Count == count); + return builder.ToImmutableAndFree(); + } + } + + internal static bool SequenceEqual(this ImmutableArray array1, ImmutableArray array2, TArg arg, Func predicate) + { + // The framework implementation of SequenceEqual forces a NullRef for default array1 and 2, so we + // maintain the same behavior in this extension + if (array1.IsDefault) + { + throw new NullReferenceException(); + } + + if (array2.IsDefault) + { + throw new NullReferenceException(); + } + + if (array1.Length != array2.Length) + { + return false; + } + + for (int i = 0; i < array1.Length; i++) + { + if (!predicate(array1[i], array2[i], arg)) + { + return false; + } + } + + return true; + } + + internal static int IndexOf(this ImmutableArray array, T item, IEqualityComparer comparer) + => array.IndexOf(item, startIndex: 0, comparer); + + internal static bool IsSorted(this ImmutableArray array, Comparison comparison) + => IsSorted(array, Comparer.Create(comparison)); + + internal static bool IsSorted(this ImmutableArray array, IComparer? comparer = null) + { + comparer ??= Comparer.Default; + + for (var i = 1; i < array.Length; i++) + { + if (comparer.Compare(array[i - 1], array[i]) > 0) + { + return false; + } + } + + return true; + } + + // same as Array.BinarySearch but the ability to pass arbitrary value to the comparer without allocation + internal static int BinarySearch(this ImmutableArray array, TValue value, Func comparer) + => BinarySearch(array.AsSpan(), value, comparer); + + internal static int BinarySearch(this ReadOnlySpan array, TValue value, Func comparer) + { + int low = 0; + int high = array.Length - 1; + + while (low <= high) + { + int middle = low + ((high - low) >> 1); + int comparison = comparer(array[middle], value); + + if (comparison == 0) + { + return middle; + } + + if (comparison > 0) + { + high = middle - 1; + } + else + { + low = middle + 1; + } + } + + return ~low; + } + + internal static int BinarySearch(this ImmutableSegmentedList array, TValue value, Func comparer) + { + int low = 0; + int high = array.Count - 1; + + while (low <= high) + { + int middle = low + ((high - low) >> 1); + int comparison = comparer(array[middle], value); + + if (comparison == 0) + { + return middle; + } + + if (comparison > 0) + { + high = middle - 1; + } + else + { + low = middle + 1; + } + } + + return ~low; + } + + public static bool IsSubsetOf(this ImmutableArray array, ImmutableArray other) + { + if (other.Length == 0) + { + return array.Length == 0; + } + + switch (array.Length) + { + case 0: + return true; + case 1: + return other.Contains(array[0]); + case 2: + return other.Contains(array[0]) && other.Contains(array[1]); + case 3: + return other.Contains(array[0]) && other.Contains(array[1]) && other.Contains(array[2]); + } + + var set = PooledHashSet.GetInstance(); + foreach (var item in other) + { + set.Add(item); + } + + foreach (var item in array) + { + if (!set.Contains(item)) + { + set.Free(); + return false; + } + } + + set.Free(); + return true; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ArraySortHelper.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ArraySortHelper.cs new file mode 100755 index 00000000000..0d60317f3ef --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ArraySortHelper.cs @@ -0,0 +1,1304 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +#if NET +using System.Numerics; +#else +using System.Runtime.InteropServices; +#endif + +#pragma warning disable CA1822 + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + #region ArraySortHelper for single arrays + + internal static class SegmentedArraySortHelper + { + public static void Sort(SegmentedArraySegment keys, IComparer? comparer) + { + // Add a try block here to detect IComparers (or their + // underlying IComparables, etc) that are bogus. + try + { + comparer ??= Comparer.Default; + IntrospectiveSort(keys, comparer.Compare); + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + public static int BinarySearch(SegmentedArray array, int index, int length, T value, IComparer? comparer) + { + try + { + comparer ??= Comparer.Default; + return InternalBinarySearch(array, index, length, value, comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + return 0; + } + } + + internal static void Sort(SegmentedArraySegment keys, Comparison comparer) + { + Debug.Assert(comparer != null, "Check the arguments in the caller!"); + + // Add a try block here to detect bogus comparisons + try + { + IntrospectiveSort(keys, comparer!); + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + internal static int InternalBinarySearch(SegmentedArray array, int index, int length, T value, IComparer comparer) + { + Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!"); + + int lo = index; + int hi = index + length - 1; + while (lo <= hi) + { + int i = lo + ((hi - lo) >> 1); + int order = comparer.Compare(array[i], value); + + if (order == 0) + return i; + if (order < 0) + { + lo = i + 1; + } + else + { + hi = i - 1; + } + } + + return ~lo; + } + + private static void SwapIfGreater(SegmentedArraySegment keys, Comparison comparer, int i, int j) + { + Debug.Assert(i != j); + + if (comparer(keys[i], keys[j]) > 0) + { + T key = keys[i]; + keys[i] = keys[j]; + keys[j] = key; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(SegmentedArraySegment a, int i, int j) + { + Debug.Assert(i != j); + + T t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + internal static void IntrospectiveSort(SegmentedArraySegment keys, Comparison comparer) + { + Debug.Assert(comparer != null); + + if (keys.Length > 1) + { + IntroSort(keys, 2 * (SegmentedArraySortUtils.Log2((uint)keys.Length) + 1), comparer!); + } + } + + // IntroSort is recursive; block it from being inlined into itself as + // this is currenly not profitable. + [MethodImpl(MethodImplOptions.NoInlining)] + private static void IntroSort(SegmentedArraySegment keys, int depthLimit, Comparison comparer) + { + Debug.Assert(keys.Length > 0); + Debug.Assert(depthLimit >= 0); + Debug.Assert(comparer != null); + + int partitionSize = keys.Length; + while (partitionSize > 1) + { + if (partitionSize <= SegmentedArrayHelper.IntrosortSizeThreshold) + { + + if (partitionSize == 2) + { + SwapIfGreater(keys, comparer!, 0, 1); + return; + } + + if (partitionSize == 3) + { + SwapIfGreater(keys, comparer!, 0, 1); + SwapIfGreater(keys, comparer!, 0, 2); + SwapIfGreater(keys, comparer!, 1, 2); + return; + } + + InsertionSort(keys.Slice(0, partitionSize), comparer!); + return; + } + + if (depthLimit == 0) + { + HeapSort(keys.Slice(0, partitionSize), comparer!); + return; + } + depthLimit--; + + int p = PickPivotAndPartition(keys.Slice(0, partitionSize), comparer!); + + // Note we've already partitioned around the pivot and do not have to move the pivot again. + IntroSort(keys.Slice(p + 1, partitionSize - (p + 1)), depthLimit, comparer!); + partitionSize = p; + } + } + + private static int PickPivotAndPartition(SegmentedArraySegment keys, Comparison comparer) + { + Debug.Assert(keys.Length >= SegmentedArrayHelper.IntrosortSizeThreshold); + Debug.Assert(comparer != null); + + int hi = keys.Length - 1; + + // Compute median-of-three. But also partition them, since we've done the comparison. + int middle = hi >> 1; + + // Sort lo, mid and hi appropriately, then pick mid as the pivot. + SwapIfGreater(keys, comparer!, 0, middle); // swap the low with the mid point + SwapIfGreater(keys, comparer!, 0, hi); // swap the low with the high + SwapIfGreater(keys, comparer!, middle, hi); // swap the middle with the high + + T pivot = keys[middle]; + Swap(keys, middle, hi - 1); + int left = 0, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below. + + while (left < right) + { + while (comparer!(keys[++left], pivot) < 0) + { + // Intentionally empty + } + + while (comparer(pivot, keys[--right]) < 0) + { + // Intentionally empty + } + + if (left >= right) + break; + + Swap(keys, left, right); + } + + // Put pivot in the right location. + if (left != hi - 1) + { + Swap(keys, left, hi - 1); + } + return left; + } + + private static void HeapSort(SegmentedArraySegment keys, Comparison comparer) + { + Debug.Assert(comparer != null); + Debug.Assert(keys.Length > 0); + + int n = keys.Length; + for (int i = n >> 1; i >= 1; i--) + { + DownHeap(keys, i, n, comparer!); + } + + for (int i = n; i > 1; i--) + { + Swap(keys, 0, i - 1); + DownHeap(keys, 1, i - 1, comparer!); + } + } + + private static void DownHeap(SegmentedArraySegment keys, int i, int n, Comparison comparer) + { + Debug.Assert(comparer != null); + + T d = keys[i - 1]; + while (i <= n >> 1) + { + int child = 2 * i; + if (child < n && comparer!(keys[child - 1], keys[child]) < 0) + { + child++; + } + + if (!(comparer!(d, keys[child - 1]) < 0)) + break; + + keys[i - 1] = keys[child - 1]; + i = child; + } + + keys[i - 1] = d; + } + + private static void InsertionSort(SegmentedArraySegment keys, Comparison comparer) + { + for (int i = 0; i < keys.Length - 1; i++) + { + T t = keys[i + 1]; + + int j = i; + while (j >= 0 && comparer(t, keys[j]) < 0) + { + keys[j + 1] = keys[j]; + j--; + } + + keys[j + 1] = t; + } + } + } + + internal static class SegmentedGenericArraySortHelper + where T : IComparable + { + public static void Sort(SegmentedArraySegment keys, IComparer? comparer) + { + try + { + if (comparer == null || comparer == Comparer.Default) + { + if (keys.Length > 1) + { + // For floating-point, do a pre-pass to move all NaNs to the beginning + // so that we can do an optimized comparison as part of the actual sort + // on the remainder of the values. + if (typeof(T) == typeof(double) + || typeof(T) == typeof(float) +#if NET + || typeof(T) == typeof(Half) +#endif + ) + { + int nanLeft = SegmentedArraySortUtils.MoveNansToFront(keys, default(Span)); + if (nanLeft == keys.Length) + { + return; + } + keys = keys.Slice(nanLeft); + } + + IntroSort(keys, 2 * (SegmentedArraySortUtils.Log2((uint)keys.Length) + 1)); + } + } + else + { + SegmentedArraySortHelper.IntrospectiveSort(keys, comparer.Compare); + } + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + public static int BinarySearch(SegmentedArray array, int index, int length, T value, IComparer? comparer) + { + Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!"); + + try + { + if (comparer == null || comparer == Comparer.Default) + { + return BinarySearch(array, index, length, value); + } + else + { + return SegmentedArraySortHelper.InternalBinarySearch(array, index, length, value, comparer); + } + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + return 0; + } + } + + // This function is called when the user doesn't specify any comparer. + // Since T is constrained here, we can call IComparable.CompareTo here. + // We can avoid boxing for value type and casting for reference types. + private static int BinarySearch(SegmentedArray array, int index, int length, T value) + { + int lo = index; + int hi = index + length - 1; + while (lo <= hi) + { + int i = lo + ((hi - lo) >> 1); + int order; + if (array[i] == null) + { + order = (value == null) ? 0 : -1; + } + else + { + order = array[i].CompareTo(value!); + } + + if (order == 0) + { + return i; + } + + if (order < 0) + { + lo = i + 1; + } + else + { + hi = i - 1; + } + } + + return ~lo; + } + + /// Swaps the values in the two references if the first is greater than the second. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SwapIfGreater(ref T i, ref T j) + { + if (i != null && GreaterThan(ref i, ref j)) + { + Swap(ref i, ref j); + } + } + + /// Swaps the values in the two references, regardless of whether the two references are the same. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(ref T i, ref T j) + { + Debug.Assert(!Unsafe.AreSame(ref i, ref j)); + + T t = i; + i = j; + j = t; + } + + // IntroSort is recursive; block it from being inlined into itself as + // this is currenly not profitable. + [MethodImpl(MethodImplOptions.NoInlining)] + private static void IntroSort(SegmentedArraySegment keys, int depthLimit) + { + Debug.Assert(keys.Length > 0); + Debug.Assert(depthLimit >= 0); + + int partitionSize = keys.Length; + while (partitionSize > 1) + { + if (partitionSize <= SegmentedArrayHelper.IntrosortSizeThreshold) + { + if (partitionSize == 2) + { + SwapIfGreater(ref keys[0], ref keys[1]); + return; + } + + if (partitionSize == 3) + { + ref T hiRef = ref keys[2]; + ref T him1Ref = ref keys[1]; + ref T loRef = ref keys[0]; + + SwapIfGreater(ref loRef, ref him1Ref); + SwapIfGreater(ref loRef, ref hiRef); + SwapIfGreater(ref him1Ref, ref hiRef); + return; + } + + InsertionSort(keys.Slice(0, partitionSize)); + return; + } + + if (depthLimit == 0) + { + HeapSort(keys.Slice(0, partitionSize)); + return; + } + depthLimit--; + + int p = PickPivotAndPartition(keys.Slice(0, partitionSize)); + + // Note we've already partitioned around the pivot and do not have to move the pivot again. + IntroSort(keys.Slice(p + 1, partitionSize - (p + 1)), depthLimit); + partitionSize = p; + } + } + + private static int PickPivotAndPartition(SegmentedArraySegment keys) + { + Debug.Assert(keys.Length >= SegmentedArrayHelper.IntrosortSizeThreshold); + + // Use median-of-three to select a pivot. Grab a reference to the 0th, Length-1th, and Length/2th elements, and sort them. + int zeroIndex = 0; + int lastIndex = keys.Length - 1; + int middleIndex = (keys.Length - 1) >> 1; + SwapIfGreater(ref keys[zeroIndex], ref keys[middleIndex]); + SwapIfGreater(ref keys[zeroIndex], ref keys[lastIndex]); + SwapIfGreater(ref keys[middleIndex], ref keys[lastIndex]); + + // Select the middle value as the pivot, and move it to be just before the last element. + int nextToLastIndex = keys.Length - 2; + T pivot = keys[middleIndex]; + Swap(ref keys[middleIndex], ref keys[nextToLastIndex]); + + // Walk the left and right pointers, swapping elements as necessary, until they cross. + int leftIndex = zeroIndex, rightIndex = nextToLastIndex; + while (leftIndex < rightIndex) + { + if (pivot == null) + { + while (leftIndex < nextToLastIndex && keys[++leftIndex] == null) + { + // Intentionally empty + } + + while (rightIndex > zeroIndex && keys[--rightIndex] != null) + { + // Intentionally empty + } + } + else + { + while (leftIndex < nextToLastIndex && GreaterThan(ref pivot, ref keys[++leftIndex])) + { + // Intentionally empty + } + + while (rightIndex > zeroIndex && LessThan(ref pivot, ref keys[--rightIndex])) + { + // Intentionally empty + } + } + + if (leftIndex >= rightIndex) + { + break; + } + + Swap(ref keys[leftIndex], ref keys[rightIndex]); + } + + // Put the pivot in the correct location. + if (leftIndex != nextToLastIndex) + { + Swap(ref keys[leftIndex], ref keys[nextToLastIndex]); + } + + return leftIndex; + } + + private static void HeapSort(SegmentedArraySegment keys) + { + Debug.Assert(keys.Length > 0); + + int n = keys.Length; + for (int i = n >> 1; i >= 1; i--) + { + DownHeap(keys, i, n); + } + + for (int i = n; i > 1; i--) + { + Swap(ref keys[0], ref keys[i - 1]); + DownHeap(keys, 1, i - 1); + } + } + + private static void DownHeap(SegmentedArraySegment keys, int i, int n) + { + T d = keys[i - 1]; + while (i <= n >> 1) + { + int child = 2 * i; + if (child < n && (keys[child - 1] == null || LessThan(ref keys[child - 1], ref keys[child]))) + { + child++; + } + + if (keys[child - 1] == null || !LessThan(ref d, ref keys[child - 1])) + break; + + keys[i - 1] = keys[child - 1]; + i = child; + } + + keys[i - 1] = d; + } + + private static void InsertionSort(SegmentedArraySegment keys) + { + for (int i = 0; i < keys.Length - 1; i++) + { + T t = keys[i + 1]; + + int j = i; + while (j >= 0 && (t == null || LessThan(ref t, ref keys[j]))) + { + keys[j + 1] = keys[j]; + j--; + } + + keys[j + 1] = t!; + } + } + + // - These methods exist for use in sorting, where the additional operations present in + // the CompareTo methods that would otherwise be used on these primitives add non-trivial overhead, + // in particular for floating point where the CompareTo methods need to factor in NaNs. + // - The floating-point comparisons here assume no NaNs, which is valid only because the sorting routines + // themselves special-case NaN with a pre-pass that ensures none are present in the values being sorted + // by moving them all to the front first and then sorting the rest. + // - These are duplicated here rather than being on a helper type due to current limitations around generic inlining. + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // compiles to a single comparison or method call + private static bool LessThan(ref T left, ref T right) + { + if (typeof(T) == typeof(byte)) + return (byte)(object)left < (byte)(object)right; + if (typeof(T) == typeof(sbyte)) + return (sbyte)(object)left < (sbyte)(object)right; + if (typeof(T) == typeof(ushort)) + return (ushort)(object)left < (ushort)(object)right; + if (typeof(T) == typeof(short)) + return (short)(object)left < (short)(object)right; + if (typeof(T) == typeof(uint)) + return (uint)(object)left < (uint)(object)right; + if (typeof(T) == typeof(int)) + return (int)(object)left < (int)(object)right; + if (typeof(T) == typeof(ulong)) + return (ulong)(object)left < (ulong)(object)right; + if (typeof(T) == typeof(long)) + return (long)(object)left < (long)(object)right; + if (typeof(T) == typeof(UIntPtr)) + return (nuint)(object)left < (nuint)(object)right; + if (typeof(T) == typeof(IntPtr)) + return (nint)(object)left < (nint)(object)right; + if (typeof(T) == typeof(float)) + return (float)(object)left < (float)(object)right; + if (typeof(T) == typeof(double)) + return (double)(object)left < (double)(object)right; +#if NET + if (typeof(T) == typeof(Half)) + return (Half)(object)left < (Half)(object)right; +#endif + return left.CompareTo(right) < 0 ? true : false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // compiles to a single comparison or method call + private static bool GreaterThan(ref T left, ref T right) + { + if (typeof(T) == typeof(byte)) + return (byte)(object)left > (byte)(object)right; + if (typeof(T) == typeof(sbyte)) + return (sbyte)(object)left > (sbyte)(object)right; + if (typeof(T) == typeof(ushort)) + return (ushort)(object)left > (ushort)(object)right; + if (typeof(T) == typeof(short)) + return (short)(object)left > (short)(object)right; + if (typeof(T) == typeof(uint)) + return (uint)(object)left > (uint)(object)right; + if (typeof(T) == typeof(int)) + return (int)(object)left > (int)(object)right; + if (typeof(T) == typeof(ulong)) + return (ulong)(object)left > (ulong)(object)right; + if (typeof(T) == typeof(long)) + return (long)(object)left > (long)(object)right; + if (typeof(T) == typeof(UIntPtr)) + return (nuint)(object)left > (nuint)(object)right; + if (typeof(T) == typeof(IntPtr)) + return (nint)(object)left > (nint)(object)right; + if (typeof(T) == typeof(float)) + return (float)(object)left > (float)(object)right; + if (typeof(T) == typeof(double)) + return (double)(object)left > (double)(object)right; +#if NET + if (typeof(T) == typeof(Half)) + return (Half)(object)left > (Half)(object)right; +#endif + return left.CompareTo(right) > 0 ? true : false; + } + } + + #endregion + + #region ArraySortHelper for paired key and value arrays + + internal static class SegmentedArraySortHelper + { + public static void Sort(SegmentedArraySegment keys, Span values, IComparer? comparer) + { + // Add a try block here to detect IComparers (or their + // underlying IComparables, etc) that are bogus. + try + { + IntrospectiveSort(keys, values, comparer ?? Comparer.Default); + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + private static void SwapIfGreaterWithValues(SegmentedArraySegment keys, Span values, IComparer comparer, int i, int j) + { + Debug.Assert(comparer != null); + Debug.Assert(0 <= i && i < keys.Length && i < values.Length); + Debug.Assert(0 <= j && j < keys.Length && j < values.Length); + Debug.Assert(i != j); + + if (comparer!.Compare(keys[i], keys[j]) > 0) + { + TKey key = keys[i]; + keys[i] = keys[j]; + keys[j] = key; + + TValue value = values[i]; + values[i] = values[j]; + values[j] = value; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(SegmentedArraySegment keys, Span values, int i, int j) + { + Debug.Assert(i != j); + + TKey k = keys[i]; + keys[i] = keys[j]; + keys[j] = k; + + TValue v = values[i]; + values[i] = values[j]; + values[j] = v; + } + + internal static void IntrospectiveSort(SegmentedArraySegment keys, Span values, IComparer comparer) + { + Debug.Assert(comparer != null); + Debug.Assert(keys.Length == values.Length); + + if (keys.Length > 1) + { + IntroSort(keys, values, 2 * (SegmentedArraySortUtils.Log2((uint)keys.Length) + 1), comparer!); + } + } + + private static void IntroSort(SegmentedArraySegment keys, Span values, int depthLimit, IComparer comparer) + { + Debug.Assert(keys.Length > 0); + Debug.Assert(values.Length == keys.Length); + Debug.Assert(depthLimit >= 0); + Debug.Assert(comparer != null); + + int partitionSize = keys.Length; + while (partitionSize > 1) + { + if (partitionSize <= SegmentedArrayHelper.IntrosortSizeThreshold) + { + + if (partitionSize == 2) + { + SwapIfGreaterWithValues(keys, values, comparer!, 0, 1); + return; + } + + if (partitionSize == 3) + { + SwapIfGreaterWithValues(keys, values, comparer!, 0, 1); + SwapIfGreaterWithValues(keys, values, comparer!, 0, 2); + SwapIfGreaterWithValues(keys, values, comparer!, 1, 2); + return; + } + + InsertionSort(keys.Slice(0, partitionSize), values.Slice(0, partitionSize), comparer!); + return; + } + + if (depthLimit == 0) + { + HeapSort(keys.Slice(0, partitionSize), values.Slice(0, partitionSize), comparer!); + return; + } + depthLimit--; + + int p = PickPivotAndPartition(keys.Slice(0, partitionSize), values.Slice(0, partitionSize), comparer!); + + // Note we've already partitioned around the pivot and do not have to move the pivot again. + IntroSort(keys.Slice(p + 1, partitionSize - (p + 1)), values.Slice(p + 1, partitionSize - (p + 1)), depthLimit, comparer!); + partitionSize = p; + } + } + + private static int PickPivotAndPartition(SegmentedArraySegment keys, Span values, IComparer comparer) + { + Debug.Assert(keys.Length >= SegmentedArrayHelper.IntrosortSizeThreshold); + Debug.Assert(comparer != null); + + int hi = keys.Length - 1; + + // Compute median-of-three. But also partition them, since we've done the comparison. + int middle = hi >> 1; + + // Sort lo, mid and hi appropriately, then pick mid as the pivot. + SwapIfGreaterWithValues(keys, values, comparer!, 0, middle); // swap the low with the mid point + SwapIfGreaterWithValues(keys, values, comparer!, 0, hi); // swap the low with the high + SwapIfGreaterWithValues(keys, values, comparer!, middle, hi); // swap the middle with the high + + TKey pivot = keys[middle]; + Swap(keys, values, middle, hi - 1); + int left = 0, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below. + + while (left < right) + { + while (comparer!.Compare(keys[++left], pivot) < 0) + { + // Intentionally empty + } + + while (comparer.Compare(pivot, keys[--right]) < 0) + { + // Intentionally empty + } + + if (left >= right) + break; + + Swap(keys, values, left, right); + } + + // Put pivot in the right location. + if (left != hi - 1) + { + Swap(keys, values, left, hi - 1); + } + return left; + } + + private static void HeapSort(SegmentedArraySegment keys, Span values, IComparer comparer) + { + Debug.Assert(comparer != null); + Debug.Assert(keys.Length > 0); + + int n = keys.Length; + for (int i = n >> 1; i >= 1; i--) + { + DownHeap(keys, values, i, n, comparer!); + } + + for (int i = n; i > 1; i--) + { + Swap(keys, values, 0, i - 1); + DownHeap(keys, values, 1, i - 1, comparer!); + } + } + + private static void DownHeap(SegmentedArraySegment keys, Span values, int i, int n, IComparer comparer) + { + Debug.Assert(comparer != null); + + TKey d = keys[i - 1]; + TValue dValue = values[i - 1]; + + while (i <= n >> 1) + { + int child = 2 * i; + if (child < n && comparer!.Compare(keys[child - 1], keys[child]) < 0) + { + child++; + } + + if (!(comparer!.Compare(d, keys[child - 1]) < 0)) + break; + + keys[i - 1] = keys[child - 1]; + values[i - 1] = values[child - 1]; + i = child; + } + + keys[i - 1] = d; + values[i - 1] = dValue; + } + + private static void InsertionSort(SegmentedArraySegment keys, Span values, IComparer comparer) + { + Debug.Assert(comparer != null); + + for (int i = 0; i < keys.Length - 1; i++) + { + TKey t = keys[i + 1]; + TValue tValue = values[i + 1]; + + int j = i; + while (j >= 0 && comparer!.Compare(t, keys[j]) < 0) + { + keys[j + 1] = keys[j]; + values[j + 1] = values[j]; + j--; + } + + keys[j + 1] = t; + values[j + 1] = tValue; + } + } + } + + internal static class SegmentedGenericArraySortHelper + where TKey : IComparable + { + public static void Sort(SegmentedArraySegment keys, Span values, IComparer? comparer) + { + // Add a try block here to detect IComparers (or their + // underlying IComparables, etc) that are bogus. + try + { + if (comparer == null || comparer == Comparer.Default) + { + if (keys.Length > 1) + { + // For floating-point, do a pre-pass to move all NaNs to the beginning + // so that we can do an optimized comparison as part of the actual sort + // on the remainder of the values. + if (typeof(TKey) == typeof(double) + || typeof(TKey) == typeof(float) +#if NET + || typeof(TKey) == typeof(Half) +#endif + ) + { + int nanLeft = SegmentedArraySortUtils.MoveNansToFront(keys, values); + if (nanLeft == keys.Length) + { + return; + } + keys = keys.Slice(nanLeft); + values = values.Slice(nanLeft); + } + + IntroSort(keys, values, 2 * (SegmentedArraySortUtils.Log2((uint)keys.Length) + 1)); + } + } + else + { + SegmentedArraySortHelper.IntrospectiveSort(keys, values, comparer); + } + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + private static void SwapIfGreaterWithValues(SegmentedArraySegment keys, Span values, int i, int j) + { + Debug.Assert(i != j); + + ref TKey keyRef = ref keys[i]; + if (keyRef != null && GreaterThan(ref keyRef, ref keys[j])) + { + TKey key = keyRef; + keys[i] = keys[j]; + keys[j] = key; + + TValue value = values[i]; + values[i] = values[j]; + values[j] = value; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(SegmentedArraySegment keys, Span values, int i, int j) + { + Debug.Assert(i != j); + + TKey k = keys[i]; + keys[i] = keys[j]; + keys[j] = k; + + TValue v = values[i]; + values[i] = values[j]; + values[j] = v; + } + + private static void IntroSort(SegmentedArraySegment keys, Span values, int depthLimit) + { + Debug.Assert(keys.Length > 0); + Debug.Assert(values.Length == keys.Length); + Debug.Assert(depthLimit >= 0); + + int partitionSize = keys.Length; + while (partitionSize > 1) + { + if (partitionSize <= SegmentedArrayHelper.IntrosortSizeThreshold) + { + + if (partitionSize == 2) + { + SwapIfGreaterWithValues(keys, values, 0, 1); + return; + } + + if (partitionSize == 3) + { + SwapIfGreaterWithValues(keys, values, 0, 1); + SwapIfGreaterWithValues(keys, values, 0, 2); + SwapIfGreaterWithValues(keys, values, 1, 2); + return; + } + + InsertionSort(keys.Slice(0, partitionSize), values.Slice(0, partitionSize)); + return; + } + + if (depthLimit == 0) + { + HeapSort(keys.Slice(0, partitionSize), values.Slice(0, partitionSize)); + return; + } + depthLimit--; + + int p = PickPivotAndPartition(keys.Slice(0, partitionSize), values.Slice(0, partitionSize)); + + // Note we've already partitioned around the pivot and do not have to move the pivot again. + IntroSort(keys.Slice(p + 1, partitionSize - (p + 1)), values.Slice(p + 1, partitionSize - (p + 1)), depthLimit); + partitionSize = p; + } + } + + private static int PickPivotAndPartition(SegmentedArraySegment keys, Span values) + { + Debug.Assert(keys.Length >= SegmentedArrayHelper.IntrosortSizeThreshold); + + int hi = keys.Length - 1; + + // Compute median-of-three. But also partition them, since we've done the comparison. + int middle = hi >> 1; + + // Sort lo, mid and hi appropriately, then pick mid as the pivot. + SwapIfGreaterWithValues(keys, values, 0, middle); // swap the low with the mid point + SwapIfGreaterWithValues(keys, values, 0, hi); // swap the low with the high + SwapIfGreaterWithValues(keys, values, middle, hi); // swap the middle with the high + + TKey pivot = keys[middle]; + Swap(keys, values, middle, hi - 1); + int left = 0, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below. + + while (left < right) + { + if (pivot == null) + { + while (left < (hi - 1) && keys[++left] == null) + { + // Intentionally empty + } + + while (right > 0 && keys[--right] != null) + { + // Intentionally empty + } + } + else + { + while (GreaterThan(ref pivot, ref keys[++left])) + { + // Intentionally empty + } + + while (LessThan(ref pivot, ref keys[--right])) + { + // Intentionally empty + } + } + + if (left >= right) + break; + + Swap(keys, values, left, right); + } + + // Put pivot in the right location. + if (left != hi - 1) + { + Swap(keys, values, left, hi - 1); + } + return left; + } + + private static void HeapSort(SegmentedArraySegment keys, Span values) + { + Debug.Assert(keys.Length > 0); + + int n = keys.Length; + for (int i = n >> 1; i >= 1; i--) + { + DownHeap(keys, values, i, n); + } + + for (int i = n; i > 1; i--) + { + Swap(keys, values, 0, i - 1); + DownHeap(keys, values, 1, i - 1); + } + } + + private static void DownHeap(SegmentedArraySegment keys, Span values, int i, int n) + { + TKey d = keys[i - 1]; + TValue dValue = values[i - 1]; + + while (i <= n >> 1) + { + int child = 2 * i; + if (child < n && (keys[child - 1] == null || LessThan(ref keys[child - 1], ref keys[child]))) + { + child++; + } + + if (keys[child - 1] == null || !LessThan(ref d, ref keys[child - 1])) + break; + + keys[i - 1] = keys[child - 1]; + values[i - 1] = values[child - 1]; + i = child; + } + + keys[i - 1] = d; + values[i - 1] = dValue; + } + + private static void InsertionSort(SegmentedArraySegment keys, Span values) + { + for (int i = 0; i < keys.Length - 1; i++) + { + TKey t = keys[i + 1]; + TValue tValue = values[i + 1]; + + int j = i; + while (j >= 0 && (t == null || LessThan(ref t, ref keys[j]))) + { + keys[j + 1] = keys[j]; + values[j + 1] = values[j]; + j--; + } + + keys[j + 1] = t!; + values[j + 1] = tValue; + } + } + + // - These methods exist for use in sorting, where the additional operations present in + // the CompareTo methods that would otherwise be used on these primitives add non-trivial overhead, + // in particular for floating point where the CompareTo methods need to factor in NaNs. + // - The floating-point comparisons here assume no NaNs, which is valid only because the sorting routines + // themselves special-case NaN with a pre-pass that ensures none are present in the values being sorted + // by moving them all to the front first and then sorting the rest. + // - These are duplicated here rather than being on a helper type due to current limitations around generic inlining. + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // compiles to a single comparison or method call + private static bool LessThan(ref TKey left, ref TKey right) + { + if (typeof(TKey) == typeof(byte)) + return (byte)(object)left < (byte)(object)right; + if (typeof(TKey) == typeof(sbyte)) + return (sbyte)(object)left < (sbyte)(object)right; + if (typeof(TKey) == typeof(ushort)) + return (ushort)(object)left < (ushort)(object)right; + if (typeof(TKey) == typeof(short)) + return (short)(object)left < (short)(object)right; + if (typeof(TKey) == typeof(uint)) + return (uint)(object)left < (uint)(object)right; + if (typeof(TKey) == typeof(int)) + return (int)(object)left < (int)(object)right; + if (typeof(TKey) == typeof(ulong)) + return (ulong)(object)left < (ulong)(object)right; + if (typeof(TKey) == typeof(long)) + return (long)(object)left < (long)(object)right; + if (typeof(TKey) == typeof(UIntPtr)) + return (nuint)(object)left < (nuint)(object)right; + if (typeof(TKey) == typeof(IntPtr)) + return (nint)(object)left < (nint)(object)right; + if (typeof(TKey) == typeof(float)) + return (float)(object)left < (float)(object)right; + if (typeof(TKey) == typeof(double)) + return (double)(object)left < (double)(object)right; +#if NET + if (typeof(TKey) == typeof(Half)) + return (Half)(object)left < (Half)(object)right; +#endif + return left.CompareTo(right) < 0 ? true : false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // compiles to a single comparison or method call + private static bool GreaterThan(ref TKey left, ref TKey right) + { + if (typeof(TKey) == typeof(byte)) + return (byte)(object)left > (byte)(object)right; + if (typeof(TKey) == typeof(sbyte)) + return (sbyte)(object)left > (sbyte)(object)right; + if (typeof(TKey) == typeof(ushort)) + return (ushort)(object)left > (ushort)(object)right; + if (typeof(TKey) == typeof(short)) + return (short)(object)left > (short)(object)right; + if (typeof(TKey) == typeof(uint)) + return (uint)(object)left > (uint)(object)right; + if (typeof(TKey) == typeof(int)) + return (int)(object)left > (int)(object)right; + if (typeof(TKey) == typeof(ulong)) + return (ulong)(object)left > (ulong)(object)right; + if (typeof(TKey) == typeof(long)) + return (long)(object)left > (long)(object)right; + if (typeof(TKey) == typeof(UIntPtr)) + return (nuint)(object)left > (nuint)(object)right; + if (typeof(TKey) == typeof(IntPtr)) + return (nint)(object)left > (nint)(object)right; + if (typeof(TKey) == typeof(float)) + return (float)(object)left > (float)(object)right; + if (typeof(TKey) == typeof(double)) + return (double)(object)left > (double)(object)right; +#if NET + if (typeof(TKey) == typeof(Half)) + return (Half)(object)left > (Half)(object)right; +#endif + return left.CompareTo(right) > 0 ? true : false; + } + } + + #endregion + + /// Helper methods for use in array/span sorting routines. + internal static class SegmentedArraySortUtils + { +#if !NETCOREAPP + private static ReadOnlySpan Log2DeBruijn => new byte[32] + { + 00, 09, 01, 10, 13, 21, 02, 29, + 11, 14, 16, 18, 22, 25, 03, 30, + 08, 12, 20, 28, 15, 17, 24, 07, + 19, 27, 23, 06, 26, 05, 04, 31, + }; +#endif + + public static int MoveNansToFront(SegmentedArraySegment keys, Span values) where TKey : notnull + { + Debug.Assert(typeof(TKey) == typeof(double) || typeof(TKey) == typeof(float)); + + int left = 0; + + for (int i = 0; i < keys.Length; i++) + { + if ((typeof(TKey) == typeof(double) && double.IsNaN((double)(object)keys[i])) + || (typeof(TKey) == typeof(float) && float.IsNaN((float)(object)keys[i])) +#if NET + || (typeof(TKey) == typeof(Half) && Half.IsNaN((Half)(object)keys[i])) +#endif + ) + { + TKey temp = keys[left]; + keys[left] = keys[i]; + keys[i] = temp; + + if ((uint)i < (uint)values.Length) // check to see if we have values + { + TValue tempValue = values[left]; + values[left] = values[i]; + values[i] = tempValue; + } + + left++; + } + } + + return left; + } + + public static int Log2(uint value) + { +#if NET + return BitOperations.Log2(value); +#else + // Fallback contract is 0->0 + return Log2SoftwareFallback(value); +#endif + } + +#if !NETCOREAPP + /// + /// Returns the integer (floor) log of the specified value, base 2. + /// Note that by convention, input value 0 returns 0 since Log(0) is undefined. + /// Does not directly use any hardware intrinsics, nor does it incur branching. + /// + /// The value. + private static int Log2SoftwareFallback(uint value) + { + // No AggressiveInlining due to large method size + // Has conventional contract 0->0 (Log(0) is undefined) + + // Fill trailing zeros with ones, eg 00010010 becomes 00011111 + value |= value >> 01; + value |= value >> 02; + value |= value >> 04; + value |= value >> 08; + value |= value >> 16; + + // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check + return Unsafe.AddByteOffset( + // Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_1100_0100_1010_1100_1101_1101u + ref MemoryMarshal.GetReference(Log2DeBruijn), + // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here + (IntPtr)(int)((value * 0x07C4ACDDu) >> 27)); + } +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/BitHelper.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/BitHelper.cs new file mode 100755 index 00000000000..a9238e0e47c --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/BitHelper.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/Common/src/System/Collections/Generic/BitHelper.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal ref struct BitHelper + { + private const int IntSize = sizeof(int) * 8; + private readonly Span _span; + + internal BitHelper(Span span, bool clear) + { + if (clear) + { + span.Clear(); + } + _span = span; + } + + internal readonly void MarkBit(int bitPosition) + { + Debug.Assert(bitPosition >= 0); + + uint bitArrayIndex = (uint)bitPosition / IntSize; + + // Workaround for https://github.com/dotnet/runtime/issues/72004 + Span span = _span; + if (bitArrayIndex < (uint)span.Length) + { + span[(int)bitArrayIndex] |= (1 << (int)((uint)bitPosition % IntSize)); + } + } + + internal readonly bool IsMarked(int bitPosition) + { + Debug.Assert(bitPosition >= 0); + + uint bitArrayIndex = (uint)bitPosition / IntSize; + + // Workaround for https://github.com/dotnet/runtime/issues/72004 + Span span = _span; + return + bitArrayIndex < (uint)span.Length && + (span[(int)bitArrayIndex] & (1 << ((int)((uint)bitPosition % IntSize)))) != 0; + } + + /// How many ints must be allocated to represent n bits. Returns (n+31)/32, but avoids overflow. + internal static int ToIntArrayLength(int n) => n > 0 ? ((n - 1) / IntSize + 1) : 0; + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/HashHelpers.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/HashHelpers.cs new file mode 100755 index 00000000000..1dfe0939094 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/HashHelpers.cs @@ -0,0 +1,123 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal static class HashHelpers + { + // This is the maximum prime smaller than Array.MaxLength. + public const int MaxPrimeArrayLength = 0x7FFFFFC3; + + public const int HashPrime = 101; + + // Table of prime numbers to use as hash table sizes. + // A typical resize algorithm would pick the smallest prime number in this array + // that is larger than twice the previous capacity. + // Suppose our Hashtable currently has capacity x and enough elements are added + // such that a resize needs to occur. Resizing first computes 2x then finds the + // first prime in the table greater than 2x, i.e. if primes are ordered + // p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n. + // Doubling is important for preserving the asymptotic complexity of the + // hashtable operations such as add. Having a prime guarantees that double + // hashing does not lead to infinite loops. IE, your hash function will be + // h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime. + // We prefer the low computation costs of higher prime numbers over the increased + // memory allocation of a fixed prime number i.e. when right sizing a HashSet. + private static readonly ImmutableArray s_primes = ImmutableArray.Create( + 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, + 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, + 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, + 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, + 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369); + + public static bool IsPrime(int candidate) + { + if ((candidate & 1) != 0) + { + var limit = (int)Math.Sqrt(candidate); + for (var divisor = 3; divisor <= limit; divisor += 2) + { + if ((candidate % divisor) == 0) + return false; + } + return true; + } + return candidate == 2; + } + + public static int GetPrime(int min) + { + if (min < 0) + throw new ArgumentException(SR.Arg_HTCapacityOverflow); + + foreach (var prime in s_primes) + { + if (prime >= min) + return prime; + } + + // Outside of our predefined table. Compute the hard way. + for (var i = (min | 1); i < int.MaxValue; i += 2) + { + if (IsPrime(i) && ((i - 1) % HashPrime != 0)) + return i; + } + return min; + } + + // Returns size of hashtable to grow to. + public static int ExpandPrime(int oldSize) + { + var newSize = 2 * oldSize; + + // Allow the hashtables to grow to maximum possible size (~2G elements) before encountering capacity overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize) + { + Debug.Assert(MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength"); + return MaxPrimeArrayLength; + } + + return GetPrime(newSize); + } + + /// Returns approximate reciprocal of the divisor: ceil(2**64 / divisor). + /// This should only be used on 64-bit. + public static ulong GetFastModMultiplier(uint divisor) + => ulong.MaxValue / divisor + 1; + + /// Performs a mod operation using the multiplier pre-computed with . + /// + /// PERF: This improves performance in 64-bit scenarios at the expense of performance in 32-bit scenarios. Since + /// we only build a single AnyCPU binary, we opt for improved performance in the 64-bit scenario. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint FastMod(uint value, uint divisor, ulong multiplier) + { + // We use modified Daniel Lemire's fastmod algorithm (https://github.com/dotnet/runtime/pull/406), + // which allows to avoid the long multiplication if the divisor is less than 2**31. + Debug.Assert(divisor <= int.MaxValue); + + // This is equivalent of (uint)Math.BigMul(multiplier * value, divisor, out _). This version + // is faster than BigMul currently because we only need the high bits. + var highbits = (uint)(((((multiplier * value) >> 32) + 1) * divisor) >> 32); + + Debug.Assert(highbits == value % divisor); + return highbits; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ICollectionCalls.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ICollectionCalls.cs new file mode 100755 index 00000000000..e45d9116104 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ICollectionCalls.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement the + /// member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class ICollectionCalls + { + public static bool IsSynchronized(ref TCollection collection) + where TCollection : ICollection + => collection.IsSynchronized; + + public static void CopyTo(ref TCollection collection, Array array, int index) + where TCollection : ICollection + { + collection.CopyTo(array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ICollectionCalls`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ICollectionCalls`1.cs new file mode 100755 index 00000000000..f902f8b817b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ICollectionCalls`1.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement + /// the member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class ICollectionCalls + { + public static bool IsReadOnly(ref TCollection collection) + where TCollection : ICollection + => collection.IsReadOnly; + + public static void Add(ref TCollection collection, T item) + where TCollection : ICollection + => collection.Add(item); + + public static void CopyTo(ref TCollection collection, T[] array, int arrayIndex) + where TCollection : ICollection + => collection.CopyTo(array, arrayIndex); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ICollectionDebugView`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ICollectionDebugView`1.cs new file mode 100755 index 00000000000..f59fa686a6a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ICollectionDebugView`1.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ICollectionDebugView.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal sealed class ICollectionDebugView + { + private readonly ICollection _collection; + + public ICollectionDebugView(ICollection collection) + { + _collection = collection ?? throw new ArgumentNullException(nameof(collection)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public T[] Items + { + get + { + var items = new T[_collection.Count]; + _collection.CopyTo(items, 0); + return items; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IDictionaryCalls.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IDictionaryCalls.cs new file mode 100755 index 00000000000..a26d4425a6d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IDictionaryCalls.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement the + /// member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class IDictionaryCalls + { + public static bool IsFixedSize(ref TDictionary dictionary) + where TDictionary : IDictionary + => dictionary.IsFixedSize; + + public static bool IsReadOnly(ref TDictionary dictionary) + where TDictionary : IDictionary + => dictionary.IsReadOnly; + + public static object? GetItem(ref TDictionary dictionary, object key) + where TDictionary : IDictionary + => dictionary[key]; + + public static void SetItem(ref TDictionary dictionary, object key, object? value) + where TDictionary : IDictionary + => dictionary[key] = value; + + public static void Add(ref TDictionary dictionary, object key, object? value) + where TDictionary : IDictionary + => dictionary.Add(key, value); + + public static bool Contains(ref TDictionary dictionary, object key) + where TDictionary : IDictionary + => dictionary.Contains(key); + + public static void CopyTo(ref TDictionary dictionary, Array array, int index) + where TDictionary : IDictionary + => dictionary.CopyTo(array, index); + + public static IDictionaryEnumerator GetEnumerator(ref TDictionary dictionary) + where TDictionary : IDictionary + => dictionary.GetEnumerator(); + + public static void Remove(ref TDictionary dictionary, object key) + where TDictionary : IDictionary + => dictionary.Remove(key); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IDictionaryDebugView`2.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IDictionaryDebugView`2.cs new file mode 100755 index 00000000000..265c29b08a3 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IDictionaryDebugView`2.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionaryDebugView.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal sealed class IDictionaryDebugView + where K : notnull + { + private readonly IDictionary _dict; + + public IDictionaryDebugView(IDictionary dictionary) + { + _dict = dictionary ?? throw new ArgumentNullException(nameof(dictionary)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public KeyValuePair[] Items + { + get + { + var items = new KeyValuePair[_dict.Count]; + _dict.CopyTo(items, 0); + return items; + } + } + } + + internal sealed class DictionaryKeyCollectionDebugView + { + private readonly ICollection _collection; + + public DictionaryKeyCollectionDebugView(ICollection collection) + { + _collection = collection ?? throw new ArgumentNullException(nameof(collection)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public TKey[] Items + { + get + { + var items = new TKey[_collection.Count]; + _collection.CopyTo(items, 0); + return items; + } + } + } + + internal sealed class DictionaryValueCollectionDebugView + { + private readonly ICollection _collection; + + public DictionaryValueCollectionDebugView(ICollection collection) + { + _collection = collection ?? throw new ArgumentNullException(nameof(collection)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public TValue[] Items + { + get + { + var items = new TValue[_collection.Count]; + _collection.CopyTo(items, 0); + return items; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IEnumerableCalls.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IEnumerableCalls.cs new file mode 100755 index 00000000000..4bdd34da0e1 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IEnumerableCalls.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement the + /// member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class IEnumerableCalls + { + public static IEnumerator GetEnumerator(ref TEnumerable enumerable) + where TEnumerable : IEnumerable + { + return enumerable.GetEnumerator(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IEnumerableCalls`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IEnumerableCalls`1.cs new file mode 100755 index 00000000000..000fd0d7075 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IEnumerableCalls`1.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement + /// the member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class IEnumerableCalls + { + public static IEnumerator GetEnumerator(ref TEnumerable enumerable) + where TEnumerable : IEnumerable + { + return enumerable.GetEnumerator(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IListCalls.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IListCalls.cs new file mode 100755 index 00000000000..f7555e2429d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/IListCalls.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement the + /// member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class IListCalls + { + public static object? GetItem(ref TList list, int index) + where TList : IList + => list[index]; + + public static void SetItem(ref TList list, int index, object? value) + where TList : IList + => list[index] = value; + + public static bool IsFixedSize(ref TList list) + where TList : IList + => list.IsFixedSize; + + public static bool IsReadOnly(ref TList list) + where TList : IList + => list.IsReadOnly; + + public static int Add(ref TList list, object? value) + where TList : IList + { + return list.Add(value); + } + + public static bool Contains(ref TList list, object? value) + where TList : IList + { + return list.Contains(value); + } + + public static int IndexOf(ref TList list, object? value) + where TList : IList + { + return list.IndexOf(value); + } + + public static void Insert(ref TList list, int index, object? value) + where TList : IList + { + list.Insert(index, value); + } + + public static void Remove(ref TList list, object? value) + where TList : IList + { + list.Remove(value); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/InsertionBehavior.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/InsertionBehavior.cs new file mode 100755 index 00000000000..40e2d12ad2a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/InsertionBehavior.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/InsertionBehavior.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Used internally to control behavior of insertion into a or . + /// + internal enum InsertionBehavior : byte + { + /// + /// The default insertion behavior. + /// + None = 0, + + /// + /// Specifies that an existing entry with the same key should be overwritten if encountered. + /// + OverwriteExisting = 1, + + /// + /// Specifies that if an existing entry with the same key is encountered, an exception should be thrown. + /// + ThrowOnExisting = 2 + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/RoslynUnsafe.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/RoslynUnsafe.cs new file mode 100755 index 00000000000..d8d40e90c5d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/RoslynUnsafe.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal static unsafe class RoslynUnsafe + { + /// + /// Returns a by-ref to type that is a null reference. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref T NullRef() + => ref Unsafe.AsRef(null); + + /// + /// Returns if a given by-ref to type is a null reference. + /// + /// + /// This check is conceptually similar to (void*)(&source) == nullptr. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsNullRef(ref T source) + => Unsafe.AsPointer(ref source) == null; + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SR.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SR.cs new file mode 100755 index 00000000000..894542ecc44 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SR.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.CodeAnalysis.Collections.Internal; + +internal static class SR +{ + // Strings not localized, should only be used for internal API contract messages and not surfaced to users. + + internal const string Arg_ArrayPlusOffTooSmall = "Destination array is not long enough to copy all the items in the collection. Check array index and length."; + internal const string Arg_HTCapacityOverflow = "Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table."; + internal const string Arg_KeyNotFoundWithKey = "The given key '{0}' was not present in the dictionary."; + internal const string Arg_LongerThanDestArray = "Destination array was not long enough. Check the destination index, length, and the array's lower bounds."; + internal const string Arg_LongerThanSrcArray = "Source array was not long enough. Check the source index, length, and the array's lower bounds."; + internal const string Arg_NonZeroLowerBound = "The lower bound of target array must be zero."; + internal const string Arg_RankMultiDimNotSupported = "Only single dimensional arrays are supported for the requested action."; + internal const string Arg_WrongType = "The value \"{0}\" is not of type \"{1}\" and cannot be used in this generic collection."; + internal const string Argument_AddingDuplicateWithKey = "An item with the same key has already been added. Key: {0}"; + internal const string Argument_IncompatibleArrayType = "Target array type is not compatible with the type of items in the collection."; + internal const string Argument_InvalidOffLen = "Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection."; + internal const string ArgumentOutOfRange_ArrayLB = "Number was less than the array's lower bound in the first dimension."; + internal const string ArgumentOutOfRange_BiggerThanCollection = "Larger than collection size."; + internal const string ArgumentOutOfRange_Count = "Count must be positive and count must refer to a location within the string/array/collection."; + internal const string ArgumentOutOfRange_IndexMustBeLess = "Index was out of range. Must be non-negative and less than the size of the collection."; + internal const string ArgumentOutOfRange_ListInsert = "Index must be within the bounds of the List."; + internal const string ArgumentOutOfRange_NeedNonNegNum = "Non-negative number required."; + internal const string ArgumentOutOfRange_SmallCapacity = "capacity was less than the current size."; + internal const string InvalidOperation_ConcurrentOperationsNotSupported = "Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct."; + internal const string InvalidOperation_EnumFailedVersion = "Collection was modified; enumeration operation may not execute."; + internal const string InvalidOperation_EnumOpCantHappen = "Enumeration has either not started or has already finished."; + internal const string InvalidOperation_IComparerFailed = "Failed to compare two elements in the array."; + internal const string NotSupported_KeyCollectionSet = "Mutating a key collection derived from a dictionary is not allowed."; + internal const string NotSupported_ValueCollectionSet = "Mutating a value collection derived from a dictionary is not allowed."; + internal const string Rank_MustMatch = "The specified arrays must have the same number of dimensions."; + internal const string NotSupported_FixedSizeCollection = "Collection was of a fixed size."; + internal const string ArgumentException_OtherNotArrayOfCorrectLength = "Object is not a array with the same number of elements as the array to compare it to."; + internal const string Arg_BogusIComparer = "Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: '{0}'."; + internal const string CannotFindOldValue = "Cannot find the old value"; + internal const string ArgumentOutOfRange_IndexMustBeLessOrEqual = "Index was out of range. Must be non-negative and less than or equal to the size of the collection."; +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SegmentedArrayHelper.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SegmentedArrayHelper.cs new file mode 100755 index 00000000000..70d87cbaea2 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SegmentedArrayHelper.cs @@ -0,0 +1,206 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal static class SegmentedArrayHelper + { + // This is the threshold where Introspective sort switches to Insertion sort. + // Empirically, 16 seems to speed up most cases without slowing down others, at least for integers. + // Large value types may benefit from a smaller number. + internal const int IntrosortSizeThreshold = 16; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int GetSegmentSize() + { + return Unsafe.SizeOf() switch + { + // Hard code common values since not all versions of the .NET JIT support reducing this computation to a + // constant value at runtime. Values are validated against the reference implementation in + // CalculateSegmentSize in unit tests. + 1 => 65536, + 2 => 32768, + 4 => 16384, + 8 => 8192, + 12 => 4096, + 16 => 4096, + 24 => 2048, + 28 => 2048, + 32 => 2048, + 40 => 2048, + 64 => 1024, +#if NETCOREAPP3_0_OR_GREATER + _ => InlineCalculateSegmentSize(Unsafe.SizeOf()), +#else + _ => FallbackSegmentHelper.SegmentSize, +#endif + }; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int GetSegmentShift() + { + return Unsafe.SizeOf() switch + { + // Hard code common values since not all versions of the .NET JIT support reducing this computation to a + // constant value at runtime. Values are validated against the reference implementation in + // CalculateSegmentSize in unit tests. + 1 => 16, + 2 => 15, + 4 => 14, + 8 => 13, + 12 => 12, + 16 => 12, + 24 => 11, + 28 => 11, + 32 => 11, + 40 => 11, + 64 => 10, +#if NETCOREAPP3_0_OR_GREATER + _ => InlineCalculateSegmentShift(Unsafe.SizeOf()), +#else + _ => FallbackSegmentHelper.SegmentShift, +#endif + }; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int GetOffsetMask() + { + return Unsafe.SizeOf() switch + { + // Hard code common values since not all versions of the .NET JIT support reducing this computation to a + // constant value at runtime. Values are validated against the reference implementation in + // CalculateSegmentSize in unit tests. + 1 => 65535, + 2 => 32767, + 4 => 16383, + 8 => 8191, + 12 => 4095, + 16 => 4095, + 24 => 2047, + 28 => 2047, + 32 => 2047, + 40 => 2047, + 64 => 1023, +#if NETCOREAPP3_0_OR_GREATER + _ => InlineCalculateOffsetMask(Unsafe.SizeOf()), +#else + _ => FallbackSegmentHelper.OffsetMask, +#endif + }; + } + + /// + /// Calculates the maximum number of elements of size which can fit into an array + /// which has the following characteristics: + /// + /// The array can be allocated in the small object heap. + /// The array length is a power of 2. + /// + /// + /// The size of the elements in the array. + /// The segment size to use for small object heap segmented arrays. + private static int CalculateSegmentSize(int elementSize) + { + // Default Large Object Heap size threshold + // https://github.com/dotnet/runtime/blob/c9d69e38d0e54bea5d188593ef6c3b30139f3ab1/src/coreclr/src/gc/gc.h#L111 + const int Threshold = 85000; + + var segmentSize = 2; + while (ArraySize(elementSize, segmentSize << 1) < Threshold) + { + segmentSize <<= 1; + } + + return segmentSize; + + static int ArraySize(int elementSize, int segmentSize) + { + // Array object header, plus space for the elements + return (2 * IntPtr.Size + 8) + (elementSize * segmentSize); + } + } + + /// + /// Calculates a shift which can be applied to an absolute index to get the page index within a segmented array. + /// + /// The number of elements in each page of the segmented array. Must be a power of 2. + /// The shift to apply to the absolute index to get the page index within a segmented array. + private static int CalculateSegmentShift(int segmentSize) + { + var segmentShift = 0; + while (0 != (segmentSize >>= 1)) + { + segmentShift++; + } + + return segmentShift; + } + + /// + /// Calculates a mask, which can be applied to an absolute index to get the index within a page of a segmented + /// array. + /// + /// The number of elements in each page of the segmented array. Must be a power of 2. + /// The bit mask to obtain the index within a page from an absolute index within a segmented array. + private static int CalculateOffsetMask(int segmentSize) + { + Debug.Assert(segmentSize == 1 || (segmentSize & (segmentSize - 1)) == 0, "Expected size of 1, or a power of 2"); + return segmentSize - 1; + } + + // Faster inline implementation for NETCOREAPP to avoid static constructors and non-inlineable + // generics with runtime lookups +#if NETCOREAPP3_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int InlineCalculateSegmentSize(int elementSize) + { + return 1 << InlineCalculateSegmentShift(elementSize); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int InlineCalculateSegmentShift(int elementSize) + { + // Default Large Object Heap size threshold + // https://github.com/dotnet/runtime/blob/c9d69e38d0e54bea5d188593ef6c3b30139f3ab1/src/coreclr/src/gc/gc.h#L111 + const uint Threshold = 85000; + return System.Numerics.BitOperations.Log2((uint)((Threshold / elementSize) - (2 * Unsafe.SizeOf() + 8))); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int InlineCalculateOffsetMask(int elementSize) + { + return InlineCalculateSegmentSize(elementSize) - 1; + } +#endif + + internal static class TestAccessor + { + public static int CalculateSegmentSize(int elementSize) + => SegmentedArrayHelper.CalculateSegmentSize(elementSize); + + public static int CalculateSegmentShift(int segmentSize) + => SegmentedArrayHelper.CalculateSegmentShift(segmentSize); + + public static int CalculateOffsetMask(int segmentSize) + => SegmentedArrayHelper.CalculateOffsetMask(segmentSize); + } + +#if !NETCOREAPP3_0_OR_GREATER + private static class FallbackSegmentHelper + { + public static readonly int SegmentSize = CalculateSegmentSize(Unsafe.SizeOf()); + public static readonly int SegmentShift = CalculateSegmentShift(SegmentSize); + public static readonly int OffsetMask = CalculateOffsetMask(SegmentSize); + } +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SegmentedArraySegment`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SegmentedArraySegment`1.cs new file mode 100755 index 00000000000..69d490ea85f --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SegmentedArraySegment`1.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal readonly struct SegmentedArraySegment + { + public SegmentedArray Array { get; } + public int Start { get; } + public int Length { get; } + + public SegmentedArraySegment(SegmentedArray array, int start, int length) + { + Array = array; + Start = start; + Length = length; + } + + public ref T this[int index] + { + get + { + if ((uint)index >= (uint)Length) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return ref Array[index + Start]; + } + } + + public SegmentedArraySegment Slice(int start) + { + if ((uint)start >= (uint)Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new SegmentedArraySegment(Array, Start + start, Length - start); + } + + public SegmentedArraySegment Slice(int start, int length) + { + // Since start and length are both 32-bit, their sum can be computed across a 64-bit domain + // without loss of fidelity. The cast to uint before the cast to ulong ensures that the + // extension from 32- to 64-bit is zero-extending rather than sign-extending. The end result + // of this is that if either input is negative or if the input sum overflows past Int32.MaxValue, + // that information is captured correctly in the comparison against the backing _length field. + if ((uint)start + (ulong)(uint)length > (uint)Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new SegmentedArraySegment(Array, Start + start, length); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SegmentedHashSetEqualityComparer`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SegmentedHashSetEqualityComparer`1.cs new file mode 100755 index 00000000000..5946c81f763 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/SegmentedHashSetEqualityComparer`1.cs @@ -0,0 +1,90 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSetEqualityComparer.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// Equality comparer for hashsets of hashsets + internal sealed class SegmentedHashSetEqualityComparer : IEqualityComparer?> + { + public bool Equals(SegmentedHashSet? x, SegmentedHashSet? y) + { + // If they're the exact same instance, they're equal. + if (ReferenceEquals(x, y)) + { + return true; + } + + // They're not both null, so if either is null, they're not equal. + if (x == null || y == null) + { + return false; + } + + var defaultComparer = EqualityComparer.Default; + + // If both sets use the same comparer, they're equal if they're the same + // size and one is a "subset" of the other. + if (SegmentedHashSet.EqualityComparersAreEqual(x, y)) + { + return x.Count == y.Count && y.IsSubsetOfHashSetWithSameComparer(x); + } + + // Otherwise, do an O(N^2) match. + // 🐛 This is non-symmetrical, but matches original: https://github.com/dotnet/runtime/issues/69218 + foreach (var yi in y) + { + var found = false; + foreach (var xi in x) + { + if (defaultComparer.Equals(yi, xi)) + { + found = true; + break; + } + } + + if (!found) + { + return false; + } + } + + return true; + } + + public int GetHashCode(SegmentedHashSet? obj) + { + var hashCode = 0; // default to 0 for null/empty set + + if (obj != null) + { + foreach (var t in obj) + { + if (t != null) + { + hashCode ^= t.GetHashCode(); // same hashcode as default comparer + } + } + } + + return hashCode; + } + + // Equals method for the comparer itself. + public override bool Equals([NotNullWhen(true)] object? obj) => obj is SegmentedHashSetEqualityComparer; + + public override int GetHashCode() => EqualityComparer.Default.GetHashCode(); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ThrowHelper.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ThrowHelper.cs new file mode 100755 index 00000000000..994a252a9ce --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Internal/ThrowHelper.cs @@ -0,0 +1,383 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// This file defines an internal class used to throw exceptions in BCL code. +// The main purpose is to reduce code size. +// +// The old way to throw an exception generates quite a lot IL code and assembly code. +// Following is an example: +// C# source +// throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key); +// IL code: +// IL_0003: ldstr "key" +// IL_0008: ldstr "ArgumentNull_Key" +// IL_000d: call string System.Environment::GetResourceString(string) +// IL_0012: newobj instance void System.ArgumentNullException::.ctor(string,string) +// IL_0017: throw +// which is 21bytes in IL. +// +// So we want to get rid of the ldstr and call to Environment.GetResource in IL. +// In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the +// argument name and resource name in a small integer. The source code will be changed to +// ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key); +// +// The IL code will be 7 bytes. +// IL_0008: ldc.i4.4 +// IL_0009: ldc.i4.4 +// IL_000a: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument) +// IL_000f: ldarg.0 +// +// This will also reduce the Jitted code size a lot. +// +// It is very important we do this for generic classes because we can easily generate the same code +// multiple times for different instantiation. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal static class ThrowHelper + { + [DoesNotReturn] + internal static void ThrowIndexOutOfRangeException() + { + throw new IndexOutOfRangeException(); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRangeException() + { + throw new ArgumentOutOfRangeException(); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRange_IndexMustBeLessException() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.index, + ExceptionResource.ArgumentOutOfRange_IndexMustBeLess); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.index, + ExceptionResource.ArgumentOutOfRange_IndexMustBeLessOrEqual); + } + + [DoesNotReturn] + internal static void ThrowArgumentException_BadComparer(object? comparer) + { + throw new ArgumentException(string.Format(SR.Arg_BogusIComparer, comparer)); + } + + [DoesNotReturn] + internal static void ThrowIndexArgumentOutOfRange_NeedNonNegNumException() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.index, + ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + [DoesNotReturn] + internal static void ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.length, + ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + [DoesNotReturn] + internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLessOrEqual() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex, + ExceptionResource.ArgumentOutOfRange_IndexMustBeLessOrEqual); + } + + [DoesNotReturn] + internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex, + ExceptionResource.ArgumentOutOfRange_IndexMustBeLess); + } + + [DoesNotReturn] + internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.count, + ExceptionResource.ArgumentOutOfRange_Count); + } + + [DoesNotReturn] + internal static void ThrowWrongKeyTypeArgumentException(T key, Type targetType) + { + // Generic key to move the boxing to the right hand side of throw + throw GetWrongKeyTypeArgumentException(key, targetType); + } + + [DoesNotReturn] + internal static void ThrowWrongValueTypeArgumentException(T value, Type targetType) + { + // Generic key to move the boxing to the right hand side of throw + throw GetWrongValueTypeArgumentException(value, targetType); + } + + private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object? key) + { + return new ArgumentException(string.Format(SR.Argument_AddingDuplicateWithKey, key)); + } + + [DoesNotReturn] + internal static void ThrowAddingDuplicateWithKeyArgumentException(T key) + { + // Generic key to move the boxing to the right hand side of throw + throw GetAddingDuplicateWithKeyArgumentException(key); + } + + [DoesNotReturn] + internal static void ThrowKeyNotFoundException(T key) + { + // Generic key to move the boxing to the right hand side of throw + throw GetKeyNotFoundException(key); + } + + [DoesNotReturn] + internal static void ThrowArgumentException(ExceptionResource resource) + { + throw GetArgumentException(resource); + } + + private static ArgumentNullException GetArgumentNullException(ExceptionArgument argument) + { + return new ArgumentNullException(GetArgumentName(argument)); + } + + [DoesNotReturn] + internal static void ThrowArgumentNullException(ExceptionArgument argument) + { + throw GetArgumentNullException(argument); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument) + { + throw new ArgumentOutOfRangeException(GetArgumentName(argument)); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) + { + throw GetArgumentOutOfRangeException(argument, resource); + } + + [DoesNotReturn] + internal static void ThrowInvalidOperationException(ExceptionResource resource, Exception e) + { + throw new InvalidOperationException(GetResourceString(resource), e); + } + + [DoesNotReturn] + internal static void ThrowNotSupportedException(ExceptionResource resource) + { + throw new NotSupportedException(GetResourceString(resource)); + } + + [DoesNotReturn] + internal static void ThrowArgumentException_Argument_IncompatibleArrayType() + { + throw new ArgumentException(SR.Argument_IncompatibleArrayType); + } + + [DoesNotReturn] + internal static void ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion() + { + throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + } + + [DoesNotReturn] + internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen() + { + throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); + } + + [DoesNotReturn] + internal static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported() + { + throw new InvalidOperationException(SR.InvalidOperation_ConcurrentOperationsNotSupported); + } + + private static ArgumentException GetArgumentException(ExceptionResource resource) + { + return new ArgumentException(GetResourceString(resource)); + } + + private static ArgumentException GetWrongKeyTypeArgumentException(object? key, Type targetType) + { + return new ArgumentException(string.Format(SR.Arg_WrongType, key, targetType), nameof(key)); + } + + private static ArgumentException GetWrongValueTypeArgumentException(object? value, Type targetType) + { + return new ArgumentException(string.Format(SR.Arg_WrongType, value, targetType), nameof(value)); + } + + private static KeyNotFoundException GetKeyNotFoundException(object? key) + { + return new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, key)); + } + + private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) + { + return new ArgumentOutOfRangeException(GetArgumentName(argument), GetResourceString(resource)); + } + + // Allow nulls for reference types and Nullable, but not for value types. + // Aggressively inline so the jit evaluates the if in place and either drops the call altogether + // Or just leaves null test and call to the Non-returning ThrowHelper.ThrowArgumentNullException + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void IfNullAndNullsAreIllegalThenThrow(object? value, ExceptionArgument argName) + { + // Note that default(T) is not equal to null for value types except when T is Nullable. + if (!(default(T) == null) && value == null) + ThrowHelper.ThrowArgumentNullException(argName); + } + + private static string GetArgumentName(ExceptionArgument argument) + { + switch (argument) + { + case ExceptionArgument.dictionary: + return "dictionary"; + case ExceptionArgument.array: + return "array"; + case ExceptionArgument.info: + return "info"; + case ExceptionArgument.key: + return "key"; + case ExceptionArgument.value: + return "value"; + case ExceptionArgument.startIndex: + return "startIndex"; + case ExceptionArgument.index: + return "index"; + case ExceptionArgument.capacity: + return "capacity"; + case ExceptionArgument.collection: + return "collection"; + case ExceptionArgument.item: + return "item"; + case ExceptionArgument.converter: + return "converter"; + case ExceptionArgument.match: + return "match"; + case ExceptionArgument.count: + return "count"; + case ExceptionArgument.action: + return "action"; + case ExceptionArgument.comparison: + return "comparison"; + case ExceptionArgument.source: + return "source"; + case ExceptionArgument.length: + return "length"; + case ExceptionArgument.destinationArray: + return "destinationArray"; + case ExceptionArgument.other: + return "other"; + default: + Debug.Fail("The enum value is not defined, please check the ExceptionArgument Enum."); + return ""; + } + } + + private static string GetResourceString(ExceptionResource resource) + { + switch (resource) + { + case ExceptionResource.ArgumentOutOfRange_IndexMustBeLessOrEqual: + return SR.ArgumentOutOfRange_IndexMustBeLessOrEqual; + case ExceptionResource.ArgumentOutOfRange_IndexMustBeLess: + return SR.ArgumentOutOfRange_IndexMustBeLess; + case ExceptionResource.ArgumentOutOfRange_Count: + return SR.ArgumentOutOfRange_Count; + case ExceptionResource.Arg_ArrayPlusOffTooSmall: + return SR.Arg_ArrayPlusOffTooSmall; + case ExceptionResource.Arg_RankMultiDimNotSupported: + return SR.Arg_RankMultiDimNotSupported; + case ExceptionResource.Arg_NonZeroLowerBound: + return SR.Arg_NonZeroLowerBound; + case ExceptionResource.ArgumentOutOfRange_ListInsert: + return SR.ArgumentOutOfRange_ListInsert; + case ExceptionResource.ArgumentOutOfRange_NeedNonNegNum: + return SR.ArgumentOutOfRange_NeedNonNegNum; + case ExceptionResource.ArgumentOutOfRange_SmallCapacity: + return SR.ArgumentOutOfRange_SmallCapacity; + case ExceptionResource.Argument_InvalidOffLen: + return SR.Argument_InvalidOffLen; + case ExceptionResource.ArgumentOutOfRange_BiggerThanCollection: + return SR.ArgumentOutOfRange_BiggerThanCollection; + case ExceptionResource.NotSupported_KeyCollectionSet: + return SR.NotSupported_KeyCollectionSet; + case ExceptionResource.NotSupported_ValueCollectionSet: + return SR.NotSupported_ValueCollectionSet; + case ExceptionResource.InvalidOperation_IComparerFailed: + return SR.InvalidOperation_IComparerFailed; + default: + Debug.Fail("The enum value is not defined, please check the ExceptionResource Enum."); + return ""; + } + } + } + + // + // The convention for this enum is using the argument name as the enum name + // + internal enum ExceptionArgument + { + dictionary, + array, + info, + key, + value, + startIndex, + index, + capacity, + collection, + item, + converter, + match, + count, + action, + comparison, + source, + length, + destinationArray, + other, + } + + // + // The convention for this enum is using the resource name as the enum name + // + internal enum ExceptionResource + { + ArgumentOutOfRange_IndexMustBeLessOrEqual, + ArgumentOutOfRange_IndexMustBeLess, + ArgumentOutOfRange_Count, + Arg_ArrayPlusOffTooSmall, + Arg_RankMultiDimNotSupported, + Arg_NonZeroLowerBound, + ArgumentOutOfRange_ListInsert, + ArgumentOutOfRange_NeedNonNegNum, + ArgumentOutOfRange_SmallCapacity, + Argument_InvalidOffLen, + ArgumentOutOfRange_BiggerThanCollection, + NotSupported_KeyCollectionSet, + NotSupported_ValueCollectionSet, + InvalidOperation_IComparerFailed, + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/OneOrMany.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/OneOrMany.cs new file mode 100755 index 00000000000..eaad4dcf1c1 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/OneOrMany.cs @@ -0,0 +1,287 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.PooledObjects; + +namespace Roslyn.Utilities +{ + /// + /// Represents a single item or many items (including none). + /// + /// + /// Used when a collection usually contains a single item but sometimes might contain multiple. + /// + [DebuggerDisplay("{GetDebuggerDisplay(),nq}")] + [DebuggerTypeProxy(typeof(OneOrMany<>.DebuggerProxy))] + internal readonly struct OneOrMany + { + public static readonly OneOrMany Empty = new OneOrMany(ImmutableArray.Empty); + + private readonly T? _one; + private readonly ImmutableArray _many; + + public OneOrMany(T one) + { + _one = one; + _many = default; + } + + public OneOrMany(ImmutableArray many) + { + if (many.IsDefault) + { + throw new ArgumentNullException(nameof(many)); + } + + if (many is [var item]) + { + _one = item; + _many = default; + } + else + { + _one = default; + _many = many; + } + } + + /// + /// True if the collection has a single item. This item is stored in . + /// + [MemberNotNullWhen(true, nameof(_one))] + private bool HasOneItem + => _many.IsDefault; + + public bool IsDefault + => _one == null && _many.IsDefault; + + public T this[int index] + { + get + { + if (HasOneItem) + { + if (index != 0) + { + throw new IndexOutOfRangeException(); + } + + return _one; + } + else + { + return _many[index]; + } + } + } + + public int Count + => HasOneItem ? 1 : _many.Length; + + public bool IsEmpty + => Count == 0; + + public OneOrMany Add(T item) + => HasOneItem ? OneOrMany.Create(_one, item) : + IsEmpty ? OneOrMany.Create(item) : + OneOrMany.Create(_many.Add(item)); + + public void AddRangeTo(ArrayBuilder builder) + { + if (HasOneItem) + { + builder.Add(_one); + } + else + { + builder.AddRange(_many); + } + } + + public bool Contains(T item) + => HasOneItem ? EqualityComparer.Default.Equals(item, _one) : _many.Contains(item); + + public OneOrMany RemoveAll(T item) + { + if (HasOneItem) + { + return EqualityComparer.Default.Equals(item, _one) ? Empty : this; + } + + return OneOrMany.Create(_many.WhereAsArray(static (value, item) => !EqualityComparer.Default.Equals(value, item), item)); + } + + public OneOrMany Select(Func selector) + { + return HasOneItem ? + OneOrMany.Create(selector(_one)) : + OneOrMany.Create(_many.SelectAsArray(selector)); + } + + public OneOrMany Select(Func selector, TArg arg) + { + return HasOneItem ? + OneOrMany.Create(selector(_one, arg)) : + OneOrMany.Create(_many.SelectAsArray(selector, arg)); + } + + public T First() => this[0]; + + public T? FirstOrDefault() + => HasOneItem ? _one : _many.FirstOrDefault(); + + public T? FirstOrDefault(Func predicate) + { + if (HasOneItem) + { + return predicate(_one) ? _one : default; + } + + return _many.FirstOrDefault(predicate); + } + + public T? FirstOrDefault(Func predicate, TArg arg) + { + if (HasOneItem) + { + return predicate(_one, arg) ? _one : default; + } + + return _many.FirstOrDefault(predicate, arg); + } + + public static OneOrMany CastUp(OneOrMany from) where TDerived : class, T + { + return from.HasOneItem + ? new OneOrMany(from._one) + : new OneOrMany(ImmutableArray.CastUp(from._many)); + } + + public bool All(Func predicate) + => HasOneItem ? predicate(_one) : _many.All(predicate); + + public bool All(Func predicate, TArg arg) + => HasOneItem ? predicate(_one, arg) : _many.All(predicate, arg); + + public bool Any() + => !IsEmpty; + + public bool Any(Func predicate) + => HasOneItem ? predicate(_one) : _many.Any(predicate); + + public bool Any(Func predicate, TArg arg) + => HasOneItem ? predicate(_one, arg) : _many.Any(predicate, arg); + + public ImmutableArray ToImmutable() + => HasOneItem ? ImmutableArray.Create(_one) : _many; + + public T[] ToArray() + => HasOneItem ? new[] { _one } : _many.ToArray(); + + public bool SequenceEqual(OneOrMany other, IEqualityComparer? comparer = null) + { + comparer ??= EqualityComparer.Default; + + if (Count != other.Count) + { + return false; + } + + Debug.Assert(HasOneItem == other.HasOneItem); + + return HasOneItem ? comparer.Equals(_one, other._one!) : + System.Linq.ImmutableArrayExtensions.SequenceEqual(_many, other._many, comparer); + } + + public bool SequenceEqual(ImmutableArray other, IEqualityComparer? comparer = null) + => SequenceEqual(OneOrMany.Create(other), comparer); + + public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) + { + comparer ??= EqualityComparer.Default; + + if (!HasOneItem) + { + return _many.SequenceEqual(other, comparer); + } + + var first = true; + foreach (var otherItem in other) + { + if (!first || !comparer.Equals(_one, otherItem)) + { + return false; + } + + first = false; + } + + return true; + } + + public Enumerator GetEnumerator() + => new(this); + + internal struct Enumerator + { + private readonly OneOrMany _collection; + private int _index; + + internal Enumerator(OneOrMany collection) + { + _collection = collection; + _index = -1; + } + + public bool MoveNext() + { + _index++; + return _index < _collection.Count; + } + + public T Current => _collection[_index]; + } + + private sealed class DebuggerProxy(OneOrMany instance) + { + private readonly OneOrMany _instance = instance; + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public T[] Items => _instance.ToArray(); + } + + private string GetDebuggerDisplay() + => "Count = " + Count; + } + + internal static class OneOrMany + { + public static OneOrMany Create(T one) + => new OneOrMany(one); + + public static OneOrMany Create(T one, T two) + => new OneOrMany(ImmutableArray.Create(one, two)); + + public static OneOrMany OneOrNone(T? one) + => one is null ? OneOrMany.Empty : new OneOrMany(one); + + public static OneOrMany Create(ImmutableArray many) + => new OneOrMany(many); + + public static bool SequenceEqual(this ImmutableArray array, OneOrMany other, IEqualityComparer? comparer = null) + => Create(array).SequenceEqual(other, comparer); + + public static bool SequenceEqual(this IEnumerable array, OneOrMany other, IEqualityComparer? comparer = null) + => other.SequenceEqual(array, comparer); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/RoslynEnumerable.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/RoslynEnumerable.cs new file mode 100755 index 00000000000..5edd13ee2e5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/RoslynEnumerable.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; +using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace System.Linq +{ + internal static class RoslynEnumerable + { + public static SegmentedList ToSegmentedList(this IEnumerable source) + { + if (source == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + + return new SegmentedList(source); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/RoslynImmutableInterlocked.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/RoslynImmutableInterlocked.cs new file mode 100755 index 00000000000..ae317798435 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/RoslynImmutableInterlocked.cs @@ -0,0 +1,639 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Threading; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static class RoslynImmutableInterlocked + { + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of value stored by the list. + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, + /// as it may run multiple times when races occur with other threads. + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedList location, Func, ImmutableSegmentedList> transformer) + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedList.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of value stored by the list. + /// The type of argument passed to the . + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, as it may run multiple times + /// when races occur with other threads. + /// The argument to pass to . + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedList location, Func, TArg, ImmutableSegmentedList> transformer, TArg transformerArgument) + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedList.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue, transformerArgument); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Assigns a field or variable containing an immutable list to the specified value and returns the previous + /// value. + /// + /// The type of value stored by the list. + /// The field or local variable to change. + /// The new value to assign. + /// The prior value at the specified . + public static ImmutableSegmentedList InterlockedExchange(ref ImmutableSegmentedList location, ImmutableSegmentedList value) + { + return ImmutableSegmentedList.PrivateMarshal.InterlockedExchange(ref location, value); + } + + /// + /// Assigns a field or variable containing an immutable list to the specified value if it is currently equal to + /// another specified value. Returns the previous value. + /// + /// The type of value stored by the list. + /// The field or local variable to change. + /// The new value to assign. + /// The value to check equality for before assigning. + /// The prior value at the specified . + public static ImmutableSegmentedList InterlockedCompareExchange(ref ImmutableSegmentedList location, ImmutableSegmentedList value, ImmutableSegmentedList comparand) + { + return ImmutableSegmentedList.PrivateMarshal.InterlockedCompareExchange(ref location, value, comparand); + } + + /// + /// Assigns a field or variable containing an immutable list to the specified value if it is has not yet been + /// initialized. + /// + /// The type of value stored by the list. + /// The field or local variable to change. + /// The new value to assign. + /// if the field was assigned the specified value; otherwise, + /// if it was previously initialized. + public static bool InterlockedInitialize(ref ImmutableSegmentedList location, ImmutableSegmentedList value) + { + return InterlockedCompareExchange(ref location, value, default(ImmutableSegmentedList)).IsDefault; + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of value stored by the set. + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, + /// as it may run multiple times when races occur with other threads. + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedHashSet location, Func, ImmutableSegmentedHashSet> transformer) + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedHashSet.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of value stored by the set. + /// The type of argument passed to the . + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, as it may run multiple times + /// when races occur with other threads. + /// The argument to pass to . + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedHashSet location, Func, TArg, ImmutableSegmentedHashSet> transformer, TArg transformerArgument) + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedHashSet.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue, transformerArgument); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Assigns a field or variable containing an immutable set to the specified value and returns the + /// previous value. + /// + /// The type of value stored by the set. + /// The field or local variable to change. + /// The new value to assign. + /// The prior value at the specified . + public static ImmutableSegmentedHashSet InterlockedExchange(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value) + { + return ImmutableSegmentedHashSet.PrivateMarshal.InterlockedExchange(ref location, value); + } + + /// + /// Assigns a field or variable containing an immutable set to the specified value if it is currently + /// equal to another specified value. Returns the previous value. + /// + /// The type of value stored by the set. + /// The field or local variable to change. + /// The new value to assign. + /// The value to check equality for before assigning. + /// The prior value at the specified . + public static ImmutableSegmentedHashSet InterlockedCompareExchange(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value, ImmutableSegmentedHashSet comparand) + { + return ImmutableSegmentedHashSet.PrivateMarshal.InterlockedCompareExchange(ref location, value, comparand); + } + + /// + /// Assigns a field or variable containing an immutable set to the specified value if it is has not yet + /// been initialized. + /// + /// The type of value stored by the set. + /// The field or local variable to change. + /// The new value to assign. + /// if the field was assigned the specified value; otherwise, + /// if it was previously initialized. + public static bool InterlockedInitialize(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value) + { + return InterlockedCompareExchange(ref location, value, default(ImmutableSegmentedHashSet)).IsDefault; + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, + /// as it may run multiple times when races occur with other threads. + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedDictionary location, Func, ImmutableSegmentedDictionary> transformer) + where TKey : notnull + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// The type of argument passed to the . + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, as it may run multiple times + /// when races occur with other threads. + /// The argument to pass to . + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedDictionary location, Func, TArg, ImmutableSegmentedDictionary> transformer, TArg transformerArgument) + where TKey : notnull + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue, transformerArgument); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Assigns a field or variable containing an immutable dictionary to the specified value and returns the + /// previous value. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// The field or local variable to change. + /// The new value to assign. + /// The prior value at the specified . + public static ImmutableSegmentedDictionary InterlockedExchange(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value) + where TKey : notnull + { + return ImmutableSegmentedDictionary.PrivateMarshal.InterlockedExchange(ref location, value); + } + + /// + /// Assigns a field or variable containing an immutable dictionary to the specified value if it is currently + /// equal to another specified value. Returns the previous value. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// The field or local variable to change. + /// The new value to assign. + /// The value to check equality for before assigning. + /// The prior value at the specified . + public static ImmutableSegmentedDictionary InterlockedCompareExchange(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value, ImmutableSegmentedDictionary comparand) + where TKey : notnull + { + return ImmutableSegmentedDictionary.PrivateMarshal.InterlockedCompareExchange(ref location, value, comparand); + } + + /// + /// Assigns a field or variable containing an immutable dictionary to the specified value if it is has not yet + /// been initialized. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// The field or local variable to change. + /// The new value to assign. + /// if the field was assigned the specified value; otherwise, + /// if it was previously initialized. + public static bool InterlockedInitialize(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value) + where TKey : notnull + { + return InterlockedCompareExchange(ref location, value, default(ImmutableSegmentedDictionary)).IsDefault; + } + + /// + public static TValue GetOrAdd(ref ImmutableSegmentedDictionary location, TKey key, Func valueFactory, TArg factoryArgument) + where TKey : notnull + { + if (valueFactory is null) + throw new ArgumentNullException(nameof(valueFactory)); + + var map = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + if (map.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (map.TryGetValue(key, out var value)) + { + return value; + } + + value = valueFactory(key, factoryArgument); + return GetOrAdd(ref location, key, value); + } + + /// + public static TValue GetOrAdd(ref ImmutableSegmentedDictionary location, TKey key, Func valueFactory) + where TKey : notnull + { + if (valueFactory is null) + throw new ArgumentNullException(nameof(valueFactory)); + + var map = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + if (map.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (map.TryGetValue(key, out var value)) + { + return value; + } + + value = valueFactory(key); + return GetOrAdd(ref location, key, value); + } + + /// + public static TValue GetOrAdd(ref ImmutableSegmentedDictionary location, TKey key, TValue value) + where TKey : notnull + { + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (priorCollection.TryGetValue(key, out var oldValue)) + { + return oldValue; + } + + var updatedCollection = priorCollection.Add(key, value); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + // We won the race-condition and have updated the collection. + // Return the value that is in the collection (as of the Interlocked operation). + return value; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static TValue AddOrUpdate(ref ImmutableSegmentedDictionary location, TKey key, Func addValueFactory, Func updateValueFactory) + where TKey : notnull + { + if (addValueFactory is null) + throw new ArgumentNullException(nameof(addValueFactory)); + if (updateValueFactory is null) + throw new ArgumentNullException(nameof(updateValueFactory)); + + TValue newValue; + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (priorCollection.TryGetValue(key, out var oldValue)) + { + newValue = updateValueFactory(key, oldValue); + } + else + { + newValue = addValueFactory(key); + } + + var updatedCollection = priorCollection.SetItem(key, newValue); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + // We won the race-condition and have updated the collection. + // Return the value that is in the collection (as of the Interlocked operation). + return newValue; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static TValue AddOrUpdate(ref ImmutableSegmentedDictionary location, TKey key, TValue addValue, Func updateValueFactory) + where TKey : notnull + { + if (updateValueFactory is null) + throw new ArgumentNullException(nameof(updateValueFactory)); + + TValue newValue; + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (priorCollection.TryGetValue(key, out var oldValue)) + { + newValue = updateValueFactory(key, oldValue); + } + else + { + newValue = addValue; + } + + var updatedCollection = priorCollection.SetItem(key, newValue); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + // We won the race-condition and have updated the collection. + // Return the value that is in the collection (as of the Interlocked operation). + return newValue; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static bool TryAdd(ref ImmutableSegmentedDictionary location, TKey key, TValue value) + where TKey : notnull + { + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (priorCollection.ContainsKey(key)) + { + return false; + } + + var updatedCollection = priorCollection.Add(key, value); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + return true; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static bool TryUpdate(ref ImmutableSegmentedDictionary location, TKey key, TValue newValue, TValue comparisonValue) + where TKey : notnull + { + var valueComparer = EqualityComparer.Default; + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (!priorCollection.TryGetValue(key, out var priorValue) || !valueComparer.Equals(priorValue, comparisonValue)) + { + // The key isn't in the dictionary, or its current value doesn't match what the caller expected. + return false; + } + + var updatedCollection = priorCollection.SetItem(key, newValue); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + return true; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static bool TryRemove(ref ImmutableSegmentedDictionary location, TKey key, [MaybeNullWhen(false)] out TValue value) + where TKey : notnull + { + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (!priorCollection.TryGetValue(key, out value)) + { + return false; + } + + var updatedCollection = priorCollection.Remove(key); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + return true; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Reads from an ImmutableArray location, ensuring that a read barrier is inserted to prevent any subsequent reads from being reordered before this read. + /// + /// + /// This method is not intended to be used to provide write barriers. + /// + public static ImmutableArray VolatileRead(ref readonly ImmutableArray location) + { + var value = location; + // When Volatile.ReadBarrier() is available in .NET 10, it can be used here. + Interlocked.MemoryBarrier(); + return value; + } + + /// + /// Writes to an ImmutableArray location, ensuring that a write barrier is inserted to prevent any prior writes from being reordered after this write. + /// + /// + /// This method is not intended to be used to provide read barriers. + /// + public static void VolatileWrite(ref ImmutableArray location, ImmutableArray value) + { + // When Volatile.WriteBarrier() is available in .NET 10, it can be used here. + Interlocked.MemoryBarrier(); + location = value; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary.cs new file mode 100755 index 00000000000..70ca2fa8c17 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Provides methods for creating a segmented dictionary that is immutable; meaning it cannot be changed once it is + /// created. + /// + internal static class ImmutableSegmentedDictionary + { + public static ImmutableSegmentedDictionary Create() + where TKey : notnull + => ImmutableSegmentedDictionary.Empty; + + public static ImmutableSegmentedDictionary Create(IEqualityComparer? keyComparer) + where TKey : notnull + => ImmutableSegmentedDictionary.Empty.WithComparer(keyComparer); + + public static ImmutableSegmentedDictionary.Builder CreateBuilder() + where TKey : notnull + => Create().ToBuilder(); + + public static ImmutableSegmentedDictionary.Builder CreateBuilder(IEqualityComparer? keyComparer) + where TKey : notnull + => Create(keyComparer).ToBuilder(); + + public static ImmutableSegmentedDictionary CreateRange(IEnumerable> items) + where TKey : notnull + => ImmutableSegmentedDictionary.Empty.AddRange(items); + + public static ImmutableSegmentedDictionary CreateRange(IEqualityComparer? keyComparer, IEnumerable> items) + where TKey : notnull + => ImmutableSegmentedDictionary.Empty.WithComparer(keyComparer).AddRange(items); + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable> items) + where TKey : notnull + => ToImmutableSegmentedDictionary(items, keyComparer: null); + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this ImmutableSegmentedDictionary.Builder builder) + where TKey : notnull + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + return builder.ToImmutable(); + } + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable> items, IEqualityComparer? keyComparer) + where TKey : notnull + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + if (items is ImmutableSegmentedDictionary existingDictionary) + return existingDictionary.WithComparer(keyComparer); + + return ImmutableSegmentedDictionary.Empty.WithComparer(keyComparer).AddRange(items); + } + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable source, Func keySelector, Func elementSelector) + where TKey : notnull + => ToImmutableSegmentedDictionary(source, keySelector, elementSelector, keyComparer: null); + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? keyComparer) + where TKey : notnull + { + if (source is null) + throw new ArgumentNullException(nameof(source)); + if (keySelector is null) + throw new ArgumentNullException(nameof(keySelector)); + if (elementSelector is null) + throw new ArgumentNullException(nameof(elementSelector)); + + return ImmutableSegmentedDictionary.Empty.WithComparer(keyComparer) + .AddRange(source.Select(element => new KeyValuePair(keySelector(element), elementSelector(element)))); + } + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable source, Func keySelector) + where TKey : notnull + => ToImmutableSegmentedDictionary(source, keySelector, elementSelector: static x => x, keyComparer: null); + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable source, Func keySelector, IEqualityComparer? keyComparer) + where TKey : notnull + => ToImmutableSegmentedDictionary(source, keySelector, elementSelector: static x => x, keyComparer); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder+KeyCollection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder+KeyCollection.cs new file mode 100755 index 00000000000..6f406539a72 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder+KeyCollection.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public partial class Builder + { + public readonly struct KeyCollection : ICollection, IReadOnlyCollection, ICollection + { + private readonly ImmutableSegmentedDictionary.Builder _dictionary; + + internal KeyCollection(ImmutableSegmentedDictionary.Builder dictionary) + { + Debug.Assert(dictionary is not null); + _dictionary = dictionary!; + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => false; + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + void ICollection.Add(TKey item) + => throw new NotSupportedException(); + + public void Clear() + => _dictionary.Clear(); + + public bool Contains(TKey item) + => _dictionary.ContainsKey(item); + + public void CopyTo(TKey[] array, int arrayIndex) + => _dictionary.ReadOnlyDictionary.Keys.CopyTo(array, arrayIndex); + + public ImmutableSegmentedDictionary.KeyCollection.Enumerator GetEnumerator() + => new(_dictionary.GetEnumerator()); + + public bool Remove(TKey item) + => _dictionary.Remove(item); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary.ReadOnlyDictionary.Keys).CopyTo(array, index); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder+PrivateMarshal.cs new file mode 100755 index 00000000000..174a53dfc09 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder+PrivateMarshal.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections; + +internal readonly partial struct ImmutableSegmentedDictionary +{ + public partial class Builder + { + /// + /// Private helper class for use only by . + /// + internal static class PrivateMarshal + { + /// + public static ref TValue FindValue(Builder dictionary, TKey key) + => ref SegmentedCollectionsMarshal.GetValueRefOrNullRef(dictionary._builder.GetOrCreateMutableDictionary(), key); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder+ValueCollection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder+ValueCollection.cs new file mode 100755 index 00000000000..bf68f898f0a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder+ValueCollection.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public partial class Builder + { + public readonly struct ValueCollection : ICollection, IReadOnlyCollection, ICollection + { + private readonly ImmutableSegmentedDictionary.Builder _dictionary; + + internal ValueCollection(ImmutableSegmentedDictionary.Builder dictionary) + { + Debug.Assert(dictionary is not null); + _dictionary = dictionary!; + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => false; + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + void ICollection.Add(TValue item) + => throw new NotSupportedException(); + + public void Clear() + => _dictionary.Clear(); + + public bool Contains(TValue item) + => _dictionary.ContainsValue(item); + + public void CopyTo(TValue[] array, int arrayIndex) + => _dictionary.ReadOnlyDictionary.Values.CopyTo(array, arrayIndex); + + public ImmutableSegmentedDictionary.ValueCollection.Enumerator GetEnumerator() + => new(_dictionary.GetEnumerator()); + + bool ICollection.Remove(TValue item) + => throw new NotSupportedException(); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary.ReadOnlyDictionary.Values).CopyTo(array, index); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder.cs new file mode 100755 index 00000000000..a1e438608ac --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Builder.cs @@ -0,0 +1,159 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public sealed partial class Builder : IDictionary, IReadOnlyDictionary, IDictionary + { + /// + /// The private builder implementation. + /// + private ValueBuilder _builder; + + internal Builder(ImmutableSegmentedDictionary dictionary) + => _builder = new ValueBuilder(dictionary); + + public IEqualityComparer KeyComparer + { + get => _builder.KeyComparer; + set => _builder.KeyComparer = value; + } + + public int Count => _builder.Count; + + public KeyCollection Keys => new(this); + + public ValueCollection Values => new(this); + + private SegmentedDictionary ReadOnlyDictionary => _builder.ReadOnlyDictionary; + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Values => Values; + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + bool ICollection>.IsReadOnly => ICollectionCalls>.IsReadOnly(ref _builder); + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + bool IDictionary.IsReadOnly => IDictionaryCalls.IsReadOnly(ref _builder); + + bool IDictionary.IsFixedSize => IDictionaryCalls.IsFixedSize(ref _builder); + + object ICollection.SyncRoot => this; + + bool ICollection.IsSynchronized => ICollectionCalls.IsSynchronized(ref _builder); + + public TValue this[TKey key] + { + get => _builder[key]; + set => _builder[key] = value; + } + + object? IDictionary.this[object key] + { + get => IDictionaryCalls.GetItem(ref _builder, key); + set => IDictionaryCalls.SetItem(ref _builder, key, value); + } + + public void Add(TKey key, TValue value) + => _builder.Add(key, value); + + public void Add(KeyValuePair item) + => _builder.Add(item); + + public void AddRange(IEnumerable> items) + => _builder.AddRange(items); + + public void Clear() + => _builder.Clear(); + + public bool Contains(KeyValuePair item) + => _builder.Contains(item); + + public bool ContainsKey(TKey key) + => _builder.ContainsKey(key); + + public bool ContainsValue(TValue value) + => _builder.ContainsValue(value); + + public Enumerator GetEnumerator() + => _builder.GetEnumerator(); + + public TValue? GetValueOrDefault(TKey key) + => _builder.GetValueOrDefault(key); + + public TValue GetValueOrDefault(TKey key, TValue defaultValue) + => _builder.GetValueOrDefault(key, defaultValue); + + public bool Remove(TKey key) + => _builder.Remove(key); + + public bool Remove(KeyValuePair item) + => _builder.Remove(item); + + public void RemoveRange(IEnumerable keys) + => _builder.RemoveRange(keys); + + public bool TryGetKey(TKey equalKey, out TKey actualKey) + => _builder.TryGetKey(equalKey, out actualKey); + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + => _builder.TryGetValue(key, out value); + + public ImmutableSegmentedDictionary ToImmutable() + => _builder.ToImmutable(); + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + => ICollectionCalls>.CopyTo(ref _builder, array, arrayIndex); + + IEnumerator> IEnumerable>.GetEnumerator() + => IEnumerableCalls>.GetEnumerator(ref _builder); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + + bool IDictionary.Contains(object key) + => IDictionaryCalls.Contains(ref _builder, key); + + void IDictionary.Add(object key, object? value) + => IDictionaryCalls.Add(ref _builder, key, value); + + IDictionaryEnumerator IDictionary.GetEnumerator() + => IDictionaryCalls.GetEnumerator(ref _builder); + + void IDictionary.Remove(object key) + => IDictionaryCalls.Remove(ref _builder, key); + + void ICollection.CopyTo(Array array, int index) + => ICollectionCalls.CopyTo(ref _builder, array, index); + + internal TestAccessor GetTestAccessor() + => new TestAccessor(this); + + internal readonly struct TestAccessor(Builder instance) + { + internal SegmentedDictionary GetOrCreateMutableDictionary() + => instance._builder.GetOrCreateMutableDictionary(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Enumerator.cs new file mode 100755 index 00000000000..5513c12bbc7 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+Enumerator.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public struct Enumerator : IEnumerator>, IDictionaryEnumerator + { + private readonly SegmentedDictionary _dictionary; + private readonly ReturnType _returnType; + private SegmentedDictionary.Enumerator _enumerator; + + internal Enumerator(SegmentedDictionary dictionary, ReturnType returnType) + { + _dictionary = dictionary; + _returnType = returnType; + _enumerator = dictionary.GetEnumerator(); + } + + internal enum ReturnType + { + /// + /// The return value from the implementation of is + /// . This is the return value for most instances of this + /// enumerator. + /// + KeyValuePair, + + /// + /// The return value from the implementation of is + /// . This is the return value for instances of this + /// enumerator created by the implementation in + /// . + /// + DictionaryEntry, + } + + public readonly KeyValuePair Current => _enumerator.Current; + + readonly object IEnumerator.Current => _returnType == ReturnType.DictionaryEntry ? ((IDictionaryEnumerator)this).Entry : Current; + + readonly DictionaryEntry IDictionaryEnumerator.Entry => new(Current.Key, Current.Value); + + readonly object IDictionaryEnumerator.Key => Current.Key; + + readonly object? IDictionaryEnumerator.Value => Current.Value; + + public readonly void Dispose() + => _enumerator.Dispose(); + + public bool MoveNext() + => _enumerator.MoveNext(); + + public void Reset() + { + _enumerator = _dictionary.GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection+Enumerator.cs new file mode 100755 index 00000000000..d4a04d85269 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection+Enumerator.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public partial struct KeyCollection + { + public struct Enumerator : IEnumerator + { + private ImmutableSegmentedDictionary.Enumerator _enumerator; + + internal Enumerator(ImmutableSegmentedDictionary.Enumerator enumerator) + { + _enumerator = enumerator; + } + + public readonly TKey Current => _enumerator.Current.Key; + + readonly object IEnumerator.Current => Current; + + public readonly void Dispose() + => _enumerator.Dispose(); + + public bool MoveNext() + => _enumerator.MoveNext(); + + public void Reset() + => _enumerator.Reset(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection.cs new file mode 100755 index 00000000000..dbdbd4e515d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public readonly partial struct KeyCollection : IReadOnlyCollection, ICollection, ICollection + { + private readonly ImmutableSegmentedDictionary _dictionary; + + internal KeyCollection(ImmutableSegmentedDictionary dictionary) + { + _dictionary = dictionary; + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => true; + + bool ICollection.IsSynchronized => true; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + public Enumerator GetEnumerator() + => new(_dictionary.GetEnumerator()); + + public bool Contains(TKey item) + => _dictionary.ContainsKey(item); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + void ICollection.CopyTo(TKey[] array, int arrayIndex) + => _dictionary._dictionary.Keys.CopyTo(array, arrayIndex); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary._dictionary.Keys).CopyTo(array, index); + + void ICollection.Add(TKey item) + => throw new NotSupportedException(); + + void ICollection.Clear() + => throw new NotSupportedException(); + + bool ICollection.Remove(TKey item) + => throw new NotSupportedException(); + + public bool All(Func predicate, TArg arg) + { + foreach (var item in this) + { + if (!predicate(item, arg)) + { + return false; + } + } + + return true; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+PrivateMarshal.cs new file mode 100755 index 00000000000..3b6ee1c382d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+PrivateMarshal.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + /// + /// Private helper class for use only by and + /// . + /// + internal static class PrivateMarshal + { + internal static ImmutableSegmentedDictionary VolatileRead(in ImmutableSegmentedDictionary location) + { + var dictionary = Volatile.Read(ref Unsafe.AsRef(in location._dictionary)); + if (dictionary is null) + return default; + + return new ImmutableSegmentedDictionary(dictionary); + } + + internal static ImmutableSegmentedDictionary InterlockedExchange(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value) + { + var dictionary = Interlocked.Exchange(ref Unsafe.AsRef(in location._dictionary), value._dictionary); + if (dictionary is null) + return default; + + return new ImmutableSegmentedDictionary(dictionary); + } + + internal static ImmutableSegmentedDictionary InterlockedCompareExchange(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value, ImmutableSegmentedDictionary comparand) + { + var dictionary = Interlocked.CompareExchange(ref Unsafe.AsRef(in location._dictionary), value._dictionary, comparand._dictionary); + if (dictionary is null) + return default; + + return new ImmutableSegmentedDictionary(dictionary); + } + + /// + public static ref readonly TValue FindValue(ImmutableSegmentedDictionary dictionary, TKey key) + => ref SegmentedCollectionsMarshal.GetValueRefOrNullRef(dictionary._dictionary, key); + + /// + internal static ImmutableSegmentedDictionary AsImmutableSegmentedDictionary(SegmentedDictionary? dictionary) + => dictionary is not null ? new ImmutableSegmentedDictionary(dictionary) : default; + + /// + internal static SegmentedDictionary? AsSegmentedDictionary(ImmutableSegmentedDictionary dictionary) + => dictionary._dictionary; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+ValueBuilder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+ValueBuilder.cs new file mode 100755 index 00000000000..f57337bbd1d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+ValueBuilder.cs @@ -0,0 +1,261 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + private struct ValueBuilder : IDictionary, IReadOnlyDictionary, IDictionary + { + /// + /// The immutable collection this builder is based on. + /// + private ImmutableSegmentedDictionary _dictionary; + + /// + /// The current mutable collection this builder is operating on. This field is initialized to a copy of + /// the first time a change is made. + /// + private SegmentedDictionary? _mutableDictionary; + + internal ValueBuilder(ImmutableSegmentedDictionary dictionary) + { + _dictionary = dictionary; + _mutableDictionary = null; + } + + public IEqualityComparer KeyComparer + { + readonly get + { + return ReadOnlyDictionary.Comparer; + } + + set + { + if (value is null) + throw new ArgumentNullException(nameof(value)); + + if (value != KeyComparer) + { + // Rewrite the mutable dictionary using a new comparer + var valuesToAdd = ReadOnlyDictionary; + _mutableDictionary = new SegmentedDictionary(value); + _dictionary = default; + AddRange(valuesToAdd); + } + } + } + + public readonly int Count => ReadOnlyDictionary.Count; + + internal readonly SegmentedDictionary ReadOnlyDictionary => _mutableDictionary ?? _dictionary._dictionary; + + readonly IEnumerable IReadOnlyDictionary.Keys => throw new NotSupportedException(); + + readonly IEnumerable IReadOnlyDictionary.Values => throw new NotSupportedException(); + + readonly ICollection IDictionary.Keys => throw new NotSupportedException(); + + readonly ICollection IDictionary.Values => throw new NotSupportedException(); + + readonly bool ICollection>.IsReadOnly => false; + + readonly ICollection IDictionary.Keys => throw new NotSupportedException(); + + readonly ICollection IDictionary.Values => throw new NotSupportedException(); + + readonly bool IDictionary.IsReadOnly => false; + + readonly bool IDictionary.IsFixedSize => false; + + readonly object ICollection.SyncRoot => throw new NotSupportedException(); + + readonly bool ICollection.IsSynchronized => false; + + public TValue this[TKey key] + { + readonly get => ReadOnlyDictionary[key]; + set => GetOrCreateMutableDictionary()[key] = value; + } + + object? IDictionary.this[object key] + { + readonly get => ((IDictionary)ReadOnlyDictionary)[key]; + set => ((IDictionary)GetOrCreateMutableDictionary())[key] = value; + } + + internal SegmentedDictionary GetOrCreateMutableDictionary() + { + if (_mutableDictionary is null) + { + var originalDictionary = RoslynImmutableInterlocked.InterlockedExchange(ref _dictionary, default); + if (originalDictionary.IsDefault) + throw new InvalidOperationException($"Unexpected concurrent access to {GetType()}"); + + _mutableDictionary = new SegmentedDictionary(originalDictionary._dictionary, originalDictionary.KeyComparer); + } + + return _mutableDictionary; + } + + public void Add(TKey key, TValue value) + { + if (Contains(new KeyValuePair(key, value))) + return; + + GetOrCreateMutableDictionary().Add(key, value); + } + + public void Add(KeyValuePair item) + => Add(item.Key, item.Value); + + public void AddRange(IEnumerable> items) + { + if (items == null) + throw new ArgumentNullException(nameof(items)); + + foreach (var pair in items) + Add(pair.Key, pair.Value); + } + + public void Clear() + { + if (ReadOnlyDictionary.Count != 0) + { + if (_mutableDictionary is null) + { + _mutableDictionary = new SegmentedDictionary(KeyComparer); + _dictionary = default; + } + else + { + _mutableDictionary.Clear(); + } + } + } + + public readonly bool Contains(KeyValuePair item) + { + return TryGetValue(item.Key, out var value) + && EqualityComparer.Default.Equals(value, item.Value); + } + + public readonly bool ContainsKey(TKey key) + => ReadOnlyDictionary.ContainsKey(key); + + public readonly bool ContainsValue(TValue value) + => ReadOnlyDictionary.ContainsValue(value); + + public Enumerator GetEnumerator() + => new(GetOrCreateMutableDictionary(), Enumerator.ReturnType.KeyValuePair); + + public readonly TValue? GetValueOrDefault(TKey key) + { + if (TryGetValue(key, out var value)) + return value; + + return default; + } + + public readonly TValue GetValueOrDefault(TKey key, TValue defaultValue) + { + if (TryGetValue(key, out var value)) + return value; + + return defaultValue; + } + + public bool Remove(TKey key) + { + if (_mutableDictionary is null && !ContainsKey(key)) + return false; + + return GetOrCreateMutableDictionary().Remove(key); + } + + public bool Remove(KeyValuePair item) + { + if (!Contains(item)) + { + return false; + } + + GetOrCreateMutableDictionary().Remove(item.Key); + return true; + } + + public void RemoveRange(IEnumerable keys) + { + if (keys is null) + throw new ArgumentNullException(nameof(keys)); + + foreach (var key in keys) + { + Remove(key); + } + } + +#pragma warning disable IDE0251 // Make member 'readonly' (false positive: https://github.com/dotnet/roslyn/issues/72335) + public bool TryGetKey(TKey equalKey, out TKey actualKey) +#pragma warning restore IDE0251 // Make member 'readonly' + { + foreach (var pair in this) + { + if (KeyComparer.Equals(pair.Key, equalKey)) + { + actualKey = pair.Key; + return true; + } + } + + actualKey = equalKey; + return false; + } + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + public readonly bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + => ReadOnlyDictionary.TryGetValue(key, out value); + + public ImmutableSegmentedDictionary ToImmutable() + { + _dictionary = new ImmutableSegmentedDictionary(ReadOnlyDictionary); + _mutableDictionary = null; + return _dictionary; + } + + readonly void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + => ((ICollection>)ReadOnlyDictionary).CopyTo(array, arrayIndex); + + IEnumerator> IEnumerable>.GetEnumerator() + => new Enumerator(GetOrCreateMutableDictionary(), Enumerator.ReturnType.KeyValuePair); + + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(GetOrCreateMutableDictionary(), Enumerator.ReturnType.KeyValuePair); + + readonly bool IDictionary.Contains(object key) + => ((IDictionary)ReadOnlyDictionary).Contains(key); + + void IDictionary.Add(object key, object? value) + => ((IDictionary)GetOrCreateMutableDictionary()).Add(key, value); + + IDictionaryEnumerator IDictionary.GetEnumerator() + => new Enumerator(GetOrCreateMutableDictionary(), Enumerator.ReturnType.DictionaryEntry); + + void IDictionary.Remove(object key) + => ((IDictionary)GetOrCreateMutableDictionary()).Remove(key); + + readonly void ICollection.CopyTo(Array array, int index) + => ((ICollection)ReadOnlyDictionary).CopyTo(array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection+Enumerator.cs new file mode 100755 index 00000000000..dccb9177d81 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection+Enumerator.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public partial struct ValueCollection + { + public struct Enumerator : IEnumerator + { + private ImmutableSegmentedDictionary.Enumerator _enumerator; + + internal Enumerator(ImmutableSegmentedDictionary.Enumerator enumerator) + { + _enumerator = enumerator; + } + + public readonly TValue Current => _enumerator.Current.Value; + + readonly object? IEnumerator.Current => Current; + + public readonly void Dispose() + => _enumerator.Dispose(); + + public bool MoveNext() + => _enumerator.MoveNext(); + + public void Reset() + => _enumerator.Reset(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection.cs new file mode 100755 index 00000000000..966328f845f --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public readonly partial struct ValueCollection : IReadOnlyCollection, ICollection, ICollection + { + private readonly ImmutableSegmentedDictionary _dictionary; + + internal ValueCollection(ImmutableSegmentedDictionary dictionary) + { + _dictionary = dictionary; + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => true; + + bool ICollection.IsSynchronized => true; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + public Enumerator GetEnumerator() + => new(_dictionary.GetEnumerator()); + + public bool Contains(TValue item) + => _dictionary.ContainsValue(item); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + void ICollection.CopyTo(TValue[] array, int arrayIndex) + => _dictionary._dictionary.Values.CopyTo(array, arrayIndex); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary._dictionary.Values).CopyTo(array, index); + + void ICollection.Add(TValue item) + => throw new NotSupportedException(); + + void ICollection.Clear() + => throw new NotSupportedException(); + + bool ICollection.Remove(TValue item) + => throw new NotSupportedException(); + + public bool All(Func predicate, TArg arg) + { + foreach (var item in this) + { + if (!predicate(item, arg)) + { + return false; + } + } + + return true; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2.cs new file mode 100755 index 00000000000..8898ed1e367 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedDictionary`2.cs @@ -0,0 +1,392 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a segmented dictionary that is immutable; meaning it cannot be changed once it is created. + /// + /// + /// There are different scenarios best for and others + /// best for . + /// + /// In general, is applicable in scenarios most like + /// the scenarios where is applicable, and + /// is applicable in scenarios most like the scenarios where + /// is applicable. + /// + /// The following table summarizes the performance characteristics of + /// : + /// + /// + /// + /// Operation + /// Complexity + /// Complexity + /// Comments + /// + /// + /// Item + /// O(1) + /// O(log n) + /// Directly index into the underlying segmented dictionary + /// + /// + /// Add() + /// O(n) + /// O(log n) + /// Requires creating a new segmented dictionary + /// + /// + /// + /// This type is backed by segmented arrays to avoid using the Large Object Heap without impacting algorithmic + /// complexity. + /// + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + /// + /// This type has a documented contract of being exactly one reference-type field in size. Our own + /// class depends on it, as well as others externally. + /// + /// IMPORTANT NOTICE FOR MAINTAINERS AND REVIEWERS: + /// + /// This type should be thread-safe. As a struct, it cannot protect its own fields from being changed from one + /// thread while its members are executing on other threads because structs can change in place simply by + /// reassigning the field containing this struct. Therefore it is extremely important that ⚠⚠ Every member + /// should only dereference this ONCE ⚠⚠. If a member needs to reference the + /// field, that counts as a dereference of this. Calling other instance members + /// (properties or methods) also counts as dereferencing this. Any member that needs to use this more + /// than once must instead assign this to a local variable and use that for the rest of the code instead. + /// This effectively copies the one field in the struct to a local variable so that it is insulated from other + /// threads. + /// + internal readonly partial struct ImmutableSegmentedDictionary : IImmutableDictionary, IDictionary, IReadOnlyDictionary, IDictionary, IEquatable> + where TKey : notnull + { + public static readonly ImmutableSegmentedDictionary Empty = new(new SegmentedDictionary()); + + private readonly SegmentedDictionary _dictionary; + + private ImmutableSegmentedDictionary(SegmentedDictionary dictionary) + { + _dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary)); + } + + public IEqualityComparer KeyComparer => _dictionary.Comparer; + + public int Count => _dictionary.Count; + + public bool IsEmpty => _dictionary.Count == 0; + + public bool IsDefault => _dictionary == null; + + public bool IsDefaultOrEmpty => _dictionary?.Count is null or 0; + + public KeyCollection Keys => new(this); + + public ValueCollection Values => new(this); + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Values => Values; + + bool ICollection>.IsReadOnly => true; + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + bool IDictionary.IsReadOnly => true; + + bool IDictionary.IsFixedSize => true; + + object ICollection.SyncRoot => _dictionary; + + bool ICollection.IsSynchronized => true; + + public TValue this[TKey key] => _dictionary[key]; + + TValue IDictionary.this[TKey key] + { + get => this[key]; + set => throw new NotSupportedException(); + } + + object? IDictionary.this[object key] + { + get => ((IDictionary)_dictionary)[key]; + set => throw new NotSupportedException(); + } + + public static bool operator ==(ImmutableSegmentedDictionary left, ImmutableSegmentedDictionary right) + => left.Equals(right); + + public static bool operator !=(ImmutableSegmentedDictionary left, ImmutableSegmentedDictionary right) + => !left.Equals(right); + + public static bool operator ==(ImmutableSegmentedDictionary? left, ImmutableSegmentedDictionary? right) + => left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + public static bool operator !=(ImmutableSegmentedDictionary? left, ImmutableSegmentedDictionary? right) + => !left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + public ImmutableSegmentedDictionary Add(TKey key, TValue value) + { + var self = this; + if (self.Contains(new KeyValuePair(key, value))) + return self; + + var builder = ToValueBuilder(); + builder.Add(key, value); + return builder.ToImmutable(); + } + + public ImmutableSegmentedDictionary AddRange(IEnumerable> pairs) + { + var self = this; + + // Optimize the case of adding to an empty collection + if (self.IsEmpty && TryCastToImmutableSegmentedDictionary(pairs, out var other) && self.KeyComparer == other.KeyComparer) + { + return other; + } + + var builder = ToValueBuilder(); + builder.AddRange(pairs); + return builder.ToImmutable(); + } + + public ImmutableSegmentedDictionary Clear() + { + var self = this; + if (self.IsEmpty) + { + return self; + } + + return Empty.WithComparer(self.KeyComparer); + } + + public bool Contains(KeyValuePair pair) + { + return TryGetValue(pair.Key, out var value) + && EqualityComparer.Default.Equals(value, pair.Value); + } + + public bool ContainsKey(TKey key) + => _dictionary.ContainsKey(key); + + public bool ContainsValue(TValue value) + => _dictionary.ContainsValue(value); + + public Enumerator GetEnumerator() + => new(_dictionary, Enumerator.ReturnType.KeyValuePair); + + public ImmutableSegmentedDictionary Remove(TKey key) + { + var self = this; + if (!self._dictionary.ContainsKey(key)) + return self; + + var builder = ToValueBuilder(); + builder.Remove(key); + return builder.ToImmutable(); + } + + public ImmutableSegmentedDictionary RemoveRange(IEnumerable keys) + { + if (keys is null) + throw new ArgumentNullException(nameof(keys)); + + var result = ToValueBuilder(); + result.RemoveRange(keys); + return result.ToImmutable(); + } + + public ImmutableSegmentedDictionary SetItem(TKey key, TValue value) + { + var self = this; + if (self.Contains(new KeyValuePair(key, value))) + { + return self; + } + + var builder = ToValueBuilder(); + builder[key] = value; + return builder.ToImmutable(); + } + + public ImmutableSegmentedDictionary SetItems(IEnumerable> items) + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + var result = ToValueBuilder(); + foreach (var item in items) + { + result[item.Key] = item.Value; + } + + return result.ToImmutable(); + } + + public bool TryGetKey(TKey equalKey, out TKey actualKey) + { + var self = this; + foreach (var key in self.Keys) + { + if (self.KeyComparer.Equals(key, equalKey)) + { + actualKey = key; + return true; + } + } + + actualKey = equalKey; + return false; + } + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + => _dictionary.TryGetValue(key, out value); + + public ImmutableSegmentedDictionary WithComparer(IEqualityComparer? keyComparer) + { + keyComparer ??= EqualityComparer.Default; + + var self = this; + if (self.KeyComparer == keyComparer) + { + // Don't need to reconstruct the dictionary because the key comparer is the same + return self; + } + else if (self.IsEmpty) + { + if (keyComparer == Empty.KeyComparer) + { + return Empty; + } + else + { + return new ImmutableSegmentedDictionary(new SegmentedDictionary(keyComparer)); + } + } + else + { + return ImmutableSegmentedDictionary.CreateRange(keyComparer, self); + } + } + + public Builder ToBuilder() + => new(this); + + private ValueBuilder ToValueBuilder() + => new(this); + + public override int GetHashCode() + => _dictionary?.GetHashCode() ?? 0; + + public override bool Equals(object? obj) + { + return obj is ImmutableSegmentedDictionary other + && Equals(other); + } + + public bool Equals(ImmutableSegmentedDictionary other) + => _dictionary == other._dictionary; + + IImmutableDictionary IImmutableDictionary.Clear() + => Clear(); + + IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) + => Add(key, value); + + IImmutableDictionary IImmutableDictionary.AddRange(IEnumerable> pairs) + => AddRange(pairs); + + IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) + => SetItem(key, value); + + IImmutableDictionary IImmutableDictionary.SetItems(IEnumerable> items) + => SetItems(items); + + IImmutableDictionary IImmutableDictionary.RemoveRange(IEnumerable keys) + => RemoveRange(keys); + + IImmutableDictionary IImmutableDictionary.Remove(TKey key) => Remove(key); + + IEnumerator> IEnumerable>.GetEnumerator() + => new Enumerator(_dictionary, Enumerator.ReturnType.KeyValuePair); + + IDictionaryEnumerator IDictionary.GetEnumerator() + => new Enumerator(_dictionary, Enumerator.ReturnType.DictionaryEntry); + + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(_dictionary, Enumerator.ReturnType.KeyValuePair); + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + => ((ICollection>)_dictionary).CopyTo(array, arrayIndex); + + bool IDictionary.Contains(object key) + => ((IDictionary)_dictionary).Contains(key); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary).CopyTo(array, index); + + void IDictionary.Add(TKey key, TValue value) + => throw new NotSupportedException(); + + bool IDictionary.Remove(TKey key) + => throw new NotSupportedException(); + + void ICollection>.Add(KeyValuePair item) + => throw new NotSupportedException(); + + void ICollection>.Clear() + => throw new NotSupportedException(); + + bool ICollection>.Remove(KeyValuePair item) + => throw new NotSupportedException(); + + void IDictionary.Add(object key, object? value) + => throw new NotSupportedException(); + + void IDictionary.Clear() + => throw new NotSupportedException(); + + void IDictionary.Remove(object key) + => throw new NotSupportedException(); + + private static bool TryCastToImmutableSegmentedDictionary(IEnumerable> pairs, out ImmutableSegmentedDictionary other) + { + if (pairs is ImmutableSegmentedDictionary dictionary) + { + other = dictionary; + return true; + } + + if (pairs is ImmutableSegmentedDictionary.Builder builder) + { + other = builder.ToImmutable(); + return true; + } + + other = default; + return false; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet.cs new file mode 100755 index 00000000000..63e2a1e8969 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static class ImmutableSegmentedHashSet + { + /// + public static ImmutableSegmentedHashSet Create() + => ImmutableSegmentedHashSet.Empty; + + /// + public static ImmutableSegmentedHashSet Create(T item) + => ImmutableSegmentedHashSet.Empty.Add(item); + + /// + public static ImmutableSegmentedHashSet Create(params T[] items) + => ImmutableSegmentedHashSet.Empty.Union(items); + + /// + public static ImmutableSegmentedHashSet Create(IEqualityComparer? equalityComparer) + => ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer); + + /// + public static ImmutableSegmentedHashSet Create(IEqualityComparer? equalityComparer, T item) + => ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).Add(item); + + /// + public static ImmutableSegmentedHashSet Create(IEqualityComparer? equalityComparer, params T[] items) + => ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).Union(items); + + /// + public static ImmutableSegmentedHashSet.Builder CreateBuilder() + => ImmutableSegmentedHashSet.Empty.ToBuilder(); + + /// + public static ImmutableSegmentedHashSet.Builder CreateBuilder(IEqualityComparer? equalityComparer) + => ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).ToBuilder(); + + /// + public static ImmutableSegmentedHashSet CreateRange(IEnumerable items) + { + if (items is ImmutableSegmentedHashSet existingSet) + return existingSet.WithComparer(null); + + return ImmutableSegmentedHashSet.Empty.Union(items); + } + + /// + public static ImmutableSegmentedHashSet CreateRange(IEqualityComparer? equalityComparer, IEnumerable items) + { + if (items is ImmutableSegmentedHashSet existingSet) + return existingSet.WithComparer(equalityComparer); + + return ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).Union(items); + } + + /// + public static ImmutableSegmentedHashSet ToImmutableSegmentedHashSet(this IEnumerable source) + { + if (source is ImmutableSegmentedHashSet existingSet) + return existingSet.WithComparer(null); + + return ImmutableSegmentedHashSet.Empty.Union(source); + } + + /// + public static ImmutableSegmentedHashSet ToImmutableSegmentedHashSet(this IEnumerable source, IEqualityComparer? equalityComparer) + { + if (source is ImmutableSegmentedHashSet existingSet) + return existingSet.WithComparer(equalityComparer); + + return ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).Union(source); + } + + /// + public static ImmutableSegmentedHashSet ToImmutableSegmentedHashSet(this ImmutableSegmentedHashSet.Builder builder) + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + return builder.ToImmutable(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+Builder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+Builder.cs new file mode 100755 index 00000000000..d8273f710b8 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+Builder.cs @@ -0,0 +1,130 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedHashSet + { + public sealed class Builder : ISet, IReadOnlyCollection + { + /// + /// The private builder implementation. + /// + private ValueBuilder _builder; + + internal Builder(ImmutableSegmentedHashSet set) + => _builder = new ValueBuilder(set); + + /// + public IEqualityComparer KeyComparer + { + get => _builder.KeyComparer; + set => _builder.KeyComparer = value; + } + + /// + public int Count => _builder.Count; + + bool ICollection.IsReadOnly => ICollectionCalls.IsReadOnly(ref _builder); + + /// + public bool Add(T item) + => _builder.Add(item); + + /// + public void Clear() + => _builder.Clear(); + + /// + public bool Contains(T item) + => _builder.Contains(item); + + /// + public void ExceptWith(IEnumerable other) + { + if (other == this) + { + // The ValueBuilder knows how to optimize for this case by calling Clear, provided it does not need + // to access properties of the wrapping Builder instance. + _builder.ExceptWith(_builder.ReadOnlySet); + } + else + { + _builder.ExceptWith(other); + } + } + + /// + public Enumerator GetEnumerator() + => _builder.GetEnumerator(); + + /// + public void IntersectWith(IEnumerable other) + => _builder.IntersectWith(other); + + /// + public bool IsProperSubsetOf(IEnumerable other) + => _builder.IsProperSubsetOf(other); + + /// + public bool IsProperSupersetOf(IEnumerable other) + => _builder.IsProperSupersetOf(other); + + /// + public bool IsSubsetOf(IEnumerable other) + => _builder.IsSubsetOf(other); + + /// + public bool IsSupersetOf(IEnumerable other) + => _builder.IsSupersetOf(other); + + /// + public bool Overlaps(IEnumerable other) + => _builder.Overlaps(other); + + /// + public bool Remove(T item) + => _builder.Remove(item); + + /// + public bool SetEquals(IEnumerable other) + => _builder.SetEquals(other); + + /// + public void SymmetricExceptWith(IEnumerable other) + => _builder.SymmetricExceptWith(other); + + /// + public bool TryGetValue(T equalValue, out T actualValue) + => _builder.TryGetValue(equalValue, out actualValue); + + /// + public void UnionWith(IEnumerable other) + => _builder.UnionWith(other); + + /// + public ImmutableSegmentedHashSet ToImmutable() + => _builder.ToImmutable(); + + void ICollection.Add(T item) + => ICollectionCalls.Add(ref _builder, item); + + void ICollection.CopyTo(T[] array, int arrayIndex) + => ICollectionCalls.CopyTo(ref _builder, array, arrayIndex); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+Enumerator.cs new file mode 100755 index 00000000000..add645bb303 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+Enumerator.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedHashSet + { + /// + public struct Enumerator : IEnumerator + { + private readonly SegmentedHashSet _set; + private SegmentedHashSet.Enumerator _enumerator; + + internal Enumerator(SegmentedHashSet set) + { + _set = set; + _enumerator = set.GetEnumerator(); + } + + /// + public readonly T Current => _enumerator.Current; + + readonly object? IEnumerator.Current => ((IEnumerator)_enumerator).Current; + + /// + public readonly void Dispose() + => _enumerator.Dispose(); + + /// + public bool MoveNext() + => _enumerator.MoveNext(); + + /// + public void Reset() + { + // Create a new enumerator, since _enumerator.Reset() will fail for cases where the set was mutated + // after enumeration started, and ImmutableSegmentHashSet.Builder allows for this case without error. + _enumerator = _set.GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+PrivateMarshal.cs new file mode 100755 index 00000000000..282cbfb17a5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+PrivateMarshal.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedHashSet + { + /// + /// Private helper class for use only by and + /// . + /// + internal static class PrivateMarshal + { + internal static ImmutableSegmentedHashSet VolatileRead(in ImmutableSegmentedHashSet location) + { + var set = Volatile.Read(ref Unsafe.AsRef(in location._set)); + if (set is null) + return default; + + return new ImmutableSegmentedHashSet(set); + } + + internal static ImmutableSegmentedHashSet InterlockedExchange(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value) + { + var set = Interlocked.Exchange(ref Unsafe.AsRef(in location._set), value._set); + if (set is null) + return default; + + return new ImmutableSegmentedHashSet(set); + } + + internal static ImmutableSegmentedHashSet InterlockedCompareExchange(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value, ImmutableSegmentedHashSet comparand) + { + var set = Interlocked.CompareExchange(ref Unsafe.AsRef(in location._set), value._set, comparand._set); + if (set is null) + return default; + + return new ImmutableSegmentedHashSet(set); + } + + /// + internal static ImmutableSegmentedHashSet AsImmutableSegmentedHashSet(SegmentedHashSet? set) + => set is not null ? new ImmutableSegmentedHashSet(set) : default; + + /// + internal static SegmentedHashSet? AsSegmentedHashSet(ImmutableSegmentedHashSet set) + => set._set; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+ValueBuilder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+ValueBuilder.cs new file mode 100755 index 00000000000..8c8f2f88690 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1+ValueBuilder.cs @@ -0,0 +1,284 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedHashSet + { + private struct ValueBuilder : ISet, IReadOnlyCollection + { + /// + /// The immutable collection this builder is based on. + /// + private ImmutableSegmentedHashSet _set; + + /// + /// The current mutable collection this builder is operating on. This field is initialized to a copy of + /// the first time a change is made. + /// + private SegmentedHashSet? _mutableSet; + + internal ValueBuilder(ImmutableSegmentedHashSet set) + { + _set = set; + _mutableSet = null; + } + + /// + public IEqualityComparer KeyComparer + { + readonly get + { + return ReadOnlySet.Comparer; + } + + set + { + if (Equals(KeyComparer, value ?? EqualityComparer.Default)) + return; + + _mutableSet = new SegmentedHashSet(ReadOnlySet, value ?? EqualityComparer.Default); + _set = default; + } + } + + /// + public readonly int Count => ReadOnlySet.Count; + + internal readonly SegmentedHashSet ReadOnlySet => _mutableSet ?? _set._set; + + readonly bool ICollection.IsReadOnly => false; + + private SegmentedHashSet GetOrCreateMutableSet() + { + if (_mutableSet is null) + { + var originalSet = RoslynImmutableInterlocked.InterlockedExchange(ref _set, default); + if (originalSet.IsDefault) + throw new InvalidOperationException($"Unexpected concurrent access to {GetType()}"); + + _mutableSet = new SegmentedHashSet(originalSet._set, originalSet.KeyComparer); + } + + return _mutableSet; + } + + /// + public bool Add(T item) + { + if (_mutableSet is null && Contains(item)) + return false; + + return GetOrCreateMutableSet().Add(item); + } + + /// + public void Clear() + { + if (ReadOnlySet.Count != 0) + { + if (_mutableSet is null) + { + _mutableSet = new SegmentedHashSet(KeyComparer); + _set = default; + } + else + { + _mutableSet.Clear(); + } + } + } + + /// + public readonly bool Contains(T item) + => ReadOnlySet.Contains(item); + + /// + public void ExceptWith(IEnumerable other) + { + if (other is null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + + if (_mutableSet is not null) + { + _mutableSet.ExceptWith(other); + return; + } + + // ValueBuilder is not a public API, so there shouldn't be any callers trying to pass a boxed instance + // to this method. + Debug.Assert(other is not ValueBuilder); + + if (other == ReadOnlySet) + { + Clear(); + return; + } + else if (other is ImmutableSegmentedHashSet otherSet) + { + if (otherSet == _set) + { + Clear(); + return; + } + else if (otherSet.IsEmpty) + { + // No action required + return; + } + else + { + GetOrCreateMutableSet().ExceptWith(otherSet._set); + return; + } + } + else + { + // Manually enumerate to avoid changes to the builder if 'other' is empty or does not contain any + // items present in the current set. + SegmentedHashSet? mutableSet = null; + foreach (var item in other) + { + if (mutableSet is null) + { + if (!ReadOnlySet.Contains(item)) + continue; + + mutableSet = GetOrCreateMutableSet(); + } + + mutableSet.Remove(item); + } + + return; + } + } + + /// + public Enumerator GetEnumerator() + => new(GetOrCreateMutableSet()); + + /// + public void IntersectWith(IEnumerable other) + => GetOrCreateMutableSet().IntersectWith(other); + + /// + public readonly bool IsProperSubsetOf(IEnumerable other) + => ReadOnlySet.IsProperSubsetOf(other); + + /// + public readonly bool IsProperSupersetOf(IEnumerable other) + => ReadOnlySet.IsProperSupersetOf(other); + + /// + public readonly bool IsSubsetOf(IEnumerable other) + => ReadOnlySet.IsSubsetOf(other); + + /// + public readonly bool IsSupersetOf(IEnumerable other) + => ReadOnlySet.IsSupersetOf(other); + + /// + public readonly bool Overlaps(IEnumerable other) + => ReadOnlySet.Overlaps(other); + + /// + public bool Remove(T item) + { + if (_mutableSet is null && !Contains(item)) + return false; + + return GetOrCreateMutableSet().Remove(item); + } + + /// + public readonly bool SetEquals(IEnumerable other) + => ReadOnlySet.SetEquals(other); + + /// + public void SymmetricExceptWith(IEnumerable other) + => GetOrCreateMutableSet().SymmetricExceptWith(other); + + /// + public readonly bool TryGetValue(T equalValue, out T actualValue) + { + if (ReadOnlySet.TryGetValue(equalValue, out var value)) + { + actualValue = value; + return true; + } + + actualValue = equalValue; + return false; + } + + /// + public void UnionWith(IEnumerable other) + { + if (other is null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + + if (_mutableSet is not null) + { + _mutableSet.UnionWith(other); + return; + } + + if (other is ImmutableSegmentedHashSet { IsEmpty: true }) + { + return; + } + else + { + // Manually enumerate to avoid changes to the builder if 'other' is empty or only contains items + // already present in the current set. + SegmentedHashSet? mutableSet = null; + foreach (var item in other) + { + if (mutableSet is null) + { + if (ReadOnlySet.Contains(item)) + continue; + + mutableSet = GetOrCreateMutableSet(); + } + + mutableSet.Add(item); + } + + return; + } + } + + /// + public ImmutableSegmentedHashSet ToImmutable() + { + _set = new ImmutableSegmentedHashSet(ReadOnlySet); + _mutableSet = null; + return _set; + } + + void ICollection.Add(T item) + => ((ICollection)GetOrCreateMutableSet()).Add(item); + + readonly void ICollection.CopyTo(T[] array, int arrayIndex) + => ((ICollection)ReadOnlySet).CopyTo(array, arrayIndex); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1.cs new file mode 100755 index 00000000000..4728fa7a05b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedHashSet`1.cs @@ -0,0 +1,394 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a segmented hash set that is immutable; meaning it cannot be changed once it is created. + /// + /// + /// There are different scenarios best for and others + /// best for . + /// + /// The following table summarizes the performance characteristics of + /// : + /// + /// + /// + /// Operation + /// Complexity + /// Complexity + /// Comments + /// + /// + /// Contains + /// O(1) + /// O(log n) + /// Directly index into the underlying segmented list + /// + /// + /// Add() + /// O(n) + /// O(log n) + /// Requires creating a new segmented hash set and cloning all impacted segments + /// + /// + /// + /// This type is backed by segmented arrays to avoid using the Large Object Heap without impacting algorithmic + /// complexity. + /// + /// The type of the value in the set. + /// + /// This type has a documented contract of being exactly one reference-type field in size. Our own + /// class depends on it, as well as others externally. + /// + /// IMPORTANT NOTICE FOR MAINTAINERS AND REVIEWERS: + /// + /// This type should be thread-safe. As a struct, it cannot protect its own fields from being changed from one + /// thread while its members are executing on other threads because structs can change in place simply by + /// reassigning the field containing this struct. Therefore it is extremely important that ⚠⚠ Every member + /// should only dereference this ONCE ⚠⚠. If a member needs to reference the + /// field, that counts as a dereference of this. Calling other instance members + /// (properties or methods) also counts as dereferencing this. Any member that needs to use this more + /// than once must instead assign this to a local variable and use that for the rest of the code instead. + /// This effectively copies the one field in the struct to a local variable so that it is insulated from other + /// threads. + /// + internal readonly partial struct ImmutableSegmentedHashSet : IImmutableSet, ISet, ICollection, IEquatable> + { + /// + public static readonly ImmutableSegmentedHashSet Empty = new(new SegmentedHashSet()); + + private readonly SegmentedHashSet _set; + + private ImmutableSegmentedHashSet(SegmentedHashSet set) + { + _set = set; + } + + /// + public IEqualityComparer KeyComparer => _set.Comparer; + + /// + public int Count => _set.Count; + + public bool IsDefault => _set == null; + + /// + public bool IsEmpty => _set.Count == 0; + + bool ICollection.IsReadOnly => true; + + bool ICollection.IsSynchronized => true; + + object ICollection.SyncRoot => _set; + + public static bool operator ==(ImmutableSegmentedHashSet left, ImmutableSegmentedHashSet right) + => left.Equals(right); + + public static bool operator !=(ImmutableSegmentedHashSet left, ImmutableSegmentedHashSet right) + => !left.Equals(right); + + public static bool operator ==(ImmutableSegmentedHashSet? left, ImmutableSegmentedHashSet? right) + => left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + public static bool operator !=(ImmutableSegmentedHashSet? left, ImmutableSegmentedHashSet? right) + => !left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + /// + public ImmutableSegmentedHashSet Add(T value) + { + var self = this; + + if (self.IsEmpty) + { + var set = new SegmentedHashSet(self.KeyComparer) { value }; + return new ImmutableSegmentedHashSet(set); + } + else if (self.Contains(value)) + { + return self; + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.Add(value); + return builder.ToImmutable(); + } + } + + /// + public ImmutableSegmentedHashSet Clear() + { + var self = this; + + if (self.IsEmpty) + { + return self; + } + + return Empty.WithComparer(self.KeyComparer); + } + + /// + public bool Contains(T value) + => _set.Contains(value); + + /// + public ImmutableSegmentedHashSet Except(IEnumerable other) + { + var self = this; + + if (other is ImmutableSegmentedHashSet { IsEmpty: true }) + { + return self; + } + else if (self.IsEmpty) + { + // Enumerate the argument to match behavior of ImmutableHashSet + foreach (var _ in other) + { + // Intentionally empty + } + + return self; + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.ExceptWith(other); + return builder.ToImmutable(); + } + } + + /// + public Enumerator GetEnumerator() + => new(_set); + + /// + public ImmutableSegmentedHashSet Intersect(IEnumerable other) + { + var self = this; + + if (self.IsEmpty || other is ImmutableSegmentedHashSet { IsEmpty: true }) + { + return self.Clear(); + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.IntersectWith(other); + return builder.ToImmutable(); + } + } + + /// + public bool IsProperSubsetOf(IEnumerable other) + => _set.IsProperSubsetOf(other); + + /// + public bool IsProperSupersetOf(IEnumerable other) + => _set.IsProperSupersetOf(other); + + /// + public bool IsSubsetOf(IEnumerable other) + => _set.IsSubsetOf(other); + + /// + public bool IsSupersetOf(IEnumerable other) + => _set.IsSupersetOf(other); + + /// + public bool Overlaps(IEnumerable other) + => _set.Overlaps(other); + + /// + public ImmutableSegmentedHashSet Remove(T value) + { + var self = this; + + if (!self.Contains(value)) + { + return self; + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.Remove(value); + return builder.ToImmutable(); + } + } + + /// + public bool SetEquals(IEnumerable other) + => _set.SetEquals(other); + + /// + public ImmutableSegmentedHashSet SymmetricExcept(IEnumerable other) + { + var self = this; + + if (other is ImmutableSegmentedHashSet otherSet) + { + if (otherSet.IsEmpty) + return self; + else if (self.IsEmpty) + return otherSet.WithComparer(self.KeyComparer); + } + + if (self.IsEmpty) + { + return ImmutableSegmentedHashSet.CreateRange(self.KeyComparer, other); + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.SymmetricExceptWith(other); + return builder.ToImmutable(); + } + } + + /// + public bool TryGetValue(T equalValue, out T actualValue) + { + if (_set.TryGetValue(equalValue, out var value)) + { + actualValue = value; + return true; + } + + actualValue = equalValue; + return false; + } + + /// + public ImmutableSegmentedHashSet Union(IEnumerable other) + { + var self = this; + + if (other is ImmutableSegmentedHashSet otherSet) + { + if (otherSet.IsEmpty) + return self; + else if (self.IsEmpty) + return otherSet.WithComparer(self.KeyComparer); + } + + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.UnionWith(other); + return builder.ToImmutable(); + } + + /// + public Builder ToBuilder() + => new(this); + + private ValueBuilder ToValueBuilder() + => new ValueBuilder(this); + + /// + public ImmutableSegmentedHashSet WithComparer(IEqualityComparer? equalityComparer) + { + var self = this; + + equalityComparer ??= EqualityComparer.Default; + if (Equals(self.KeyComparer, equalityComparer)) + return self; + + return new ImmutableSegmentedHashSet(new SegmentedHashSet(self._set, equalityComparer)); + } + + public override int GetHashCode() + => _set?.GetHashCode() ?? 0; + + public override bool Equals(object? obj) + => obj is ImmutableSegmentedHashSet other && Equals(other); + + public bool Equals(ImmutableSegmentedHashSet other) + => _set == other._set; + + IImmutableSet IImmutableSet.Clear() + => Clear(); + + IImmutableSet IImmutableSet.Add(T value) + => Add(value); + + IImmutableSet IImmutableSet.Remove(T value) + => Remove(value); + + IImmutableSet IImmutableSet.Intersect(IEnumerable other) + => Intersect(other); + + IImmutableSet IImmutableSet.Except(IEnumerable other) + => Except(other); + + IImmutableSet IImmutableSet.SymmetricExcept(IEnumerable other) + => SymmetricExcept(other); + + IImmutableSet IImmutableSet.Union(IEnumerable other) + => Union(other); + + void ICollection.CopyTo(T[] array, int arrayIndex) + => _set.CopyTo(array, arrayIndex); + + void ICollection.CopyTo(Array array, int index) + { + if (array is null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (array.Length < index + Count) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + + foreach (var item in this) + { + array.SetValue(item, index++); + } + } + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + bool ISet.Add(T item) + => throw new NotSupportedException(); + + void ISet.UnionWith(IEnumerable other) + => throw new NotSupportedException(); + + void ISet.IntersectWith(IEnumerable other) + => throw new NotSupportedException(); + + void ISet.ExceptWith(IEnumerable other) + => throw new NotSupportedException(); + + void ISet.SymmetricExceptWith(IEnumerable other) + => throw new NotSupportedException(); + + void ICollection.Add(T item) + => throw new NotSupportedException(); + + void ICollection.Clear() + => throw new NotSupportedException(); + + bool ICollection.Remove(T item) + => throw new NotSupportedException(); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList.cs new file mode 100755 index 00000000000..9272bfb5976 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static class ImmutableSegmentedList + { + /// + public static ImmutableSegmentedList Create() + => ImmutableSegmentedList.Empty; + + /// + public static ImmutableSegmentedList Create(T item) + => ImmutableSegmentedList.Empty.Add(item); + + /// + public static ImmutableSegmentedList Create(params T[] items) + => ImmutableSegmentedList.Empty.AddRange(items); + + /// + public static ImmutableSegmentedList.Builder CreateBuilder() + => ImmutableSegmentedList.Empty.ToBuilder(); + + /// + public static ImmutableSegmentedList CreateRange(IEnumerable items) + => ImmutableSegmentedList.Empty.AddRange(items); + + /// + public static ImmutableSegmentedList ToImmutableSegmentedList(this IEnumerable source) + { + if (source is ImmutableSegmentedList existingList) + return existingList; + + return ImmutableSegmentedList.Empty.AddRange(source); + } + + /// + public static ImmutableSegmentedList ToImmutableSegmentedList(this ImmutableSegmentedList.Builder builder) + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + return builder.ToImmutable(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedListExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedListExtensions.cs new file mode 100755 index 00000000000..a7675a069b7 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedListExtensions.cs @@ -0,0 +1,120 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; +using Microsoft.CodeAnalysis.Collections; + +#pragma warning disable RS0001 // Use 'SpecializedCollections.EmptyEnumerable()' + +namespace System.Linq +{ + /// + internal static class ImmutableSegmentedListExtensions + { + public static bool All(this ImmutableSegmentedList immutableList, Func predicate) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + if (predicate is null) + throw new ArgumentNullException(nameof(predicate)); + + foreach (var item in immutableList) + { + if (!predicate(item)) + return false; + } + + return true; + } + + public static bool Any(this ImmutableSegmentedList immutableList) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + + return !immutableList.IsEmpty; + } + + public static bool Any(this ImmutableSegmentedList.Builder builder) + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + return builder.Count > 0; + } + + public static bool Any(this ImmutableSegmentedList immutableList, Func predicate) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + if (predicate is null) + throw new ArgumentNullException(nameof(predicate)); + + foreach (var item in immutableList) + { + if (predicate(item)) + return true; + } + + return false; + } + + public static T Last(this ImmutableSegmentedList immutableList) + { + // In the event of an empty list, generate the same exception + // that the linq extension method would. + return immutableList.Count > 0 + ? immutableList[immutableList.Count - 1] + : Enumerable.Last(immutableList); + } + + public static T Last(this ImmutableSegmentedList.Builder builder) + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + // In the event of an empty list, generate the same exception + // that the linq extension method would. + return builder.Count > 0 + ? builder[builder.Count - 1] + : Enumerable.Last(builder); + } + + public static T Last(this ImmutableSegmentedList immutableList, Func predicate) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + if (predicate is null) + throw new ArgumentNullException(nameof(predicate)); + + for (var i = immutableList.Count - 1; i >= 0; i--) + { + if (predicate(immutableList[i])) + return immutableList[i]; + } + + // Throw the same exception that LINQ would. + return Enumerable.Empty().Last(); + } + + public static IEnumerable Select(this ImmutableSegmentedList immutableList, Func selector) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + if (selector is null) + throw new ArgumentNullException(nameof(selector)); + + if (immutableList.IsEmpty) + { + return Enumerable.Empty(); + } + else + { + return Enumerable.Select(immutableList, selector); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+Builder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+Builder.cs new file mode 100755 index 00000000000..6ffd557d665 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+Builder.cs @@ -0,0 +1,251 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial struct ImmutableSegmentedList + { + public sealed class Builder : IList, IReadOnlyList, IList + { + /// + /// The private builder implementation. + /// + private ValueBuilder _builder; + + internal Builder(ImmutableSegmentedList list) + => _builder = new ValueBuilder(list); + + public int Count => _builder.Count; + + bool ICollection.IsReadOnly => ICollectionCalls.IsReadOnly(ref _builder); + + bool IList.IsFixedSize => IListCalls.IsFixedSize(ref _builder); + + bool IList.IsReadOnly => IListCalls.IsReadOnly(ref _builder); + + bool ICollection.IsSynchronized => ICollectionCalls.IsSynchronized(ref _builder); + + object ICollection.SyncRoot => this; + + public T this[int index] + { + get => _builder[index]; + set => _builder[index] = value; + } + + object? IList.this[int index] + { + get => IListCalls.GetItem(ref _builder, index); + set => IListCalls.SetItem(ref _builder, index, value); + } + + /// + public ref readonly T ItemRef(int index) + => ref _builder.ItemRef(index); + + public void Add(T item) + => _builder.Add(item); + + /// + public void AddRange(IEnumerable items) + => _builder.AddRange(items); + + /// + public int BinarySearch(T item) + => _builder.BinarySearch(item); + + /// + public int BinarySearch(T item, IComparer? comparer) + => _builder.BinarySearch(item, comparer); + + /// + public int BinarySearch(int index, int count, T item, IComparer? comparer) + => _builder.BinarySearch(index, count, item, comparer); + + public void Clear() + => _builder.Clear(); + + public bool Contains(T item) + => _builder.Contains(item); + + /// + public ImmutableSegmentedList ConvertAll(Converter converter) + => _builder.ConvertAll(converter); + + /// + public void CopyTo(T[] array) + => _builder.CopyTo(array); + + public void CopyTo(T[] array, int arrayIndex) + => _builder.CopyTo(array, arrayIndex); + + /// + public void CopyTo(int index, T[] array, int arrayIndex, int count) + => _builder.CopyTo(index, array, arrayIndex, count); + + /// + public bool Exists(Predicate match) + => _builder.Exists(match); + + /// + public T? Find(Predicate match) + => _builder.Find(match); + + /// + public ImmutableSegmentedList FindAll(Predicate match) + => _builder.FindAll(match); + + /// + public int FindIndex(Predicate match) + => _builder.FindIndex(match); + + /// + public int FindIndex(int startIndex, Predicate match) + => _builder.FindIndex(startIndex, match); + + /// + public int FindIndex(int startIndex, int count, Predicate match) + => _builder.FindIndex(startIndex, count, match); + + /// + public T? FindLast(Predicate match) + => _builder.FindLast(match); + + /// + public int FindLastIndex(Predicate match) + => _builder.FindLastIndex(match); + + /// + public int FindLastIndex(int startIndex, Predicate match) + => _builder.FindLastIndex(startIndex, match); + + /// + public int FindLastIndex(int startIndex, int count, Predicate match) + => _builder.FindLastIndex(startIndex, count, match); + + /// + public void ForEach(Action action) + => _builder.ForEach(action); + + /// + public Enumerator GetEnumerator() + => _builder.GetEnumerator(); + + /// + public ImmutableSegmentedList GetRange(int index, int count) + => _builder.GetRange(index, count); + + public int IndexOf(T item) + => _builder.IndexOf(item); + + /// + public int IndexOf(T item, int index) + => _builder.IndexOf(item, index); + + /// + public int IndexOf(T item, int index, int count) + => _builder.IndexOf(item, index, count); + + /// + public int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) + => _builder.IndexOf(item, index, count, equalityComparer); + + public void Insert(int index, T item) + => _builder.Insert(index, item); + + /// + public void InsertRange(int index, IEnumerable items) + => _builder.InsertRange(index, items); + + /// + public int LastIndexOf(T item) + => _builder.LastIndexOf(item); + + /// + public int LastIndexOf(T item, int startIndex) + => _builder.LastIndexOf(item, startIndex); + + /// + public int LastIndexOf(T item, int startIndex, int count) + => _builder.LastIndexOf(item, startIndex, count); + + /// + public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer? equalityComparer) + => _builder.LastIndexOf(item, startIndex, count, equalityComparer); + + public bool Remove(T item) + => _builder.Remove(item); + + /// + public int RemoveAll(Predicate match) + => _builder.RemoveAll(match); + + public void RemoveAt(int index) + => _builder.RemoveAt(index); + + /// + public void Reverse() + => _builder.Reverse(); + + /// + public void Reverse(int index, int count) + => _builder.Reverse(index, count); + + /// + public void Sort() + => _builder.Sort(); + + /// + public void Sort(IComparer? comparer) + => _builder.Sort(comparer); + + /// + public void Sort(Comparison comparison) + => _builder.Sort(comparison); + + /// + public void Sort(int index, int count, IComparer? comparer) + => _builder.Sort(index, count, comparer); + + /// + public ImmutableSegmentedList ToImmutable() + => _builder.ToImmutable(); + + /// + public bool TrueForAll(Predicate match) + => _builder.TrueForAll(match); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + + int IList.Add(object? value) + => IListCalls.Add(ref _builder, value); + + bool IList.Contains(object? value) + => IListCalls.Contains(ref _builder, value); + + int IList.IndexOf(object? value) + => IListCalls.IndexOf(ref _builder, value); + + void IList.Insert(int index, object? value) + => IListCalls.Insert(ref _builder, index, value); + + void IList.Remove(object? value) + => IListCalls.Remove(ref _builder, value); + + void ICollection.CopyTo(Array array, int index) + => ICollectionCalls.CopyTo(ref _builder, array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+Enumerator.cs new file mode 100755 index 00000000000..6d61c3a3178 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+Enumerator.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial struct ImmutableSegmentedList + { + public struct Enumerator : IEnumerator + { + private readonly SegmentedList _list; + private SegmentedList.Enumerator _enumerator; + + internal Enumerator(SegmentedList list) + { + _list = list; + _enumerator = list.GetEnumerator(); + } + + public readonly T Current => _enumerator.Current; + + readonly object? IEnumerator.Current => ((IEnumerator)_enumerator).Current; + + public readonly void Dispose() + => _enumerator.Dispose(); + + public bool MoveNext() + => _enumerator.MoveNext(); + + public void Reset() + { + // Create a new enumerator, since _enumerator.Reset() will fail for cases where the list was mutated + // after enumeration started, and ImmutableSegmentList.Builder allows for this case without error. + _enumerator = _list.GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+PrivateMarshal.cs new file mode 100755 index 00000000000..1b9cae87e4a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+PrivateMarshal.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial struct ImmutableSegmentedList + { + /// + /// Private helper class for use only by and + /// . + /// + internal static class PrivateMarshal + { + internal static ImmutableSegmentedList VolatileRead(in ImmutableSegmentedList location) + { + var list = Volatile.Read(ref Unsafe.AsRef(in location._list)); + if (list is null) + return default; + + return new ImmutableSegmentedList(list); + } + + internal static ImmutableSegmentedList InterlockedExchange(ref ImmutableSegmentedList location, ImmutableSegmentedList value) + { + var list = Interlocked.Exchange(ref Unsafe.AsRef(in location._list), value._list); + if (list is null) + return default; + + return new ImmutableSegmentedList(list); + } + + internal static ImmutableSegmentedList InterlockedCompareExchange(ref ImmutableSegmentedList location, ImmutableSegmentedList value, ImmutableSegmentedList comparand) + { + var list = Interlocked.CompareExchange(ref Unsafe.AsRef(in location._list), value._list, comparand._list); + if (list is null) + return default; + + return new ImmutableSegmentedList(list); + } + + /// + internal static ImmutableSegmentedList AsImmutableSegmentedList(SegmentedList? list) + => list is not null ? new ImmutableSegmentedList(list) : default; + + /// + internal static SegmentedList? AsSegmentedList(ImmutableSegmentedList list) + => list._list; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+ValueBuilder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+ValueBuilder.cs new file mode 100755 index 00000000000..f71b14da7f5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1+ValueBuilder.cs @@ -0,0 +1,360 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial struct ImmutableSegmentedList + { + private struct ValueBuilder : IList, IReadOnlyList, IList + { + /// + /// The immutable collection this builder is based on. + /// + private ImmutableSegmentedList _list; + + /// + /// The current mutable collection this builder is operating on. This field is initialized to a copy of + /// the first time a change is made. + /// + private SegmentedList? _mutableList; + + internal ValueBuilder(ImmutableSegmentedList list) + { + _list = list; + _mutableList = null; + } + + public readonly int Count => ReadOnlyList.Count; + + private readonly SegmentedList ReadOnlyList => _mutableList ?? _list._list; + + readonly bool ICollection.IsReadOnly => false; + + readonly bool IList.IsFixedSize => false; + + readonly bool IList.IsReadOnly => false; + + readonly bool ICollection.IsSynchronized => false; + + readonly object ICollection.SyncRoot => throw new NotSupportedException(); + + public T this[int index] + { + readonly get => ReadOnlyList[index]; + set => GetOrCreateMutableList()[index] = value; + } + + object? IList.this[int index] + { + readonly get => ((IList)ReadOnlyList)[index]; + set => ((IList)GetOrCreateMutableList())[index] = value; + } + + public readonly ref readonly T ItemRef(int index) + { + // Following trick can reduce the range check by one + if ((uint)index >= (uint)ReadOnlyList.Count) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + + return ref ReadOnlyList._items[index]; + } + + private SegmentedList GetOrCreateMutableList() + { + if (_mutableList is null) + { + var originalList = RoslynImmutableInterlocked.InterlockedExchange(ref _list, default); + if (originalList.IsDefault) + throw new InvalidOperationException($"Unexpected concurrent access to {GetType()}"); + + _mutableList = new SegmentedList(originalList._list); + } + + return _mutableList; + } + + public void Add(T item) + => GetOrCreateMutableList().Add(item); + + public void AddRange(IEnumerable items) + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + GetOrCreateMutableList().AddRange(items); + } + + public readonly int BinarySearch(T item) + => ReadOnlyList.BinarySearch(item); + + public readonly int BinarySearch(T item, IComparer? comparer) + => ReadOnlyList.BinarySearch(item, comparer); + + public readonly int BinarySearch(int index, int count, T item, IComparer? comparer) + => ReadOnlyList.BinarySearch(index, count, item, comparer); + + public void Clear() + { + if (ReadOnlyList.Count != 0) + { + if (_mutableList is null) + { + _mutableList = new SegmentedList(); + _list = default; + } + else + { + _mutableList.Clear(); + } + } + } + + public readonly bool Contains(T item) + => ReadOnlyList.Contains(item); + + public readonly ImmutableSegmentedList ConvertAll(Converter converter) + => new ImmutableSegmentedList(ReadOnlyList.ConvertAll(converter)); + + public readonly void CopyTo(T[] array) + => ReadOnlyList.CopyTo(array); + + public readonly void CopyTo(T[] array, int arrayIndex) + => ReadOnlyList.CopyTo(array, arrayIndex); + + public readonly void CopyTo(int index, T[] array, int arrayIndex, int count) + => ReadOnlyList.CopyTo(index, array, arrayIndex, count); + + public readonly bool Exists(Predicate match) + => ReadOnlyList.Exists(match); + + public readonly T? Find(Predicate match) + => ReadOnlyList.Find(match); + + public readonly ImmutableSegmentedList FindAll(Predicate match) + => new ImmutableSegmentedList(ReadOnlyList.FindAll(match)); + + public readonly int FindIndex(Predicate match) + => ReadOnlyList.FindIndex(match); + + public readonly int FindIndex(int startIndex, Predicate match) + => ReadOnlyList.FindIndex(startIndex, match); + + public readonly int FindIndex(int startIndex, int count, Predicate match) + => ReadOnlyList.FindIndex(startIndex, count, match); + + public readonly T? FindLast(Predicate match) + => ReadOnlyList.FindLast(match); + + public readonly int FindLastIndex(Predicate match) + => ReadOnlyList.FindLastIndex(match); + + public readonly int FindLastIndex(int startIndex, Predicate match) + { + if (startIndex == 0 && Count == 0) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return ReadOnlyList.FindLastIndex(startIndex, match); + } + + public readonly int FindLastIndex(int startIndex, int count, Predicate match) + { + if (count == 0 && startIndex == 0 && Count == 0) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return ReadOnlyList.FindLastIndex(startIndex, count, match); + } + + public readonly void ForEach(Action action) + => ReadOnlyList.ForEach(action); + + public Enumerator GetEnumerator() + => new Enumerator(GetOrCreateMutableList()); + + public ImmutableSegmentedList GetRange(int index, int count) + { + if (index == 0 && count == Count) + return ToImmutable(); + + return new ImmutableSegmentedList(ReadOnlyList.GetRange(index, count)); + } + + public readonly int IndexOf(T item) + => ReadOnlyList.IndexOf(item); + + public readonly int IndexOf(T item, int index) + => ReadOnlyList.IndexOf(item, index); + + public readonly int IndexOf(T item, int index, int count) + => ReadOnlyList.IndexOf(item, index, count); + + public readonly int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) + => ReadOnlyList.IndexOf(item, index, count, equalityComparer); + + public void Insert(int index, T item) + => GetOrCreateMutableList().Insert(index, item); + + public void InsertRange(int index, IEnumerable items) + => GetOrCreateMutableList().InsertRange(index, items); + + public readonly int LastIndexOf(T item) + => ReadOnlyList.LastIndexOf(item); + + public readonly int LastIndexOf(T item, int startIndex) + { + if (startIndex == 0 && Count == 0) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return ReadOnlyList.LastIndexOf(item, startIndex); + } + + public readonly int LastIndexOf(T item, int startIndex, int count) + { + if (count == 0 && startIndex == 0 && Count == 0) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return ReadOnlyList.LastIndexOf(item, startIndex, count); + } + + public readonly int LastIndexOf(T item, int startIndex, int count, IEqualityComparer? equalityComparer) + { + if (startIndex < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (count < 0 || count > Count) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count); + if (startIndex - count + 1 < 0) + throw new ArgumentException(); + + return ReadOnlyList.LastIndexOf(item, startIndex, count, equalityComparer); + } + + public bool Remove(T item) + { + if (_mutableList is null) + { + var index = IndexOf(item); + if (index < 0) + return false; + + RemoveAt(index); + return true; + } + else + { + return _mutableList.Remove(item); + } + } + + public int RemoveAll(Predicate match) + => GetOrCreateMutableList().RemoveAll(match); + + public void RemoveAt(int index) + => GetOrCreateMutableList().RemoveAt(index); + + public void RemoveRange(int index, int count) + => GetOrCreateMutableList().RemoveRange(index, count); + + public void Reverse() + { + if (Count < 2) + return; + + GetOrCreateMutableList().Reverse(); + } + + public void Reverse(int index, int count) + => GetOrCreateMutableList().Reverse(index, count); + + public void Sort() + { + if (Count < 2) + return; + + GetOrCreateMutableList().Sort(); + } + + public void Sort(IComparer? comparer) + { + if (Count < 2) + return; + + GetOrCreateMutableList().Sort(comparer); + } + + public void Sort(Comparison comparison) + { + if (comparison == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); + } + + if (Count < 2) + return; + + GetOrCreateMutableList().Sort(comparison); + } + + public void Sort(int index, int count, IComparer? comparer) + => GetOrCreateMutableList().Sort(index, count, comparer); + + public ImmutableSegmentedList ToImmutable() + { + _list = new ImmutableSegmentedList(ReadOnlyList); + _mutableList = null; + return _list; + } + + public readonly bool TrueForAll(Predicate match) + => ReadOnlyList.TrueForAll(match); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + int IList.Add(object? value) + => ((IList)GetOrCreateMutableList()).Add(value); + + readonly bool IList.Contains(object? value) + => ((IList)ReadOnlyList).Contains(value); + + readonly int IList.IndexOf(object? value) + => ((IList)ReadOnlyList).IndexOf(value); + + void IList.Insert(int index, object? value) + => ((IList)GetOrCreateMutableList()).Insert(index, value); + + void IList.Remove(object? value) + => ((IList)GetOrCreateMutableList()).Remove(value); + + readonly void ICollection.CopyTo(Array array, int index) + => ((ICollection)ReadOnlyList).CopyTo(array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1.cs new file mode 100755 index 00000000000..41a5c8473f2 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/ImmutableSegmentedList`1.cs @@ -0,0 +1,693 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a segmented list that is immutable; meaning it cannot be changed once it is created. + /// + /// + /// There are different scenarios best for and others + /// best for . + /// + /// The following table summarizes the performance characteristics of + /// : + /// + /// + /// + /// Operation + /// Complexity + /// Complexity + /// Comments + /// + /// + /// Item + /// O(1) + /// O(log n) + /// Directly index into the underlying segmented list + /// + /// + /// Add() + /// Currently O(n), but could be O(1) with a relatively large constant + /// O(log n) + /// Currently requires creating a new segmented list, but could be modified to only clone the segments with changes + /// + /// + /// Insert() + /// O(n) + /// O(log n) + /// Requires creating a new segmented list and cloning all impacted segments + /// + /// + /// + /// This type is backed by segmented arrays to avoid using the Large Object Heap without impacting algorithmic + /// complexity. + /// + /// The type of the value in the list. + /// + /// This type has a documented contract of being exactly one reference-type field in size. Our own + /// class depends on it, as well as others externally. + /// + /// IMPORTANT NOTICE FOR MAINTAINERS AND REVIEWERS: + /// + /// This type should be thread-safe. As a struct, it cannot protect its own fields from being changed from one + /// thread while its members are executing on other threads because structs can change in place simply by + /// reassigning the field containing this struct. Therefore it is extremely important that ⚠⚠ Every member + /// should only dereference this ONCE ⚠⚠. If a member needs to reference the + /// field, that counts as a dereference of this. Calling other instance members + /// (properties or methods) also counts as dereferencing this. Any member that needs to use this more + /// than once must instead assign this to a local variable and use that for the rest of the code instead. + /// This effectively copies the one field in the struct to a local variable so that it is insulated from other + /// threads. + /// + internal readonly partial struct ImmutableSegmentedList : IImmutableList, IReadOnlyList, IList, IList, IEquatable> + { + /// + public static readonly ImmutableSegmentedList Empty = new(new SegmentedList()); + + private readonly SegmentedList _list; + + private ImmutableSegmentedList(SegmentedList list) + => _list = list; + + public int Count => _list.Count; + + public bool IsDefault => _list == null; + + /// + public bool IsEmpty => _list.Count == 0; + + bool ICollection.IsReadOnly => true; + + bool IList.IsFixedSize => true; + + bool IList.IsReadOnly => true; + + bool ICollection.IsSynchronized => true; + + object ICollection.SyncRoot => _list; + + public T this[int index] => _list[index]; + + T IList.this[int index] + { + get => _list[index]; + set => throw new NotSupportedException(); + } + + object? IList.this[int index] + { + get => _list[index]; + set => throw new NotSupportedException(); + } + + public static bool operator ==(ImmutableSegmentedList left, ImmutableSegmentedList right) + => left.Equals(right); + + public static bool operator !=(ImmutableSegmentedList left, ImmutableSegmentedList right) + => !left.Equals(right); + + public static bool operator ==(ImmutableSegmentedList? left, ImmutableSegmentedList? right) + => left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + public static bool operator !=(ImmutableSegmentedList? left, ImmutableSegmentedList? right) + => !left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + /// + public ref readonly T ItemRef(int index) + { + var self = this; + + // Following trick can reduce the number of range comparison operations by one + if (unchecked((uint)index) >= (uint)self.Count) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + + return ref self._list._items[index]; + } + + /// + public ImmutableSegmentedList Add(T value) + { + var self = this; + + if (self.IsEmpty) + { + var list = new SegmentedList { value }; + return new ImmutableSegmentedList(list); + } + else + { + // TODO: Optimize this to share all segments except for the last one + // TODO: Only resize the last page the minimum amount necessary + var builder = self.ToValueBuilder(); + builder.Add(value); + return builder.ToImmutable(); + } + } + + /// + public ImmutableSegmentedList AddRange(IEnumerable items) + { + var self = this; + + if (items is ICollection { Count: 0 }) + { + return self; + } + else if (self.IsEmpty) + { + if (items is ImmutableSegmentedList immutableList) + return immutableList; + else if (items is ImmutableSegmentedList.Builder builder) + return builder.ToImmutable(); + + var list = new SegmentedList(items); + return new ImmutableSegmentedList(list); + } + else + { + // TODO: Optimize this to share all segments except for the last one + var builder = self.ToValueBuilder(); + builder.AddRange(items); + return builder.ToImmutable(); + } + } + + /// + public int BinarySearch(T item) + => _list.BinarySearch(item); + + /// + public int BinarySearch(T item, IComparer? comparer) + => _list.BinarySearch(item, comparer); + + /// + public int BinarySearch(int index, int count, T item, IComparer? comparer) + => _list.BinarySearch(index, count, item, comparer); + + /// + public ImmutableSegmentedList Clear() + => Empty; + + public bool Contains(T value) + => _list.Contains(value); + + /// + public ImmutableSegmentedList ConvertAll(Converter converter) + => new ImmutableSegmentedList(_list.ConvertAll(converter)); + + /// + public void CopyTo(T[] array) + => _list.CopyTo(array); + + public void CopyTo(T[] array, int arrayIndex) + => _list.CopyTo(array, arrayIndex); + + /// + public void CopyTo(int index, T[] array, int arrayIndex, int count) + => _list.CopyTo(index, array, arrayIndex, count); + + /// + public bool Exists(Predicate match) + => _list.Exists(match); + + /// + public T? Find(Predicate match) + => _list.Find(match); + + /// + public ImmutableSegmentedList FindAll(Predicate match) + => new ImmutableSegmentedList(_list.FindAll(match)); + + /// + public int FindIndex(Predicate match) + => _list.FindIndex(match); + + /// + public int FindIndex(int startIndex, Predicate match) + => _list.FindIndex(startIndex, match); + + /// + public int FindIndex(int startIndex, int count, Predicate match) + => _list.FindIndex(startIndex, count, match); + + /// + public T? FindLast(Predicate match) + => _list.FindLast(match); + + /// + public int FindLastIndex(Predicate match) + => _list.FindLastIndex(match); + + /// + public int FindLastIndex(int startIndex, Predicate match) + { + var self = this; + + if (startIndex == 0 && self.IsEmpty) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return self._list.FindLastIndex(startIndex, match); + } + + /// + public int FindLastIndex(int startIndex, int count, Predicate match) + { + var self = this; + + if (count == 0 && startIndex == 0 && self.IsEmpty) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return self._list.FindLastIndex(startIndex, count, match); + } + + /// + public void ForEach(Action action) + => _list.ForEach(action); + + /// + public Enumerator GetEnumerator() + => new(_list); + + /// + public ImmutableSegmentedList GetRange(int index, int count) + { + var self = this; + + if (index == 0 && count == self.Count) + return self; + + return new ImmutableSegmentedList(self._list.GetRange(index, count)); + } + + public int IndexOf(T value) + => _list.IndexOf(value); + + public int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) + => _list.IndexOf(item, index, count, equalityComparer); + + /// + public ImmutableSegmentedList Insert(int index, T item) + { + var self = this; + + if (index == self.Count) + return self.Add(item); + + // TODO: Optimize this to share all segments prior to index + // TODO: Only resize the last page the minimum amount necessary + var builder = self.ToValueBuilder(); + builder.Insert(index, item); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList InsertRange(int index, IEnumerable items) + { + var self = this; + + if (index == self.Count) + return self.AddRange(items); + + // TODO: Optimize this to share all segments prior to index + // TODO: Only resize the last page the minimum amount necessary + var builder = self.ToValueBuilder(); + builder.InsertRange(index, items); + return builder.ToImmutable(); + } + + public int LastIndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) + { + var self = this; + + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (count < 0 || count > self.Count) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count); + if (index - count + 1 < 0) + throw new ArgumentException(); + + if (count == 0 && index == 0 && self.IsEmpty) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return self._list.LastIndexOf(item, index, count, equalityComparer); + } + + /// + public ImmutableSegmentedList Remove(T value) + { + var self = this; + + var index = self.IndexOf(value); + if (index < 0) + return self; + + return self.RemoveAt(index); + } + + /// + public ImmutableSegmentedList Remove(T value, IEqualityComparer? equalityComparer) + { + var self = this; + + var index = self.IndexOf(value, 0, Count, equalityComparer); + if (index < 0) + return self; + + return self.RemoveAt(index); + } + + /// + public ImmutableSegmentedList RemoveAll(Predicate match) + { + // TODO: Optimize this to avoid allocations if no items are removed + // TODO: Optimize this to share pages prior to the first removed item + var builder = ToValueBuilder(); + builder.RemoveAll(match); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList RemoveAt(int index) + { + // TODO: Optimize this to share pages prior to the removed item + var builder = ToValueBuilder(); + builder.RemoveAt(index); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList RemoveRange(IEnumerable items) + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + var self = this; + + if (self.IsEmpty) + return self; + + var builder = ToValueBuilder(); + foreach (var item in items) + { + var index = builder.IndexOf(item); + if (index < 0) + continue; + + builder.RemoveAt(index); + } + + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList RemoveRange(IEnumerable items, IEqualityComparer? equalityComparer) + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + var self = this; + + if (self.IsEmpty) + return self; + + var builder = ToValueBuilder(); + foreach (var item in items) + { + var index = builder.IndexOf(item, 0, builder.Count, equalityComparer); + if (index < 0) + continue; + + builder.RemoveAt(index); + } + + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList RemoveRange(int index, int count) + { + var self = this; + + if (count == 0 && index >= 0 && index <= self.Count) + { + return self; + } + + // TODO: Optimize this to share pages prior to the first removed item + var builder = self.ToValueBuilder(); + builder.RemoveRange(index, count); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Replace(T oldValue, T newValue) + { + var self = this; + + var index = self.IndexOf(oldValue); + if (index < 0) + { + throw new ArgumentException(SR.CannotFindOldValue, nameof(oldValue)); + } + + return self.SetItem(index, newValue); + } + + /// + public ImmutableSegmentedList Replace(T oldValue, T newValue, IEqualityComparer? equalityComparer) + { + var self = this; + + var index = self.IndexOf(oldValue, equalityComparer); + if (index < 0) + { + throw new ArgumentException(SR.CannotFindOldValue, nameof(oldValue)); + } + + return self.SetItem(index, newValue); + } + + /// + public ImmutableSegmentedList Reverse() + { + var self = this; + if (self.Count < 2) + return self; + + var builder = self.ToValueBuilder(); + builder.Reverse(); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Reverse(int index, int count) + { + var builder = ToValueBuilder(); + builder.Reverse(index, count); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList SetItem(int index, T value) + { + // TODO: Optimize this to share all pages except the one with 'index' + var builder = ToValueBuilder(); + builder[index] = value; + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Sort() + { + var self = this; + + if (self.Count < 2) + return self; + + // TODO: Optimize this to avoid allocations if the list is already sorted + var builder = self.ToValueBuilder(); + builder.Sort(); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Sort(IComparer? comparer) + { + var self = this; + + if (self.Count < 2) + return self; + + // TODO: Optimize this to avoid allocations if the list is already sorted + var builder = self.ToValueBuilder(); + builder.Sort(comparer); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Sort(Comparison comparison) + { + if (comparison == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); + } + + var self = this; + + if (self.Count < 2) + return self; + + // TODO: Optimize this to avoid allocations if the list is already sorted + var builder = self.ToValueBuilder(); + builder.Sort(comparison); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Sort(int index, int count, IComparer? comparer) + { + // TODO: Optimize this to avoid allocations if the list is already sorted + var builder = ToValueBuilder(); + builder.Sort(index, count, comparer); + return builder.ToImmutable(); + } + + /// + public Builder ToBuilder() + => new Builder(this); + + private ValueBuilder ToValueBuilder() + => new ValueBuilder(this); + + public override int GetHashCode() + => _list?.GetHashCode() ?? 0; + + public override bool Equals(object? obj) + { + return obj is ImmutableSegmentedList other + && Equals(other); + } + + public bool Equals(ImmutableSegmentedList other) + => _list == other._list; + + /// + public bool TrueForAll(Predicate match) + => _list.TrueForAll(match); + + IImmutableList IImmutableList.Clear() + => Clear(); + + IImmutableList IImmutableList.Add(T value) + => Add(value); + + IImmutableList IImmutableList.AddRange(IEnumerable items) + => AddRange(items); + + IImmutableList IImmutableList.Insert(int index, T element) + => Insert(index, element); + + IImmutableList IImmutableList.InsertRange(int index, IEnumerable items) + => InsertRange(index, items); + + IImmutableList IImmutableList.Remove(T value, IEqualityComparer? equalityComparer) + => Remove(value, equalityComparer); + + IImmutableList IImmutableList.RemoveAll(Predicate match) + => RemoveAll(match); + + IImmutableList IImmutableList.RemoveRange(IEnumerable items, IEqualityComparer? equalityComparer) + => RemoveRange(items, equalityComparer); + + IImmutableList IImmutableList.RemoveRange(int index, int count) + => RemoveRange(index, count); + + IImmutableList IImmutableList.RemoveAt(int index) + => RemoveAt(index); + + IImmutableList IImmutableList.SetItem(int index, T value) + => SetItem(index, value); + + IImmutableList IImmutableList.Replace(T oldValue, T newValue, IEqualityComparer? equalityComparer) + => Replace(oldValue, newValue, equalityComparer); + + IEnumerator IEnumerable.GetEnumerator() + => IsEmpty ? Enumerable.Empty().GetEnumerator() : GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => ((IEnumerable)this).GetEnumerator(); + + void IList.Insert(int index, T item) + => throw new NotSupportedException(); + + void IList.RemoveAt(int index) + => throw new NotSupportedException(); + + void ICollection.Add(T item) + => throw new NotSupportedException(); + + void ICollection.Clear() + => throw new NotSupportedException(); + + bool ICollection.Remove(T item) + => throw new NotSupportedException(); + + int IList.Add(object? value) + => throw new NotSupportedException(); + + void IList.Clear() + => throw new NotSupportedException(); + + bool IList.Contains(object? value) + { + IList backingList = _list; + return backingList.Contains(value); + } + + int IList.IndexOf(object? value) + { + IList backingList = _list; + return backingList.IndexOf(value); + } + + void IList.Insert(int index, object? value) + => throw new NotSupportedException(); + + void IList.Remove(object? value) + => throw new NotSupportedException(); + + void IList.RemoveAt(int index) + => throw new NotSupportedException(); + + void ICollection.CopyTo(Array array, int index) + { + IList backingList = _list; + backingList.CopyTo(array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedArray.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedArray.cs new file mode 100755 index 00000000000..56301f0c088 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedArray.cs @@ -0,0 +1,802 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static class SegmentedArray + { +#if NET6_0_OR_GREATER + /// +#endif + internal static void Clear(SegmentedArray array) + => Clear(array, 0, array.Length); + + /// + internal static void Clear(SegmentedArray array, int index, int length) + { + foreach (var memory in array.GetSegments(index, length)) + { + memory.Span.Clear(); + } + } + + /// + internal static void Copy(SegmentedArray sourceArray, SegmentedArray destinationArray, int length) + { + if (length == 0) + return; + + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length)); + if (length > sourceArray.Length) + throw new ArgumentException(SR.Arg_LongerThanSrcArray, nameof(sourceArray)); + if (length > destinationArray.Length) + throw new ArgumentException(SR.Arg_LongerThanDestArray, nameof(destinationArray)); + + foreach (var (first, second) in GetSegments(sourceArray, destinationArray, length)) + { + first.CopyTo(second); + } + } + + public static void Copy(SegmentedArray sourceArray, Array destinationArray, int length) + { + if (destinationArray is null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.destinationArray); + if (length == 0) + return; + + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length)); + if (length > sourceArray.Length) + throw new ArgumentException(SR.Arg_LongerThanSrcArray, nameof(sourceArray)); + if (length > destinationArray.Length) + throw new ArgumentException(SR.Arg_LongerThanDestArray, nameof(destinationArray)); + + var copied = 0; + foreach (var memory in sourceArray.GetSegments(0, length)) + { + if (!MemoryMarshal.TryGetArray(memory, out var segment)) + { + throw new NotSupportedException(); + } + + Array.Copy(segment.Array!, sourceIndex: segment.Offset, destinationArray: destinationArray, destinationIndex: copied, length: segment.Count); + copied += segment.Count; + } + } + + public static void Copy(SegmentedArray sourceArray, int sourceIndex, SegmentedArray destinationArray, int destinationIndex, int length) + { + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum); + if (sourceIndex < 0) + throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_ArrayLB); + if (destinationIndex < 0) + throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_ArrayLB); + if ((uint)(sourceIndex + length) > sourceArray.Length) + throw new ArgumentException(SR.Arg_LongerThanSrcArray, nameof(sourceArray)); + if ((uint)(destinationIndex + length) > destinationArray.Length) + throw new ArgumentException(SR.Arg_LongerThanDestArray, nameof(destinationArray)); + + if (length == 0) + return; + + if (SegmentedCollectionsMarshal.AsSegments(sourceArray) == SegmentedCollectionsMarshal.AsSegments(destinationArray) + && sourceIndex + length > destinationIndex) + { + // We are copying in the same array with overlap + CopyOverlapped(sourceArray, sourceIndex, destinationIndex, length); + } + else + { + foreach (var (first, second) in GetSegmentsUnaligned(sourceArray, sourceIndex, destinationArray, destinationIndex, length)) + { + first.CopyTo(second); + } + } + } + + // PERF: Avoid inlining this path in Copy + [MethodImpl(MethodImplOptions.NoInlining)] + private static void CopyOverlapped(SegmentedArray array, int sourceIndex, int destinationIndex, int length) + { + Debug.Assert(length > 0); + Debug.Assert(sourceIndex >= 0); + Debug.Assert(destinationIndex >= 0); + Debug.Assert((uint)(sourceIndex + length) <= array.Length); + Debug.Assert((uint)(destinationIndex + length) <= array.Length); + + var unalignedEnumerator = GetSegmentsUnaligned(array, sourceIndex, array, destinationIndex, length); + if (sourceIndex < destinationIndex) + { + // We are copying forward in the same array with overlap + foreach (var (first, second) in unalignedEnumerator.Reverse()) + { + first.CopyTo(second); + } + } + else + { + foreach (var (first, second) in unalignedEnumerator) + { + first.CopyTo(second); + } + } + } + + public static void Copy(SegmentedArray sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length) + { + if (destinationArray == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.destinationArray); + + if (typeof(T[]) != destinationArray.GetType() && destinationArray.Rank != 1) + throw new RankException(SR.Rank_MustMatch); + + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum); + if (sourceIndex < 0) + throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_ArrayLB); + + var dstLB = destinationArray.GetLowerBound(0); + if (destinationIndex < dstLB || destinationIndex - dstLB < 0) + throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_ArrayLB); + destinationIndex -= dstLB; + + if ((uint)(sourceIndex + length) > sourceArray.Length) + throw new ArgumentException(SR.Arg_LongerThanSrcArray, nameof(sourceArray)); + if ((uint)(destinationIndex + length) > (nuint)destinationArray.LongLength) + throw new ArgumentException(SR.Arg_LongerThanDestArray, nameof(destinationArray)); + + var copied = 0; + foreach (var memory in sourceArray.GetSegments(sourceIndex, length)) + { + if (!MemoryMarshal.TryGetArray(memory, out var segment)) + { + throw new NotSupportedException(); + } + + Array.Copy(segment.Array!, sourceIndex: segment.Offset, destinationArray: destinationArray, destinationIndex: destinationIndex + copied, length: segment.Count); + copied += segment.Count; + } + } + + public static int BinarySearch(SegmentedArray array, T value) + { + return BinarySearch(array, 0, array.Length, value, comparer: null); + } + + public static int BinarySearch(SegmentedArray array, T value, IComparer? comparer) + { + return BinarySearch(array, 0, array.Length, value, comparer); + } + + public static int BinarySearch(SegmentedArray array, int index, int length, T value) + { + return BinarySearch(array, index, length, value, comparer: null); + } + + public static int BinarySearch(SegmentedArray array, int index, int length, T value, IComparer? comparer) + { + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (length < 0) + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); + if (array.Length - index < length) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + return SegmentedArraySortHelper.BinarySearch(array, index, length, value, comparer); + } + + public static int IndexOf(SegmentedArray array, T value) + { + return IndexOf(array, value, 0, array.Length, comparer: null); + } + + public static int IndexOf(SegmentedArray array, T value, int startIndex) + { + return IndexOf(array, value, startIndex, array.Length - startIndex, comparer: null); + } + + public static int IndexOf(SegmentedArray array, T value, int startIndex, int count) + { + return IndexOf(array, value, startIndex, count, comparer: null); + } + + public static int IndexOf(SegmentedArray array, T value, int startIndex, int count, IEqualityComparer? comparer) + { + if ((uint)startIndex > (uint)array.Length) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLessOrEqual(); + } + + if ((uint)count > (uint)(array.Length - startIndex)) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + var offset = startIndex; + foreach (var memory in array.GetSegments(startIndex, count)) + { + if (!MemoryMarshal.TryGetArray(memory, out var segment)) + { + throw new NotSupportedException(); + } + + int index; + if (comparer is null || comparer == EqualityComparer.Default) + { + index = Array.IndexOf(segment.Array!, value, segment.Offset, segment.Count); + } + else + { + index = -1; + var endIndex = segment.Offset + segment.Count; + for (var i = segment.Offset; i < endIndex; i++) + { + if (comparer.Equals(array[i], value)) + { + index = i; + break; + } + } + } + + if (index >= 0) + { + return index + offset - segment.Offset; + } + + offset += segment.Count; + } + + return -1; + } + + public static int LastIndexOf(SegmentedArray array, T value) + { + return LastIndexOf(array, value, array.Length - 1, array.Length, comparer: null); + } + + public static int LastIndexOf(SegmentedArray array, T value, int startIndex) + { + return LastIndexOf(array, value, startIndex, array.Length == 0 ? 0 : startIndex + 1, comparer: null); + } + + public static int LastIndexOf(SegmentedArray array, T value, int startIndex, int count) + { + return LastIndexOf(array, value, startIndex, count, comparer: null); + } + + public static int LastIndexOf(SegmentedArray array, T value, int startIndex, int count, IEqualityComparer? comparer) + { + if (array.Length == 0) + { + // Special case for 0 length List + // accept -1 and 0 as valid startIndex for compatibility reason. + if (startIndex is not (-1) and not 0) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); + } + + // only 0 is a valid value for count if array is empty + if (count != 0) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + return -1; + } + + // Make sure we're not out of range + if ((uint)startIndex >= (uint)array.Length) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); + } + + // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. + if (count < 0 || startIndex - count + 1 < 0) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + if (comparer is null || comparer == EqualityComparer.Default) + { + var endIndex = startIndex - count + 1; + for (var i = startIndex; i >= endIndex; i--) + { + if (EqualityComparer.Default.Equals(array[i], value)) + return i; + } + } + else + { + var endIndex = startIndex - count + 1; + for (var i = startIndex; i >= endIndex; i--) + { + if (comparer.Equals(array[i], value)) + return i; + } + } + + return -1; + } + + public static void Reverse(SegmentedArray array) + { + Reverse(array, 0, array.Length); + } + + public static void Reverse(SegmentedArray array, int index, int length) + { + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (length < 0) + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); + if (array.Length - index < length) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (length <= 1) + return; + + var firstIndex = index; + var lastIndex = index + length - 1; + do + { + var temp = array[firstIndex]; + array[firstIndex] = array[lastIndex]; + array[lastIndex] = temp; + firstIndex++; + lastIndex--; + } while (firstIndex < lastIndex); + } + + public static void Sort(SegmentedArray array) + { + if (array.Length > 1) + { + var segment = new SegmentedArraySegment(array, 0, array.Length); + SegmentedArraySortHelper.Sort(segment, (IComparer?)null); + } + } + + public static void Sort(SegmentedArray array, int index, int length) + { + Sort(array, index, length, comparer: null); + } + + public static void Sort(SegmentedArray array, IComparer? comparer) + { + Sort(array, 0, array.Length, comparer); + } + + public static void Sort(SegmentedArray array, int index, int length, IComparer? comparer) + { + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (length < 0) + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); + if (array.Length - index < length) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (length > 1) + { + var segment = new SegmentedArraySegment(array, index, length); + SegmentedArraySortHelper.Sort(segment, comparer); + } + } + + public static void Sort(SegmentedArray array, Comparison comparison) + { + if (comparison is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); + } + + if (array.Length > 1) + { + var segment = new SegmentedArraySegment(array, 0, array.Length); + SegmentedArraySortHelper.Sort(segment, comparison); + } + } + + private static SegmentEnumerable GetSegments(this SegmentedArray array, int offset, int length) + => new(array, offset, length); + + private static AlignedSegmentEnumerable GetSegments(SegmentedArray first, SegmentedArray second, int length) + => new(first, second, length); + +#pragma warning disable IDE0051 // Remove unused private members (will be used in follow-up) + private static AlignedSegmentEnumerable GetSegmentsAligned(SegmentedArray first, int firstOffset, SegmentedArray second, int secondOffset, int length) + => new(first, firstOffset, second, secondOffset, length); +#pragma warning restore IDE0051 // Remove unused private members + + private static UnalignedSegmentEnumerable GetSegmentsUnaligned(SegmentedArray first, int firstOffset, SegmentedArray second, int secondOffset, int length) + => new(first, firstOffset, second, secondOffset, length); + + private readonly struct AlignedSegmentEnumerable + { + private readonly SegmentedArray _first; + private readonly int _firstOffset; + private readonly SegmentedArray _second; + private readonly int _secondOffset; + private readonly int _length; + + public AlignedSegmentEnumerable(SegmentedArray first, SegmentedArray second, int length) + : this(first, 0, second, 0, length) + { + } + + public AlignedSegmentEnumerable(SegmentedArray first, int firstOffset, SegmentedArray second, int secondOffset, int length) + { + _first = first; + _firstOffset = firstOffset; + _second = second; + _secondOffset = secondOffset; + _length = length; + } + + public AlignedSegmentEnumerator GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_first), _firstOffset, SegmentedCollectionsMarshal.AsSegments(_second), _secondOffset, _length); + } + + private struct AlignedSegmentEnumerator + { + private readonly T[][] _firstSegments; + private readonly int _firstOffset; + private readonly T[][] _secondSegments; + private readonly int _secondOffset; + private readonly int _length; + + private int _completed; + private (Memory first, Memory second) _current; + + public AlignedSegmentEnumerator(T[][] firstSegments, int firstOffset, T[][] secondSegments, int secondOffset, int length) + { + _firstSegments = firstSegments; + _firstOffset = firstOffset; + _secondSegments = secondSegments; + _secondOffset = secondOffset; + _length = length; + + _completed = 0; + _current = (Memory.Empty, Memory.Empty); + } + + public readonly (Memory first, Memory second) Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = (Memory.Empty, Memory.Empty); + return false; + } + + if (_completed == 0) + { + var initialFirstSegment = _firstOffset >> SegmentedArrayHelper.GetSegmentShift(); + var initialSecondSegment = _secondOffset >> SegmentedArrayHelper.GetSegmentShift(); + var offset = _firstOffset & SegmentedArrayHelper.GetOffsetMask(); + Debug.Assert(offset == (_secondOffset & SegmentedArrayHelper.GetOffsetMask()), "Aligned views must start at the same segment offset"); + + var firstSegment = _firstSegments[initialFirstSegment]; + var secondSegment = _secondSegments[initialSecondSegment]; + var remainingInSegment = firstSegment.Length - offset; + var currentSegmentLength = Math.Min(remainingInSegment, _length); + _current = (firstSegment.AsMemory().Slice(offset, currentSegmentLength), secondSegment.AsMemory().Slice(offset, currentSegmentLength)); + _completed = currentSegmentLength; + return true; + } + else + { + var firstSegment = _firstSegments[(_completed + _firstOffset) >> SegmentedArrayHelper.GetSegmentShift()]; + var secondSegment = _secondSegments[(_completed + _secondOffset) >> SegmentedArrayHelper.GetSegmentShift()]; + var currentSegmentLength = Math.Min(SegmentedArrayHelper.GetSegmentSize(), _length - _completed); + _current = (firstSegment.AsMemory().Slice(0, currentSegmentLength), secondSegment.AsMemory().Slice(0, currentSegmentLength)); + _completed += currentSegmentLength; + return true; + } + } + } + + private readonly struct UnalignedSegmentEnumerable + { + private readonly SegmentedArray _first; + private readonly int _firstOffset; + private readonly SegmentedArray _second; + private readonly int _secondOffset; + private readonly int _length; + + public UnalignedSegmentEnumerable(SegmentedArray first, SegmentedArray second, int length) + : this(first, 0, second, 0, length) + { + } + + public UnalignedSegmentEnumerable(SegmentedArray first, int firstOffset, SegmentedArray second, int secondOffset, int length) + { + _first = first; + _firstOffset = firstOffset; + _second = second; + _secondOffset = secondOffset; + _length = length; + } + + public UnalignedSegmentEnumerator GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_first), _firstOffset, SegmentedCollectionsMarshal.AsSegments(_second), _secondOffset, _length); + + public ReverseEnumerable Reverse() + => new(this); + + public readonly struct ReverseEnumerable + { + private readonly UnalignedSegmentEnumerable _enumerable; + + public ReverseEnumerable(UnalignedSegmentEnumerable enumerable) + { + _enumerable = enumerable; + } + + public UnalignedSegmentEnumerator.Reverse GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_enumerable._first), _enumerable._firstOffset, SegmentedCollectionsMarshal.AsSegments(_enumerable._second), _enumerable._secondOffset, _enumerable._length); + + public UnalignedSegmentEnumerable Reverse() + => _enumerable; + } + } + + private struct UnalignedSegmentEnumerator + { + private readonly T[][] _firstSegments; + private readonly int _firstOffset; + private readonly T[][] _secondSegments; + private readonly int _secondOffset; + private readonly int _length; + + private int _completed; + private (Memory first, Memory second) _current; + + public UnalignedSegmentEnumerator(T[][] firstSegments, int firstOffset, T[][] secondSegments, int secondOffset, int length) + { + _firstSegments = firstSegments; + _firstOffset = firstOffset; + _secondSegments = secondSegments; + _secondOffset = secondOffset; + _length = length; + + _completed = 0; + _current = (Memory.Empty, Memory.Empty); + } + + public readonly (Memory first, Memory second) Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = (Memory.Empty, Memory.Empty); + return false; + } + + var initialFirstSegment = (_completed + _firstOffset) >> SegmentedArrayHelper.GetSegmentShift(); + var initialSecondSegment = (_completed + _secondOffset) >> SegmentedArrayHelper.GetSegmentShift(); + var firstOffset = (_completed + _firstOffset) & SegmentedArrayHelper.GetOffsetMask(); + var secondOffset = (_completed + _secondOffset) & SegmentedArrayHelper.GetOffsetMask(); + + var firstSegment = _firstSegments[initialFirstSegment]; + var secondSegment = _secondSegments[initialSecondSegment]; + var remainingInFirstSegment = firstSegment.Length - firstOffset; + var remainingInSecondSegment = secondSegment.Length - secondOffset; + var currentSegmentLength = Math.Min(Math.Min(remainingInFirstSegment, remainingInSecondSegment), _length - _completed); + _current = (firstSegment.AsMemory().Slice(firstOffset, currentSegmentLength), secondSegment.AsMemory().Slice(secondOffset, currentSegmentLength)); + _completed += currentSegmentLength; + return true; + } + + public struct Reverse + { + private readonly T[][] _firstSegments; + private readonly int _firstOffset; + private readonly T[][] _secondSegments; + private readonly int _secondOffset; + private readonly int _length; + + private int _completed; + private (Memory first, Memory second) _current; + + public Reverse(T[][] firstSegments, int firstOffset, T[][] secondSegments, int secondOffset, int length) + { + _firstSegments = firstSegments; + _firstOffset = firstOffset; + _secondSegments = secondSegments; + _secondOffset = secondOffset; + _length = length; + + _completed = 0; + _current = (Memory.Empty, Memory.Empty); + } + + public readonly (Memory first, Memory second) Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = (Memory.Empty, Memory.Empty); + return false; + } + + var initialFirstSegment = (_firstOffset + _length - _completed - 1) >> SegmentedArrayHelper.GetSegmentShift(); + var initialSecondSegment = (_secondOffset + _length - _completed - 1) >> SegmentedArrayHelper.GetSegmentShift(); + var firstOffset = (_firstOffset + _length - _completed - 1) & SegmentedArrayHelper.GetOffsetMask(); + var secondOffset = (_secondOffset + _length - _completed - 1) & SegmentedArrayHelper.GetOffsetMask(); + + var firstSegment = _firstSegments[initialFirstSegment]; + var secondSegment = _secondSegments[initialSecondSegment]; + var remainingInFirstSegment = firstOffset + 1; + var remainingInSecondSegment = secondOffset + 1; + var currentSegmentLength = Math.Min(Math.Min(remainingInFirstSegment, remainingInSecondSegment), _length - _completed); + _current = (firstSegment.AsMemory().Slice(firstOffset - currentSegmentLength + 1, currentSegmentLength), secondSegment.AsMemory().Slice(secondOffset - currentSegmentLength + 1, currentSegmentLength)); + _completed += currentSegmentLength; + return true; + } + } + } + + private readonly struct SegmentEnumerable + { + private readonly SegmentedArray _array; + private readonly int _offset; + private readonly int _length; + + public SegmentEnumerable(SegmentedArray array) + { + _array = array; + _offset = 0; + _length = array.Length; + } + + public SegmentEnumerable(SegmentedArray array, int offset, int length) + { + if (offset < 0 || length < 0 || (uint)(offset + length) > (uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + _array = array; + _offset = offset; + _length = length; + } + + public SegmentEnumerator GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_array), _offset, _length); + + public ReverseEnumerable Reverse() + => new(this); + + public readonly struct ReverseEnumerable + { + private readonly SegmentEnumerable _enumerable; + + public ReverseEnumerable(SegmentEnumerable enumerable) + { + _enumerable = enumerable; + } + + public SegmentEnumerator.Reverse GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_enumerable._array), _enumerable._offset, _enumerable._length); + + public SegmentEnumerable Reverse() + => _enumerable; + } + } + + private struct SegmentEnumerator + { + private readonly T[][] _segments; + private readonly int _offset; + private readonly int _length; + + private int _completed; + private Memory _current; + + public SegmentEnumerator(T[][] segments, int offset, int length) + { + _segments = segments; + _offset = offset; + _length = length; + + _completed = 0; + _current = Memory.Empty; + } + + public readonly Memory Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = Memory.Empty; + return false; + } + + if (_completed == 0) + { + var firstSegment = _offset >> SegmentedArrayHelper.GetSegmentShift(); + var offset = _offset & SegmentedArrayHelper.GetOffsetMask(); + + var segment = _segments[firstSegment]; + var remainingInSegment = segment.Length - offset; + _current = segment.AsMemory().Slice(offset, Math.Min(remainingInSegment, _length)); + _completed = _current.Length; + return true; + } + else + { + var segment = _segments[(_completed + _offset) >> SegmentedArrayHelper.GetSegmentShift()]; + _current = segment.AsMemory().Slice(0, Math.Min(SegmentedArrayHelper.GetSegmentSize(), _length - _completed)); + _completed += _current.Length; + return true; + } + } + + public struct Reverse + { + private readonly T[][] _segments; + private readonly int _offset; + private readonly int _length; + + private int _completed; + private Memory _current; + + public Reverse(T[][] segments, int offset, int length) + { + _segments = segments; + _offset = offset; + _length = length; + + _completed = 0; + _current = Memory.Empty; + } + + public readonly Memory Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = Memory.Empty; + return false; + } + + if (_completed == 0) + { + var firstSegment = _offset >> SegmentedArrayHelper.GetSegmentShift(); + var offset = _offset & SegmentedArrayHelper.GetOffsetMask(); + + var segment = _segments[firstSegment]; + var remainingInSegment = segment.Length - offset; + _current = segment.AsMemory().Slice(offset, Math.Min(remainingInSegment, _length)); + _completed = _current.Length; + return true; + } + else + { + var segment = _segments[(_completed + _offset) >> SegmentedArrayHelper.GetSegmentShift()]; + _current = segment.AsMemory().Slice(0, Math.Min(SegmentedArrayHelper.GetSegmentSize(), _length - _completed)); + _completed += _current.Length; + return true; + } + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedArray`1+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedArray`1+PrivateMarshal.cs new file mode 100755 index 00000000000..54bb94d2ffa --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedArray`1+PrivateMarshal.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections; + +internal readonly partial struct SegmentedArray +{ + /// + /// Private helper class for use only by . + /// + internal static class PrivateMarshal + { + /// + public static T[][] AsSegments(SegmentedArray array) + => array._items; + + public static SegmentedArray AsSegmentedArray(int length, T[][] segments) + => new SegmentedArray(length, segments); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedArray`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedArray`1.cs new file mode 100755 index 00000000000..c544295a66a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedArray`1.cs @@ -0,0 +1,426 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Defines a fixed-size collection with the same API surface and behavior as an "SZArray", which is a + /// single-dimensional zero-based array commonly represented in C# as T[]. The implementation of this + /// collection uses segmented arrays to avoid placing objects on the Large Object Heap. + /// + /// The type of elements stored in the array. + internal readonly partial struct SegmentedArray : ICloneable, IList, IStructuralComparable, IStructuralEquatable, IList, IReadOnlyList, IEquatable> + { + /// + /// The number of elements in each page of the segmented array of type . + /// + /// + /// The segment size is calculated according to , performs the IL operation + /// defined by . ECMA-335 defines this operation with the following note: + /// + /// sizeof returns the total size that would be occupied by each element in an array of this type – + /// including any padding the implementation chooses to add. Specifically, array elements lie sizeof + /// bytes apart. + /// + private static int SegmentSize + { + get + { + return SegmentedArrayHelper.GetSegmentSize(); + } + } + + /// + /// The bit shift to apply to an array index to get the page index within . + /// + private static int SegmentShift + { + get + { + return SegmentedArrayHelper.GetSegmentShift(); + } + } + + /// + /// The bit mask to apply to an array index to get the index within a page of . + /// + private static int OffsetMask + { + get + { + return SegmentedArrayHelper.GetOffsetMask(); + } + } + + private readonly int _length; + private readonly T[][] _items; + + public SegmentedArray(int length) + { + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + if (length == 0) + { + _items = Array.Empty(); + _length = 0; + } + else + { + _items = new T[(length + SegmentSize - 1) >> SegmentShift][]; + for (var i = 0; i < _items.Length - 1; i++) + { + _items[i] = new T[SegmentSize]; + } + + // Make sure the last page only contains the number of elements required for the desired length. This + // collection is not resizeable so any additional padding would be a waste of space. + // + // Avoid using (length & s_offsetMask) because it doesn't handle a last page size of s_segmentSize. + var lastPageSize = length - ((_items.Length - 1) << SegmentShift); + + _items[_items.Length - 1] = new T[lastPageSize]; + _length = length; + } + } + + private SegmentedArray(int length, T[][] items) + { + _length = length; + _items = items; + } + + public bool IsFixedSize => true; + + public bool IsReadOnly => true; + + public bool IsSynchronized => false; + + public int Length => _length; + + public object SyncRoot => _items; + + public ref T this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref _items[index >> SegmentShift][index & OffsetMask]; + } + } + + int ICollection.Count => Length; + + int ICollection.Count => Length; + + int IReadOnlyCollection.Count => Length; + + T IReadOnlyList.this[int index] => this[index]; + + T IList.this[int index] + { + get => this[index]; + set => this[index] = value; + } + + object? IList.this[int index] + { + get => this[index]; + set => this[index] = (T)value!; + } + + public object Clone() + { + var items = (T[][])_items.Clone(); + for (var i = 0; i < items.Length; i++) + { + items[i] = (T[])items[i].Clone(); + } + + return new SegmentedArray(Length, items); + } + + public void CopyTo(Array array, int index) + { + for (var i = 0; i < _items.Length; i++) + { + _items[i].CopyTo(array, index + (i * SegmentSize)); + } + } + + void ICollection.CopyTo(T[] array, int arrayIndex) + { + for (var i = 0; i < _items.Length; i++) + { + ICollection collection = _items[i]; + collection.CopyTo(array, arrayIndex + (i * SegmentSize)); + } + } + + public Enumerator GetEnumerator() + => new(this); + + public override bool Equals(object? obj) + { + return obj is SegmentedArray other + && Equals(other); + } + + public override int GetHashCode() + { + return _items.GetHashCode(); + } + + public bool Equals(SegmentedArray other) + { + return _items == other._items; + } + + int IList.Add(object? value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void ICollection.Add(T value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.Clear() + { + // Matches System.Array + // https://github.com/dotnet/runtime/blob/e0ec035994179e8ebd6ccf081711ee11d4c5491b/src/libraries/System.Private.CoreLib/src/System/Array.cs#L279-L282 + foreach (IList list in _items) + { + list.Clear(); + } + } + + void ICollection.Clear() + { + // Matches `((ICollection)new T[1]).Clear()` + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + bool IList.Contains(object? value) + { + foreach (IList list in _items) + { + if (list.Contains(value)) + return true; + } + + return false; + } + + bool ICollection.Contains(T value) + { + foreach (ICollection collection in _items) + { + if (collection.Contains(value)) + return true; + } + + return false; + } + + int IList.IndexOf(object? value) + { + for (var i = 0; i < _items.Length; i++) + { + IList list = _items[i]; + var index = list.IndexOf(value); + if (index >= 0) + { + return index + i * SegmentSize; + } + } + + return -1; + } + + int IList.IndexOf(T value) + { + for (var i = 0; i < _items.Length; i++) + { + IList list = _items[i]; + var index = list.IndexOf(value); + if (index >= 0) + { + return index + i * SegmentSize; + } + } + + return -1; + } + + void IList.Insert(int index, object? value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.Insert(int index, T value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.Remove(object? value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + bool ICollection.Remove(T value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.RemoveAt(int index) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.RemoveAt(int index) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + int IStructuralComparable.CompareTo(object? other, IComparer comparer) + { + if (other is null) + return 1; + + // Matches System.Array + // https://github.com/dotnet/runtime/blob/e0ec035994179e8ebd6ccf081711ee11d4c5491b/src/libraries/System.Private.CoreLib/src/System/Array.cs#L320-L323 + if (other is not SegmentedArray o + || Length != o.Length) + { + throw new ArgumentException(SR.ArgumentException_OtherNotArrayOfCorrectLength, nameof(other)); + } + + for (var i = 0; i < Length; i++) + { + var result = comparer.Compare(this[i], o[i]); + if (result != 0) + return result; + } + + return 0; + } + + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) + { + if (other is null) + return false; + + if (other is not SegmentedArray o) + return false; + + if (ReferenceEquals(_items, o._items)) + return true; + + if (Length != o.Length) + return false; + + for (var i = 0; i < Length; i++) + { + if (!comparer.Equals(this[i], o[i])) + return false; + } + + return true; + } + + int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) + { + _ = comparer ?? throw new ArgumentNullException(nameof(comparer)); + + // Matches System.Array + // https://github.com/dotnet/runtime/blob/e0ec035994179e8ebd6ccf081711ee11d4c5491b/src/libraries/System.Private.CoreLib/src/System/Array.cs#L380-L383 + var ret = 0; + for (var i = Length >= 8 ? Length - 8 : 0; i < Length; i++) + { +#if NET + ret = HashCode.Combine(comparer.GetHashCode(this[i]!), ret); +#else + ret = unchecked((ret * (int)0xA5555529) + comparer.GetHashCode(this[i]!)); +#endif + } + + return ret; + } + + public struct Enumerator : IEnumerator + { + private readonly T[][] _items; + private int _nextItemSegment; + private int _nextItemIndex; + private T _current; + + public Enumerator(SegmentedArray array) + { + _items = array._items; + _nextItemSegment = 0; + _nextItemIndex = 0; + _current = default!; + } + + public readonly T Current => _current; + readonly object? IEnumerator.Current => Current; + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + if (_items.Length == 0) + return false; + + if (_nextItemIndex == _items[_nextItemSegment].Length) + { + if (_nextItemSegment == _items.Length - 1) + { + return false; + } + + _nextItemSegment++; + _nextItemIndex = 0; + } + + _current = _items[_nextItemSegment][_nextItemIndex]; + _nextItemIndex++; + return true; + } + + public void Reset() + { + _nextItemSegment = 0; + _nextItemIndex = 0; + _current = default!; + } + } + + internal static class TestAccessor + { + public static int SegmentSize => SegmentedArray.SegmentSize; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedCollectionsMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedCollectionsMarshal.cs new file mode 100755 index 00000000000..56c6f38b5e1 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedCollectionsMarshal.cs @@ -0,0 +1,226 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections; + +/// +/// An unsafe class that provides a set of methods to access the underlying data representations of immutable segmented +/// collections. +/// +internal static class SegmentedCollectionsMarshal +{ + /// + /// Gets the backing storage array for a . + /// + /// The type of elements stored in the array. + /// The segmented array. + /// The backing storage array for the segmented array. Note that replacing segments within the returned + /// value will invalidate the data structure. + public static T[][] AsSegments(SegmentedArray array) + => SegmentedArray.PrivateMarshal.AsSegments(array); + + /// + /// Gets a value wrapping the input T[][]. + /// + /// The type of elements in the input. + /// The combined length of the input arrays + /// The input array to wrap in the returned value. + /// A value wrapping . + /// + /// + /// When using this method, callers should take extra care to ensure that they're the sole owners of the input + /// array, and that it won't be modified once the returned value starts + /// being used. Doing so might cause undefined behavior in code paths which don't expect the contents of a given + /// values to change outside their control. + /// + /// + /// Thrown when is + public static SegmentedArray AsSegmentedArray(int length, T[][] segments) + => SegmentedArray.PrivateMarshal.AsSegmentedArray(length, segments); + + /// + /// Gets either a ref to a in the or a + /// ref null if it does not exist in the . + /// + /// The dictionary to get the ref to from. + /// The key used for lookup. + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + /// + /// Items should not be added or removed from the while the ref + /// is in use. The ref null can be detected using . + /// + [SuppressMessage("Documentation", "CA1200", Justification = "Not all targets can resolve the documented method reference.")] + public static ref TValue GetValueRefOrNullRef(SegmentedDictionary dictionary, TKey key) + where TKey : notnull + => ref SegmentedDictionary.PrivateMarshal.FindValue(dictionary, key); + + /// + /// Gets either a read-only ref to a in the + /// or a ref null if it does not exist in the . + /// + /// The dictionary to get the ref to from. + /// The key used for lookup. + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + /// + /// The ref null can be detected using . + /// + [SuppressMessage("Documentation", "CA1200", Justification = "Not all targets can resolve the documented method reference.")] + public static ref readonly TValue GetValueRefOrNullRef(ImmutableSegmentedDictionary dictionary, TKey key) + where TKey : notnull + => ref ImmutableSegmentedDictionary.PrivateMarshal.FindValue(dictionary, key); + + /// + /// Gets either a ref to a in the + /// or a ref null if it does not exist in the . + /// + /// The dictionary to get the ref to from. + /// The key used for lookup. + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + /// + /// Items should not be added or removed from the + /// while the ref is in use. The ref null can be detected using + /// . + /// + [SuppressMessage("Documentation", "CA1200", Justification = "Not all targets can resolve the documented method reference.")] + public static ref TValue GetValueRefOrNullRef(ImmutableSegmentedDictionary.Builder dictionary, TKey key) + where TKey : notnull + => ref ImmutableSegmentedDictionary.Builder.PrivateMarshal.FindValue(dictionary, key); + + /// + /// Gets an value wrapping the input . + /// + /// The type of elements in the input segmented list. + /// The input segmented list to wrap in the returned value. + /// An value wrapping . + /// + /// + /// When using this method, callers should take extra care to ensure that they're the sole owners of the input + /// list, and that it won't be modified once the returned value starts + /// being used. Doing so might cause undefined behavior in code paths which don't expect the contents of a given + /// values to change after its creation. + /// + /// + /// If is , the returned value + /// will be uninitialized (i.e. its property will be + /// ). + /// + /// + public static ImmutableSegmentedList AsImmutableSegmentedList(SegmentedList? list) + => ImmutableSegmentedList.PrivateMarshal.AsImmutableSegmentedList(list); + + /// + /// Gets the underlying for an input value. + /// + /// The type of elements in the input value. + /// The input value to get the underlying from. + /// The underlying for , if present; otherwise, . + /// + /// + /// When using this method, callers should make sure to not pass the resulting underlying list to methods that + /// might mutate it. Doing so might cause undefined behavior in code paths using which + /// don't expect the contents of the value to change. + /// + /// + /// If is uninitialized (i.e. its property is + /// ), the resulting will be . + /// + /// + public static SegmentedList? AsSegmentedList(ImmutableSegmentedList list) + => ImmutableSegmentedList.PrivateMarshal.AsSegmentedList(list); + + /// + /// Gets an value wrapping the input . + /// + /// The type of elements in the input segmented hash set. + /// The input segmented hash set to wrap in the returned value. + /// An value wrapping . + /// + /// + /// When using this method, callers should take extra care to ensure that they're the sole owners of the input + /// set, and that it won't be modified once the returned value starts + /// being used. Doing so might cause undefined behavior in code paths which don't expect the contents of a given + /// values to change after its creation. + /// + /// + /// If is , the returned + /// value will be uninitialized (i.e. its property will be + /// ). + /// + /// + public static ImmutableSegmentedHashSet AsImmutableSegmentedHashSet(SegmentedHashSet? set) + => ImmutableSegmentedHashSet.PrivateMarshal.AsImmutableSegmentedHashSet(set); + + /// + /// Gets the underlying for an input value. + /// + /// The type of elements in the input value. + /// The input value to get the underlying from. + /// The underlying for , if present; otherwise, . + /// + /// + /// When using this method, callers should make sure to not pass the resulting underlying hash set to methods that + /// might mutate it. Doing so might cause undefined behavior in code paths using which + /// don't expect the contents of the value to change. + /// + /// + /// If is uninitialized (i.e. its + /// property is ), the resulting will be . + /// + /// + public static SegmentedHashSet? AsSegmentedHashSet(ImmutableSegmentedHashSet set) + => ImmutableSegmentedHashSet.PrivateMarshal.AsSegmentedHashSet(set); + + /// + /// Gets an value wrapping the input . + /// + /// The type of keys in the input segmented dictionary. + /// The type of values in the input segmented dictionary. + /// The input segmented dictionary to wrap in the returned value. + /// An value wrapping . + /// + /// + /// When using this method, callers should take extra care to ensure that they're the sole owners of the input + /// dictionary, and that it won't be modified once the returned + /// value starts being used. Doing so might cause undefined behavior in code paths which don't expect the contents + /// of a given values to change after its creation. + /// + /// + /// If is , the returned + /// value will be uninitialized (i.e. its + /// property will be ). + /// + /// + public static ImmutableSegmentedDictionary AsImmutableSegmentedDictionary(SegmentedDictionary? dictionary) + where TKey : notnull + => ImmutableSegmentedDictionary.PrivateMarshal.AsImmutableSegmentedDictionary(dictionary); + + /// + /// Gets the underlying for an input value. + /// + /// The type of keys in the input value. + /// The type of values in the input value. + /// The input value to get the underlying from. + /// The underlying for , if present; otherwise, . + /// + /// + /// When using this method, callers should make sure to not pass the resulting underlying dictionary to methods that + /// might mutate it. Doing so might cause undefined behavior in code paths using which + /// don't expect the contents of the value to change. + /// + /// + /// If is uninitialized (i.e. its + /// property is ), the resulting will be . + /// + /// + public static SegmentedDictionary? AsSegmentedDictionary(ImmutableSegmentedDictionary dictionary) + where TKey : notnull + => ImmutableSegmentedDictionary.PrivateMarshal.AsSegmentedDictionary(dictionary); +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedDictionary`2+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedDictionary`2+PrivateMarshal.cs new file mode 100755 index 00000000000..d29131abc2b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedDictionary`2+PrivateMarshal.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections; + +internal sealed partial class SegmentedDictionary +{ + /// + /// Private helper class for use only by . + /// + internal static class PrivateMarshal + { + /// + public static ref TValue FindValue(SegmentedDictionary dictionary, TKey key) + => ref dictionary.FindValue(key); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedDictionary`2.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedDictionary`2.cs new file mode 100755 index 00000000000..0a9302a05e6 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedDictionary`2.cs @@ -0,0 +1,1707 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a collection of keys and values. + /// + /// + /// This collection has the same performance characteristics as , but + /// uses segmented arrays to avoid allocations in the Large Object Heap. + /// + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + [DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))] + [DebuggerDisplay("Count = {Count}")] + internal sealed partial class SegmentedDictionary : IDictionary, IDictionary, IReadOnlyDictionary + where TKey : notnull + { + private const bool SupportsComparerDevirtualization +#if NET + = true; +#else + = false; +#endif + + private static IEnumerator>? s_emptyEnumerator; + + private SegmentedArray _buckets; + private SegmentedArray _entries; + private ulong _fastModMultiplier; + private int _count; + private int _freeList; + private int _freeCount; + private int _version; +#if NET + private readonly IEqualityComparer? _comparer; +#else + /// + /// doesn't devirtualize on .NET Framework, so we always ensure + /// is initialized to a non- value. + /// + private readonly IEqualityComparer _comparer; +#endif + private KeyCollection? _keys; + private ValueCollection? _values; + private const int StartOfFreeList = -3; + + public SegmentedDictionary() + : this(0, null) + { + } + + public SegmentedDictionary(int capacity) + : this(capacity, null) + { + } + + public SegmentedDictionary(IEqualityComparer? comparer) + : this(0, comparer) + { + } + + public SegmentedDictionary(int capacity, IEqualityComparer? comparer) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + if (capacity > 0) + { + Initialize(capacity); + } + + // For reference types, we always want to store a comparer instance, either + // the one provided, or if one wasn't provided, the default (accessing + // EqualityComparer.Default with shared generics on every dictionary + // access can add measurable overhead). For value types, if no comparer is + // provided, or if the default is provided, we'd prefer to use + // EqualityComparer.Default.Equals on every use, enabling the JIT to + // devirtualize and possibly inline the operation. + if (!typeof(TKey).IsValueType) + { + _comparer = comparer ?? EqualityComparer.Default; + } + else if (comparer is not null && // first check for null to avoid forcing default comparer instantiation unnecessarily + comparer != EqualityComparer.Default) + { + _comparer = comparer; + } + +#if !NETCOREAPP + // .NET Framework doesn't support devirtualization, so we always initialize comparer to a non-null value + _comparer ??= EqualityComparer.Default; +#endif + } + + public SegmentedDictionary(IDictionary dictionary) + : this(dictionary, null) + { + } + + public SegmentedDictionary(IDictionary dictionary, IEqualityComparer? comparer) + : this(dictionary?.Count ?? 0, comparer) + { + if (dictionary == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); + } + + AddRange(dictionary); + } + + public SegmentedDictionary(IEnumerable> collection) + : this(collection, null) + { + } + + public SegmentedDictionary(IEnumerable> collection, IEqualityComparer? comparer) + : this((collection as ICollection>)?.Count ?? 0, comparer) + { + if (collection == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + + AddRange(collection); + } + + private void AddRange(IEnumerable> enumerable) + { + // It is likely that the passed-in enumerable is SegmentedDictionary. When this is the case, + // avoid the enumerator allocation and overhead by looping through the entries array directly. + // We only do this when dictionary is SegmentedDictionary and not a subclass, to maintain + // back-compat with subclasses that may have overridden the enumerator behavior. + if (enumerable.GetType() == typeof(SegmentedDictionary)) + { + var source = (SegmentedDictionary)enumerable; + + if (source.Count == 0) + { + // Nothing to copy, all done + return; + } + + // This is not currently a true .AddRange as it needs to be an initialized dictionary + // of the correct size, and also an empty dictionary with no current entities (and no argument checks). + Debug.Assert(_entries.Length >= source.Count); + Debug.Assert(_count == 0); + + var oldEntries = source._entries; + if (source._comparer == _comparer) + { + // If comparers are the same, we can copy _entries without rehashing. + CopyEntries(oldEntries, source._count); + return; + } + + // Comparers differ need to rehash all the entries via Add + var count = source._count; + for (var i = 0; i < count; i++) + { + // Only copy if an entry + if (oldEntries[i]._next >= -1) + { + Add(oldEntries[i]._key, oldEntries[i]._value); + } + } + return; + } + + // We similarly special-case KVP<>[] and List>, as they're commonly used to seed dictionaries, and + // we want to avoid the enumerator costs (e.g. allocation) for them as well. Extract a span if possible. + ReadOnlySpan> span; + if (enumerable is KeyValuePair[] array) + { + span = array; + } +#if NET5_0_OR_GREATER + else if (enumerable.GetType() == typeof(List>)) + { + span = CollectionsMarshal.AsSpan((List>)enumerable); + } +#endif + else + { + // Fallback path for all other enumerables + foreach (var pair in enumerable) + { + Add(pair.Key, pair.Value); + } + return; + } + + // We got a span. Add the elements to the dictionary. + foreach (var pair in span) + { + Add(pair.Key, pair.Value); + } + } + + public IEqualityComparer Comparer + { + get + { + return _comparer ?? EqualityComparer.Default; + } + } + + public int Count => _count - _freeCount; + + public KeyCollection Keys => _keys ??= new KeyCollection(this); + + ICollection IDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + public ValueCollection Values => _values ??= new ValueCollection(this); + + ICollection IDictionary.Values => Values; + + IEnumerable IReadOnlyDictionary.Values => Values; + + public TValue this[TKey key] + { + get + { + ref var value = ref FindValue(key); + if (!RoslynUnsafe.IsNullRef(ref value)) + { + return value; + } + + ThrowHelper.ThrowKeyNotFoundException(key); + return default; + } + set + { + var modified = TryInsert(key, value, InsertionBehavior.OverwriteExisting); + Debug.Assert(modified); + } + } + + public void Add(TKey key, TValue value) + { + var modified = TryInsert(key, value, InsertionBehavior.ThrowOnExisting); + Debug.Assert(modified); // If there was an existing key and the Add failed, an exception will already have been thrown. + } + + void ICollection>.Add(KeyValuePair keyValuePair) + => Add(keyValuePair.Key, keyValuePair.Value); + + bool ICollection>.Contains(KeyValuePair keyValuePair) + { + ref var value = ref FindValue(keyValuePair.Key); + if (!RoslynUnsafe.IsNullRef(ref value) && EqualityComparer.Default.Equals(value, keyValuePair.Value)) + { + return true; + } + + return false; + } + + bool ICollection>.Remove(KeyValuePair keyValuePair) + { + ref var value = ref FindValue(keyValuePair.Key); + if (!RoslynUnsafe.IsNullRef(ref value) && EqualityComparer.Default.Equals(value, keyValuePair.Value)) + { + Remove(keyValuePair.Key); + return true; + } + + return false; + } + + public void Clear() + { + var count = _count; + if (count > 0) + { + Debug.Assert(_buckets.Length > 0, "_buckets should be non-empty"); + Debug.Assert(_entries.Length > 0, "_entries should be non-empty"); + + SegmentedArray.Clear(_buckets); + + _count = 0; + _freeList = -1; + _freeCount = 0; + SegmentedArray.Clear(_entries, 0, count); + } + } + + public bool ContainsKey(TKey key) + => !RoslynUnsafe.IsNullRef(ref FindValue(key)); + + public bool ContainsValue(TValue value) + { + var entries = _entries; + if (value == null) + { + for (var i = 0; i < _count; i++) + { + if (entries[i]._next >= -1 && entries[i]._value == null) + { + return true; + } + } + } + else if (SupportsComparerDevirtualization && typeof(TValue).IsValueType) + { + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + for (var i = 0; i < _count; i++) + { + if (entries[i]._next >= -1 && EqualityComparer.Default.Equals(entries[i]._value, value)) + { + return true; + } + } + } + else + { + // Object type: Shared Generic, EqualityComparer.Default won't devirtualize + // https://github.com/dotnet/runtime/issues/10050 + // So cache in a local rather than get EqualityComparer per loop iteration + var defaultComparer = EqualityComparer.Default; + for (var i = 0; i < _count; i++) + { + if (entries[i]._next >= -1 && defaultComparer.Equals(entries[i]._value, value)) + { + return true; + } + } + } + + return false; + } + + private void CopyTo(KeyValuePair[] array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if ((uint)index > (uint)array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + var count = _count; + var entries = _entries; + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + { + array[index++] = new KeyValuePair(entries[i]._key, entries[i]._value); + } + } + } + + public Enumerator GetEnumerator() + => new(this, Enumerator.KeyValuePair); + + IEnumerator> IEnumerable>.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + private static IEnumerator> GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedDictionary(), Enumerator.KeyValuePair))!; + } + + private ref TValue FindValue(TKey key) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + ref var entry = ref RoslynUnsafe.NullRef(); + if (_buckets.Length > 0) + { + Debug.Assert(_entries.Length > 0, "expected entries to be non-empty"); + var comparer = _comparer; + if (SupportsComparerDevirtualization + && typeof(TKey).IsValueType // comparer can only be null for value types; enable JIT to eliminate entire if block for ref types + && comparer == null) + { + var hashCode = (uint)key.GetHashCode(); + var i = GetBucket(hashCode); + var entries = _entries; + uint collisionCount = 0; + + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + i--; // Value in _buckets is 1-based; subtract 1 from i. We do it here so it fuses with the following conditional. + do + { + // Should be a while loop https://github.com/dotnet/runtime/issues/9422 + // Test in if to drop range check for following array access + if ((uint)i >= (uint)entries.Length) + { + goto ReturnNotFound; + } + + entry = ref entries[i]; + if (entry._hashCode == hashCode && EqualityComparer.Default.Equals(entry._key, key)) + { + goto ReturnFound; + } + + i = entry._next; + + collisionCount++; + } while (collisionCount <= (uint)entries.Length); + + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + goto ConcurrentOperation; + } + else + { + Debug.Assert(comparer is not null); + var hashCode = (uint)comparer!.GetHashCode(key); + var i = GetBucket(hashCode); + var entries = _entries; + uint collisionCount = 0; + i--; // Value in _buckets is 1-based; subtract 1 from i. We do it here so it fuses with the following conditional. + do + { + // Should be a while loop https://github.com/dotnet/runtime/issues/9422 + // Test in if to drop range check for following array access + if ((uint)i >= (uint)entries.Length) + { + goto ReturnNotFound; + } + + entry = ref entries[i]; + if (entry._hashCode == hashCode && comparer.Equals(entry._key, key)) + { + goto ReturnFound; + } + + i = entry._next; + + collisionCount++; + } while (collisionCount <= (uint)entries.Length); + + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + goto ConcurrentOperation; + } + } + + goto ReturnNotFound; + +ConcurrentOperation: + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); +ReturnFound: + ref TValue value = ref entry._value; +Return: + return ref value; +ReturnNotFound: + value = ref RoslynUnsafe.NullRef(); + goto Return; + } + + private int Initialize(int capacity) + { + var size = HashHelpers.GetPrime(capacity); + var buckets = new SegmentedArray(size); + var entries = new SegmentedArray(size); + + // Assign member variables after both arrays allocated to guard against corruption from OOM if second fails + _freeList = -1; + _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)size); + _buckets = buckets; + _entries = entries; + + return size; + } + + private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + if (_buckets.Length == 0) + { + Initialize(0); + } + Debug.Assert(_buckets.Length > 0); + + var entries = _entries; + Debug.Assert(entries.Length > 0, "expected entries to be non-empty"); + + var comparer = _comparer; + Debug.Assert(comparer is not null || (SupportsComparerDevirtualization && typeof(TKey).IsValueType)); + var hashCode = (uint)((SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null) ? key.GetHashCode() : comparer!.GetHashCode(key)); + + uint collisionCount = 0; + ref var bucket = ref GetBucket(hashCode); + var i = bucket - 1; // Value in _buckets is 1-based + + if (SupportsComparerDevirtualization + && typeof(TKey).IsValueType // comparer can only be null for value types; enable JIT to eliminate entire if block for ref types + && comparer == null) + { + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + while (true) + { + // Should be a while loop https://github.com/dotnet/runtime/issues/9422 + // Test uint in if rather than loop condition to drop range check for following array access + if ((uint)i >= (uint)entries.Length) + { + break; + } + + if (entries[i]._hashCode == hashCode && EqualityComparer.Default.Equals(entries[i]._key, key)) + { + if (behavior == InsertionBehavior.OverwriteExisting) + { + entries[i]._value = value; + return true; + } + + if (behavior == InsertionBehavior.ThrowOnExisting) + { + ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key); + } + + return false; + } + + i = entries[i]._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + else + { + Debug.Assert(comparer is not null); + while (true) + { + // Should be a while loop https://github.com/dotnet/runtime/issues/9422 + // Test uint in if rather than loop condition to drop range check for following array access + if ((uint)i >= (uint)entries.Length) + { + break; + } + + if (entries[i]._hashCode == hashCode && comparer!.Equals(entries[i]._key, key)) + { + if (behavior == InsertionBehavior.OverwriteExisting) + { + entries[i]._value = value; + return true; + } + + if (behavior == InsertionBehavior.ThrowOnExisting) + { + ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key); + } + + return false; + } + + i = entries[i]._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + + int index; + if (_freeCount > 0) + { + index = _freeList; + Debug.Assert((StartOfFreeList - entries[_freeList]._next) >= -1, "shouldn't overflow because `next` cannot underflow"); + _freeList = StartOfFreeList - entries[_freeList]._next; + _freeCount--; + } + else + { + var count = _count; + if (count == entries.Length) + { + Resize(); + bucket = ref GetBucket(hashCode); + } + index = count; + _count = count + 1; + entries = _entries; + } + + ref var entry = ref entries![index]; + entry._hashCode = hashCode; + entry._next = bucket - 1; // Value in _buckets is 1-based + entry._key = key; + entry._value = value; + bucket = index + 1; // Value in _buckets is 1-based + _version++; + return true; + } + + private void Resize() + => Resize(HashHelpers.ExpandPrime(_count)); + + private void Resize(int newSize) + { + Debug.Assert(_entries.Length > 0, "_entries should be non-empty"); + Debug.Assert(newSize >= _entries.Length); + + var count = _count; + + // Rather than creating a copy of _entries, instead reuse as much of it's data as possible. + var entries = CreateNewSegmentedArrayReusingOldSegments(_entries, newSize); + + // Assign member variables after both arrays allocated to guard against corruption from OOM if second fails + _buckets = new SegmentedArray(newSize); + _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)newSize); + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + { + ref var bucket = ref GetBucket(entries[i]._hashCode); + entries[i]._next = bucket - 1; // Value in _buckets is 1-based + bucket = i + 1; + } + } + + _entries = entries; + } + + private static SegmentedArray CreateNewSegmentedArrayReusingOldSegments(SegmentedArray oldArray, int newSize) + { + var segments = SegmentedCollectionsMarshal.AsSegments(oldArray); + + var oldSegmentCount = segments.Length; + var newSegmentCount = (newSize + SegmentedArrayHelper.GetSegmentSize() - 1) >> SegmentedArrayHelper.GetSegmentShift(); + + // Grow the array of segments, if necessary + Array.Resize(ref segments, newSegmentCount); + + // Resize all segments to full segment size from the last old segment to the next to last + // new segment. + for (var i = oldSegmentCount - 1; i < newSegmentCount - 1; i++) + Array.Resize(ref segments[i], SegmentedArrayHelper.GetSegmentSize()); + + // Resize the last segment + var lastSegmentSize = newSize - ((newSegmentCount - 1) << SegmentedArrayHelper.GetSegmentShift()); + Array.Resize(ref segments[newSegmentCount - 1], lastSegmentSize); + + return SegmentedCollectionsMarshal.AsSegmentedArray(newSize, segments); + } + + public bool Remove(TKey key) + { + // The overload Remove(TKey key, out TValue value) is a copy of this method with one additional + // statement to copy the value for entry being removed into the output parameter. + // Code has been intentionally duplicated for performance reasons. + + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + if (_buckets.Length > 0) + { + Debug.Assert(_entries.Length > 0, "entries should be non-empty"); + uint collisionCount = 0; + + var comparer = _comparer; + Debug.Assert((SupportsComparerDevirtualization && typeof(TKey).IsValueType) || comparer is not null); + var hashCode = (uint)(SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null ? key.GetHashCode() : comparer!.GetHashCode(key)); + + ref var bucket = ref GetBucket(hashCode); + var entries = _entries; + var last = -1; + var i = bucket - 1; // Value in buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + + if (entry._hashCode == hashCode && + (SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null ? EqualityComparer.Default.Equals(entry._key, key) : comparer!.Equals(entry._key, key))) + { + if (last < 0) + { + bucket = entry._next + 1; // Value in buckets is 1-based + } + else + { + entries[last]._next = entry._next; + } + + Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646"); + entry._next = StartOfFreeList - _freeList; + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._key = default!; + } + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._value = default!; + } + + _freeList = i; + _freeCount++; + return true; + } + + last = i; + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + return false; + } + + public bool Remove(TKey key, [MaybeNullWhen(false)] out TValue value) + { + // This overload is a copy of the overload Remove(TKey key) with one additional + // statement to copy the value for entry being removed into the output parameter. + // Code has been intentionally duplicated for performance reasons. + + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + if (_buckets.Length > 0) + { + Debug.Assert(_entries.Length > 0, "entries should be non-empty"); + uint collisionCount = 0; + + var comparer = _comparer; + Debug.Assert((SupportsComparerDevirtualization && typeof(TKey).IsValueType) || comparer is not null); + var hashCode = (uint)(SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null ? key.GetHashCode() : comparer!.GetHashCode(key)); + + ref var bucket = ref GetBucket(hashCode); + var entries = _entries; + var last = -1; + var i = bucket - 1; // Value in buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + + if (entry._hashCode == hashCode && + (SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null ? EqualityComparer.Default.Equals(entry._key, key) : comparer!.Equals(entry._key, key))) + { + if (last < 0) + { + bucket = entry._next + 1; // Value in buckets is 1-based + } + else + { + entries[last]._next = entry._next; + } + + value = entry._value; + + Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646"); + entry._next = StartOfFreeList - _freeList; + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._key = default!; + } + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._value = default!; + } + + _freeList = i; + _freeCount++; + return true; + } + + last = i; + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + + value = default; + return false; + } + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + { + ref var valRef = ref FindValue(key); + if (!RoslynUnsafe.IsNullRef(ref valRef)) + { + value = valRef; + return true; + } + + value = default; + return false; + } + + public bool TryAdd(TKey key, TValue value) + => TryInsert(key, value, InsertionBehavior.None); + + bool ICollection>.IsReadOnly => false; + + void ICollection>.CopyTo(KeyValuePair[] array, int index) + => CopyTo(array, index); + + void ICollection.CopyTo(Array array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (array.Rank != 1) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); + } + + if (array.GetLowerBound(0) != 0) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); + } + + if ((uint)index > (uint)array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + if (array is KeyValuePair[] pairs) + { + CopyTo(pairs, index); + } + else if (array is DictionaryEntry[] dictEntryArray) + { + var entries = _entries; + for (var i = 0; i < _count; i++) + { + if (entries[i]._next >= -1) + { + dictEntryArray[index++] = new DictionaryEntry(entries[i]._key, entries[i]._value); + } + } + } + else + { + var objects = array as object[]; + if (objects == null) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + + try + { + var count = _count; + var entries = _entries; + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + { + objects[index++] = new KeyValuePair(entries[i]._key, entries[i]._value); + } + } + } + catch (ArrayTypeMismatchException) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + } + } + + IEnumerator IEnumerable.GetEnumerator() + => ((IEnumerable>)this).GetEnumerator(); + + /// + /// Ensures that the dictionary can hold up to 'capacity' entries without any further expansion of its backing storage + /// + public int EnsureCapacity(int capacity) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + var currentCapacity = _entries.Length; + if (currentCapacity >= capacity) + { + return currentCapacity; + } + + _version++; + + if (_buckets.Length == 0) + { + return Initialize(capacity); + } + + var newSize = HashHelpers.GetPrime(capacity); + Resize(newSize); + return newSize; + } + + /// + /// Sets the capacity of this dictionary to what it would be if it had been originally initialized with all its entries + /// + /// + /// This method can be used to minimize the memory overhead + /// once it is known that no new elements will be added. + /// + /// To allocate minimum size storage array, execute the following statements: + /// + /// dictionary.Clear(); + /// dictionary.TrimExcess(); + /// + public void TrimExcess() + => TrimExcess(Count); + + /// + /// Sets the capacity of this dictionary to hold up 'capacity' entries without any further expansion of its backing storage + /// + /// + /// This method can be used to minimize the memory overhead + /// once it is known that no new elements will be added. + /// + public void TrimExcess(int capacity) + { + if (capacity < Count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + var newSize = HashHelpers.GetPrime(capacity); + var oldEntries = _entries; + var currentCapacity = oldEntries.Length; + if (newSize >= currentCapacity) + { + return; + } + + var oldCount = _count; + _version++; + Initialize(newSize); + + CopyEntries(oldEntries, oldCount); + } + + private void CopyEntries(SegmentedArray entries, int count) + { + var newEntries = _entries; + var newCount = 0; + for (var i = 0; i < count; i++) + { + var hashCode = entries[i]._hashCode; + if (entries[i]._next >= -1) + { + ref var entry = ref newEntries[newCount]; + entry = entries[i]; + ref var bucket = ref GetBucket(hashCode); + entry._next = bucket - 1; // Value in _buckets is 1-based + bucket = newCount + 1; + newCount++; + } + } + + _count = newCount; + _freeCount = 0; + } + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => this; + + bool IDictionary.IsFixedSize => false; + + bool IDictionary.IsReadOnly => false; + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + object? IDictionary.this[object key] + { + get + { + if (IsCompatibleKey(key)) + { + ref var value = ref FindValue((TKey)key); + if (!RoslynUnsafe.IsNullRef(ref value)) + { + return value; + } + } + + return null; + } + set + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(value, ExceptionArgument.value); + + try + { + var tempKey = (TKey)key; + try + { + this[tempKey] = (TValue)value!; + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue)); + } + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey)); + } + } + } + + private static bool IsCompatibleKey(object key) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + return key is TKey; + } + + void IDictionary.Add(object key, object? value) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(value, ExceptionArgument.value); + + try + { + var tempKey = (TKey)key; + + try + { + Add(tempKey, (TValue)value!); + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue)); + } + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey)); + } + } + + bool IDictionary.Contains(object key) + { + if (IsCompatibleKey(key)) + { + return ContainsKey((TKey)key); + } + + return false; + } + + IDictionaryEnumerator IDictionary.GetEnumerator() + => new Enumerator(this, Enumerator.DictEntry); + + void IDictionary.Remove(object key) + { + if (IsCompatibleKey(key)) + { + Remove((TKey)key); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private ref int GetBucket(uint hashCode) + { + var buckets = _buckets; + return ref buckets[(int)HashHelpers.FastMod(hashCode, (uint)buckets.Length, _fastModMultiplier)]; + } + + private struct Entry + { + public uint _hashCode; + /// + /// 0-based index of next entry in chain: -1 means end of chain + /// also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3, + /// so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc. + /// + public int _next; + public TKey _key; // Key of entry + public TValue _value; // Value of entry + } + + public struct Enumerator : IEnumerator>, IDictionaryEnumerator + { + private readonly SegmentedDictionary _dictionary; + private readonly int _version; + private int _index; + private KeyValuePair _current; + private readonly int _getEnumeratorRetType; // What should Enumerator.Current return? + + internal const int DictEntry = 1; + internal const int KeyValuePair = 2; + + internal Enumerator(SegmentedDictionary dictionary, int getEnumeratorRetType) + { + _dictionary = dictionary; + _version = dictionary._version; + _index = 0; + _getEnumeratorRetType = getEnumeratorRetType; + _current = default; + } + + public bool MoveNext() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. + // dictionary.count+1 could be negative if dictionary.count is int.MaxValue + while ((uint)_index < (uint)_dictionary._count) + { + ref var entry = ref _dictionary._entries[_index++]; + + if (entry._next >= -1) + { + _current = new KeyValuePair(entry._key, entry._value); + return true; + } + } + + _index = _dictionary._count + 1; + _current = default; + return false; + } + + public readonly KeyValuePair Current => _current; + + public readonly void Dispose() + { + } + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + if (_getEnumeratorRetType == DictEntry) + { + return new DictionaryEntry(_current.Key, _current.Value); + } + + return new KeyValuePair(_current.Key, _current.Value); + } + } + + void IEnumerator.Reset() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _current = default; + } + + readonly DictionaryEntry IDictionaryEnumerator.Entry + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return new DictionaryEntry(_current.Key, _current.Value); + } + } + + readonly object IDictionaryEnumerator.Key + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _current.Key; + } + } + + readonly object? IDictionaryEnumerator.Value + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _current.Value; + } + } + } + + [DebuggerTypeProxy(typeof(DictionaryKeyCollectionDebugView<,>))] + [DebuggerDisplay("Count = {Count}")] + public sealed class KeyCollection : ICollection, ICollection, IReadOnlyCollection + { + private static IEnumerator? s_emptyEnumerator; + + private readonly SegmentedDictionary _dictionary; + + public KeyCollection(SegmentedDictionary dictionary) + { + if (dictionary == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); + } + + _dictionary = dictionary; + } + + public Enumerator GetEnumerator() + => new Enumerator(_dictionary); + + public void CopyTo(TKey[] array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (index < 0 || index > array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < _dictionary.Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + var count = _dictionary._count; + var entries = _dictionary._entries; + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + array[index++] = entries[i]._key; + } + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => true; + + void ICollection.Add(TKey item) + => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet); + + void ICollection.Clear() + => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet); + + public bool Contains(TKey item) + => _dictionary.ContainsKey(item); + + bool ICollection.Remove(TKey item) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet); + return false; + } + + IEnumerator IEnumerable.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + private static IEnumerator GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedDictionary()))!; + } + + IEnumerator IEnumerable.GetEnumerator() + => ((IEnumerable)this).GetEnumerator(); + + void ICollection.CopyTo(Array array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (array.Rank != 1) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); + } + + if (array.GetLowerBound(0) != 0) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); + } + + if ((uint)index > (uint)array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < _dictionary.Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + if (array is TKey[] keys) + { + CopyTo(keys, index); + } + else + { + var objects = array as object[]; + if (objects == null) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + + var count = _dictionary._count; + var entries = _dictionary._entries; + try + { + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + objects[index++] = entries[i]._key; + } + } + catch (ArrayTypeMismatchException) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + } + } + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + public struct Enumerator : IEnumerator, IEnumerator + { + private readonly SegmentedDictionary _dictionary; + private int _index; + private readonly int _version; + private TKey? _currentKey; + + internal Enumerator(SegmentedDictionary dictionary) + { + _dictionary = dictionary; + _version = dictionary._version; + _index = 0; + _currentKey = default; + } + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + while ((uint)_index < (uint)_dictionary._count) + { + ref var entry = ref _dictionary._entries[_index++]; + + if (entry._next >= -1) + { + _currentKey = entry._key; + return true; + } + } + + _index = _dictionary._count + 1; + _currentKey = default; + return false; + } + + public readonly TKey Current => _currentKey!; + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _currentKey; + } + } + + void IEnumerator.Reset() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _currentKey = default; + } + } + } + + [DebuggerTypeProxy(typeof(DictionaryValueCollectionDebugView<,>))] + [DebuggerDisplay("Count = {Count}")] + public sealed class ValueCollection : ICollection, ICollection, IReadOnlyCollection + { + private static IEnumerator? s_emptyEnumerator; + + private readonly SegmentedDictionary _dictionary; + + public ValueCollection(SegmentedDictionary dictionary) + { + if (dictionary == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); + } + + _dictionary = dictionary; + } + + public Enumerator GetEnumerator() + => new Enumerator(_dictionary); + + public void CopyTo(TValue[] array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if ((uint)index > array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < _dictionary.Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + var count = _dictionary._count; + var entries = _dictionary._entries; + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + array[index++] = entries[i]._value; + } + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => true; + + void ICollection.Add(TValue item) + => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet); + + bool ICollection.Remove(TValue item) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet); + return false; + } + + void ICollection.Clear() + => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet); + + bool ICollection.Contains(TValue item) + => _dictionary.ContainsValue(item); + + IEnumerator IEnumerable.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + private static IEnumerator GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedDictionary()))!; + } + + IEnumerator IEnumerable.GetEnumerator() + => ((IEnumerable)this).GetEnumerator(); + + void ICollection.CopyTo(Array array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (array.Rank != 1) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); + } + + if (array.GetLowerBound(0) != 0) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); + } + + if ((uint)index > (uint)array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < _dictionary.Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + if (array is TValue[] values) + { + CopyTo(values, index); + } + else + { + var objects = array as object[]; + if (objects == null) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + + var count = _dictionary._count; + var entries = _dictionary._entries; + try + { + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + objects[index++] = entries[i]._value!; + } + } + catch (ArrayTypeMismatchException) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + } + } + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + public struct Enumerator : IEnumerator, IEnumerator + { + private readonly SegmentedDictionary _dictionary; + private int _index; + private readonly int _version; + private TValue? _currentValue; + + internal Enumerator(SegmentedDictionary dictionary) + { + _dictionary = dictionary; + _version = dictionary._version; + _index = 0; + _currentValue = default; + } + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + while ((uint)_index < (uint)_dictionary._count) + { + ref var entry = ref _dictionary._entries[_index++]; + + if (entry._next >= -1) + { + _currentValue = entry._value; + return true; + } + } + _index = _dictionary._count + 1; + _currentValue = default; + return false; + } + + public readonly TValue Current => _currentValue!; + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _currentValue; + } + } + + void IEnumerator.Reset() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _currentValue = default; + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedHashSet`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedHashSet`1.cs new file mode 100755 index 00000000000..59d4528bc6d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedHashSet`1.cs @@ -0,0 +1,1456 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Threading; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + [DebuggerTypeProxy(typeof(ICollectionDebugView<>))] + [DebuggerDisplay("Count = {Count}")] + internal class SegmentedHashSet : ICollection, ISet, IReadOnlyCollection +#if NET5_0_OR_GREATER + , IReadOnlySet +#endif + { + private const bool SupportsComparerDevirtualization +#if NET + = true; +#else + = false; +#endif + + // This uses the same array-based implementation as Dictionary. + + /// Cutoff point for stackallocs. This corresponds to the number of ints. + private const int StackAllocThreshold = 100; + + /// + /// When constructing a hashset from an existing collection, it may contain duplicates, + /// so this is used as the max acceptable excess ratio of capacity to count. Note that + /// this is only used on the ctor and not to automatically shrink if the hashset has, e.g, + /// a lot of adds followed by removes. Users must explicitly shrink by calling TrimExcess. + /// This is set to 3 because capacity is acceptable as 2x rounded up to nearest prime. + /// + private const int ShrinkThreshold = 3; + private const int StartOfFreeList = -3; + + private static IEnumerator? s_emptyEnumerator; + + private SegmentedArray _buckets; + private SegmentedArray _entries; + private ulong _fastModMultiplier; + private int _count; + private int _freeList; + private int _freeCount; + private int _version; +#if NET + private readonly IEqualityComparer? _comparer; +#else + /// + /// doesn't devirtualize on .NET Framework, so we always ensure + /// is initialized to a non- value. + /// + private readonly IEqualityComparer _comparer; +#endif + + #region Constructors + + public SegmentedHashSet() : this((IEqualityComparer?)null) { } + + public SegmentedHashSet(IEqualityComparer? comparer) + { + // For reference types, we always want to store a comparer instance, either + // the one provided, or if one wasn't provided, the default (accessing + // EqualityComparer.Default with shared generics on every dictionary + // access can add measurable overhead). For value types, if no comparer is + // provided, or if the default is provided, we'd prefer to use + // EqualityComparer.Default.Equals on every use, enabling the JIT to + // devirtualize and possibly inline the operation. + if (!typeof(T).IsValueType) + { + _comparer = comparer ?? EqualityComparer.Default; + } + else if (comparer is not null && // first check for null to avoid forcing default comparer instantiation unnecessarily + comparer != EqualityComparer.Default) + { + _comparer = comparer; + } + +#if !NETCOREAPP + // .NET Framework doesn't support devirtualization, so we always initialize comparer to a non-null value + _comparer ??= EqualityComparer.Default; +#endif + } + + public SegmentedHashSet(int capacity) : this(capacity, null) { } + + public SegmentedHashSet(IEnumerable collection) : this(collection, null) { } + + public SegmentedHashSet(IEnumerable collection, IEqualityComparer? comparer) : this(comparer) + { + if (collection == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + + if (collection is SegmentedHashSet otherAsHashSet && EqualityComparersAreEqual(this, otherAsHashSet)) + { + ConstructFrom(otherAsHashSet); + } + else + { + // To avoid excess resizes, first set size based on collection's count. The collection may + // contain duplicates, so call TrimExcess if resulting SegmentedHashSet is larger than the threshold. + if (collection is ICollection coll) + { + var count = coll.Count; + if (count > 0) + { + Initialize(count); + } + } + + UnionWith(collection); + + if (_count > 0 && _entries.Length / _count > ShrinkThreshold) + { + TrimExcess(); + } + } + } + + public SegmentedHashSet(int capacity, IEqualityComparer? comparer) : this(comparer) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + if (capacity > 0) + { + Initialize(capacity); + } + } + + /// Initializes the SegmentedHashSet from another SegmentedHashSet with the same element type and equality comparer. + private void ConstructFrom(SegmentedHashSet source) + { + if (source.Count == 0) + { + // As well as short-circuiting on the rest of the work done, + // this avoids errors from trying to access source._buckets + // or source._entries when they aren't initialized. + return; + } + + var capacity = source._buckets.Length; + var threshold = HashHelpers.ExpandPrime(source.Count + 1); + + if (threshold >= capacity) + { + _buckets = (SegmentedArray)source._buckets.Clone(); + _entries = (SegmentedArray)source._entries.Clone(); + _freeList = source._freeList; + _freeCount = source._freeCount; + _count = source._count; + _fastModMultiplier = source._fastModMultiplier; + } + else + { + Initialize(source.Count); + + var entries = source._entries; + for (var i = 0; i < source._count; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + AddIfNotPresent(entry._value, out _); + } + } + } + + Debug.Assert(Count == source.Count); + } + + #endregion + + #region ICollection methods + + void ICollection.Add(T item) => AddIfNotPresent(item, out _); + + /// Removes all elements from the object. + public void Clear() + { + var count = _count; + if (count > 0) + { + Debug.Assert(_buckets.Length > 0, "_buckets should be non-empty"); + Debug.Assert(_entries.Length > 0, "_entries should be non-empty"); + + SegmentedArray.Clear(_buckets); + _count = 0; + _freeList = -1; + _freeCount = 0; + SegmentedArray.Clear(_entries, 0, count); + } + } + + /// Determines whether the contains the specified element. + /// The element to locate in the object. + /// true if the object contains the specified element; otherwise, false. + public bool Contains(T item) => FindItemIndex(item) >= 0; + + /// Gets the index of the item in , or -1 if it's not in the set. + private int FindItemIndex(T item) + { + var buckets = _buckets; + if (buckets.Length > 0) + { + var entries = _entries; + Debug.Assert(entries.Length > 0, "Expected _entries to be initialized"); + + uint collisionCount = 0; + var comparer = _comparer; + + if (SupportsComparerDevirtualization && + typeof(T).IsValueType && // comparer can only be null for value types; enable JIT to eliminate entire if block for ref types + comparer == null) + { + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + var hashCode = item!.GetHashCode(); + var i = GetBucketRef(hashCode) - 1; // Value in _buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + if (entry._hashCode == hashCode && EqualityComparer.Default.Equals(entry._value, item)) + { + return i; + } + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop, which means a concurrent update has happened. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + else + { + Debug.Assert(comparer is not null); + var hashCode = item != null ? comparer!.GetHashCode(item) : 0; + var i = GetBucketRef(hashCode) - 1; // Value in _buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + if (entry._hashCode == hashCode && comparer!.Equals(entry._value, item)) + { + return i; + } + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop, which means a concurrent update has happened. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + } + + return -1; + } + + /// Gets a reference to the specified hashcode's bucket, containing an index into . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private ref int GetBucketRef(int hashCode) + { + var buckets = _buckets; + return ref buckets[(int)HashHelpers.FastMod((uint)hashCode, (uint)buckets.Length, _fastModMultiplier)]; + } + + public bool Remove(T item) + { + if (_buckets.Length > 0) + { + var entries = _entries; + Debug.Assert(entries.Length > 0, "entries should be non-empty"); + + uint collisionCount = 0; + var last = -1; + + IEqualityComparer? comparer = _comparer; + Debug.Assert((SupportsComparerDevirtualization && typeof(T).IsValueType) || comparer is not null); + int hashCode = + SupportsComparerDevirtualization && typeof(T).IsValueType && comparer == null ? item!.GetHashCode() : + item is not null ? comparer!.GetHashCode(item) : + 0; + + ref var bucket = ref GetBucketRef(hashCode); + var i = bucket - 1; // Value in buckets is 1-based + + while (i >= 0) + { + ref var entry = ref entries[i]; + + if (entry._hashCode == hashCode && (comparer?.Equals(entry._value, item) ?? EqualityComparer.Default.Equals(entry._value, item))) + { + if (last < 0) + { + bucket = entry._next + 1; // Value in buckets is 1-based + } + else + { + entries[last]._next = entry._next; + } + + Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646"); + entry._next = StartOfFreeList - _freeList; + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._value = default!; + } + + _freeList = i; + _freeCount++; + return true; + } + + last = i; + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + + return false; + } + + /// Gets the number of elements that are contained in the set. + public int Count => _count - _freeCount; + + bool ICollection.IsReadOnly => false; + + #endregion + + #region IEnumerable methods + + public Enumerator GetEnumerator() => new(this); + + IEnumerator IEnumerable.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this).GetEnumerator(); + + private static IEnumerator GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedHashSet()))!; + } + + #endregion + + #region SegmentedHashSet methods + + /// Adds the specified element to the . + /// The element to add to the set. + /// true if the element is added to the object; false if the element is already present. + public bool Add(T item) => AddIfNotPresent(item, out _); + + /// Searches the set for a given value and returns the equal value it finds, if any. + /// The value to search for. + /// The value from the set that the search found, or the default value of when the search yielded no match. + /// A value indicating whether the search was successful. + /// + /// This can be useful when you want to reuse a previously stored reference instead of + /// a newly constructed one (so that more sharing of references can occur) or to look up + /// a value that has more complete data than the value you currently have, although their + /// comparer functions indicate they are equal. + /// + public bool TryGetValue(T equalValue, [MaybeNullWhen(false)] out T actualValue) + { + if (_buckets.Length > 0) + { + var index = FindItemIndex(equalValue); + if (index >= 0) + { + actualValue = _entries[index]._value; + return true; + } + } + + actualValue = default; + return false; + } + + /// Modifies the current object to contain all elements that are present in itself, the specified collection, or both. + /// The collection to compare to the current object. + public void UnionWith(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + foreach (var item in other) + { + AddIfNotPresent(item, out _); + } + } + + /// Modifies the current object to contain only elements that are present in that object and in the specified collection. + /// The collection to compare to the current object. + public void IntersectWith(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // Intersection of anything with empty set is empty set, so return if count is 0. + // Same if the set intersecting with itself is the same set. + if (Count == 0 || other == this) + { + return; + } + + // If other is known to be empty, intersection is empty set; remove all elements, and we're done. + if (other is ICollection otherAsCollection) + { + if (otherAsCollection.Count == 0) + { + Clear(); + return; + } + + // Faster if other is a hashset using same equality comparer; so check + // that other is a hashset using the same equality comparer. + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + IntersectWithHashSetWithSameComparer(otherAsSet); + return; + } + } + + IntersectWithEnumerable(other); + } + + /// Removes all elements in the specified collection from the current object. + /// The collection to compare to the current object. + public void ExceptWith(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // This is already the empty set; return. + if (Count == 0) + { + return; + } + + // Special case if other is this; a set minus itself is the empty set. + if (other == this) + { + Clear(); + return; + } + + // Remove every element in other from this. + foreach (var element in other) + { + Remove(element); + } + } + + /// Modifies the current object to contain only elements that are present either in that object or in the specified collection, but not both. + /// The collection to compare to the current object. + public void SymmetricExceptWith(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // If set is empty, then symmetric difference is other. + if (Count == 0) + { + UnionWith(other); + return; + } + + // Special-case this; the symmetric difference of a set with itself is the empty set. + if (other == this) + { + Clear(); + return; + } + + // If other is a SegmentedHashSet, it has unique elements according to its equality comparer, + // but if they're using different equality comparers, then assumption of uniqueness + // will fail. So first check if other is a hashset using the same equality comparer; + // symmetric except is a lot faster and avoids bit array allocations if we can assume + // uniqueness. + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + SymmetricExceptWithUniqueHashSet(otherAsSet); + } + else + { + SymmetricExceptWithEnumerable(other); + } + } + + /// Determines whether a object is a subset of the specified collection. + /// The collection to compare to the current object. + /// true if the object is a subset of ; otherwise, false. + public bool IsSubsetOf(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // The empty set is a subset of any set, and a set is a subset of itself. + // Set is always a subset of itself + if (Count == 0 || other == this) + { + return true; + } + + // Faster if other has unique elements according to this equality comparer; so check + // that other is a hashset using the same equality comparer. + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + // if this has more elements then it can't be a subset + if (Count > otherAsSet.Count) + { + return false; + } + + // already checked that we're using same equality comparer. simply check that + // each element in this is contained in other. + return IsSubsetOfHashSetWithSameComparer(otherAsSet); + } + + (var uniqueCount, var unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: false); + return uniqueCount == Count && unfoundCount >= 0; + } + + /// Determines whether a object is a proper subset of the specified collection. + /// The collection to compare to the current object. + /// true if the object is a proper subset of ; otherwise, false. + public bool IsProperSubsetOf(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // No set is a proper subset of itself. + if (other == this) + { + return false; + } + + if (other is ICollection otherAsCollection) + { + // No set is a proper subset of an empty set. + if (otherAsCollection.Count == 0) + { + return false; + } + + // The empty set is a proper subset of anything but the empty set. + if (Count == 0) + { + return otherAsCollection.Count > 0; + } + + // Faster if other is a hashset (and we're using same equality comparer). + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + if (Count >= otherAsSet.Count) + { + return false; + } + + // This has strictly less than number of items in other, so the following + // check suffices for proper subset. + return IsSubsetOfHashSetWithSameComparer(otherAsSet); + } + } + + (var uniqueCount, var unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: false); + return uniqueCount == Count && unfoundCount > 0; + } + + /// Determines whether a object is a proper superset of the specified collection. + /// The collection to compare to the current object. + /// true if the object is a superset of ; otherwise, false. + public bool IsSupersetOf(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // A set is always a superset of itself. + if (other == this) + { + return true; + } + + // Try to fall out early based on counts. + if (other is ICollection otherAsCollection) + { + // If other is the empty set then this is a superset. + if (otherAsCollection.Count == 0) + { + return true; + } + + // Try to compare based on counts alone if other is a hashset with same equality comparer. + if (other is SegmentedHashSet otherAsSet && + EqualityComparersAreEqual(this, otherAsSet) && + otherAsSet.Count > Count) + { + return false; + } + } + + foreach (T element in other) + { + if (!Contains(element)) + { + return false; + } + } + + return true; + } + + /// Determines whether a object is a proper superset of the specified collection. + /// The collection to compare to the current object. + /// true if the object is a proper superset of ; otherwise, false. + public bool IsProperSupersetOf(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // The empty set isn't a proper superset of any set, and a set is never a strict superset of itself. + if (Count == 0 || other == this) + { + return false; + } + + if (other is ICollection otherAsCollection) + { + // If other is the empty set then this is a superset. + if (otherAsCollection.Count == 0) + { + // Note that this has at least one element, based on above check. + return true; + } + + // Faster if other is a hashset with the same equality comparer + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + if (otherAsSet.Count >= Count) + { + return false; + } + + // Now perform element check. + return otherAsSet.IsSubsetOfHashSetWithSameComparer(this); + } + } + + // Couldn't fall out in the above cases; do it the long way + (var uniqueCount, var unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: true); + return uniqueCount < Count && unfoundCount == 0; + } + + /// Determines whether the current object and a specified collection share common elements. + /// The collection to compare to the current object. + /// true if the object and share at least one common element; otherwise, false. + public bool Overlaps(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + if (Count == 0) + { + return false; + } + + // Set overlaps itself + if (other == this) + { + return true; + } + + foreach (var element in other) + { + if (Contains(element)) + { + return true; + } + } + + return false; + } + + /// Determines whether a object and the specified collection contain the same elements. + /// The collection to compare to the current object. + /// true if the object is equal to ; otherwise, false. + public bool SetEquals(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // A set is equal to itself. + if (other == this) + { + return true; + } + + // Faster if other is a hashset and we're using same equality comparer. + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + // Attempt to return early: since both contain unique elements, if they have + // different counts, then they can't be equal. + if (Count != otherAsSet.Count) + { + return false; + } + + // Already confirmed that the sets have the same number of distinct elements, so if + // one is a subset of the other then they must be equal. + return IsSubsetOfHashSetWithSameComparer(otherAsSet); + } + else + { + // If this count is 0 but other contains at least one element, they can't be equal. + if (Count == 0 && + other is ICollection otherAsCollection && + otherAsCollection.Count > 0) + { + return false; + } + + (var uniqueCount, var unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: true); + return uniqueCount == Count && unfoundCount == 0; + } + } + + public void CopyTo(T[] array) => CopyTo(array, 0, Count); + + /// Copies the elements of a object to an array, starting at the specified array index. + /// The destination array. + /// The zero-based index in array at which copying begins. + public void CopyTo(T[] array, int arrayIndex) => CopyTo(array, arrayIndex, Count); + + public void CopyTo(T[] array, int arrayIndex, int count) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + +#if NET8_0_OR_GREATER + ArgumentOutOfRangeException.ThrowIfNegative(arrayIndex); + ArgumentOutOfRangeException.ThrowIfNegative(count); +#else + // Check array index valid index into array. + if (arrayIndex < 0) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex), arrayIndex, SR.ArgumentOutOfRange_NeedNonNegNum); + } + + // Also throw if count less than 0. + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), count, SR.ArgumentOutOfRange_NeedNonNegNum); + } +#endif + + // Will the array, starting at arrayIndex, be able to hold elements? Note: not + // checking arrayIndex >= array.Length (consistency with list of allowing + // count of 0; subsequent check takes care of the rest) + if (arrayIndex > array.Length || count > array.Length - arrayIndex) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + var entries = _entries; + for (var i = 0; i < _count && count != 0; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + array[arrayIndex++] = entry._value; + count--; + } + } + } + + /// Removes all elements that match the conditions defined by the specified predicate from a collection. + public int RemoveWhere(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + var entries = _entries; + var numRemoved = 0; + for (var i = 0; i < _count; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + // Cache value in case delegate removes it + var value = entry._value; + if (match(value)) + { + // Check again that remove actually removed it. + if (Remove(value)) + { + numRemoved++; + } + } + } + } + + return numRemoved; + } + + /// Gets the object that is used to determine equality for the values in the set. + public IEqualityComparer Comparer + { + get + { + return _comparer ?? EqualityComparer.Default; + } + } + + /// Ensures that this hash set can hold the specified number of elements without growing. + public int EnsureCapacity(int capacity) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + var currentCapacity = _entries.Length; + if (currentCapacity >= capacity) + { + return currentCapacity; + } + + if (_buckets.Length == 0) + { + return Initialize(capacity); + } + + var newSize = HashHelpers.GetPrime(capacity); + Resize(newSize); + return newSize; + } + + private void Resize() => Resize(HashHelpers.ExpandPrime(_count)); + + private void Resize(int newSize) + { + Debug.Assert(_entries.Length > 0, "_entries should be non-empty"); + Debug.Assert(newSize >= _entries.Length); + + var count = _count; + + // Rather than creating a copy of _entries, instead reuse as much of it's data as possible. + var entries = CreateNewSegmentedArrayReusingOldSegments(_entries, newSize); + + // Assign member variables after both arrays allocated to guard against corruption from OOM if second fails + _buckets = new SegmentedArray(newSize); + _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)newSize); + for (var i = 0; i < count; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + ref var bucket = ref GetBucketRef(entry._hashCode); + entry._next = bucket - 1; // Value in _buckets is 1-based + bucket = i + 1; + } + } + + _entries = entries; + } + + private static SegmentedArray CreateNewSegmentedArrayReusingOldSegments(SegmentedArray oldArray, int newSize) + { + var segments = SegmentedCollectionsMarshal.AsSegments(oldArray); + + var oldSegmentCount = segments.Length; + var newSegmentCount = (newSize + SegmentedArrayHelper.GetSegmentSize() - 1) >> SegmentedArrayHelper.GetSegmentShift(); + + // Grow the array of segments, if necessary + Array.Resize(ref segments, newSegmentCount); + + // Resize all segments to full segment size from the last old segment to the next to last + // new segment. + for (var i = oldSegmentCount - 1; i < newSegmentCount - 1; i++) + Array.Resize(ref segments[i], SegmentedArrayHelper.GetSegmentSize()); + + // Resize the last segment + var lastSegmentSize = newSize - ((newSegmentCount - 1) << SegmentedArrayHelper.GetSegmentShift()); + Array.Resize(ref segments[newSegmentCount - 1], lastSegmentSize); + + return SegmentedCollectionsMarshal.AsSegmentedArray(newSize, segments); + } + + /// + /// Sets the capacity of a object to the actual number of elements it contains, + /// rounded up to a nearby, implementation-specific value. + /// + public void TrimExcess() + { + var capacity = Count; + + var newSize = HashHelpers.GetPrime(capacity); + var oldEntries = _entries; + var currentCapacity = oldEntries.Length; + if (newSize >= currentCapacity) + { + return; + } + + var oldCount = _count; + _version++; + Initialize(newSize); + var entries = _entries; + var count = 0; + for (var i = 0; i < oldCount; i++) + { + var hashCode = oldEntries[i]._hashCode; // At this point, we know we have entries. + if (oldEntries[i]._next >= -1) + { + ref var entry = ref entries[count]; + entry = oldEntries[i]; + ref var bucket = ref GetBucketRef(hashCode); + entry._next = bucket - 1; // Value in _buckets is 1-based + bucket = count + 1; + count++; + } + } + + _count = capacity; + _freeCount = 0; + } + + #endregion + + #region Helper methods + + /// Returns an object that can be used for equality testing of a object. + public static IEqualityComparer> CreateSetComparer() => new SegmentedHashSetEqualityComparer(); + + /// + /// Initializes buckets and slots arrays. Uses suggested capacity by finding next prime + /// greater than or equal to capacity. + /// + private int Initialize(int capacity) + { + var size = HashHelpers.GetPrime(capacity); + var buckets = new SegmentedArray(size); + var entries = new SegmentedArray(size); + + // Assign member variables after both arrays are allocated to guard against corruption from OOM if second fails. + _freeList = -1; + _buckets = buckets; + _entries = entries; + _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)size); + + return size; + } + + /// Adds the specified element to the set if it's not already contained. + /// The element to add to the set. + /// The index into of the element. + /// true if the element is added to the object; false if the element is already present. + private bool AddIfNotPresent(T value, out int location) + { + if (_buckets.Length == 0) + { + Initialize(0); + } + Debug.Assert(_buckets.Length > 0); + + var entries = _entries; + Debug.Assert(entries.Length > 0, "expected entries to be non-empty"); + + var comparer = _comparer; + int hashCode; + + uint collisionCount = 0; + ref var bucket = ref RoslynUnsafe.NullRef(); + + if (SupportsComparerDevirtualization && + typeof(T).IsValueType && // comparer can only be null for value types; enable JIT to eliminate entire if block for ref types + comparer == null) + { + hashCode = value!.GetHashCode(); + bucket = ref GetBucketRef(hashCode); + var i = bucket - 1; // Value in _buckets is 1-based + + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + while (i >= 0) + { + ref var entry = ref entries[i]; + if (entry._hashCode == hashCode && EqualityComparer.Default.Equals(entry._value, value)) + { + location = i; + return false; + } + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop, which means a concurrent update has happened. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + else + { + Debug.Assert(comparer is not null); + hashCode = value != null ? comparer!.GetHashCode(value) : 0; + bucket = ref GetBucketRef(hashCode); + var i = bucket - 1; // Value in _buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + if (entry._hashCode == hashCode && comparer!.Equals(entry._value, value)) + { + location = i; + return false; + } + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop, which means a concurrent update has happened. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + + int index; + if (_freeCount > 0) + { + index = _freeList; + _freeCount--; + Debug.Assert((StartOfFreeList - entries[_freeList]._next) >= -1, "shouldn't overflow because `next` cannot underflow"); + _freeList = StartOfFreeList - entries[_freeList]._next; + } + else + { + var count = _count; + if (count == entries.Length) + { + Resize(); + bucket = ref GetBucketRef(hashCode); + } + index = count; + _count = count + 1; + entries = _entries; + } + + { + ref var entry = ref entries[index]; + entry._hashCode = hashCode; + entry._next = bucket - 1; // Value in _buckets is 1-based + entry._value = value; + bucket = index + 1; + _version++; + location = index; + } + + return true; + } + + /// + /// Implementation Notes: + /// If other is a hashset and is using same equality comparer, then checking subset is + /// faster. Simply check that each element in this is in other. + /// + /// Note: if other doesn't use same equality comparer, then Contains check is invalid, + /// which is why callers must take are of this. + /// + /// If callers are concerned about whether this is a proper subset, they take care of that. + /// + internal bool IsSubsetOfHashSetWithSameComparer(SegmentedHashSet other) + { + foreach (var item in this) + { + if (!other.Contains(item)) + { + return false; + } + } + + return true; + } + + /// + /// If other is a hashset that uses same equality comparer, intersect is much faster + /// because we can use other's Contains + /// + private void IntersectWithHashSetWithSameComparer(SegmentedHashSet other) + { + var entries = _entries; + for (var i = 0; i < _count; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + var item = entry._value; + if (!other.Contains(item)) + { + Remove(item); + } + } + } + } + + /// + /// Iterate over other. If contained in this, mark an element in bit array corresponding to + /// its position in _slots. If anything is unmarked (in bit array), remove it. + /// + /// This attempts to allocate on the stack, if below StackAllocThreshold. + /// + private unsafe void IntersectWithEnumerable(IEnumerable other) + { + Debug.Assert(_buckets.Length > 0, "_buckets shouldn't be empty; callers should check first"); + + // Keep track of current last index; don't want to move past the end of our bit array + // (could happen if another thread is modifying the collection). + var originalCount = _count; + int intArrayLength = BitHelper.ToIntArrayLength(originalCount); + + Span span = stackalloc int[StackAllocThreshold]; + var bitHelper = intArrayLength <= StackAllocThreshold + ? new BitHelper(span.Slice(0, intArrayLength), clear: true) + : new BitHelper(new int[intArrayLength], clear: false); + + // Mark if contains: find index of in slots array and mark corresponding element in bit array. + foreach (var item in other) + { + var index = FindItemIndex(item); + if (index >= 0) + { + bitHelper.MarkBit(index); + } + } + + // If anything unmarked, remove it. Perf can be optimized here if BitHelper had a + // FindFirstUnmarked method. + for (var i = 0; i < originalCount; i++) + { + ref var entry = ref _entries[i]; + if (entry._next >= -1 && !bitHelper.IsMarked(i)) + { + Remove(entry._value); + } + } + } + + /// + /// if other is a set, we can assume it doesn't have duplicate elements, so use this + /// technique: if can't remove, then it wasn't present in this set, so add. + /// + /// As with other methods, callers take care of ensuring that other is a hashset using the + /// same equality comparer. + /// + /// + private void SymmetricExceptWithUniqueHashSet(SegmentedHashSet other) + { + foreach (var item in other) + { + if (!Remove(item)) + { + AddIfNotPresent(item, out _); + } + } + } + + /// + /// Implementation notes: + /// + /// Used for symmetric except when other isn't a SegmentedHashSet. This is more tedious because + /// other may contain duplicates. SegmentedHashSet technique could fail in these situations: + /// 1. Other has a duplicate that's not in this: SegmentedHashSet technique would add then + /// remove it. + /// 2. Other has a duplicate that's in this: SegmentedHashSet technique would remove then add it + /// back. + /// In general, its presence would be toggled each time it appears in other. + /// + /// This technique uses bit marking to indicate whether to add/remove the item. If already + /// present in collection, it will get marked for deletion. If added from other, it will + /// get marked as something not to remove. + /// + /// + /// + private unsafe void SymmetricExceptWithEnumerable(IEnumerable other) + { + var originalCount = _count; + int intArrayLength = BitHelper.ToIntArrayLength(originalCount); + + Span itemsToRemoveSpan = stackalloc int[StackAllocThreshold / 2]; + var itemsToRemove = intArrayLength <= StackAllocThreshold / 2 + ? new BitHelper(itemsToRemoveSpan.Slice(0, intArrayLength), clear: true) + : new BitHelper(new int[intArrayLength], clear: false); + + Span itemsAddedFromOtherSpan = stackalloc int[StackAllocThreshold / 2]; + var itemsAddedFromOther = intArrayLength <= StackAllocThreshold / 2 + ? new BitHelper(itemsAddedFromOtherSpan.Slice(0, intArrayLength), clear: true) + : new BitHelper(new int[intArrayLength], clear: false); + + foreach (var item in other) + { + if (AddIfNotPresent(item, out var location)) + { + // wasn't already present in collection; flag it as something not to remove + // *NOTE* if location is out of range, we should ignore. BitHelper will + // detect that it's out of bounds and not try to mark it. But it's + // expected that location could be out of bounds because adding the item + // will increase _lastIndex as soon as all the free spots are filled. + itemsAddedFromOther.MarkBit(location); + } + else + { + // already there...if not added from other, mark for remove. + // *NOTE* Even though BitHelper will check that location is in range, we want + // to check here. There's no point in checking items beyond originalCount + // because they could not have been in the original collection + if (location < originalCount && !itemsAddedFromOther.IsMarked(location)) + { + itemsToRemove.MarkBit(location); + } + } + } + + // if anything marked, remove it + for (var i = 0; i < originalCount; i++) + { + if (itemsToRemove.IsMarked(i)) + { + Remove(_entries[i]._value); + } + } + } + + /// + /// Determines counts that can be used to determine equality, subset, and superset. This + /// is only used when other is an IEnumerable and not a SegmentedHashSet. If other is a SegmentedHashSet + /// these properties can be checked faster without use of marking because we can assume + /// other has no duplicates. + /// + /// The following count checks are performed by callers: + /// 1. Equals: checks if unfoundCount = 0 and uniqueFoundCount = _count; i.e. everything + /// in other is in this and everything in this is in other + /// 2. Subset: checks if unfoundCount >= 0 and uniqueFoundCount = _count; i.e. other may + /// have elements not in this and everything in this is in other + /// 3. Proper subset: checks if unfoundCount > 0 and uniqueFoundCount = _count; i.e + /// other must have at least one element not in this and everything in this is in other + /// 4. Proper superset: checks if unfound count = 0 and uniqueFoundCount strictly less + /// than _count; i.e. everything in other was in this and this had at least one element + /// not contained in other. + /// + /// An earlier implementation used delegates to perform these checks rather than returning + /// an ElementCount struct; however this was changed due to the perf overhead of delegates. + /// + /// + /// Allows us to finish faster for equals and proper superset + /// because unfoundCount must be 0. + private (int UniqueCount, int UnfoundCount) CheckUniqueAndUnfoundElements(IEnumerable other, bool returnIfUnfound) + { + // Need special case in case this has no elements. + if (_count == 0) + { + var numElementsInOther = 0; + foreach (var item in other) + { + numElementsInOther++; + break; // break right away, all we want to know is whether other has 0 or 1 elements + } + + return (UniqueCount: 0, UnfoundCount: numElementsInOther); + } + + Debug.Assert((_buckets.Length > 0) && (_count > 0), "_buckets was empty but count greater than 0"); + + var originalCount = _count; + int intArrayLength = BitHelper.ToIntArrayLength(originalCount); + + Span span = stackalloc int[StackAllocThreshold]; + var bitHelper = intArrayLength <= StackAllocThreshold + ? new BitHelper(span.Slice(0, intArrayLength), clear: true) + : new BitHelper(new int[intArrayLength], clear: false); + + var unfoundCount = 0; // count of items in other not found in this + var uniqueFoundCount = 0; // count of unique items in other found in this + + foreach (var item in other) + { + var index = FindItemIndex(item); + if (index >= 0) + { + if (!bitHelper.IsMarked(index)) + { + // Item hasn't been seen yet. + bitHelper.MarkBit(index); + uniqueFoundCount++; + } + } + else + { + unfoundCount++; + if (returnIfUnfound) + { + break; + } + } + } + + return (uniqueFoundCount, unfoundCount); + } + + /// + /// Checks if equality comparers are equal. This is used for algorithms that can + /// speed up if it knows the other item has unique elements. I.e. if they're using + /// different equality comparers, then uniqueness assumption between sets break. + /// + internal static bool EqualityComparersAreEqual(SegmentedHashSet set1, SegmentedHashSet set2) => set1.Comparer.Equals(set2.Comparer); + + #endregion + + private struct Entry + { + public int _hashCode; + /// + /// 0-based index of next entry in chain: -1 means end of chain + /// also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3, + /// so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc. + /// + public int _next; + public T _value; + } + + public struct Enumerator : IEnumerator + { + private readonly SegmentedHashSet _hashSet; + private readonly int _version; + private int _index; + private T _current; + + internal Enumerator(SegmentedHashSet hashSet) + { + _hashSet = hashSet; + _version = hashSet._version; + _index = 0; + _current = default!; + } + + public bool MoveNext() + { + if (_version != _hashSet._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. + // dictionary.count+1 could be negative if dictionary.count is int.MaxValue + while ((uint)_index < (uint)_hashSet._count) + { + ref var entry = ref _hashSet._entries[_index++]; + if (entry._next >= -1) + { + _current = entry._value; + return true; + } + } + + _index = _hashSet._count + 1; + _current = default!; + return false; + } + + public readonly T Current => _current; + + public readonly void Dispose() { } + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || (_index == _hashSet._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _current; + } + } + + void IEnumerator.Reset() + { + if (_version != _hashSet._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _current = default!; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedList`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedList`1.cs new file mode 100755 index 00000000000..407d7925951 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Segmented/SegmentedList`1.cs @@ -0,0 +1,1397 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a strongly typed list of objects that can be accessed by index. Provides methods to search, sort, and + /// manipulate lists. + /// + /// + /// This collection has the same performance characteristics as , but uses segmented + /// arrays to avoid allocations in the Large Object Heap. + /// + /// The type of elements in the list. + [DebuggerTypeProxy(typeof(ICollectionDebugView<>))] + [DebuggerDisplay("Count = {Count}")] + internal class SegmentedList : IList, IList, IReadOnlyList + { + private const int DefaultCapacity = 4; + private const int MaxLength = 0x7FFFFFC7; + + internal SegmentedArray _items; + internal int _size; + internal int _version; + + private static readonly SegmentedArray s_emptyArray = new(0); + private static IEnumerator? s_emptyEnumerator; + + // Constructs a SegmentedList. The list is initially empty and has a capacity + // of zero. Upon adding the first element to the list the capacity is + // increased to DefaultCapacity, and then increased in multiples of two + // as required. + public SegmentedList() + { + _items = s_emptyArray; + } + + // Constructs a SegmentedList with a given initial capacity. The list is + // initially empty, but will have room for the given number of elements + // before any reallocations are required. + // + public SegmentedList(int capacity) + { + if (capacity < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + + if (capacity == 0) + _items = s_emptyArray; + else + _items = new SegmentedArray(capacity); + } + + // Constructs a SegmentedList, copying the contents of the given collection. The + // size and capacity of the new list will both be equal to the size of the + // given collection. + // + public SegmentedList(IEnumerable collection) + { + if (collection == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + + if (collection is SegmentedList segmentedList) + { + _items = (SegmentedArray)segmentedList._items.Clone(); + _size = segmentedList._size; + return; + } + + if (collection is ICollection c) + { + var count = c.Count; + if (count == 0) + { + _items = s_emptyArray; + return; + } + else + { + _items = new SegmentedArray(count); + if (SegmentedCollectionsMarshal.AsSegments(_items) is { Length: 1 } segments) + { + c.CopyTo(segments[0], 0); + _size = count; + return; + } + } + + // Continue below to add the items + } + else + { + _items = s_emptyArray; + + // Continue below to add the items + } + + using var en = collection.GetEnumerator(); + while (en.MoveNext()) + { + Add(en.Current); + } + } + + // Gets and sets the capacity of this list. The capacity is the size of + // the internal array used to hold items. When set, the internal + // array of the list is reallocated to the given capacity. + // + public int Capacity + { + get => _items.Length; + set + { + if (value < _size) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity); + } + + if (value == _items.Length) + return; + + if (value <= 0) + { + _items = s_emptyArray; + return; + } + + if (_items.Length == 0) + { + // No data from existing array to reuse, just create a new one. + _items = new SegmentedArray(value); + } + else + { + // Rather than creating a copy of _items, instead reuse as much of it's data as possible. + _items = CreateNewSegmentedArrayReusingOldSegments(_items, value); + } + } + } + + private static SegmentedArray CreateNewSegmentedArrayReusingOldSegments(SegmentedArray oldArray, int newSize) + { + var segments = SegmentedCollectionsMarshal.AsSegments(oldArray); + + var oldSegmentCount = segments.Length; + var newSegmentCount = (newSize + SegmentedArrayHelper.GetSegmentSize() - 1) >> SegmentedArrayHelper.GetSegmentShift(); + + // Grow the array of segments, if necessary + Array.Resize(ref segments, newSegmentCount); + + // Resize all segments to full segment size from the last old segment to the next to last + // new segment. + for (var i = oldSegmentCount - 1; i < newSegmentCount - 1; i++) + Array.Resize(ref segments[i], SegmentedArrayHelper.GetSegmentSize()); + + // Resize the last segment + var lastSegmentSize = newSize - ((newSegmentCount - 1) << SegmentedArrayHelper.GetSegmentShift()); + Array.Resize(ref segments[newSegmentCount - 1], lastSegmentSize); + + return SegmentedCollectionsMarshal.AsSegmentedArray(newSize, segments); + } + + // Read-only property describing how many elements are in the SegmentedList. + public int Count => _size; + + bool IList.IsFixedSize => false; + + // Is this SegmentedList read-only? + bool ICollection.IsReadOnly => false; + + bool IList.IsReadOnly => false; + + // Is this SegmentedList synchronized (thread-safe)? + bool ICollection.IsSynchronized => false; + + // Synchronization root for this object. + object ICollection.SyncRoot => this; + + // Sets or Gets the element at the given index. + public T this[int index] + { + get + { + // Following trick can reduce the range check by one + if ((uint)index >= (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + return _items[index]; + } + + set + { + if ((uint)index >= (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + _items[index] = value; + _version++; + } + } + + private static bool IsCompatibleObject(object? value) + { + // Non-null values are fine. Only accept nulls if T is a class or Nullable. + // Note that default(T) is not equal to null for value types except when T is Nullable. + return (value is T) || (value == null && default(T) == null); + } + + object? IList.this[int index] + { + get => this[index]; + set + { + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(value, ExceptionArgument.value); + + try + { + this[index] = (T)value!; + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T)); + } + } + } + + // Adds the given object to the end of this list. The size of the list is + // increased by one. If required, the capacity of the list is doubled + // before adding the new element. + // + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(T item) + { + _version++; + var array = _items; + var size = _size; + if ((uint)size < (uint)array.Length) + { + _size = size + 1; + array[size] = item; + } + else + { + AddWithResize(item); + } + } + + // Non-inline from SegmentedList.Add to improve its code quality as uncommon path + [MethodImpl(MethodImplOptions.NoInlining)] + private void AddWithResize(T item) + { + Debug.Assert(_size == _items.Length); + var size = _size; + Grow(size + 1); + _size = size + 1; + _items[size] = item; + } + + int IList.Add(object? item) + { + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(item, ExceptionArgument.item); + + try + { + Add((T)item!); + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(item, typeof(T)); + } + + return Count - 1; + } + + // Adds the elements of the given collection to the end of this list. If + // required, the capacity of the list is increased to twice the previous + // capacity or the new size, whichever is larger. + // + public void AddRange(IEnumerable collection) + { + if (collection == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + + if (collection is ICollection c) + { + var count = c.Count; + if (count > 0) + { + if (_items.Length - _size < count) + { + Grow(checked(_size + count)); + } + + if (c is SegmentedList list) + { + SegmentedArray.Copy(list._items, 0, _items, _size, list.Count); + } + else if (c is SegmentedArray array) + { + SegmentedArray.Copy(array, 0, _items, _size, array.Length); + } + else + { + var targetIndex = _size; + foreach (var item in c) + _items[targetIndex++] = item; + } + + _size += count; + _version++; + } + } + else + { + using var en = collection.GetEnumerator(); + while (en.MoveNext()) + { + Add(en.Current); + } + } + } + + public ReadOnlyCollection AsReadOnly() + => new(this); + + // Searches a section of the list for a given element using a binary search + // algorithm. Elements of the list are compared to the search value using + // the given IComparer interface. If comparer is null, elements of + // the list are compared to the search value using the IComparable + // interface, which in that case must be implemented by all elements of the + // list and the given search value. This method assumes that the given + // section of the list is already sorted; if this is not the case, the + // result will be incorrect. + // + // The method returns the index of the given value in the list. If the + // list does not contain the given value, the method returns a negative + // integer. The bitwise complement operator (~) can be applied to a + // negative result to produce the index of the first element (if any) that + // is larger than the given search value. This is also the index at which + // the search value should be inserted into the list in order for the list + // to remain sorted. + // + // The method uses the Array.BinarySearch method to perform the + // search. + // + public int BinarySearch(int index, int count, T item, IComparer? comparer) + { + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (count < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + if (_size - index < count) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + return SegmentedArray.BinarySearch(_items, index, count, item, comparer); + } + + public int BinarySearch(T item) + => BinarySearch(0, Count, item, null); + + public int BinarySearch(T item, IComparer? comparer) + => BinarySearch(0, Count, item, comparer); + + // Clears the contents of SegmentedList. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Clear() + { + _version++; +#if NET + if (!RuntimeHelpers.IsReferenceOrContainsReferences()) + { + _size = 0; + return; + } +#endif + + var size = _size; + _size = 0; + if (size > 0) + { + SegmentedArray.Clear(_items, 0, size); // Clear the elements so that the gc can reclaim the references. + } + } + + // Contains returns true if the specified element is in the SegmentedList. + // It does a linear, O(n) search. Equality is determined by calling + // EqualityComparer.Default.Equals(). + // + public bool Contains(T item) + { + // PERF: IndexOf calls Array.IndexOf, which internally + // calls EqualityComparer.Default.IndexOf, which + // is specialized for different types. This + // boosts performance since instead of making a + // virtual method call each iteration of the loop, + // via EqualityComparer.Default.Equals, we + // only make one virtual call to EqualityComparer.IndexOf. + + return _size != 0 && IndexOf(item) >= 0; + } + + bool IList.Contains(object? item) + { + if (IsCompatibleObject(item)) + { + return Contains((T)item!); + } + return false; + } + + public SegmentedList ConvertAll(Converter converter) + { + if (converter == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter); + } + + var list = new SegmentedList(_size); + for (var i = 0; i < _size; i++) + { + list._items[i] = converter(_items[i]); + } + list._size = _size; + return list; + } + + // Copies this SegmentedList into array, which must be of a + // compatible array type. + public void CopyTo(T[] array) + => CopyTo(array, 0); + + // Copies this SegmentedList into array, which must be of a + // compatible array type. + void ICollection.CopyTo(Array array, int arrayIndex) + { + if ((array != null) && (array.Rank != 1)) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); + } + + try + { + // Array.Copy will check for NULL. + SegmentedArray.Copy(_items, 0, array!, arrayIndex, _size); + } + catch (ArrayTypeMismatchException) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + } + + // Copies a section of this list to the given array at the given index. + // + // The method uses the Array.Copy method to copy the elements. + // + public void CopyTo(int index, T[] array, int arrayIndex, int count) + { + if (_size - index < count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + } + + // Delegate rest of error checking to Array.Copy. + SegmentedArray.Copy(_items, index, array, arrayIndex, count); + } + + public void CopyTo(T[] array, int arrayIndex) + { + // Delegate rest of error checking to Array.Copy. + SegmentedArray.Copy(_items, 0, array, arrayIndex, _size); + } + + /// + /// Ensures that the capacity of this list is at least the specified . + /// If the current capacity of the list is less than specified , + /// the capacity is increased by continuously twice current capacity until it is at least the specified . + /// + /// The minimum capacity to ensure. + /// The new capacity of this list. + public int EnsureCapacity(int capacity) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + if (_items.Length < capacity) + { + Grow(capacity); + } + + return _items.Length; + } + + /// + /// Increase the capacity of this list to at least the specified . + /// + /// The minimum capacity to ensure. + internal void Grow(int capacity) + { + Debug.Assert(_items.Length < capacity); + + var newCapacity = 0; + + if (_items.Length < SegmentedArrayHelper.GetSegmentSize() / 2) + { + // The array isn't near the maximum segment size. If the array is empty, the new capacity + // should be DefaultCapacity. Otherwise, the new capacity should be double the current array size. + newCapacity = _items.Length == 0 ? DefaultCapacity : _items.Length * 2; + } + else if (_items.Length < SegmentedArrayHelper.GetSegmentSize()) + { + // There is only a single segment that is over half full. Increase it to a full segment. + newCapacity = SegmentedArrayHelper.GetSegmentSize(); + } + else + { + // If the last segment is fully sized, increase the number of segments by the desired growth rate + if (0 == (_items.Length & SegmentedArrayHelper.GetOffsetMask())) + { + // This value determines the growth rate of the number of segments to use. + // For a value of 3, this means the segment count will grow at a rate of + // 1 + (1 >> 3) or 12.5% + const int segmentGrowthShiftValue = 3; + + var oldSegmentCount = (_items.Length + SegmentedArrayHelper.GetSegmentSize() - 1) >> SegmentedArrayHelper.GetSegmentShift(); + var newSegmentCount = oldSegmentCount + Math.Max(1, oldSegmentCount >> segmentGrowthShiftValue); + + newCapacity = SegmentedArrayHelper.GetSegmentSize() * newSegmentCount; + } + } + + // If the computed capacity is less than specified, set to the original argument. + // Capacities exceeding Array.MaxLength will be surfaced as OutOfMemoryException by Array.Resize. + if (newCapacity < capacity) + newCapacity = capacity; + + if (newCapacity > SegmentedArrayHelper.GetSegmentSize()) + { + // If the last segment isn't fully sized, increase the new capacity such that it will be. + var lastSegmentLength = newCapacity & SegmentedArrayHelper.GetOffsetMask(); + if (lastSegmentLength > 0) + newCapacity = (newCapacity - lastSegmentLength) + SegmentedArrayHelper.GetSegmentSize(); + + // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + if ((uint)newCapacity > MaxLength) + newCapacity = MaxLength; + } + + Capacity = newCapacity; + } + + public bool Exists(Predicate match) + => FindIndex(match) != -1; + + public T? Find(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + for (var i = 0; i < _size; i++) + { + if (match(_items[i])) + { + return _items[i]; + } + } + return default; + } + + public SegmentedList FindAll(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + var list = new SegmentedList(); + for (var i = 0; i < _size; i++) + { + if (match(_items[i])) + { + list.Add(_items[i]); + } + } + return list; + } + + public int FindIndex(Predicate match) + => FindIndex(0, _size, match); + + public int FindIndex(int startIndex, Predicate match) + => FindIndex(startIndex, _size - startIndex, match); + + public int FindIndex(int startIndex, int count, Predicate match) + { + if ((uint)startIndex > (uint)_size) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLessOrEqual(); + } + + if (count < 0 || startIndex > _size - count) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + var endIndex = startIndex + count; + for (var i = startIndex; i < endIndex; i++) + { + if (match(_items[i])) + return i; + } + return -1; + } + + public T? FindLast(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + for (var i = _size - 1; i >= 0; i--) + { + if (match(_items[i])) + { + return _items[i]; + } + } + return default; + } + + public int FindLastIndex(Predicate match) + => FindLastIndex(_size - 1, _size, match); + + public int FindLastIndex(int startIndex, Predicate match) + => FindLastIndex(startIndex, startIndex + 1, match); + + public int FindLastIndex(int startIndex, int count, Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + if (_size == 0) + { + // Special case for 0 length SegmentedList + if (startIndex != -1) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); + } + } + else + { + // Make sure we're not out of range + if ((uint)startIndex >= (uint)_size) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); + } + } + + // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. + if (count < 0 || startIndex - count + 1 < 0) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + var endIndex = startIndex - count; + for (var i = startIndex; i > endIndex; i--) + { + if (match(_items[i])) + { + return i; + } + } + return -1; + } + + public void ForEach(Action action) + { + if (action == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action); + } + + var version = _version; + + for (var i = 0; i < _size; i++) + { + if (version != _version) + { + break; + } + action(_items[i]); + } + + if (version != _version) + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + // Returns an enumerator for this list with the given + // permission for removal of elements. If modifications made to the list + // while an enumeration is in progress, the MoveNext and + // GetObject methods of the enumerator will throw an exception. + // + public Enumerator GetEnumerator() => new(this); + + IEnumerator IEnumerable.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this).GetEnumerator(); + + private static IEnumerator GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedList(0)))!; + } + + public SegmentedList GetRange(int index, int count) + { + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_size - index < count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + } + + var list = new SegmentedList(count); + SegmentedArray.Copy(_items, index, list._items, 0, count); + list._size = count; + return list; + } + + /// + /// Creates a shallow copy of a range of elements in the source . + /// + /// The zero-based index at which the range starts. + /// The length of the range. + /// A shallow copy of a range of elements in the source . + /// + /// is less than 0. + /// -or- + /// is less than 0. + /// + /// and do not denote a valid range of elements in the . + public SegmentedList Slice(int start, int length) => GetRange(start, length); + + // Returns the index of the first occurrence of a given value in a range of + // this list. The list is searched forwards from beginning to end. + // The elements of the list are compared to the given value using the + // Object.Equals method. + // + // This method uses the Array.IndexOf method to perform the + // search. + // + public int IndexOf(T item) + => SegmentedArray.IndexOf(_items, item, 0, _size); + + int IList.IndexOf(object? item) + { + if (IsCompatibleObject(item)) + { + return IndexOf((T)item!); + } + return -1; + } + + // Returns the index of the first occurrence of a given value in a range of + // this list. The list is searched forwards, starting at index + // index and ending at count number of elements. The + // elements of the list are compared to the given value using the + // Object.Equals method. + // + // This method uses the Array.IndexOf method to perform the + // search. + // + public int IndexOf(T item, int index) + { + if (index > _size) + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException(); + return SegmentedArray.IndexOf(_items, item, index, _size - index); + } + + // Returns the index of the first occurrence of a given value in a range of + // this list. The list is searched forwards, starting at index + // index and upto count number of elements. The + // elements of the list are compared to the given value using the + // Object.Equals method. + // + // This method uses the Array.IndexOf method to perform the + // search. + // + public int IndexOf(T item, int index, int count) + { + if (index > _size) + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException(); + + if (count < 0 || index > _size - count) + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + + return SegmentedArray.IndexOf(_items, item, index, count); + } + + public int IndexOf(T item, int index, int count, IEqualityComparer? comparer) + { + if (index > _size) + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException(); + + if (count < 0 || index > _size - count) + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + + return SegmentedArray.IndexOf(_items, item, index, count, comparer); + } + + // Inserts an element into this list at a given index. The size of the list + // is increased by one. If required, the capacity of the list is doubled + // before inserting the new element. + // + public void Insert(int index, T item) + { + // Note that insertions at the end are legal. + if ((uint)index > (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert); + } + if (_size == _items.Length) + Grow(_size + 1); + if (index < _size) + { + SegmentedArray.Copy(_items, index, _items, index + 1, _size - index); + } + _items[index] = item; + _size++; + _version++; + } + + void IList.Insert(int index, object? item) + { + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(item, ExceptionArgument.item); + + try + { + Insert(index, (T)item!); + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(item, typeof(T)); + } + } + + // Inserts the elements of the given collection at a given index. If + // required, the capacity of the list is increased to twice the previous + // capacity or the new size, whichever is larger. Ranges may be added + // to the end of the list by setting index to the SegmentedList's size. + // + public void InsertRange(int index, IEnumerable collection) + { + if (collection == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + + if ((uint)index > (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException(); + } + + if (collection is ICollection c) + { + var count = c.Count; + if (count > 0) + { + if (_items.Length - _size < count) + { + Grow(checked(_size + count)); + } + if (index < _size) + { + SegmentedArray.Copy(_items, index, _items, index + count, _size - index); + } + + // If we're inserting a SegmentedList into itself, we want to be able to deal with that. + if (this == c) + { + // Copy first part of _items to insert location + SegmentedArray.Copy(_items, 0, _items, index, index); + // Copy last part of _items back to inserted location + SegmentedArray.Copy(_items, index + count, _items, index * 2, _size - index); + } + else if (c is SegmentedList list) + { + SegmentedArray.Copy(list._items, 0, _items, index, list.Count); + } + else if (c is SegmentedArray array) + { + SegmentedArray.Copy(array, 0, _items, index, array.Length); + } + else + { + var targetIndex = index; + foreach (var item in c) + _items[targetIndex++] = item; + } + + _size += count; + _version++; + } + } + else + { + using var en = collection.GetEnumerator(); + while (en.MoveNext()) + { + Insert(index++, en.Current); + } + } + } + + // Returns the index of the last occurrence of a given value in a range of + // this list. The list is searched backwards, starting at the end + // and ending at the first element in the list. The elements of the list + // are compared to the given value using the Object.Equals method. + // + // This method uses the Array.LastIndexOf method to perform the + // search. + // + public int LastIndexOf(T item) + { + if (_size == 0) + { // Special case for empty list + return -1; + } + else + { + return LastIndexOf(item, _size - 1, _size); + } + } + + // Returns the index of the last occurrence of a given value in a range of + // this list. The list is searched backwards, starting at index + // index and ending at the first element in the list. The + // elements of the list are compared to the given value using the + // Object.Equals method. + // + // This method uses the Array.LastIndexOf method to perform the + // search. + // + public int LastIndexOf(T item, int index) + { + if (index >= _size) + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + return LastIndexOf(item, index, index + 1); + } + + // Returns the index of the last occurrence of a given value in a range of + // this list. The list is searched backwards, starting at index + // index and upto count elements. The elements of + // the list are compared to the given value using the Object.Equals + // method. + // + // This method uses the Array.LastIndexOf method to perform the + // search. + // + public int LastIndexOf(T item, int index, int count) + { + if (_size == 0) + { + // Special case for empty list + return -1; + } + + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (index >= _size) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection); + } + + if (count > index + 1) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection); + } + + return SegmentedArray.LastIndexOf(_items, item, index, count); + } + + public int LastIndexOf(T item, int index, int count, IEqualityComparer? comparer) + { + if (_size == 0) + { + // Special case for empty list + return -1; + } + + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (index >= _size) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection); + } + + if (count > index + 1) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection); + } + + return SegmentedArray.LastIndexOf(_items, item, index, count, comparer); + } + + // Removes the first occurrence of the given element, if found. + // The size of the list is decreased by one if successful. + public bool Remove(T item) + { + var index = IndexOf(item); + if (index >= 0) + { + RemoveAt(index); + return true; + } + + return false; + } + + void IList.Remove(object? item) + { + if (IsCompatibleObject(item)) + { + Remove((T)item!); + } + } + + // This method removes all items which matches the predicate. + // The complexity is O(n). + public int RemoveAll(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + var freeIndex = 0; // the first free slot in items array + + // Find the first item which needs to be removed. + while (freeIndex < _size && !match(_items[freeIndex])) + freeIndex++; + if (freeIndex >= _size) + return 0; + + var current = freeIndex + 1; + while (current < _size) + { + // Find the first item which needs to be kept. + while (current < _size && match(_items[current])) + current++; + + if (current < _size) + { + // copy item to the free slot. + _items[freeIndex++] = _items[current++]; + } + } + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + SegmentedArray.Clear(_items, freeIndex, _size - freeIndex); // Clear the elements so that the gc can reclaim the references. + } + + var result = _size - freeIndex; + _size = freeIndex; + _version++; + return result; + } + + // Removes the element at the given index. The size of the list is + // decreased by one. + public void RemoveAt(int index) + { + if ((uint)index >= (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + _size--; + if (index < _size) + { + SegmentedArray.Copy(_items, index + 1, _items, index, _size - index); + } +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + _items[_size] = default!; + } + _version++; + } + + // Removes a range of elements from this list. + public void RemoveRange(int index, int count) + { + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_size - index < count) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (count > 0) + { + _size -= count; + if (index < _size) + { + SegmentedArray.Copy(_items, index + count, _items, index, _size - index); + } + + _version++; +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + SegmentedArray.Clear(_items, _size, count); + } + } + } + + // Reverses the elements in this list. + public void Reverse() + => Reverse(0, Count); + + // Reverses the elements in a range of this list. Following a call to this + // method, an element in the range given by index and count + // which was previously located at index i will now be located at + // index index + (index + count - i - 1). + // + public void Reverse(int index, int count) + { + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_size - index < count) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (count > 1) + { + SegmentedArray.Reverse(_items, index, count); + } + _version++; + } + + // Sorts the elements in this list. Uses the default comparer and + // Array.Sort. + public void Sort() + => Sort(0, Count, null); + + // Sorts the elements in this list. Uses Array.Sort with the + // provided comparer. + public void Sort(IComparer? comparer) + => Sort(0, Count, comparer); + + // Sorts the elements in a section of this list. The sort compares the + // elements to each other using the given IComparer interface. If + // comparer is null, the elements are compared to each other using + // the IComparable interface, which in that case must be implemented by all + // elements of the list. + // + // This method uses the Array.Sort method to sort the elements. + // + public void Sort(int index, int count, IComparer? comparer) + { + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_size - index < count) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (count > 1) + { + SegmentedArray.Sort(_items, index, count, comparer); + } + _version++; + } + + public void Sort(Comparison comparison) + { + if (comparison == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); + } + + if (_size > 1) + { + var segment = new SegmentedArraySegment(_items, 0, _size); + SegmentedArraySortHelper.Sort(segment, comparison); + } + _version++; + } + + // ToArray returns an array containing the contents of the SegmentedList. + // This requires copying the SegmentedList, which is an O(n) operation. + public T[] ToArray() + { + if (_size == 0) + { + return Array.Empty(); + } + + var array = new T[_size]; + SegmentedArray.Copy(_items, array, _size); + return array; + } + + // Sets the capacity of this list to the size of the list. This method can + // be used to minimize a list's memory overhead once it is known that no + // new elements will be added to the list. To completely clear a list and + // release all memory referenced by the list, execute the following + // statements: + // + // list.Clear(); + // list.TrimExcess(); + // + public void TrimExcess() + { + var threshold = (int)(_items.Length * 0.9); + if (_size < threshold) + { + Capacity = _size; + } + } + + public bool TrueForAll(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + for (var i = 0; i < _size; i++) + { + if (!match(_items[i])) + { + return false; + } + } + return true; + } + + public struct Enumerator : IEnumerator, IEnumerator + { + private readonly SegmentedList _list; + private int _index; + private readonly int _version; + private T? _current; + + internal Enumerator(SegmentedList list) + { + _list = list; + _index = 0; + _version = list._version; + _current = default; + } + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + var localList = _list; + + if (_version == localList._version && ((uint)_index < (uint)localList._size)) + { + _current = localList._items[_index]; + _index++; + return true; + } + return MoveNextRare(); + } + + private bool MoveNextRare() + { + if (_version != _list._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = _list._size + 1; + _current = default; + return false; + } + + public readonly T Current => _current!; + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || _index == _list._size + 1) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + return Current; + } + } + + void IEnumerator.Reset() + { + if (_version != _list._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _current = default; + } + } + + internal TestAccessor GetTestAccessor() + => new TestAccessor(this); + + internal readonly struct TestAccessor(SegmentedList instance) + { + public ref SegmentedArray Items => ref instance._items; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Collection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Collection.cs new file mode 100755 index 00000000000..4885f9d0d14 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Collection.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static partial class SpecializedCollections + { + private static partial class Empty + { + internal class Collection : Enumerable, ICollection + { + public static readonly ICollection Instance = new Collection(); + + protected Collection() + { + } + + public void Add(T item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(T item) + { + return false; + } + + public void CopyTo(T[] array, int arrayIndex) + { + } + + public int Count => 0; + + public bool IsReadOnly => true; + + public bool Remove(T item) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Dictionary.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Dictionary.cs new file mode 100755 index 00000000000..98164c6c405 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Dictionary.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Dictionary +#nullable disable + // Note: if the interfaces we implement weren't oblivious, then we'd warn about the `[MaybeNullWhen(false)] out TValue value` parameter below + // We can remove this once `IDictionary` is annotated with `[MaybeNullWhen(false)]` + : Collection>, IDictionary, IReadOnlyDictionary +#nullable enable + where TKey : notnull + { + public static new readonly Dictionary Instance = new(); + + private Dictionary() + { + } + + public void Add(TKey key, TValue value) + { + throw new NotSupportedException(); + } + + public bool ContainsKey(TKey key) + { + return false; + } + + public ICollection Keys + { + get + { + return Collection.Instance; + } + } + + IEnumerable IReadOnlyDictionary.Keys => Keys; + IEnumerable IReadOnlyDictionary.Values => Values; + + public bool Remove(TKey key) + { + throw new NotSupportedException(); + } + + public bool TryGetValue(TKey key, [MaybeNullWhen(returnValue: false)] out TValue value) + { + value = default!; + return false; + } + + public ICollection Values + { + get + { + return Collection.Instance; + } + } + + public TValue this[TKey key] + { + get + { + throw new NotSupportedException(); + } + + set + { + throw new NotSupportedException(); + } + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Enumerable.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Enumerable.cs new file mode 100755 index 00000000000..9db162535cd --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Enumerable.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Enumerable : IEnumerable + { + // PERF: cache the instance of enumerator. + // accessing a generic static field is kinda slow from here, + // but since empty enumerables are singletons, there is no harm in having + // one extra instance field + private readonly IEnumerator _enumerator = Enumerator.Instance; + + public IEnumerator GetEnumerator() + { + return _enumerator; + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Enumerator.cs new file mode 100755 index 00000000000..dfb79c7028b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Enumerator.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Enumerator : IEnumerator + { + public static readonly IEnumerator Instance = new Enumerator(); + + protected Enumerator() + { + } + + public object? Current => throw new InvalidOperationException(); + + public bool MoveNext() + { + return false; + } + + public void Reset() + { + throw new InvalidOperationException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Enumerator`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Enumerator`1.cs new file mode 100755 index 00000000000..3e253bae606 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Enumerator`1.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Enumerator : Enumerator, IEnumerator + { + public static new readonly IEnumerator Instance = new Enumerator(); + + protected Enumerator() + { + } + + public new T Current => throw new InvalidOperationException(); + + public void Dispose() + { + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.List.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.List.cs new file mode 100755 index 00000000000..57e4cdd8d8e --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.List.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal static class BoxedImmutableArray + { + // empty boxed immutable array + public static readonly IReadOnlyList Instance = ImmutableArray.Empty; + } + + internal class List : Collection, IList, IReadOnlyList + { + public static new readonly List Instance = new(); + + protected List() + { + } + + public int IndexOf(T item) + { + return -1; + } + + public void Insert(int index, T item) + { + throw new NotSupportedException(); + } + + public void RemoveAt(int index) + { + throw new NotSupportedException(); + } + + public T this[int index] + { + get + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + set + { + throw new NotSupportedException(); + } + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Set.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Set.cs new file mode 100755 index 00000000000..be9f0dd34d9 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.Set.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Linq; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Set : Collection, ISet, IReadOnlySet + { + public static new readonly Set Instance = new(); + + protected Set() + { + } + + public new bool Add(T item) + { + throw new NotSupportedException(); + } + + public void ExceptWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public void IntersectWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public bool IsProperSubsetOf(IEnumerable other) + { + return other.Any(); + } + + public bool IsProperSupersetOf(IEnumerable other) + { + return false; + } + + public bool IsSubsetOf(IEnumerable other) + { + return true; + } + + public bool IsSupersetOf(IEnumerable other) + { + return !other.Any(); + } + + public bool Overlaps(IEnumerable other) + { + return false; + } + + public bool SetEquals(IEnumerable other) + { + return !other.Any(); + } + + public void SymmetricExceptWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public void UnionWith(IEnumerable other) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.cs new file mode 100755 index 00000000000..84fcd89e5f2 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Empty.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private static partial class Empty + { + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Collection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Collection.cs new file mode 100755 index 00000000000..f9a15d99ab9 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Collection.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private static partial class ReadOnly + { + internal class Collection : Enumerable, ICollection + where TUnderlying : ICollection + { + public Collection(TUnderlying underlying) + : base(underlying) + { + } + + public void Add(T item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(T item) + { + return this.Underlying.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + this.Underlying.CopyTo(array, arrayIndex); + } + + public int Count + { + get + { + return this.Underlying.Count; + } + } + + public bool IsReadOnly => true; + + public bool Remove(T item) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`1.cs new file mode 100755 index 00000000000..54741cb4ed6 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`1.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class ReadOnly + { + internal class Enumerable : IEnumerable + where TUnderlying : IEnumerable + { + protected readonly TUnderlying Underlying; + + public Enumerable(TUnderlying underlying) + { + this.Underlying = underlying; + } + + public IEnumerator GetEnumerator() + { + return this.Underlying.GetEnumerator(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`2.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`2.cs new file mode 100755 index 00000000000..de762618c35 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`2.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class ReadOnly + { + internal class Enumerable : Enumerable, IEnumerable + where TUnderlying : IEnumerable + { + public Enumerable(TUnderlying underlying) + : base(underlying) + { + } + + public new IEnumerator GetEnumerator() + { + return this.Underlying.GetEnumerator(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Set.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Set.cs new file mode 100755 index 00000000000..1a52178fc55 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.ReadOnly.Set.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class ReadOnly + { + internal class Set : Collection, ISet, IReadOnlySet + where TUnderlying : ISet + { + public Set(TUnderlying underlying) + : base(underlying) + { + } + + public new bool Add(T item) + { + throw new NotSupportedException(); + } + + public void ExceptWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public void IntersectWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public bool IsProperSubsetOf(IEnumerable other) + { + return Underlying.IsProperSubsetOf(other); + } + + public bool IsProperSupersetOf(IEnumerable other) + { + return Underlying.IsProperSupersetOf(other); + } + + public bool IsSubsetOf(IEnumerable other) + { + return Underlying.IsSubsetOf(other); + } + + public bool IsSupersetOf(IEnumerable other) + { + return Underlying.IsSupersetOf(other); + } + + public bool Overlaps(IEnumerable other) + { + return Underlying.Overlaps(other); + } + + public bool SetEquals(IEnumerable other) + { + return Underlying.SetEquals(other); + } + + public void SymmetricExceptWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public void UnionWith(IEnumerable other) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Singleton.Collection`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Singleton.Collection`1.cs new file mode 100755 index 00000000000..17e8e2709f2 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Singleton.Collection`1.cs @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static partial class SpecializedCollections + { + private static partial class Singleton + { + internal sealed class List : IReadOnlyList, IList, IReadOnlyCollection + { + private readonly T _loneValue; + + public List(T value) + { + _loneValue = value; + } + + public void Add(T item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(T item) + { + return EqualityComparer.Default.Equals(_loneValue, item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + array[arrayIndex] = _loneValue; + } + + public int Count => 1; + + public bool IsReadOnly => true; + + public bool Remove(T item) + { + throw new NotSupportedException(); + } + + public IEnumerator GetEnumerator() + { + return new Enumerator(_loneValue); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public T this[int index] + { + get + { + if (index != 0) + { + throw new IndexOutOfRangeException(); + } + + return _loneValue; + } + + set + { + throw new NotSupportedException(); + } + } + + public int IndexOf(T item) + { + if (Equals(_loneValue, item)) + { + return 0; + } + + return -1; + } + + public void Insert(int index, T item) + { + throw new NotSupportedException(); + } + + public void RemoveAt(int index) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Singleton.Enumerator`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Singleton.Enumerator`1.cs new file mode 100755 index 00000000000..d061ebd4039 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.Singleton.Enumerator`1.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static partial class SpecializedCollections + { + private static partial class Singleton + { + internal class Enumerator : IEnumerator + { + private readonly T _loneValue; + private bool _moveNextCalled; + + public Enumerator(T value) + { + _loneValue = value; + _moveNextCalled = false; + } + + public T Current => _loneValue; + + object? IEnumerator.Current => _loneValue; + + public void Dispose() + { + } + + public bool MoveNext() + { + if (!_moveNextCalled) + { + _moveNextCalled = true; + return true; + } + + return false; + } + + public void Reset() + { + _moveNextCalled = false; + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.cs new file mode 100755 index 00000000000..a37cac03076 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/Specialized/SpecializedCollections.cs @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static partial class SpecializedCollections + { + public static IEnumerator EmptyEnumerator() + { + return Empty.Enumerator.Instance; + } + + public static IEnumerable EmptyEnumerable() + { + return Empty.List.Instance; + } + + public static ICollection EmptyCollection() + { + return Empty.List.Instance; + } + + public static IList EmptyList() + { + return Empty.List.Instance; + } + + public static IReadOnlyList EmptyBoxedImmutableArray() + { + return Empty.BoxedImmutableArray.Instance; + } + + public static IReadOnlyList EmptyReadOnlyList() + { + return Empty.List.Instance; + } + + public static ISet EmptySet() + { + return Empty.Set.Instance; + } + + public static IReadOnlySet EmptyReadOnlySet() + { + return Empty.Set.Instance; + } + + public static IDictionary EmptyDictionary() + where TKey : notnull + { + return Empty.Dictionary.Instance; + } + + public static IReadOnlyDictionary EmptyReadOnlyDictionary() + where TKey : notnull + { + return Empty.Dictionary.Instance; + } + + public static IEnumerable SingletonEnumerable(T value) + { + return new Singleton.List(value); + } + + public static ICollection SingletonCollection(T value) + { + return new Singleton.List(value); + } + + public static IEnumerator SingletonEnumerator(T value) + { + return new Singleton.Enumerator(value); + } + + public static IReadOnlyList SingletonReadOnlyList(T value) + { + return new Singleton.List(value); + } + + public static IList SingletonList(T value) + { + return new Singleton.List(value); + } + + public static IEnumerable ReadOnlyEnumerable(IEnumerable values) + { + return new ReadOnly.Enumerable, T>(values); + } + + public static ICollection ReadOnlyCollection(ICollection? collection) + { + return collection == null || collection.Count == 0 + ? EmptyCollection() + : new ReadOnly.Collection, T>(collection); + } + + public static ISet ReadOnlySet(ISet? set) + { + return set == null || set.Count == 0 + ? EmptySet() + : new ReadOnly.Set, T>(set); + } + + public static IReadOnlySet StronglyTypedReadOnlySet(ISet? set) + { + return set == null || set.Count == 0 + ? EmptyReadOnlySet() + : new ReadOnly.Set, T>(set); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/TemporaryArrayExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/TemporaryArrayExtensions.cs new file mode 100755 index 00000000000..df57c3f899b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/TemporaryArrayExtensions.cs @@ -0,0 +1,158 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Shared.Collections +{ + internal static class TemporaryArrayExtensions + { + /// + /// Gets a mutable reference to a stored in a using variable. + /// + /// + /// This supporting method allows , a non-copyable + /// implementing , to be used with using statements while still allowing them to + /// be passed by reference in calls. The following two calls are equivalent: + /// + /// + /// using var array = TemporaryArray<T>.Empty; + /// + /// // Using the 'Unsafe.AsRef' method + /// Method(ref Unsafe.AsRef(in array)); + /// + /// // Using this helper method + /// Method(ref array.AsRef()); + /// + /// + /// ⚠ Do not move or rename this method without updating the corresponding + /// RS0049 + /// analyzer. + /// + /// The type of element stored in the temporary array. + /// A read-only reference to a temporary array which is part of a using statement. + /// A mutable reference to the temporary array. + public static ref TemporaryArray AsRef(this in TemporaryArray array) +#pragma warning disable RS0042 // https://github.com/dotnet/roslyn-analyzers/issues/7128 + => ref Unsafe.AsRef(in array); +#pragma warning restore RS0042 + + public static bool Any(this in TemporaryArray array, Func predicate) + { + foreach (var item in array) + { + if (predicate(item)) + return true; + } + + return false; + } + + public static bool All(this in TemporaryArray array, Func predicate) + { + foreach (var item in array) + { + if (!predicate(item)) + return false; + } + + return true; + } + + private static void ThrowSequenceContainsMoreThanOneElement() + => new[] { 0, 0 }.Single(); + + public static T? SingleOrDefault(this in TemporaryArray array, Func predicate) + { + var first = true; + T? result = default; + foreach (var item in array) + { + if (predicate(item)) + { + if (!first) + { + ThrowSequenceContainsMoreThanOneElement(); + } + + first = false; + result = item; + } + } + + return result; + } + + public static T? SingleOrDefault(this in TemporaryArray array, Func predicate, TArg arg) + { + var first = true; + T? result = default; + foreach (var item in array) + { + if (predicate(item, arg)) + { + if (!first) + { + ThrowSequenceContainsMoreThanOneElement(); + } + + first = false; + result = item; + } + } + + return result; + } + + public static T? FirstOrDefault(this in TemporaryArray array) + => array.Count > 0 ? array[0] : default; + + public static T? FirstOrDefault(this in TemporaryArray array, Func predicate, TArg arg) + { + foreach (var item in array) + { + if (predicate(item, arg)) + return item; + } + + return default; + } + + public static int IndexOf(this in TemporaryArray array, Func predicate, TArg arg) + { + var index = 0; + foreach (var item in array) + { + if (predicate(item, arg)) + return index; + + index++; + } + + return -1; + } + + public static void AddIfNotNull(this ref TemporaryArray array, T? value) + where T : struct + { + if (value is not null) + { + array.Add(value.Value); + } + } + + public static void AddIfNotNull(this ref TemporaryArray array, T? value) + where T : class + { + if (value is not null) + { + array.Add(value); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/TemporaryArray`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/TemporaryArray`1.cs new file mode 100755 index 00000000000..8f1856e4a58 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/net9.0/TemporaryArray`1.cs @@ -0,0 +1,488 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Shared.Collections +{ + /// + /// Provides temporary storage for a collection of elements. This type is optimized for handling of small + /// collections, particularly for cases where the collection will eventually be discarded or used to produce an + /// . + /// + /// + /// This type stores small collections on the stack, with the ability to transition to dynamic storage if/when + /// larger number of elements are added. + /// + /// The type of elements stored in the collection. + [NonCopyable] + [StructLayout(LayoutKind.Sequential)] + internal struct TemporaryArray : IDisposable + { + /// + /// The number of elements the temporary can store inline. Storing more than this many elements requires the + /// array transition to dynamic storage. + /// + private const int InlineCapacity = 4; + + /// + /// The first inline element. + /// + /// + /// This field is only used when is . In other words, this type + /// stores elements inline or stores them in , but does not use both approaches + /// at the same time. + /// + private T _item0; + + /// + /// The second inline element. + /// + /// + private T _item1; + + /// + /// The third inline element. + /// + /// + private T _item2; + + /// + /// The fourth inline element. + /// + /// + private T _item3; + + /// + /// The number of inline elements held in the array. This value is only used when is + /// . + /// + private int _count; + + /// + /// A builder used for dynamic storage of collections that may exceed the limit for inline elements. + /// + /// + /// This field is initialized to non- the first time the + /// needs to store more than four elements. From that point, is used instead of inline + /// elements, even if items are removed to make the result smaller than four elements. + /// + private ArrayBuilder? _builder; + + private TemporaryArray(in TemporaryArray array) + { + // Intentional copy used for creating an enumerator +#pragma warning disable RS0042 // Do not copy value + this = array; +#pragma warning restore RS0042 // Do not copy value + } + + public static TemporaryArray GetInstance(int capacity) + { + // Capacity <= 4 is already supported by the Empty array value. so can just return that without allocating anything. + if (capacity <= InlineCapacity) + return Empty; + + return new TemporaryArray() + { + _builder = ArrayBuilder.GetInstance(capacity) + }; + } + + public static TemporaryArray Empty => default; + + public readonly int Count => _builder?.Count ?? _count; + + public T this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get + { + if (_builder is not null) + return _builder[index]; + + if ((uint)index >= _count) + ThrowIndexOutOfRangeException(); + + return index switch + { + 0 => _item0, + 1 => _item1, + 2 => _item2, + _ => _item3, + }; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + if (_builder is not null) + { + _builder[index] = value; + return; + } + + if ((uint)index >= _count) + ThrowIndexOutOfRangeException(); + + _ = index switch + { + 0 => _item0 = value, + 1 => _item1 = value, + 2 => _item2 = value, + _ => _item3 = value, + }; + } + } + + public void Dispose() + { + // Return _builder to the pool if necessary. There is no need to release inline storage since the majority + // case for this type is stack-allocated storage and the GC is already able to reclaim objects from the + // stack after the last use of a reference to them. + Interlocked.Exchange(ref _builder, null)?.Free(); + } + + public void Add(T item) + { + if (_builder is not null) + { + _builder.Add(item); + } + else if (_count < InlineCapacity) + { + // Increase _count before assigning a value since the indexer has a bounds check. + _count++; + this[_count - 1] = item; + } + else + { + Debug.Assert(_count == InlineCapacity); + MoveInlineToBuilder(); + _builder.Add(item); + } + } + + public void AddRange(ImmutableArray items) + { + if (_builder is not null) + { + _builder.AddRange(items); + } + else if (_count + items.Length <= InlineCapacity) + { + foreach (var item in items) + { + // Increase _count before assigning values since the indexer has a bounds check. + _count++; + this[_count - 1] = item; + } + } + else + { + MoveInlineToBuilder(); + _builder.AddRange(items); + } + } + + public void AddRange(in TemporaryArray items) + { + if (_count + items.Count <= InlineCapacity) + { + foreach (var item in items) + { + // Increase _count before assigning values since the indexer has a bounds check. + _count++; + this[_count - 1] = item; + } + } + else + { + MoveInlineToBuilder(); + foreach (var item in items) + _builder.Add(item); + } + } + + public void Clear() + { + if (_builder is not null) + { + // Keep using a builder even if we now fit in inline storage to avoid churn in the object pools. + _builder.Clear(); + } + else + { + this = Empty; + } + } + + public T RemoveLast() + { + var count = this.Count; + + var last = this[count - 1]; + this[count - 1] = default!; + + if (_builder != null) + { + _builder.Count--; + } + else + { + _count--; + } + + return last; + } + + public readonly bool Contains(T value, IEqualityComparer? equalityComparer = null) + => IndexOf(value, equalityComparer) >= 0; + + public readonly int IndexOf(T value, IEqualityComparer? equalityComparer = null) + { + equalityComparer ??= EqualityComparer.Default; + + if (_builder != null) + return _builder.IndexOf(value, equalityComparer); + + var index = 0; + foreach (var v in this) + { + if (equalityComparer.Equals(v, value)) + return index; + + index++; + } + + return -1; + } + + public readonly Enumerator GetEnumerator() + { + return new Enumerator(in this); + } + + /// + /// Create an with the elements currently held in the temporary array, and clear the + /// array. + /// + public OneOrMany ToOneOrManyAndClear() + { + switch (this.Count) + { + case 0: + return OneOrMany.Empty; + case 1: + var result = OneOrMany.Create(this[0]); + this.Clear(); + return result; + default: + return new(this.ToImmutableAndClear()); + } + } + + /// + /// Create an with the elements currently held in the temporary array, and clear + /// the array. + /// + public ImmutableArray ToImmutableAndClear() + { + if (_builder is not null) + { + return _builder.ToImmutableAndClear(); + } + else + { + var result = _count switch + { + 0 => ImmutableArray.Empty, + 1 => ImmutableArray.Create(_item0), + 2 => ImmutableArray.Create(_item0, _item1), + 3 => ImmutableArray.Create(_item0, _item1, _item2), + 4 => ImmutableArray.Create(_item0, _item1, _item2, _item3), + _ => throw ExceptionUtilities.Unreachable(), + }; + + // Since _builder is null on this path, we can overwrite the whole structure to Empty to reset all + // inline elements to their default value and the _count to 0. + this = Empty; + + return result; + } + } + + /// + /// Transitions the current from inline storage to dynamic storage storage. An + /// instance is taken from the shared pool, and all elements currently in inline + /// storage are added to it. After this point, dynamic storage will be used instead of inline storage. + /// + [MemberNotNull(nameof(_builder))] + private void MoveInlineToBuilder() + { + Debug.Assert(_builder is null); + + var builder = ArrayBuilder.GetInstance(); + for (var i = 0; i < _count; i++) + { + builder.Add(this[i]); + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + this[i] = default!; + } + } + + _count = 0; + _builder = builder; + } + + public void ReverseContents() + { + if (_builder is not null) + { + _builder.ReverseContents(); + return; + } + + switch (_count) + { + case <= 1: + // if we have one or zero items, we're already reversed. + return; + case 2: + (_item0, _item1) = (_item1, _item0); + return; + case 3: + // Just need to swap the first and last items. The middle one stays where it is. + (_item0, _item2) = (_item2, _item0); + return; + case 4: + (_item0, _item1, _item2, _item3) = (_item3, _item2, _item1, _item0); + return; + default: + throw ExceptionUtilities.Unreachable(); + } + } + + public void Sort(Comparison compare) + { + if (_builder is not null) + { + _builder.Sort(compare); + return; + } + + switch (_count) + { + case <= 1: + return; + case 2: + if (compare(_item0, _item1) > 0) + { + (_item0, _item1) = (_item1, _item0); + } + return; + case 3: + if (compare(_item0, _item1) > 0) + (_item0, _item1) = (_item1, _item0); + + if (compare(_item1, _item2) > 0) + { + (_item1, _item2) = (_item2, _item1); + + if (compare(_item0, _item1) > 0) + (_item0, _item1) = (_item1, _item0); + } + return; + case 4: + + if (compare(_item0, _item1) > 0) + (_item0, _item1) = (_item1, _item0); + + if (compare(_item2, _item3) > 0) + (_item2, _item3) = (_item3, _item2); + + if (compare(_item0, _item2) > 0) + (_item0, _item2) = (_item2, _item0); + + if (compare(_item1, _item3) > 0) + (_item1, _item3) = (_item3, _item1); + + if (compare(_item1, _item2) > 0) + (_item1, _item2) = (_item2, _item1); + + return; + default: + throw ExceptionUtilities.Unreachable(); + } + } + + /// + /// Throws . + /// + /// + /// This helper improves the ability of the JIT to inline callers. + /// + private static void ThrowIndexOutOfRangeException() + => throw new IndexOutOfRangeException(); + + [NonCopyable] + public struct Enumerator + { + private readonly TemporaryArray _array; + + private T _current; + private int _nextIndex; + + public Enumerator(in TemporaryArray array) + { + // Enumerate a copy of the original + _array = new TemporaryArray(in array); + _current = default!; + _nextIndex = 0; + } + + public T Current => _current; + + public bool MoveNext() + { + if (_nextIndex >= _array.Count) + { + return false; + } + else + { + _current = _array[_nextIndex]; + _nextIndex++; + return true; + } + } + } + + internal static class TestAccessor + { + public static int InlineCapacity => TemporaryArray.InlineCapacity; + + public static bool HasDynamicStorage(in TemporaryArray array) + => array._builder is not null; + + public static int InlineCount(in TemporaryArray array) + => array._count; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/.editorconfig b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/.editorconfig new file mode 100755 index 00000000000..e10491047f5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/.editorconfig @@ -0,0 +1,18 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +# We don't want any analyzer diagnostics to be reported for people consuming this as a source package. +dotnet_analyzer_diagnostic.severity = none + +generated_code = true + +# The above configurations don't apply to compiler warnings. Requiring all params to be documented +# is not something we require for this project, so suppressing it directly here. +dotnet_diagnostic.CS1573.severity = none + +# As above, we need to specifically disable compiler warnings that we don't want to break downstream +# builds +dotnet_diagnostic.IDE0005.severity = none \ No newline at end of file diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Extensions/ICollectionExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Extensions/ICollectionExtensions.cs new file mode 100755 index 00000000000..b6fd40d078d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Extensions/ICollectionExtensions.cs @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.PooledObjects; + +namespace Microsoft.CodeAnalysis; + +internal static class ICollectionExtensions +{ + public static void RemoveRange(this ICollection collection, IEnumerable? items) + { + if (items != null) + { + foreach (var item in items) + { + collection.Remove(item); + } + } + } + + public static void AddIfNotNull(this ICollection collection, T? value) where T : struct + { + if (value != null) + collection.Add(value.Value); + } + + public static void AddIfNotNull(this ICollection collection, T? value) where T : class + { + if (value != null) + collection.Add(value); + } + + public static void AddRange(this ICollection collection, IEnumerable? values) + { + if (values != null) + { + foreach (var item in values) + { + collection.Add(item); + } + } + } + + public static void AddRange(this ICollection collection, ArrayBuilder? values) + { + if (values != null) + { + foreach (var item in values) + collection.Add(item); + } + } + + public static void AddRange(this ICollection collection, HashSet? values) + { + if (values != null) + { + foreach (var item in values) + collection.Add(item); + } + } + + public static void AddRange(this ICollection collection, Dictionary.KeyCollection? keyCollection) where TKey : notnull + { + if (keyCollection != null) + { + foreach (var key in keyCollection) + collection.Add(key); + } + } + + public static void AddRange(this ICollection collection, ImmutableArray values) + { + if (!values.IsDefault) + { + foreach (var item in values) + { + collection.Add(item); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Extensions/IEnumerableExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Extensions/IEnumerableExtensions.cs new file mode 100755 index 00000000000..0e86991e66d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Extensions/IEnumerableExtensions.cs @@ -0,0 +1,1028 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.PooledObjects; + +namespace Roslyn.Utilities +{ + internal static partial class EnumerableExtensions + { + public static int Count(this IEnumerable source, Func predicate, TArg arg) + { + var count = 0; + foreach (var v in source) + { + if (predicate(v, arg)) + count++; + } + + return count; + } + + public static IEnumerable Do(this IEnumerable source, Action action) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + // perf optimization. try to not use enumerator if possible + if (source is IList list) + { + for (int i = 0, count = list.Count; i < count; i++) + { + action(list[i]); + } + } + else + { + foreach (var value in source) + { + action(value); + } + } + + return source; + } + + public static ImmutableArray ToImmutableArrayOrEmpty(this IEnumerable? items) + { + if (items == null) + { + return ImmutableArray.Create(); + } + + if (items is ImmutableArray array) + { + return array.NullToEmpty(); + } + + return ImmutableArray.CreateRange(items); + } + + public static IReadOnlyList ToBoxedImmutableArray(this IEnumerable? items) + { + if (items is null) + { + return SpecializedCollections.EmptyBoxedImmutableArray(); + } + + if (items is ImmutableArray array) + { + return array.IsDefaultOrEmpty ? SpecializedCollections.EmptyBoxedImmutableArray() : (IReadOnlyList)items; + } + + if (items is ICollection collection && collection.Count == 0) + { + return SpecializedCollections.EmptyBoxedImmutableArray(); + } + + return ImmutableArray.CreateRange(items); + } + + public static ReadOnlyCollection ToReadOnlyCollection(this IEnumerable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return new ReadOnlyCollection(source.ToList()); + } + + public static IEnumerable Concat(this IEnumerable source, T value) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.ConcatWorker(value); + } + + private static IEnumerable ConcatWorker(this IEnumerable source, T value) + { + foreach (var v in source) + { + yield return v; + } + + yield return value; + } + + public static bool SetEquals(this IEnumerable source1, IEnumerable source2, IEqualityComparer? comparer) + { + if (source1 == null) + { + throw new ArgumentNullException(nameof(source1)); + } + + if (source2 == null) + { + throw new ArgumentNullException(nameof(source2)); + } + + return source1.ToSet(comparer).SetEquals(source2); + } + + public static bool SetEquals(this IEnumerable source1, IEnumerable source2) + { + if (source1 == null) + { + throw new ArgumentNullException(nameof(source1)); + } + + if (source2 == null) + { + throw new ArgumentNullException(nameof(source2)); + } + + return source1.ToSet().SetEquals(source2); + } + + public static ISet ToSet(this IEnumerable source, IEqualityComparer? comparer) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return new HashSet(source, comparer); + } + + public static ISet ToSet(this IEnumerable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source as ISet ?? new HashSet(source); + } + + public static IReadOnlyCollection ToCollection(this IEnumerable sequence) + => (sequence is IReadOnlyCollection collection) ? collection : sequence.ToList(); + + public static T? FirstOrDefault(this IEnumerable source, Func predicate, TArg arg) + { + foreach (var item in source) + { + if (predicate(item, arg)) + return item; + } + + return default; + } + + public static bool Any(this IEnumerable source, Func predicate, TArg arg) + { + foreach (var item in source) + { + if (predicate(item, arg)) + return true; + } + + return false; + } + + public static T? FirstOrNull(this IEnumerable source) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.Cast().FirstOrDefault(); + } + + public static T? FirstOrNull(this IEnumerable source, Func predicate) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (predicate == null) + { + throw new ArgumentNullException(nameof(predicate)); + } + + return source.Cast().FirstOrDefault(static (v, predicate) => predicate(v!.Value), predicate); + } + + public static T? FirstOrNull(this IEnumerable source, Func predicate, TArg arg) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (predicate == null) + { + throw new ArgumentNullException(nameof(predicate)); + } + + return source.Cast().FirstOrDefault(static (v, arg) => arg.predicate(v!.Value, arg.arg), (predicate, arg)); + } + + public static T? LastOrNull(this IEnumerable source) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.Cast().LastOrDefault(); + } + + public static T? SingleOrNull(this IEnumerable source, Func predicate) + where T : struct + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return source.Cast().SingleOrDefault(v => predicate(v!.Value)); + } + + public static bool IsSingle(this IEnumerable list) + { + using var enumerator = list.GetEnumerator(); + return enumerator.MoveNext() && !enumerator.MoveNext(); + } + + public static bool IsEmpty(this IEnumerable source) + { + if (source is IReadOnlyCollection readOnlyCollection) + { + return readOnlyCollection.Count == 0; + } + + if (source is ICollection genericCollection) + { + return genericCollection.Count == 0; + } + + if (source is ICollection collection) + { + return collection.Count == 0; + } + + if (source is string str) + { + return str.Length == 0; + } + + foreach (var _ in source) + { + return false; + } + + return true; + } + + public static bool IsEmpty(this IReadOnlyCollection source) + { + return source.Count == 0; + } + + public static bool IsEmpty(this ICollection source) + { + return source.Count == 0; + } + + public static bool IsEmpty(this string source) + { + return source.Length == 0; + } + + /// + /// This method is necessary to avoid an ambiguity between and . + /// + public static bool IsEmpty(this T[] source) + { + return source.Length == 0; + } + + /// + /// This method is necessary to avoid an ambiguity between and . + /// + public static bool IsEmpty(this List source) + { + return source.Count == 0; + } + + private static readonly Func s_notNullTest = x => x != null; + + public static IEnumerable WhereNotNull(this IEnumerable source) + where T : class + { + if (source == null) + { + return SpecializedCollections.EmptyEnumerable(); + } + + return source.Where((Func)s_notNullTest)!; + } + + public static ImmutableArray WhereAsArray(this IEnumerable values, Func predicate, TArg arg) + { + var result = ArrayBuilder.GetInstance(); + + foreach (var value in values) + { + if (predicate(value, arg)) + result.Add(value); + } + + return result.ToImmutableAndFree(); + } + + public static T[] AsArray(this IEnumerable source) + => source as T[] ?? source.ToArray(); + + public static ImmutableArray SelectAsArray(this IEnumerable? source, Func selector) + { + if (source == null) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + builder.AddRange(source.Select(selector)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectAsArray(this IEnumerable? source, Func selector) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + + int index = 0; + foreach (var element in source) + { + builder.Add(selector(element, index)); + index++; + } + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectAsArray(this IReadOnlyCollection? source, Func selector) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = new TResult[source.Count]; + var index = 0; + foreach (var item in source) + { + builder[index] = selector(item); + index++; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + public static ImmutableArray SelectAsArray(this IReadOnlyCollection? source, Func selector, TArg arg) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = new TResult[source.Count]; + var index = 0; + foreach (var item in source) + { + builder[index] = selector(item, arg); + index++; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + public static ImmutableArray SelectManyAsArray(this IEnumerable? source, Func> selector) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in source) + builder.AddRange(selector(item)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectManyAsArray(this IEnumerable? source, Func> selector, TArg arg) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in source) + builder.AddRange(selector(item, arg)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectManyAsArray(this IReadOnlyCollection? source, Func> selector) + { + if (source == null) + return ImmutableArray.Empty; + + // Basic heuristic. Assume each element in the source adds one item to the result. + var builder = ArrayBuilder.GetInstance(source.Count); + foreach (var item in source) + builder.AddRange(selector(item)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectManyAsArray(this IReadOnlyCollection? source, Func> selector, TArg arg) + { + if (source == null) + return ImmutableArray.Empty; + + // Basic heuristic. Assume each element in the source adds one item to the result. + var builder = ArrayBuilder.GetInstance(source.Count); + foreach (var item in source) + builder.AddRange(selector(item, arg)); + + return builder.ToImmutableAndFree(); + } + + public static ImmutableArray SelectManyAsArray(this IEnumerable? source, Func> selector) + { + if (source == null) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in source) + selector(item).AddRangeTo(builder); + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps an immutable array through a function that returns ValueTask, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this IEnumerable source, Func> selector) + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.Add(await selector(item).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps an immutable array through a function that returns ValueTask, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this IEnumerable source, Func> selector, CancellationToken cancellationToken) + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.Add(await selector(item, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps an immutable array through a function that returns ValueTask, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this IEnumerable source, Func> selector, TArg arg, CancellationToken cancellationToken) + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.Add(await selector(item, arg, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + + public static async ValueTask> SelectManyAsArrayAsync(this IEnumerable source, Func>> selector, TArg arg, CancellationToken cancellationToken) + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.AddRange(await selector(item, arg, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + + public static async ValueTask> SelectManyInParallelAsync( + this IEnumerable sequence, + Func>> selector, + CancellationToken cancellationToken) + { + return (await Task.WhenAll(sequence.Select(item => selector(item, cancellationToken))).ConfigureAwait(false)).Flatten(); + } + + public static bool All(this IEnumerable source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + foreach (var b in source) + { + if (!b) + { + return false; + } + } + + return true; + } + + public static int IndexOf(this IEnumerable sequence, T value) + { + return sequence switch + { + IList list => list.IndexOf(value), + IReadOnlyList readOnlyList => IndexOf(readOnlyList, value, EqualityComparer.Default), + _ => EnumeratingIndexOf(sequence, value, EqualityComparer.Default) + }; + } + + public static int IndexOf(this IEnumerable sequence, T value, IEqualityComparer comparer) + { + return sequence switch + { + IReadOnlyList readOnlyList => IndexOf(readOnlyList, value, comparer), + _ => EnumeratingIndexOf(sequence, value, comparer) + }; + } + + private static int EnumeratingIndexOf(this IEnumerable sequence, T value, IEqualityComparer comparer) + { + int i = 0; + foreach (var item in sequence) + { + if (comparer.Equals(item, value)) + { + return i; + } + + i++; + } + + return -1; + } + + public static int IndexOf(this IReadOnlyList list, T value, IEqualityComparer comparer) + { + for (int i = 0, length = list.Count; i < length; i++) + { + if (comparer.Equals(list[i], value)) + { + return i; + } + } + + return -1; + } + + public static IEnumerable Flatten(this IEnumerable> sequence) + { + if (sequence == null) + { + throw new ArgumentNullException(nameof(sequence)); + } + + return sequence.SelectMany(s => s); + } + + public static IOrderedEnumerable OrderBy(this IEnumerable source, IComparer? comparer) + { + return source.OrderBy(Functions.Identity, comparer); + } + + public static IOrderedEnumerable OrderByDescending(this IEnumerable source, IComparer? comparer) + { + return source.OrderByDescending(Functions.Identity, comparer); + } + + public static IOrderedEnumerable OrderBy(this IEnumerable source, Comparison compare) + { + return source.OrderBy(Comparer.Create(compare)); + } + + public static IOrderedEnumerable OrderByDescending(this IEnumerable source, Comparison compare) + { + return source.OrderByDescending(Comparer.Create(compare)); + } + +#if NET8_0_OR_GREATER + public static IOrderedEnumerable Order(IEnumerable source) where T : IComparable +#else + public static IOrderedEnumerable Order(this IEnumerable source) where T : IComparable +#endif + { + return source.OrderBy(Comparer.Default); + } + + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, IComparer? comparer) + { + return source.ThenBy(Functions.Identity, comparer); + } + + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, Comparison compare) + { + return source.ThenBy(Comparer.Create(compare)); + } + + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source) where T : IComparable + { + return source.ThenBy(Comparer.Default); + } + + public static bool IsSorted(this IEnumerable enumerable, IComparer? comparer = null) + { + using var e = enumerable.GetEnumerator(); + if (!e.MoveNext()) + { + return true; + } + + comparer ??= Comparer.Default; + + var previous = e.Current; + while (e.MoveNext()) + { + if (comparer.Compare(previous, e.Current) > 0) + { + return false; + } + + previous = e.Current; + } + + return true; + } + + public static bool Contains(this IEnumerable sequence, Func predicate) + { + return sequence.Any(predicate); + } + + public static bool Contains(this IEnumerable sequence, string? s) + { + foreach (var item in sequence) + { + if (item == s) + { + return true; + } + } + + return false; + } + + public static IComparer ToComparer(this Comparison comparison) + { + return Comparer.Create(comparison); + } + + public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this IEnumerable>? items) + where K : notnull + { + if (items == null) + { + return ImmutableDictionary.Create(); + } + + return ImmutableDictionary.CreateRange(items); + } + + public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this IEnumerable>? items, IEqualityComparer? keyComparer) + where K : notnull + { + if (items == null) + { + return ImmutableDictionary.Create(keyComparer); + } + + return ImmutableDictionary.CreateRange(keyComparer, items); + } + +#nullable disable // Transpose doesn't handle empty arrays. Needs to be updated as appropriate. + internal static IList> Transpose(this IEnumerable> data) + { +#if DEBUG + var count = data.First().Count(); + Debug.Assert(data.All(d => d.Count() == count)); +#endif + return TransposeInternal(data).ToArray(); + } + + private static IEnumerable> TransposeInternal(this IEnumerable> data) + { + List> enumerators = new List>(); + + var width = 0; + foreach (var e in data) + { + enumerators.Add(e.GetEnumerator()); + width += 1; + } + + try + { + while (true) + { + T[] line = null; + for (int i = 0; i < width; i++) + { + var e = enumerators[i]; + if (!e.MoveNext()) + { + yield break; + } + + if (line == null) + { + line = new T[width]; + } + + line[i] = e.Current; + } + + yield return line; + } + } + finally + { + foreach (var enumerator in enumerators) + { + enumerator.Dispose(); + } + } + } +#nullable enable + + internal static Dictionary> ToMultiDictionary(this IEnumerable data, Func keySelector, IEqualityComparer? comparer = null) + where K : notnull + { + var dictionary = new Dictionary>(comparer); + var groups = data.GroupBy(keySelector, comparer); + foreach (var grouping in groups) + { + dictionary.Add(grouping.Key, [.. grouping]); + } + + return dictionary; + } + + /// + /// Returns the only element of specified sequence if it has exactly one, and default(TSource) otherwise. + /// Unlike doesn't throw if there is more than one element in the sequence. + /// + internal static TSource? AsSingleton(this IEnumerable? source) + { + if (source == null) + { + return default; + } + + if (source is IList list) + { + return (list.Count == 1) ? list[0] : default; + } + + using IEnumerator e = source.GetEnumerator(); + if (!e.MoveNext()) + { + return default; + } + + TSource result = e.Current; + if (e.MoveNext()) + { + return default; + } + + return result; + } + } + + /// + /// Cached versions of commonly used delegates. + /// + /// + internal static class Functions + { + public static readonly Func Identity = t => t; + public static readonly Func True = t => true; + } + + /// + /// Cached versions of commonly used delegates. + /// + /// + internal static class Predicates + { + public static readonly Predicate True = t => true; + } +} + +namespace System.Linq +{ + /// + /// Declare the following extension methods in System.Linq namespace to avoid accidental boxing of ImmutableArray{T} that implements IEnumerable{T}. + /// The boxing would occur if the methods were defined in Roslyn.Utilities and the file calling these methods has using Roslyn.Utilities + /// but not using System.Linq. + /// + internal static class EnumerableExtensions + { + public static bool SequenceEqual(this IEnumerable? first, IEnumerable? second, Func comparer) + { + if (first == second) + { + return true; + } + + if (first == null || second == null) + { + return false; + } + + using (var enumerator = first.GetEnumerator()) + using (var enumerator2 = second.GetEnumerator()) + { + while (enumerator.MoveNext()) + { + if (!enumerator2.MoveNext() || !comparer(enumerator.Current, enumerator2.Current)) + { + return false; + } + } + + if (enumerator2.MoveNext()) + { + return false; + } + } + + return true; + } + + public static T? AggregateOrDefault(this IEnumerable source, Func func) + { + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + { + return default; + } + + var result = e.Current; + while (e.MoveNext()) + { + result = func(result, e.Current); + } + + return result; + } + } + + // https://github.com/dotnet/runtime/issues/107723 +#if NET10_0_OR_GREATER + public static IEnumerable Reverse(T[] source) => Enumerable.Reverse(source); +#else + public static IEnumerable Reverse(this T[] source) => Enumerable.Reverse(source); +#endif + +#if NETSTANDARD + + // Copied from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Linq/src/System/Linq/Chunk.cs + public static IEnumerable Chunk(this IEnumerable source, int size) + { + if (source is null) + throw new ArgumentNullException(nameof(source)); + + if (size < 1) + throw new ArgumentOutOfRangeException(nameof(size)); + + if (source is TSource[] array) + { + // Special-case arrays, which have an immutable length. This enables us to not only do an + // empty check and avoid allocating an iterator object when empty, it enables us to have a + // much more efficient (and simpler) implementation for chunking up the array. + return array.Length != 0 ? + ArrayChunkIterator(array, size) : + []; + } + + return EnumerableChunkIterator(source, size); + } + + private static IEnumerable ArrayChunkIterator(TSource[] source, int size) + { + int index = 0; + while (index < source.Length) + { + TSource[] chunk = new ReadOnlySpan(source, index, Math.Min(size, source.Length - index)).ToArray(); + index += chunk.Length; + yield return chunk; + } + } + + private static IEnumerable EnumerableChunkIterator(IEnumerable source, int size) + { + using IEnumerator e = source.GetEnumerator(); + + // Before allocating anything, make sure there's at least one element. + if (e.MoveNext()) + { + // Now that we know we have at least one item, allocate an initial storage array. This is not + // the array we'll yield. It starts out small in order to avoid significantly overallocating + // when the source has many fewer elements than the chunk size. + int arraySize = Math.Min(size, 4); + int i; + do + { + var array = new TSource[arraySize]; + + // Store the first item. + array[0] = e.Current; + i = 1; + + if (size != array.Length) + { + // This is the first chunk. As we fill the array, grow it as needed. + for (; i < size && e.MoveNext(); i++) + { + if (i >= array.Length) + { + arraySize = (int)Math.Min((uint)size, 2 * (uint)array.Length); + Array.Resize(ref array, arraySize); + } + + array[i] = e.Current; + } + } + else + { + // For all but the first chunk, the array will already be correctly sized. + // We can just store into it until either it's full or MoveNext returns false. + TSource[] local = array; // avoid bounds checks by using cached local (`array` is lifted to iterator object as a field) + Debug.Assert(local.Length == size); + for (; (uint)i < (uint)local.Length && e.MoveNext(); i++) + { + local[i] = e.Current; + } + } + + if (i != array.Length) + { + Array.Resize(ref array, i); + } + + yield return array; + } + while (i >= size && e.MoveNext()); + } + } + +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Extensions/ImmutableArrayExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Extensions/ImmutableArrayExtensions.cs new file mode 100755 index 00000000000..06227b65bc8 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Extensions/ImmutableArrayExtensions.cs @@ -0,0 +1,1416 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Collections; +using Roslyn.Utilities; +using Microsoft.CodeAnalysis.Shared.Collections; + +#if DEBUG +using System.Linq; +#endif + +namespace Microsoft.CodeAnalysis +{ + /// + /// The collection of extension methods for the type + /// + internal static class ImmutableArrayExtensions + { + /// + /// Converts a sequence to an immutable array. + /// + /// Elemental type of the sequence. + /// The sequence to convert. + /// An immutable copy of the contents of the sequence. + /// If items is null (default) + /// If the sequence is null, this will throw + public static ImmutableArray AsImmutable(this IEnumerable items) + { + return ImmutableArray.CreateRange(items); + } + + /// + /// Converts a sequence to an immutable array. + /// + /// Elemental type of the sequence. + /// The sequence to convert. + /// An immutable copy of the contents of the sequence. + /// If the sequence is null, this will return an empty array. + public static ImmutableArray AsImmutableOrEmpty(this IEnumerable? items) + { + if (items == null) + { + return ImmutableArray.Empty; + } + + return ImmutableArray.CreateRange(items); + } + + /// + /// Converts a sequence to an immutable array. + /// + /// Elemental type of the sequence. + /// The sequence to convert. + /// An immutable copy of the contents of the sequence. + /// If the sequence is null, this will return the default (null) array. + public static ImmutableArray AsImmutableOrNull(this IEnumerable? items) + { + if (items == null) + { + return default; + } + + return ImmutableArray.CreateRange(items); + } + + /// + /// Converts an array to an immutable array. The array must not be null. + /// + /// + /// The sequence to convert + /// + public static ImmutableArray AsImmutable(this T[] items) + { + Debug.Assert(items != null); + return ImmutableArray.Create(items); + } + + /// + /// Converts a array to an immutable array. + /// + /// + /// The sequence to convert + /// + /// If the sequence is null, this will return the default (null) array. + public static ImmutableArray AsImmutableOrNull(this T[]? items) + { + if (items == null) + { + return default; + } + + return ImmutableArray.Create(items); + } + + /// + /// Converts an array to an immutable array. + /// + /// + /// The sequence to convert + /// If the array is null, this will return an empty immutable array. + public static ImmutableArray AsImmutableOrEmpty(this T[]? items) + { + if (items == null) + { + return ImmutableArray.Empty; + } + + return ImmutableArray.Create(items); + } + + /// + /// Reads bytes from specified . + /// + /// The stream. + /// Read-only content of the stream. + public static ImmutableArray ToImmutable(this MemoryStream stream) + { + return ImmutableArray.Create(stream.ToArray()); + } + + /// + /// Maps an immutable array to another immutable array. + /// + /// + /// + /// The array to map + /// The mapping delegate + /// If the items's length is 0, this will return an empty immutable array + public static ImmutableArray SelectAsArray(this ImmutableArray items, Func map) + { + return ImmutableArray.CreateRange(items, map); + } + + /// + /// Maps an immutable array to another immutable array. + /// + /// + /// + /// + /// The sequence to map + /// The mapping delegate + /// The extra input used by mapping delegate + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectAsArray(this ImmutableArray items, Func map, TArg arg) + { + return ImmutableArray.CreateRange(items, map, arg); + } + + /// + /// Maps an immutable array to another immutable array. + /// + /// + /// + /// + /// The sequence to map + /// The mapping delegate + /// The extra input used by mapping delegate + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectAsArray(this ImmutableArray items, Func map, TArg arg) + { + switch (items.Length) + { + case 0: + return ImmutableArray.Empty; + + case 1: + return ImmutableArray.Create(map(items[0], 0, arg)); + + case 2: + return ImmutableArray.Create(map(items[0], 0, arg), map(items[1], 1, arg)); + + case 3: + return ImmutableArray.Create(map(items[0], 0, arg), map(items[1], 1, arg), map(items[2], 2, arg)); + + case 4: + return ImmutableArray.Create(map(items[0], 0, arg), map(items[1], 1, arg), map(items[2], 2, arg), map(items[3], 3, arg)); + + default: + var builder = ArrayBuilder.GetInstance(items.Length); + for (int i = 0; i < items.Length; i++) + { + builder.Add(map(items[i], i, arg)); + } + + return builder.ToImmutableAndFree(); + } + } + + /// + /// Maps a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectAsArray(this ImmutableArray array, Func predicate, Func selector) + { + if (array.Length == 0) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item)) + { + builder.Add(selector(item)); + } + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// Type of the extra argument + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// The extra input used by and . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectAsArray(this ImmutableArray array, Func predicate, Func selector, TArg arg) + { + if (array.Length == 0) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item, arg)) + { + builder.Add(selector(item, arg)); + } + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// A transform function to apply to each element. + /// If the array's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + builder.AddRange(selector(item)); + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// A transform function to apply to each element. + /// If the array's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + builder.AddRange(selector(item)); + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// A transform function to apply to each element. + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + selector(item).AddRangeTo(builder); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func predicate, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item)) + builder.AddRange(selector(item)); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func predicate, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item)) + builder.AddRange(selector(item)); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func predicate, Func> selector) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item)) + selector(item).AddRangeTo(builder); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps and flattens a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the argument to pass to the predicate and selector + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectManyAsArray(this ImmutableArray array, Func predicate, Func> selector, TArg arg) + { + if (array.Length == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item, arg)) + selector(item, arg).AddRangeTo(builder); + } + + return builder.ToImmutableAndFree(); + } + + /// + /// Maps an immutable array through a function that returns ValueTasks, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this ImmutableArray array, Func> selector, CancellationToken cancellationToken) + { + if (array.IsEmpty) + return ImmutableArray.Empty; + + var builder = new TResult[array.Length]; + + for (var i = 0; i < array.Length; i++) + { + builder[i] = await selector(array[i], cancellationToken).ConfigureAwait(false); + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + /// + /// Maps an immutable array through a function that returns ValueTasks, returning the new ImmutableArray. + /// + public static async ValueTask> SelectAsArrayAsync(this ImmutableArray array, Func> selector, TArg arg, CancellationToken cancellationToken) + { + if (array.IsEmpty) + return ImmutableArray.Empty; + + var builder = new TResult[array.Length]; + + for (var i = 0; i < array.Length; i++) + { + builder[i] = await selector(array[i], arg, cancellationToken).ConfigureAwait(false); + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + public static ValueTask> SelectManyAsArrayAsync(this ImmutableArray source, Func>> selector, TArg arg, CancellationToken cancellationToken) + { + if (source.Length == 0) + { + return new ValueTask>(ImmutableArray.Empty); + } + + if (source.Length == 1) + { + return selector(source[0], arg, cancellationToken); + } + + return CreateTaskAsync(); + + async ValueTask> CreateTaskAsync() + { + var builder = ArrayBuilder.GetInstance(); + + foreach (var item in source) + { + builder.AddRange(await selector(item, arg, cancellationToken).ConfigureAwait(false)); + } + + return builder.ToImmutableAndFree(); + } + } + + /// + /// Zips two immutable arrays together through a mapping function, producing another immutable array. + /// + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray ZipAsArray(this ImmutableArray self, ImmutableArray other, Func map) + { + Debug.Assert(self.Length == other.Length); + switch (self.Length) + { + case 0: + return ImmutableArray.Empty; + + case 1: + return ImmutableArray.Create(map(self[0], other[0])); + + case 2: + return ImmutableArray.Create(map(self[0], other[0]), map(self[1], other[1])); + + case 3: + return ImmutableArray.Create(map(self[0], other[0]), map(self[1], other[1]), map(self[2], other[2])); + + case 4: + return ImmutableArray.Create(map(self[0], other[0]), map(self[1], other[1]), map(self[2], other[2]), map(self[3], other[3])); + + default: + var builder = new TResult[self.Length]; + for (int i = 0; i < self.Length; i++) + { + builder[i] = map(self[i], other[i]); + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + } + + public static ImmutableArray ZipAsArray(this ImmutableArray self, ImmutableArray other, TArg arg, Func map) + { + Debug.Assert(self.Length == other.Length); + if (self.IsEmpty) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(self.Length); + for (int i = 0; i < self.Length; i++) + { + builder.Add(map(self[i], other[i], i, arg)); + } + return builder.ToImmutableAndFree(); + } + + /// + /// Creates a new immutable array based on filtered elements by the predicate. The array must not be null. + /// + /// The array to process + /// The delegate that defines the conditions of the element to search for. + public static ImmutableArray WhereAsArray(this ImmutableArray array, Func predicate) + => WhereAsArrayImpl(array, predicate, predicateWithArg: null, arg: null); + + /// + /// Creates a new immutable array based on filtered elements by the predicate. The array must not be null. + /// + /// The array to process + /// The delegate that defines the conditions of the element to search for. + public static ImmutableArray WhereAsArray(this ImmutableArray array, Func predicate, TArg arg) + => WhereAsArrayImpl(array, predicateWithoutArg: null, predicate, arg); + + private static ImmutableArray WhereAsArrayImpl(ImmutableArray array, Func? predicateWithoutArg, Func? predicateWithArg, TArg arg) + { + Debug.Assert(!array.IsDefault); + Debug.Assert(predicateWithArg != null ^ predicateWithoutArg != null); + + ArrayBuilder? builder = null; + bool none = true; + bool all = true; + + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if ((predicateWithoutArg != null) ? predicateWithoutArg(a) : predicateWithArg!(a, arg)) + { + none = false; + if (all) + { + continue; + } + + Debug.Assert(i > 0); + if (builder == null) + { + builder = ArrayBuilder.GetInstance(); + } + + builder.Add(a); + } + else + { + if (none) + { + all = false; + continue; + } + + Debug.Assert(i > 0); + if (all) + { + Debug.Assert(builder == null); + all = false; + builder = ArrayBuilder.GetInstance(); + for (int j = 0; j < i; j++) + { + builder.Add(array[j]); + } + } + } + } + + if (builder != null) + { + Debug.Assert(!all); + Debug.Assert(!none); + return builder.ToImmutableAndFree(); + } + else if (all) + { + return array; + } + else + { + Debug.Assert(none); + return ImmutableArray.Empty; + } + } + + public static bool Any(this ImmutableArray array, Func predicate, TArg arg) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (predicate(a, arg)) + { + return true; + } + } + + return false; + } + + public static bool All(this ImmutableArray array, Func predicate, TArg arg) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (!predicate(a, arg)) + { + return false; + } + } + + return true; + } + + public static async Task AnyAsync(this ImmutableArray array, Func> predicateAsync) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (await predicateAsync(a).ConfigureAwait(false)) + { + return true; + } + } + + return false; + } + + public static async Task AnyAsync(this ImmutableArray array, Func> predicateAsync, TArg arg) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (await predicateAsync(a, arg).ConfigureAwait(false)) + { + return true; + } + } + + return false; + } + + public static async ValueTask FirstOrDefaultAsync(this ImmutableArray array, Func> predicateAsync) + { + int n = array.Length; + for (int i = 0; i < n; i++) + { + var a = array[i]; + + if (await predicateAsync(a).ConfigureAwait(false)) + { + return a; + } + } + + return default; + } + + public static TValue? FirstOrDefault(this ImmutableArray array, Func predicate, TArg arg) + { + foreach (var val in array) + { + if (predicate(val, arg)) + { + return val; + } + } + + return default; + } + + public static TValue Single(this ImmutableArray array, Func predicate, TArg arg) + { + var hasValue = false; + TValue? value = default; + foreach (var item in array) + { + if (predicate(item, arg)) + { + if (hasValue) + { + throw ExceptionUtilities.Unreachable(); + } + + value = item; + hasValue = true; + } + } + + if (!hasValue) + { + throw ExceptionUtilities.Unreachable(); + } + + return value!; + } + + /// + /// Casts the immutable array of a Type to an immutable array of its base type. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ImmutableArray Cast(this ImmutableArray items) + where TDerived : class, TBase + { + return ImmutableArray.CastUp(items); + } + + /// + /// Determines whether this instance and another immutable array are equal. + /// + /// + /// + /// + /// The comparer to determine if the two arrays are equal. + /// True if the two arrays are equal + public static bool SetEquals(this ImmutableArray array1, ImmutableArray array2, IEqualityComparer comparer) + { + if (array1.IsDefault) + { + return array2.IsDefault; + } + else if (array2.IsDefault) + { + return false; + } + + var count1 = array1.Length; + var count2 = array2.Length; + + // avoid constructing HashSets in these common cases + if (count1 == 0) + { + return count2 == 0; + } + else if (count2 == 0) + { + return false; + } + else if (count1 == 1 && count2 == 1) + { + var item1 = array1[0]; + var item2 = array2[0]; + + return comparer.Equals(item1, item2); + } + + var set1 = new HashSet(array1, comparer); + var set2 = new HashSet(array2, comparer); + + // internally recognizes that set2 is a HashSet with the same comparer (http://msdn.microsoft.com/en-us/library/bb346516.aspx) + return set1.SetEquals(set2); + } + + /// + /// Returns an empty array if the input array is null (default) + /// + public static ImmutableArray NullToEmpty(this ImmutableArray array) + { + return array.IsDefault ? ImmutableArray.Empty : array; + } + + /// + /// Returns an empty array if the input nullable value type is null or the underlying array is null (default) + /// + public static ImmutableArray NullToEmpty(this ImmutableArray? array) + => array switch + { + null or { IsDefault: true } => ImmutableArray.Empty, + { } underlying => underlying + }; + + /// + /// Returns an array of distinct elements, preserving the order in the original array. + /// If the array has no duplicates, the original array is returned. The original array must not be null. + /// + public static ImmutableArray Distinct(this ImmutableArray array, IEqualityComparer? comparer = null) + { + Debug.Assert(!array.IsDefault); + + if (array.Length < 2) + { + return array; + } + + var set = new HashSet(comparer); + var builder = ArrayBuilder.GetInstance(); + foreach (var a in array) + { + if (set.Add(a)) + { + builder.Add(a); + } + } + + var result = (builder.Count == array.Length) ? array : builder.ToImmutable(); + builder.Free(); + return result; + } + + // In DEBUG, swap the first and last elements of a read-only array, yielding a new read only array. + // This helps to avoid depending on accidentally sorted arrays. + internal static ImmutableArray ConditionallyDeOrder(this ImmutableArray array) + { +#if DEBUG + if (!array.IsDefault && array.Length >= 2) + { + T[] copy = array.ToArray(); + int last = copy.Length - 1; + var temp = copy[0]; + copy[0] = copy[last]; + copy[last] = temp; + + return ImmutableCollectionsMarshal.AsImmutableArray(copy); + } +#endif + return array; + } + + internal static ImmutableArray Flatten( + this Dictionary> dictionary, + IComparer? comparer = null) + where TKey : notnull + { + if (dictionary.Count == 0) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + + foreach (var kvp in dictionary) + { + builder.AddRange(kvp.Value); + } + + if (comparer != null && builder.Count > 1) + { + // PERF: Beware ImmutableArray.Builder.Sort allocates a Comparer wrapper object + builder.Sort(comparer); + } + + return builder.ToImmutableAndFree(); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second) + { + return first.AddRange(second); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second, ImmutableArray third) + { + var builder = new T[first.Length + second.Length + third.Length]; + var index = 0; + + foreach (var item in first) + { + builder[index++] = item; + } + + foreach (var item in second) + { + builder[index++] = item; + } + + foreach (var item in third) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second, ImmutableArray third, ImmutableArray fourth) + { + var builder = new T[first.Length + second.Length + third.Length + fourth.Length]; + var index = 0; + + foreach (var item in first) + { + builder[index++] = item; + } + + foreach (var item in second) + { + builder[index++] = item; + } + + foreach (var item in third) + { + builder[index++] = item; + } + + foreach (var item in fourth) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second, ImmutableArray third, ImmutableArray fourth, ImmutableArray fifth) + { + var builder = new T[first.Length + second.Length + third.Length + fourth.Length + fifth.Length]; + var index = 0; + + foreach (var item in first) + { + builder[index++] = item; + } + + foreach (var item in second) + { + builder[index++] = item; + } + + foreach (var item in third) + { + builder[index++] = item; + } + + foreach (var item in fourth) + { + builder[index++] = item; + } + + foreach (var item in fifth) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + internal static ImmutableArray Concat(this ImmutableArray first, ImmutableArray second, ImmutableArray third, ImmutableArray fourth, ImmutableArray fifth, ImmutableArray sixth) + { + var builder = new T[first.Length + second.Length + third.Length + fourth.Length + fifth.Length + sixth.Length]; + var index = 0; + + foreach (var item in first) + { + builder[index++] = item; + } + + foreach (var item in second) + { + builder[index++] = item; + } + + foreach (var item in third) + { + builder[index++] = item; + } + + foreach (var item in fourth) + { + builder[index++] = item; + } + + foreach (var item in fifth) + { + builder[index++] = item; + } + + foreach (var item in sixth) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + internal static ImmutableArray Concat(this ImmutableArray first, T second) + { + return first.Add(second); + } + + internal static ImmutableArray AddRange(this ImmutableArray self, in TemporaryArray items) + { + if (items.Count == 0) + { + return self; + } + + if (items.Count == 1) + { + return self.Add(items[0]); + } + + var builder = new T[self.Length + items.Count]; + var index = 0; + + foreach (var item in self) + { + builder[index++] = item; + } + + foreach (var item in items) + { + builder[index++] = item; + } + + return ImmutableCollectionsMarshal.AsImmutableArray(builder); + } + + /// + /// Determines whether duplicates exist using default equality comparer. + /// + /// Array to search for duplicates + /// Whether duplicates were found + internal static bool HasDuplicates(this ImmutableArray array) + { + switch (array.Length) + { + case 0: + case 1: + return false; + + case 2: + return EqualityComparer.Default.Equals(array[0], array[1]); + + default: + var set = PooledHashSet.GetInstance(); + var foundDuplicate = false; + + foreach (var element in array) + { + if (!set.Add(element)) + { + foundDuplicate = true; + break; + } + } + + set.Free(); + return foundDuplicate; + } + } + + /// + /// Determines whether duplicates exist using . Use other override + /// if you don't need a custom comparer. + /// + /// Array to search for duplicates + /// Comparer to use in search + /// Whether duplicates were found + internal static bool HasDuplicates(this ImmutableArray array, IEqualityComparer comparer) + { + switch (array.Length) + { + case 0: + case 1: + return false; + + case 2: + comparer ??= EqualityComparer.Default; + return comparer.Equals(array[0], array[1]); + + default: + var set = new HashSet(comparer); + foreach (var element in array) + { + if (!set.Add(element)) + { + return true; + } + } + + return false; + } + } + + public static int Count(this ImmutableArray items, Func predicate) + { + if (items.IsEmpty) + { + return 0; + } + + int count = 0; + for (int i = 0; i < items.Length; ++i) + { + if (predicate(items[i])) + { + ++count; + } + } + + return count; + } + + public static int Sum(this ImmutableArray items, Func selector) + { + var sum = 0; + foreach (var item in items) + sum += selector(item); + + return sum; + } + + public static int Sum(this ImmutableArray items, Func selector) + { + var sum = 0; + for (var i = 0; i < items.Length; i++) + sum += selector(items[i], i); + + return sum; + } + + internal static void AddToMultiValueDictionaryBuilder(Dictionary accumulator, K key, T item) + where K : notnull + where T : notnull + { + if (accumulator.TryGetValue(key, out var existingValueOrArray)) + { + if (existingValueOrArray is ArrayBuilder arrayBuilder) + { + // Already a builder in the accumulator, just add to that. + } + else + { + // Just a single value in the accumulator so far. Convert to using a builder. + arrayBuilder = ArrayBuilder.GetInstance(capacity: 2); + arrayBuilder.Add((T)existingValueOrArray); + accumulator[key] = arrayBuilder; + } + + arrayBuilder.Add(item); + } + else + { + // Nothing in the dictionary so far. Add the item directly. + accumulator.Add(key, item); + } + } + + internal static void CreateNameToMembersMap + (Dictionary dictionary, Dictionary> result) + where TKey : notnull + where TNamespaceOrTypeSymbol : class + where TNamedTypeSymbol : class, TNamespaceOrTypeSymbol + where TNamespaceSymbol : class, TNamespaceOrTypeSymbol + { + foreach (var entry in dictionary) + result.Add(entry.Key, createMembers(entry.Value)); + + return; + + static ImmutableArray createMembers(object value) + { + if (value is ArrayBuilder builder) + { + Debug.Assert(builder.Count > 1); + foreach (var item in builder) + { + if (item is TNamespaceSymbol) + return builder.ToImmutableAndFree(); + } + + return ImmutableArray.CastUp(builder.ToDowncastedImmutableAndFree()); + } + else + { + TNamespaceOrTypeSymbol symbol = (TNamespaceOrTypeSymbol)value; + return symbol is TNamespaceSymbol + ? ImmutableArray.Create(symbol) + : ImmutableArray.CastUp(ImmutableArray.Create((TNamedTypeSymbol)symbol)); + } + } + } + + internal static Dictionary> GetTypesFromMemberMap + (Dictionary> map, IEqualityComparer comparer) + where TKey : notnull + where TNamespaceOrTypeSymbol : class + where TNamedTypeSymbol : class, TNamespaceOrTypeSymbol + { + // Initialize dictionary capacity to avoid resize allocations during Add calls. + // Most iterations through the loop add an entry. If map is smaller than the + // smallest capacity dictionary will use, we'll let it grow organically as + // it's possible we might not add anything to the dictionary. + var capacity = map.Count > 3 ? map.Count : 0; + + var dictionary = new Dictionary>(capacity, comparer); + + foreach (var entry in map) + { + var namedTypes = getOrCreateNamedTypes(entry.Value); + if (namedTypes.Length > 0) + dictionary.Add(entry.Key, namedTypes); + } + + return dictionary; + + static ImmutableArray getOrCreateNamedTypes(ImmutableArray members) + { + Debug.Assert(members.Length > 0); + + // See if creator 'map' put a downcasted ImmutableArray in it. If so, we can just directly + // downcast to that and trivially reuse it. If not, that means the array must have contained at least one + // TNamespaceSymbol and we'll need to filter that out. + var membersAsNamedTypes = members.As(); + + if (!membersAsNamedTypes.IsDefault) + return membersAsNamedTypes; + + // Preallocate the right amount so we can avoid garbage reallocs. + var count = members.Count(static s => s is TNamedTypeSymbol); + + // Must have less items than in the original array. Otherwise, the .As() cast would + // have succeeded. + Debug.Assert(count < members.Length); + + if (count == 0) + return ImmutableArray.Empty; + + var builder = ArrayBuilder.GetInstance(count); + foreach (var member in members) + { + if (member is TNamedTypeSymbol namedType) + builder.Add(namedType); + } + + Debug.Assert(builder.Count == count); + return builder.ToImmutableAndFree(); + } + } + + internal static bool SequenceEqual(this ImmutableArray array1, ImmutableArray array2, TArg arg, Func predicate) + { + // The framework implementation of SequenceEqual forces a NullRef for default array1 and 2, so we + // maintain the same behavior in this extension + if (array1.IsDefault) + { + throw new NullReferenceException(); + } + + if (array2.IsDefault) + { + throw new NullReferenceException(); + } + + if (array1.Length != array2.Length) + { + return false; + } + + for (int i = 0; i < array1.Length; i++) + { + if (!predicate(array1[i], array2[i], arg)) + { + return false; + } + } + + return true; + } + + internal static int IndexOf(this ImmutableArray array, T item, IEqualityComparer comparer) + => array.IndexOf(item, startIndex: 0, comparer); + + internal static bool IsSorted(this ImmutableArray array, Comparison comparison) + => IsSorted(array, Comparer.Create(comparison)); + + internal static bool IsSorted(this ImmutableArray array, IComparer? comparer = null) + { + comparer ??= Comparer.Default; + + for (var i = 1; i < array.Length; i++) + { + if (comparer.Compare(array[i - 1], array[i]) > 0) + { + return false; + } + } + + return true; + } + + // same as Array.BinarySearch but the ability to pass arbitrary value to the comparer without allocation + internal static int BinarySearch(this ImmutableArray array, TValue value, Func comparer) + => BinarySearch(array.AsSpan(), value, comparer); + + internal static int BinarySearch(this ReadOnlySpan array, TValue value, Func comparer) + { + int low = 0; + int high = array.Length - 1; + + while (low <= high) + { + int middle = low + ((high - low) >> 1); + int comparison = comparer(array[middle], value); + + if (comparison == 0) + { + return middle; + } + + if (comparison > 0) + { + high = middle - 1; + } + else + { + low = middle + 1; + } + } + + return ~low; + } + + internal static int BinarySearch(this ImmutableSegmentedList array, TValue value, Func comparer) + { + int low = 0; + int high = array.Count - 1; + + while (low <= high) + { + int middle = low + ((high - low) >> 1); + int comparison = comparer(array[middle], value); + + if (comparison == 0) + { + return middle; + } + + if (comparison > 0) + { + high = middle - 1; + } + else + { + low = middle + 1; + } + } + + return ~low; + } + + public static bool IsSubsetOf(this ImmutableArray array, ImmutableArray other) + { + if (other.Length == 0) + { + return array.Length == 0; + } + + switch (array.Length) + { + case 0: + return true; + case 1: + return other.Contains(array[0]); + case 2: + return other.Contains(array[0]) && other.Contains(array[1]); + case 3: + return other.Contains(array[0]) && other.Contains(array[1]) && other.Contains(array[2]); + } + + var set = PooledHashSet.GetInstance(); + foreach (var item in other) + { + set.Add(item); + } + + foreach (var item in array) + { + if (!set.Contains(item)) + { + set.Free(); + return false; + } + } + + set.Free(); + return true; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ArraySortHelper.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ArraySortHelper.cs new file mode 100755 index 00000000000..0d60317f3ef --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ArraySortHelper.cs @@ -0,0 +1,1304 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +#if NET +using System.Numerics; +#else +using System.Runtime.InteropServices; +#endif + +#pragma warning disable CA1822 + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + #region ArraySortHelper for single arrays + + internal static class SegmentedArraySortHelper + { + public static void Sort(SegmentedArraySegment keys, IComparer? comparer) + { + // Add a try block here to detect IComparers (or their + // underlying IComparables, etc) that are bogus. + try + { + comparer ??= Comparer.Default; + IntrospectiveSort(keys, comparer.Compare); + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + public static int BinarySearch(SegmentedArray array, int index, int length, T value, IComparer? comparer) + { + try + { + comparer ??= Comparer.Default; + return InternalBinarySearch(array, index, length, value, comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + return 0; + } + } + + internal static void Sort(SegmentedArraySegment keys, Comparison comparer) + { + Debug.Assert(comparer != null, "Check the arguments in the caller!"); + + // Add a try block here to detect bogus comparisons + try + { + IntrospectiveSort(keys, comparer!); + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + internal static int InternalBinarySearch(SegmentedArray array, int index, int length, T value, IComparer comparer) + { + Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!"); + + int lo = index; + int hi = index + length - 1; + while (lo <= hi) + { + int i = lo + ((hi - lo) >> 1); + int order = comparer.Compare(array[i], value); + + if (order == 0) + return i; + if (order < 0) + { + lo = i + 1; + } + else + { + hi = i - 1; + } + } + + return ~lo; + } + + private static void SwapIfGreater(SegmentedArraySegment keys, Comparison comparer, int i, int j) + { + Debug.Assert(i != j); + + if (comparer(keys[i], keys[j]) > 0) + { + T key = keys[i]; + keys[i] = keys[j]; + keys[j] = key; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(SegmentedArraySegment a, int i, int j) + { + Debug.Assert(i != j); + + T t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + internal static void IntrospectiveSort(SegmentedArraySegment keys, Comparison comparer) + { + Debug.Assert(comparer != null); + + if (keys.Length > 1) + { + IntroSort(keys, 2 * (SegmentedArraySortUtils.Log2((uint)keys.Length) + 1), comparer!); + } + } + + // IntroSort is recursive; block it from being inlined into itself as + // this is currenly not profitable. + [MethodImpl(MethodImplOptions.NoInlining)] + private static void IntroSort(SegmentedArraySegment keys, int depthLimit, Comparison comparer) + { + Debug.Assert(keys.Length > 0); + Debug.Assert(depthLimit >= 0); + Debug.Assert(comparer != null); + + int partitionSize = keys.Length; + while (partitionSize > 1) + { + if (partitionSize <= SegmentedArrayHelper.IntrosortSizeThreshold) + { + + if (partitionSize == 2) + { + SwapIfGreater(keys, comparer!, 0, 1); + return; + } + + if (partitionSize == 3) + { + SwapIfGreater(keys, comparer!, 0, 1); + SwapIfGreater(keys, comparer!, 0, 2); + SwapIfGreater(keys, comparer!, 1, 2); + return; + } + + InsertionSort(keys.Slice(0, partitionSize), comparer!); + return; + } + + if (depthLimit == 0) + { + HeapSort(keys.Slice(0, partitionSize), comparer!); + return; + } + depthLimit--; + + int p = PickPivotAndPartition(keys.Slice(0, partitionSize), comparer!); + + // Note we've already partitioned around the pivot and do not have to move the pivot again. + IntroSort(keys.Slice(p + 1, partitionSize - (p + 1)), depthLimit, comparer!); + partitionSize = p; + } + } + + private static int PickPivotAndPartition(SegmentedArraySegment keys, Comparison comparer) + { + Debug.Assert(keys.Length >= SegmentedArrayHelper.IntrosortSizeThreshold); + Debug.Assert(comparer != null); + + int hi = keys.Length - 1; + + // Compute median-of-three. But also partition them, since we've done the comparison. + int middle = hi >> 1; + + // Sort lo, mid and hi appropriately, then pick mid as the pivot. + SwapIfGreater(keys, comparer!, 0, middle); // swap the low with the mid point + SwapIfGreater(keys, comparer!, 0, hi); // swap the low with the high + SwapIfGreater(keys, comparer!, middle, hi); // swap the middle with the high + + T pivot = keys[middle]; + Swap(keys, middle, hi - 1); + int left = 0, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below. + + while (left < right) + { + while (comparer!(keys[++left], pivot) < 0) + { + // Intentionally empty + } + + while (comparer(pivot, keys[--right]) < 0) + { + // Intentionally empty + } + + if (left >= right) + break; + + Swap(keys, left, right); + } + + // Put pivot in the right location. + if (left != hi - 1) + { + Swap(keys, left, hi - 1); + } + return left; + } + + private static void HeapSort(SegmentedArraySegment keys, Comparison comparer) + { + Debug.Assert(comparer != null); + Debug.Assert(keys.Length > 0); + + int n = keys.Length; + for (int i = n >> 1; i >= 1; i--) + { + DownHeap(keys, i, n, comparer!); + } + + for (int i = n; i > 1; i--) + { + Swap(keys, 0, i - 1); + DownHeap(keys, 1, i - 1, comparer!); + } + } + + private static void DownHeap(SegmentedArraySegment keys, int i, int n, Comparison comparer) + { + Debug.Assert(comparer != null); + + T d = keys[i - 1]; + while (i <= n >> 1) + { + int child = 2 * i; + if (child < n && comparer!(keys[child - 1], keys[child]) < 0) + { + child++; + } + + if (!(comparer!(d, keys[child - 1]) < 0)) + break; + + keys[i - 1] = keys[child - 1]; + i = child; + } + + keys[i - 1] = d; + } + + private static void InsertionSort(SegmentedArraySegment keys, Comparison comparer) + { + for (int i = 0; i < keys.Length - 1; i++) + { + T t = keys[i + 1]; + + int j = i; + while (j >= 0 && comparer(t, keys[j]) < 0) + { + keys[j + 1] = keys[j]; + j--; + } + + keys[j + 1] = t; + } + } + } + + internal static class SegmentedGenericArraySortHelper + where T : IComparable + { + public static void Sort(SegmentedArraySegment keys, IComparer? comparer) + { + try + { + if (comparer == null || comparer == Comparer.Default) + { + if (keys.Length > 1) + { + // For floating-point, do a pre-pass to move all NaNs to the beginning + // so that we can do an optimized comparison as part of the actual sort + // on the remainder of the values. + if (typeof(T) == typeof(double) + || typeof(T) == typeof(float) +#if NET + || typeof(T) == typeof(Half) +#endif + ) + { + int nanLeft = SegmentedArraySortUtils.MoveNansToFront(keys, default(Span)); + if (nanLeft == keys.Length) + { + return; + } + keys = keys.Slice(nanLeft); + } + + IntroSort(keys, 2 * (SegmentedArraySortUtils.Log2((uint)keys.Length) + 1)); + } + } + else + { + SegmentedArraySortHelper.IntrospectiveSort(keys, comparer.Compare); + } + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + public static int BinarySearch(SegmentedArray array, int index, int length, T value, IComparer? comparer) + { + Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!"); + + try + { + if (comparer == null || comparer == Comparer.Default) + { + return BinarySearch(array, index, length, value); + } + else + { + return SegmentedArraySortHelper.InternalBinarySearch(array, index, length, value, comparer); + } + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + return 0; + } + } + + // This function is called when the user doesn't specify any comparer. + // Since T is constrained here, we can call IComparable.CompareTo here. + // We can avoid boxing for value type and casting for reference types. + private static int BinarySearch(SegmentedArray array, int index, int length, T value) + { + int lo = index; + int hi = index + length - 1; + while (lo <= hi) + { + int i = lo + ((hi - lo) >> 1); + int order; + if (array[i] == null) + { + order = (value == null) ? 0 : -1; + } + else + { + order = array[i].CompareTo(value!); + } + + if (order == 0) + { + return i; + } + + if (order < 0) + { + lo = i + 1; + } + else + { + hi = i - 1; + } + } + + return ~lo; + } + + /// Swaps the values in the two references if the first is greater than the second. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SwapIfGreater(ref T i, ref T j) + { + if (i != null && GreaterThan(ref i, ref j)) + { + Swap(ref i, ref j); + } + } + + /// Swaps the values in the two references, regardless of whether the two references are the same. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(ref T i, ref T j) + { + Debug.Assert(!Unsafe.AreSame(ref i, ref j)); + + T t = i; + i = j; + j = t; + } + + // IntroSort is recursive; block it from being inlined into itself as + // this is currenly not profitable. + [MethodImpl(MethodImplOptions.NoInlining)] + private static void IntroSort(SegmentedArraySegment keys, int depthLimit) + { + Debug.Assert(keys.Length > 0); + Debug.Assert(depthLimit >= 0); + + int partitionSize = keys.Length; + while (partitionSize > 1) + { + if (partitionSize <= SegmentedArrayHelper.IntrosortSizeThreshold) + { + if (partitionSize == 2) + { + SwapIfGreater(ref keys[0], ref keys[1]); + return; + } + + if (partitionSize == 3) + { + ref T hiRef = ref keys[2]; + ref T him1Ref = ref keys[1]; + ref T loRef = ref keys[0]; + + SwapIfGreater(ref loRef, ref him1Ref); + SwapIfGreater(ref loRef, ref hiRef); + SwapIfGreater(ref him1Ref, ref hiRef); + return; + } + + InsertionSort(keys.Slice(0, partitionSize)); + return; + } + + if (depthLimit == 0) + { + HeapSort(keys.Slice(0, partitionSize)); + return; + } + depthLimit--; + + int p = PickPivotAndPartition(keys.Slice(0, partitionSize)); + + // Note we've already partitioned around the pivot and do not have to move the pivot again. + IntroSort(keys.Slice(p + 1, partitionSize - (p + 1)), depthLimit); + partitionSize = p; + } + } + + private static int PickPivotAndPartition(SegmentedArraySegment keys) + { + Debug.Assert(keys.Length >= SegmentedArrayHelper.IntrosortSizeThreshold); + + // Use median-of-three to select a pivot. Grab a reference to the 0th, Length-1th, and Length/2th elements, and sort them. + int zeroIndex = 0; + int lastIndex = keys.Length - 1; + int middleIndex = (keys.Length - 1) >> 1; + SwapIfGreater(ref keys[zeroIndex], ref keys[middleIndex]); + SwapIfGreater(ref keys[zeroIndex], ref keys[lastIndex]); + SwapIfGreater(ref keys[middleIndex], ref keys[lastIndex]); + + // Select the middle value as the pivot, and move it to be just before the last element. + int nextToLastIndex = keys.Length - 2; + T pivot = keys[middleIndex]; + Swap(ref keys[middleIndex], ref keys[nextToLastIndex]); + + // Walk the left and right pointers, swapping elements as necessary, until they cross. + int leftIndex = zeroIndex, rightIndex = nextToLastIndex; + while (leftIndex < rightIndex) + { + if (pivot == null) + { + while (leftIndex < nextToLastIndex && keys[++leftIndex] == null) + { + // Intentionally empty + } + + while (rightIndex > zeroIndex && keys[--rightIndex] != null) + { + // Intentionally empty + } + } + else + { + while (leftIndex < nextToLastIndex && GreaterThan(ref pivot, ref keys[++leftIndex])) + { + // Intentionally empty + } + + while (rightIndex > zeroIndex && LessThan(ref pivot, ref keys[--rightIndex])) + { + // Intentionally empty + } + } + + if (leftIndex >= rightIndex) + { + break; + } + + Swap(ref keys[leftIndex], ref keys[rightIndex]); + } + + // Put the pivot in the correct location. + if (leftIndex != nextToLastIndex) + { + Swap(ref keys[leftIndex], ref keys[nextToLastIndex]); + } + + return leftIndex; + } + + private static void HeapSort(SegmentedArraySegment keys) + { + Debug.Assert(keys.Length > 0); + + int n = keys.Length; + for (int i = n >> 1; i >= 1; i--) + { + DownHeap(keys, i, n); + } + + for (int i = n; i > 1; i--) + { + Swap(ref keys[0], ref keys[i - 1]); + DownHeap(keys, 1, i - 1); + } + } + + private static void DownHeap(SegmentedArraySegment keys, int i, int n) + { + T d = keys[i - 1]; + while (i <= n >> 1) + { + int child = 2 * i; + if (child < n && (keys[child - 1] == null || LessThan(ref keys[child - 1], ref keys[child]))) + { + child++; + } + + if (keys[child - 1] == null || !LessThan(ref d, ref keys[child - 1])) + break; + + keys[i - 1] = keys[child - 1]; + i = child; + } + + keys[i - 1] = d; + } + + private static void InsertionSort(SegmentedArraySegment keys) + { + for (int i = 0; i < keys.Length - 1; i++) + { + T t = keys[i + 1]; + + int j = i; + while (j >= 0 && (t == null || LessThan(ref t, ref keys[j]))) + { + keys[j + 1] = keys[j]; + j--; + } + + keys[j + 1] = t!; + } + } + + // - These methods exist for use in sorting, where the additional operations present in + // the CompareTo methods that would otherwise be used on these primitives add non-trivial overhead, + // in particular for floating point where the CompareTo methods need to factor in NaNs. + // - The floating-point comparisons here assume no NaNs, which is valid only because the sorting routines + // themselves special-case NaN with a pre-pass that ensures none are present in the values being sorted + // by moving them all to the front first and then sorting the rest. + // - These are duplicated here rather than being on a helper type due to current limitations around generic inlining. + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // compiles to a single comparison or method call + private static bool LessThan(ref T left, ref T right) + { + if (typeof(T) == typeof(byte)) + return (byte)(object)left < (byte)(object)right; + if (typeof(T) == typeof(sbyte)) + return (sbyte)(object)left < (sbyte)(object)right; + if (typeof(T) == typeof(ushort)) + return (ushort)(object)left < (ushort)(object)right; + if (typeof(T) == typeof(short)) + return (short)(object)left < (short)(object)right; + if (typeof(T) == typeof(uint)) + return (uint)(object)left < (uint)(object)right; + if (typeof(T) == typeof(int)) + return (int)(object)left < (int)(object)right; + if (typeof(T) == typeof(ulong)) + return (ulong)(object)left < (ulong)(object)right; + if (typeof(T) == typeof(long)) + return (long)(object)left < (long)(object)right; + if (typeof(T) == typeof(UIntPtr)) + return (nuint)(object)left < (nuint)(object)right; + if (typeof(T) == typeof(IntPtr)) + return (nint)(object)left < (nint)(object)right; + if (typeof(T) == typeof(float)) + return (float)(object)left < (float)(object)right; + if (typeof(T) == typeof(double)) + return (double)(object)left < (double)(object)right; +#if NET + if (typeof(T) == typeof(Half)) + return (Half)(object)left < (Half)(object)right; +#endif + return left.CompareTo(right) < 0 ? true : false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // compiles to a single comparison or method call + private static bool GreaterThan(ref T left, ref T right) + { + if (typeof(T) == typeof(byte)) + return (byte)(object)left > (byte)(object)right; + if (typeof(T) == typeof(sbyte)) + return (sbyte)(object)left > (sbyte)(object)right; + if (typeof(T) == typeof(ushort)) + return (ushort)(object)left > (ushort)(object)right; + if (typeof(T) == typeof(short)) + return (short)(object)left > (short)(object)right; + if (typeof(T) == typeof(uint)) + return (uint)(object)left > (uint)(object)right; + if (typeof(T) == typeof(int)) + return (int)(object)left > (int)(object)right; + if (typeof(T) == typeof(ulong)) + return (ulong)(object)left > (ulong)(object)right; + if (typeof(T) == typeof(long)) + return (long)(object)left > (long)(object)right; + if (typeof(T) == typeof(UIntPtr)) + return (nuint)(object)left > (nuint)(object)right; + if (typeof(T) == typeof(IntPtr)) + return (nint)(object)left > (nint)(object)right; + if (typeof(T) == typeof(float)) + return (float)(object)left > (float)(object)right; + if (typeof(T) == typeof(double)) + return (double)(object)left > (double)(object)right; +#if NET + if (typeof(T) == typeof(Half)) + return (Half)(object)left > (Half)(object)right; +#endif + return left.CompareTo(right) > 0 ? true : false; + } + } + + #endregion + + #region ArraySortHelper for paired key and value arrays + + internal static class SegmentedArraySortHelper + { + public static void Sort(SegmentedArraySegment keys, Span values, IComparer? comparer) + { + // Add a try block here to detect IComparers (or their + // underlying IComparables, etc) that are bogus. + try + { + IntrospectiveSort(keys, values, comparer ?? Comparer.Default); + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + private static void SwapIfGreaterWithValues(SegmentedArraySegment keys, Span values, IComparer comparer, int i, int j) + { + Debug.Assert(comparer != null); + Debug.Assert(0 <= i && i < keys.Length && i < values.Length); + Debug.Assert(0 <= j && j < keys.Length && j < values.Length); + Debug.Assert(i != j); + + if (comparer!.Compare(keys[i], keys[j]) > 0) + { + TKey key = keys[i]; + keys[i] = keys[j]; + keys[j] = key; + + TValue value = values[i]; + values[i] = values[j]; + values[j] = value; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(SegmentedArraySegment keys, Span values, int i, int j) + { + Debug.Assert(i != j); + + TKey k = keys[i]; + keys[i] = keys[j]; + keys[j] = k; + + TValue v = values[i]; + values[i] = values[j]; + values[j] = v; + } + + internal static void IntrospectiveSort(SegmentedArraySegment keys, Span values, IComparer comparer) + { + Debug.Assert(comparer != null); + Debug.Assert(keys.Length == values.Length); + + if (keys.Length > 1) + { + IntroSort(keys, values, 2 * (SegmentedArraySortUtils.Log2((uint)keys.Length) + 1), comparer!); + } + } + + private static void IntroSort(SegmentedArraySegment keys, Span values, int depthLimit, IComparer comparer) + { + Debug.Assert(keys.Length > 0); + Debug.Assert(values.Length == keys.Length); + Debug.Assert(depthLimit >= 0); + Debug.Assert(comparer != null); + + int partitionSize = keys.Length; + while (partitionSize > 1) + { + if (partitionSize <= SegmentedArrayHelper.IntrosortSizeThreshold) + { + + if (partitionSize == 2) + { + SwapIfGreaterWithValues(keys, values, comparer!, 0, 1); + return; + } + + if (partitionSize == 3) + { + SwapIfGreaterWithValues(keys, values, comparer!, 0, 1); + SwapIfGreaterWithValues(keys, values, comparer!, 0, 2); + SwapIfGreaterWithValues(keys, values, comparer!, 1, 2); + return; + } + + InsertionSort(keys.Slice(0, partitionSize), values.Slice(0, partitionSize), comparer!); + return; + } + + if (depthLimit == 0) + { + HeapSort(keys.Slice(0, partitionSize), values.Slice(0, partitionSize), comparer!); + return; + } + depthLimit--; + + int p = PickPivotAndPartition(keys.Slice(0, partitionSize), values.Slice(0, partitionSize), comparer!); + + // Note we've already partitioned around the pivot and do not have to move the pivot again. + IntroSort(keys.Slice(p + 1, partitionSize - (p + 1)), values.Slice(p + 1, partitionSize - (p + 1)), depthLimit, comparer!); + partitionSize = p; + } + } + + private static int PickPivotAndPartition(SegmentedArraySegment keys, Span values, IComparer comparer) + { + Debug.Assert(keys.Length >= SegmentedArrayHelper.IntrosortSizeThreshold); + Debug.Assert(comparer != null); + + int hi = keys.Length - 1; + + // Compute median-of-three. But also partition them, since we've done the comparison. + int middle = hi >> 1; + + // Sort lo, mid and hi appropriately, then pick mid as the pivot. + SwapIfGreaterWithValues(keys, values, comparer!, 0, middle); // swap the low with the mid point + SwapIfGreaterWithValues(keys, values, comparer!, 0, hi); // swap the low with the high + SwapIfGreaterWithValues(keys, values, comparer!, middle, hi); // swap the middle with the high + + TKey pivot = keys[middle]; + Swap(keys, values, middle, hi - 1); + int left = 0, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below. + + while (left < right) + { + while (comparer!.Compare(keys[++left], pivot) < 0) + { + // Intentionally empty + } + + while (comparer.Compare(pivot, keys[--right]) < 0) + { + // Intentionally empty + } + + if (left >= right) + break; + + Swap(keys, values, left, right); + } + + // Put pivot in the right location. + if (left != hi - 1) + { + Swap(keys, values, left, hi - 1); + } + return left; + } + + private static void HeapSort(SegmentedArraySegment keys, Span values, IComparer comparer) + { + Debug.Assert(comparer != null); + Debug.Assert(keys.Length > 0); + + int n = keys.Length; + for (int i = n >> 1; i >= 1; i--) + { + DownHeap(keys, values, i, n, comparer!); + } + + for (int i = n; i > 1; i--) + { + Swap(keys, values, 0, i - 1); + DownHeap(keys, values, 1, i - 1, comparer!); + } + } + + private static void DownHeap(SegmentedArraySegment keys, Span values, int i, int n, IComparer comparer) + { + Debug.Assert(comparer != null); + + TKey d = keys[i - 1]; + TValue dValue = values[i - 1]; + + while (i <= n >> 1) + { + int child = 2 * i; + if (child < n && comparer!.Compare(keys[child - 1], keys[child]) < 0) + { + child++; + } + + if (!(comparer!.Compare(d, keys[child - 1]) < 0)) + break; + + keys[i - 1] = keys[child - 1]; + values[i - 1] = values[child - 1]; + i = child; + } + + keys[i - 1] = d; + values[i - 1] = dValue; + } + + private static void InsertionSort(SegmentedArraySegment keys, Span values, IComparer comparer) + { + Debug.Assert(comparer != null); + + for (int i = 0; i < keys.Length - 1; i++) + { + TKey t = keys[i + 1]; + TValue tValue = values[i + 1]; + + int j = i; + while (j >= 0 && comparer!.Compare(t, keys[j]) < 0) + { + keys[j + 1] = keys[j]; + values[j + 1] = values[j]; + j--; + } + + keys[j + 1] = t; + values[j + 1] = tValue; + } + } + } + + internal static class SegmentedGenericArraySortHelper + where TKey : IComparable + { + public static void Sort(SegmentedArraySegment keys, Span values, IComparer? comparer) + { + // Add a try block here to detect IComparers (or their + // underlying IComparables, etc) that are bogus. + try + { + if (comparer == null || comparer == Comparer.Default) + { + if (keys.Length > 1) + { + // For floating-point, do a pre-pass to move all NaNs to the beginning + // so that we can do an optimized comparison as part of the actual sort + // on the remainder of the values. + if (typeof(TKey) == typeof(double) + || typeof(TKey) == typeof(float) +#if NET + || typeof(TKey) == typeof(Half) +#endif + ) + { + int nanLeft = SegmentedArraySortUtils.MoveNansToFront(keys, values); + if (nanLeft == keys.Length) + { + return; + } + keys = keys.Slice(nanLeft); + values = values.Slice(nanLeft); + } + + IntroSort(keys, values, 2 * (SegmentedArraySortUtils.Log2((uint)keys.Length) + 1)); + } + } + else + { + SegmentedArraySortHelper.IntrospectiveSort(keys, values, comparer); + } + } + catch (IndexOutOfRangeException) + { + ThrowHelper.ThrowArgumentException_BadComparer(comparer); + } + catch (Exception e) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); + } + } + + private static void SwapIfGreaterWithValues(SegmentedArraySegment keys, Span values, int i, int j) + { + Debug.Assert(i != j); + + ref TKey keyRef = ref keys[i]; + if (keyRef != null && GreaterThan(ref keyRef, ref keys[j])) + { + TKey key = keyRef; + keys[i] = keys[j]; + keys[j] = key; + + TValue value = values[i]; + values[i] = values[j]; + values[j] = value; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(SegmentedArraySegment keys, Span values, int i, int j) + { + Debug.Assert(i != j); + + TKey k = keys[i]; + keys[i] = keys[j]; + keys[j] = k; + + TValue v = values[i]; + values[i] = values[j]; + values[j] = v; + } + + private static void IntroSort(SegmentedArraySegment keys, Span values, int depthLimit) + { + Debug.Assert(keys.Length > 0); + Debug.Assert(values.Length == keys.Length); + Debug.Assert(depthLimit >= 0); + + int partitionSize = keys.Length; + while (partitionSize > 1) + { + if (partitionSize <= SegmentedArrayHelper.IntrosortSizeThreshold) + { + + if (partitionSize == 2) + { + SwapIfGreaterWithValues(keys, values, 0, 1); + return; + } + + if (partitionSize == 3) + { + SwapIfGreaterWithValues(keys, values, 0, 1); + SwapIfGreaterWithValues(keys, values, 0, 2); + SwapIfGreaterWithValues(keys, values, 1, 2); + return; + } + + InsertionSort(keys.Slice(0, partitionSize), values.Slice(0, partitionSize)); + return; + } + + if (depthLimit == 0) + { + HeapSort(keys.Slice(0, partitionSize), values.Slice(0, partitionSize)); + return; + } + depthLimit--; + + int p = PickPivotAndPartition(keys.Slice(0, partitionSize), values.Slice(0, partitionSize)); + + // Note we've already partitioned around the pivot and do not have to move the pivot again. + IntroSort(keys.Slice(p + 1, partitionSize - (p + 1)), values.Slice(p + 1, partitionSize - (p + 1)), depthLimit); + partitionSize = p; + } + } + + private static int PickPivotAndPartition(SegmentedArraySegment keys, Span values) + { + Debug.Assert(keys.Length >= SegmentedArrayHelper.IntrosortSizeThreshold); + + int hi = keys.Length - 1; + + // Compute median-of-three. But also partition them, since we've done the comparison. + int middle = hi >> 1; + + // Sort lo, mid and hi appropriately, then pick mid as the pivot. + SwapIfGreaterWithValues(keys, values, 0, middle); // swap the low with the mid point + SwapIfGreaterWithValues(keys, values, 0, hi); // swap the low with the high + SwapIfGreaterWithValues(keys, values, middle, hi); // swap the middle with the high + + TKey pivot = keys[middle]; + Swap(keys, values, middle, hi - 1); + int left = 0, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below. + + while (left < right) + { + if (pivot == null) + { + while (left < (hi - 1) && keys[++left] == null) + { + // Intentionally empty + } + + while (right > 0 && keys[--right] != null) + { + // Intentionally empty + } + } + else + { + while (GreaterThan(ref pivot, ref keys[++left])) + { + // Intentionally empty + } + + while (LessThan(ref pivot, ref keys[--right])) + { + // Intentionally empty + } + } + + if (left >= right) + break; + + Swap(keys, values, left, right); + } + + // Put pivot in the right location. + if (left != hi - 1) + { + Swap(keys, values, left, hi - 1); + } + return left; + } + + private static void HeapSort(SegmentedArraySegment keys, Span values) + { + Debug.Assert(keys.Length > 0); + + int n = keys.Length; + for (int i = n >> 1; i >= 1; i--) + { + DownHeap(keys, values, i, n); + } + + for (int i = n; i > 1; i--) + { + Swap(keys, values, 0, i - 1); + DownHeap(keys, values, 1, i - 1); + } + } + + private static void DownHeap(SegmentedArraySegment keys, Span values, int i, int n) + { + TKey d = keys[i - 1]; + TValue dValue = values[i - 1]; + + while (i <= n >> 1) + { + int child = 2 * i; + if (child < n && (keys[child - 1] == null || LessThan(ref keys[child - 1], ref keys[child]))) + { + child++; + } + + if (keys[child - 1] == null || !LessThan(ref d, ref keys[child - 1])) + break; + + keys[i - 1] = keys[child - 1]; + values[i - 1] = values[child - 1]; + i = child; + } + + keys[i - 1] = d; + values[i - 1] = dValue; + } + + private static void InsertionSort(SegmentedArraySegment keys, Span values) + { + for (int i = 0; i < keys.Length - 1; i++) + { + TKey t = keys[i + 1]; + TValue tValue = values[i + 1]; + + int j = i; + while (j >= 0 && (t == null || LessThan(ref t, ref keys[j]))) + { + keys[j + 1] = keys[j]; + values[j + 1] = values[j]; + j--; + } + + keys[j + 1] = t!; + values[j + 1] = tValue; + } + } + + // - These methods exist for use in sorting, where the additional operations present in + // the CompareTo methods that would otherwise be used on these primitives add non-trivial overhead, + // in particular for floating point where the CompareTo methods need to factor in NaNs. + // - The floating-point comparisons here assume no NaNs, which is valid only because the sorting routines + // themselves special-case NaN with a pre-pass that ensures none are present in the values being sorted + // by moving them all to the front first and then sorting the rest. + // - These are duplicated here rather than being on a helper type due to current limitations around generic inlining. + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // compiles to a single comparison or method call + private static bool LessThan(ref TKey left, ref TKey right) + { + if (typeof(TKey) == typeof(byte)) + return (byte)(object)left < (byte)(object)right; + if (typeof(TKey) == typeof(sbyte)) + return (sbyte)(object)left < (sbyte)(object)right; + if (typeof(TKey) == typeof(ushort)) + return (ushort)(object)left < (ushort)(object)right; + if (typeof(TKey) == typeof(short)) + return (short)(object)left < (short)(object)right; + if (typeof(TKey) == typeof(uint)) + return (uint)(object)left < (uint)(object)right; + if (typeof(TKey) == typeof(int)) + return (int)(object)left < (int)(object)right; + if (typeof(TKey) == typeof(ulong)) + return (ulong)(object)left < (ulong)(object)right; + if (typeof(TKey) == typeof(long)) + return (long)(object)left < (long)(object)right; + if (typeof(TKey) == typeof(UIntPtr)) + return (nuint)(object)left < (nuint)(object)right; + if (typeof(TKey) == typeof(IntPtr)) + return (nint)(object)left < (nint)(object)right; + if (typeof(TKey) == typeof(float)) + return (float)(object)left < (float)(object)right; + if (typeof(TKey) == typeof(double)) + return (double)(object)left < (double)(object)right; +#if NET + if (typeof(TKey) == typeof(Half)) + return (Half)(object)left < (Half)(object)right; +#endif + return left.CompareTo(right) < 0 ? true : false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // compiles to a single comparison or method call + private static bool GreaterThan(ref TKey left, ref TKey right) + { + if (typeof(TKey) == typeof(byte)) + return (byte)(object)left > (byte)(object)right; + if (typeof(TKey) == typeof(sbyte)) + return (sbyte)(object)left > (sbyte)(object)right; + if (typeof(TKey) == typeof(ushort)) + return (ushort)(object)left > (ushort)(object)right; + if (typeof(TKey) == typeof(short)) + return (short)(object)left > (short)(object)right; + if (typeof(TKey) == typeof(uint)) + return (uint)(object)left > (uint)(object)right; + if (typeof(TKey) == typeof(int)) + return (int)(object)left > (int)(object)right; + if (typeof(TKey) == typeof(ulong)) + return (ulong)(object)left > (ulong)(object)right; + if (typeof(TKey) == typeof(long)) + return (long)(object)left > (long)(object)right; + if (typeof(TKey) == typeof(UIntPtr)) + return (nuint)(object)left > (nuint)(object)right; + if (typeof(TKey) == typeof(IntPtr)) + return (nint)(object)left > (nint)(object)right; + if (typeof(TKey) == typeof(float)) + return (float)(object)left > (float)(object)right; + if (typeof(TKey) == typeof(double)) + return (double)(object)left > (double)(object)right; +#if NET + if (typeof(TKey) == typeof(Half)) + return (Half)(object)left > (Half)(object)right; +#endif + return left.CompareTo(right) > 0 ? true : false; + } + } + + #endregion + + /// Helper methods for use in array/span sorting routines. + internal static class SegmentedArraySortUtils + { +#if !NETCOREAPP + private static ReadOnlySpan Log2DeBruijn => new byte[32] + { + 00, 09, 01, 10, 13, 21, 02, 29, + 11, 14, 16, 18, 22, 25, 03, 30, + 08, 12, 20, 28, 15, 17, 24, 07, + 19, 27, 23, 06, 26, 05, 04, 31, + }; +#endif + + public static int MoveNansToFront(SegmentedArraySegment keys, Span values) where TKey : notnull + { + Debug.Assert(typeof(TKey) == typeof(double) || typeof(TKey) == typeof(float)); + + int left = 0; + + for (int i = 0; i < keys.Length; i++) + { + if ((typeof(TKey) == typeof(double) && double.IsNaN((double)(object)keys[i])) + || (typeof(TKey) == typeof(float) && float.IsNaN((float)(object)keys[i])) +#if NET + || (typeof(TKey) == typeof(Half) && Half.IsNaN((Half)(object)keys[i])) +#endif + ) + { + TKey temp = keys[left]; + keys[left] = keys[i]; + keys[i] = temp; + + if ((uint)i < (uint)values.Length) // check to see if we have values + { + TValue tempValue = values[left]; + values[left] = values[i]; + values[i] = tempValue; + } + + left++; + } + } + + return left; + } + + public static int Log2(uint value) + { +#if NET + return BitOperations.Log2(value); +#else + // Fallback contract is 0->0 + return Log2SoftwareFallback(value); +#endif + } + +#if !NETCOREAPP + /// + /// Returns the integer (floor) log of the specified value, base 2. + /// Note that by convention, input value 0 returns 0 since Log(0) is undefined. + /// Does not directly use any hardware intrinsics, nor does it incur branching. + /// + /// The value. + private static int Log2SoftwareFallback(uint value) + { + // No AggressiveInlining due to large method size + // Has conventional contract 0->0 (Log(0) is undefined) + + // Fill trailing zeros with ones, eg 00010010 becomes 00011111 + value |= value >> 01; + value |= value >> 02; + value |= value >> 04; + value |= value >> 08; + value |= value >> 16; + + // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check + return Unsafe.AddByteOffset( + // Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_1100_0100_1010_1100_1101_1101u + ref MemoryMarshal.GetReference(Log2DeBruijn), + // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here + (IntPtr)(int)((value * 0x07C4ACDDu) >> 27)); + } +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/BitHelper.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/BitHelper.cs new file mode 100755 index 00000000000..a9238e0e47c --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/BitHelper.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/Common/src/System/Collections/Generic/BitHelper.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal ref struct BitHelper + { + private const int IntSize = sizeof(int) * 8; + private readonly Span _span; + + internal BitHelper(Span span, bool clear) + { + if (clear) + { + span.Clear(); + } + _span = span; + } + + internal readonly void MarkBit(int bitPosition) + { + Debug.Assert(bitPosition >= 0); + + uint bitArrayIndex = (uint)bitPosition / IntSize; + + // Workaround for https://github.com/dotnet/runtime/issues/72004 + Span span = _span; + if (bitArrayIndex < (uint)span.Length) + { + span[(int)bitArrayIndex] |= (1 << (int)((uint)bitPosition % IntSize)); + } + } + + internal readonly bool IsMarked(int bitPosition) + { + Debug.Assert(bitPosition >= 0); + + uint bitArrayIndex = (uint)bitPosition / IntSize; + + // Workaround for https://github.com/dotnet/runtime/issues/72004 + Span span = _span; + return + bitArrayIndex < (uint)span.Length && + (span[(int)bitArrayIndex] & (1 << ((int)((uint)bitPosition % IntSize)))) != 0; + } + + /// How many ints must be allocated to represent n bits. Returns (n+31)/32, but avoids overflow. + internal static int ToIntArrayLength(int n) => n > 0 ? ((n - 1) / IntSize + 1) : 0; + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/HashHelpers.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/HashHelpers.cs new file mode 100755 index 00000000000..1dfe0939094 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/HashHelpers.cs @@ -0,0 +1,123 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal static class HashHelpers + { + // This is the maximum prime smaller than Array.MaxLength. + public const int MaxPrimeArrayLength = 0x7FFFFFC3; + + public const int HashPrime = 101; + + // Table of prime numbers to use as hash table sizes. + // A typical resize algorithm would pick the smallest prime number in this array + // that is larger than twice the previous capacity. + // Suppose our Hashtable currently has capacity x and enough elements are added + // such that a resize needs to occur. Resizing first computes 2x then finds the + // first prime in the table greater than 2x, i.e. if primes are ordered + // p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n. + // Doubling is important for preserving the asymptotic complexity of the + // hashtable operations such as add. Having a prime guarantees that double + // hashing does not lead to infinite loops. IE, your hash function will be + // h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime. + // We prefer the low computation costs of higher prime numbers over the increased + // memory allocation of a fixed prime number i.e. when right sizing a HashSet. + private static readonly ImmutableArray s_primes = ImmutableArray.Create( + 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, + 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, + 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, + 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, + 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369); + + public static bool IsPrime(int candidate) + { + if ((candidate & 1) != 0) + { + var limit = (int)Math.Sqrt(candidate); + for (var divisor = 3; divisor <= limit; divisor += 2) + { + if ((candidate % divisor) == 0) + return false; + } + return true; + } + return candidate == 2; + } + + public static int GetPrime(int min) + { + if (min < 0) + throw new ArgumentException(SR.Arg_HTCapacityOverflow); + + foreach (var prime in s_primes) + { + if (prime >= min) + return prime; + } + + // Outside of our predefined table. Compute the hard way. + for (var i = (min | 1); i < int.MaxValue; i += 2) + { + if (IsPrime(i) && ((i - 1) % HashPrime != 0)) + return i; + } + return min; + } + + // Returns size of hashtable to grow to. + public static int ExpandPrime(int oldSize) + { + var newSize = 2 * oldSize; + + // Allow the hashtables to grow to maximum possible size (~2G elements) before encountering capacity overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize) + { + Debug.Assert(MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength"); + return MaxPrimeArrayLength; + } + + return GetPrime(newSize); + } + + /// Returns approximate reciprocal of the divisor: ceil(2**64 / divisor). + /// This should only be used on 64-bit. + public static ulong GetFastModMultiplier(uint divisor) + => ulong.MaxValue / divisor + 1; + + /// Performs a mod operation using the multiplier pre-computed with . + /// + /// PERF: This improves performance in 64-bit scenarios at the expense of performance in 32-bit scenarios. Since + /// we only build a single AnyCPU binary, we opt for improved performance in the 64-bit scenario. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint FastMod(uint value, uint divisor, ulong multiplier) + { + // We use modified Daniel Lemire's fastmod algorithm (https://github.com/dotnet/runtime/pull/406), + // which allows to avoid the long multiplication if the divisor is less than 2**31. + Debug.Assert(divisor <= int.MaxValue); + + // This is equivalent of (uint)Math.BigMul(multiplier * value, divisor, out _). This version + // is faster than BigMul currently because we only need the high bits. + var highbits = (uint)(((((multiplier * value) >> 32) + 1) * divisor) >> 32); + + Debug.Assert(highbits == value % divisor); + return highbits; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ICollectionCalls.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ICollectionCalls.cs new file mode 100755 index 00000000000..e45d9116104 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ICollectionCalls.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement the + /// member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class ICollectionCalls + { + public static bool IsSynchronized(ref TCollection collection) + where TCollection : ICollection + => collection.IsSynchronized; + + public static void CopyTo(ref TCollection collection, Array array, int index) + where TCollection : ICollection + { + collection.CopyTo(array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ICollectionCalls`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ICollectionCalls`1.cs new file mode 100755 index 00000000000..f902f8b817b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ICollectionCalls`1.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement + /// the member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class ICollectionCalls + { + public static bool IsReadOnly(ref TCollection collection) + where TCollection : ICollection + => collection.IsReadOnly; + + public static void Add(ref TCollection collection, T item) + where TCollection : ICollection + => collection.Add(item); + + public static void CopyTo(ref TCollection collection, T[] array, int arrayIndex) + where TCollection : ICollection + => collection.CopyTo(array, arrayIndex); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ICollectionDebugView`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ICollectionDebugView`1.cs new file mode 100755 index 00000000000..f59fa686a6a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ICollectionDebugView`1.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ICollectionDebugView.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal sealed class ICollectionDebugView + { + private readonly ICollection _collection; + + public ICollectionDebugView(ICollection collection) + { + _collection = collection ?? throw new ArgumentNullException(nameof(collection)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public T[] Items + { + get + { + var items = new T[_collection.Count]; + _collection.CopyTo(items, 0); + return items; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IDictionaryCalls.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IDictionaryCalls.cs new file mode 100755 index 00000000000..a26d4425a6d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IDictionaryCalls.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement the + /// member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class IDictionaryCalls + { + public static bool IsFixedSize(ref TDictionary dictionary) + where TDictionary : IDictionary + => dictionary.IsFixedSize; + + public static bool IsReadOnly(ref TDictionary dictionary) + where TDictionary : IDictionary + => dictionary.IsReadOnly; + + public static object? GetItem(ref TDictionary dictionary, object key) + where TDictionary : IDictionary + => dictionary[key]; + + public static void SetItem(ref TDictionary dictionary, object key, object? value) + where TDictionary : IDictionary + => dictionary[key] = value; + + public static void Add(ref TDictionary dictionary, object key, object? value) + where TDictionary : IDictionary + => dictionary.Add(key, value); + + public static bool Contains(ref TDictionary dictionary, object key) + where TDictionary : IDictionary + => dictionary.Contains(key); + + public static void CopyTo(ref TDictionary dictionary, Array array, int index) + where TDictionary : IDictionary + => dictionary.CopyTo(array, index); + + public static IDictionaryEnumerator GetEnumerator(ref TDictionary dictionary) + where TDictionary : IDictionary + => dictionary.GetEnumerator(); + + public static void Remove(ref TDictionary dictionary, object key) + where TDictionary : IDictionary + => dictionary.Remove(key); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IDictionaryDebugView`2.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IDictionaryDebugView`2.cs new file mode 100755 index 00000000000..265c29b08a3 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IDictionaryDebugView`2.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionaryDebugView.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal sealed class IDictionaryDebugView + where K : notnull + { + private readonly IDictionary _dict; + + public IDictionaryDebugView(IDictionary dictionary) + { + _dict = dictionary ?? throw new ArgumentNullException(nameof(dictionary)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public KeyValuePair[] Items + { + get + { + var items = new KeyValuePair[_dict.Count]; + _dict.CopyTo(items, 0); + return items; + } + } + } + + internal sealed class DictionaryKeyCollectionDebugView + { + private readonly ICollection _collection; + + public DictionaryKeyCollectionDebugView(ICollection collection) + { + _collection = collection ?? throw new ArgumentNullException(nameof(collection)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public TKey[] Items + { + get + { + var items = new TKey[_collection.Count]; + _collection.CopyTo(items, 0); + return items; + } + } + } + + internal sealed class DictionaryValueCollectionDebugView + { + private readonly ICollection _collection; + + public DictionaryValueCollectionDebugView(ICollection collection) + { + _collection = collection ?? throw new ArgumentNullException(nameof(collection)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public TValue[] Items + { + get + { + var items = new TValue[_collection.Count]; + _collection.CopyTo(items, 0); + return items; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IEnumerableCalls.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IEnumerableCalls.cs new file mode 100755 index 00000000000..4bdd34da0e1 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IEnumerableCalls.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement the + /// member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class IEnumerableCalls + { + public static IEnumerator GetEnumerator(ref TEnumerable enumerable) + where TEnumerable : IEnumerable + { + return enumerable.GetEnumerator(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IEnumerableCalls`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IEnumerableCalls`1.cs new file mode 100755 index 00000000000..000fd0d7075 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IEnumerableCalls`1.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement + /// the member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class IEnumerableCalls + { + public static IEnumerator GetEnumerator(ref TEnumerable enumerable) + where TEnumerable : IEnumerable + { + return enumerable.GetEnumerator(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IListCalls.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IListCalls.cs new file mode 100755 index 00000000000..f7555e2429d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/IListCalls.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Provides static methods to invoke members on value types that explicitly implement the + /// member. + /// + /// + /// Normally, invocation of explicit interface members requires boxing or copying the value type, which is + /// especially problematic for operations that mutate the value. Invocation through these helpers behaves like a + /// normal call to an implicitly implemented member. + /// + internal static class IListCalls + { + public static object? GetItem(ref TList list, int index) + where TList : IList + => list[index]; + + public static void SetItem(ref TList list, int index, object? value) + where TList : IList + => list[index] = value; + + public static bool IsFixedSize(ref TList list) + where TList : IList + => list.IsFixedSize; + + public static bool IsReadOnly(ref TList list) + where TList : IList + => list.IsReadOnly; + + public static int Add(ref TList list, object? value) + where TList : IList + { + return list.Add(value); + } + + public static bool Contains(ref TList list, object? value) + where TList : IList + { + return list.Contains(value); + } + + public static int IndexOf(ref TList list, object? value) + where TList : IList + { + return list.IndexOf(value); + } + + public static void Insert(ref TList list, int index, object? value) + where TList : IList + { + list.Insert(index, value); + } + + public static void Remove(ref TList list, object? value) + where TList : IList + { + list.Remove(value); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/InsertionBehavior.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/InsertionBehavior.cs new file mode 100755 index 00000000000..40e2d12ad2a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/InsertionBehavior.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/InsertionBehavior.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// + /// Used internally to control behavior of insertion into a or . + /// + internal enum InsertionBehavior : byte + { + /// + /// The default insertion behavior. + /// + None = 0, + + /// + /// Specifies that an existing entry with the same key should be overwritten if encountered. + /// + OverwriteExisting = 1, + + /// + /// Specifies that if an existing entry with the same key is encountered, an exception should be thrown. + /// + ThrowOnExisting = 2 + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/RoslynUnsafe.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/RoslynUnsafe.cs new file mode 100755 index 00000000000..d8d40e90c5d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/RoslynUnsafe.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal static unsafe class RoslynUnsafe + { + /// + /// Returns a by-ref to type that is a null reference. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref T NullRef() + => ref Unsafe.AsRef(null); + + /// + /// Returns if a given by-ref to type is a null reference. + /// + /// + /// This check is conceptually similar to (void*)(&source) == nullptr. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsNullRef(ref T source) + => Unsafe.AsPointer(ref source) == null; + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SR.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SR.cs new file mode 100755 index 00000000000..894542ecc44 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SR.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.CodeAnalysis.Collections.Internal; + +internal static class SR +{ + // Strings not localized, should only be used for internal API contract messages and not surfaced to users. + + internal const string Arg_ArrayPlusOffTooSmall = "Destination array is not long enough to copy all the items in the collection. Check array index and length."; + internal const string Arg_HTCapacityOverflow = "Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table."; + internal const string Arg_KeyNotFoundWithKey = "The given key '{0}' was not present in the dictionary."; + internal const string Arg_LongerThanDestArray = "Destination array was not long enough. Check the destination index, length, and the array's lower bounds."; + internal const string Arg_LongerThanSrcArray = "Source array was not long enough. Check the source index, length, and the array's lower bounds."; + internal const string Arg_NonZeroLowerBound = "The lower bound of target array must be zero."; + internal const string Arg_RankMultiDimNotSupported = "Only single dimensional arrays are supported for the requested action."; + internal const string Arg_WrongType = "The value \"{0}\" is not of type \"{1}\" and cannot be used in this generic collection."; + internal const string Argument_AddingDuplicateWithKey = "An item with the same key has already been added. Key: {0}"; + internal const string Argument_IncompatibleArrayType = "Target array type is not compatible with the type of items in the collection."; + internal const string Argument_InvalidOffLen = "Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection."; + internal const string ArgumentOutOfRange_ArrayLB = "Number was less than the array's lower bound in the first dimension."; + internal const string ArgumentOutOfRange_BiggerThanCollection = "Larger than collection size."; + internal const string ArgumentOutOfRange_Count = "Count must be positive and count must refer to a location within the string/array/collection."; + internal const string ArgumentOutOfRange_IndexMustBeLess = "Index was out of range. Must be non-negative and less than the size of the collection."; + internal const string ArgumentOutOfRange_ListInsert = "Index must be within the bounds of the List."; + internal const string ArgumentOutOfRange_NeedNonNegNum = "Non-negative number required."; + internal const string ArgumentOutOfRange_SmallCapacity = "capacity was less than the current size."; + internal const string InvalidOperation_ConcurrentOperationsNotSupported = "Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct."; + internal const string InvalidOperation_EnumFailedVersion = "Collection was modified; enumeration operation may not execute."; + internal const string InvalidOperation_EnumOpCantHappen = "Enumeration has either not started or has already finished."; + internal const string InvalidOperation_IComparerFailed = "Failed to compare two elements in the array."; + internal const string NotSupported_KeyCollectionSet = "Mutating a key collection derived from a dictionary is not allowed."; + internal const string NotSupported_ValueCollectionSet = "Mutating a value collection derived from a dictionary is not allowed."; + internal const string Rank_MustMatch = "The specified arrays must have the same number of dimensions."; + internal const string NotSupported_FixedSizeCollection = "Collection was of a fixed size."; + internal const string ArgumentException_OtherNotArrayOfCorrectLength = "Object is not a array with the same number of elements as the array to compare it to."; + internal const string Arg_BogusIComparer = "Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: '{0}'."; + internal const string CannotFindOldValue = "Cannot find the old value"; + internal const string ArgumentOutOfRange_IndexMustBeLessOrEqual = "Index was out of range. Must be non-negative and less than or equal to the size of the collection."; +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SegmentedArrayHelper.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SegmentedArrayHelper.cs new file mode 100755 index 00000000000..70d87cbaea2 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SegmentedArrayHelper.cs @@ -0,0 +1,206 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal static class SegmentedArrayHelper + { + // This is the threshold where Introspective sort switches to Insertion sort. + // Empirically, 16 seems to speed up most cases without slowing down others, at least for integers. + // Large value types may benefit from a smaller number. + internal const int IntrosortSizeThreshold = 16; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int GetSegmentSize() + { + return Unsafe.SizeOf() switch + { + // Hard code common values since not all versions of the .NET JIT support reducing this computation to a + // constant value at runtime. Values are validated against the reference implementation in + // CalculateSegmentSize in unit tests. + 1 => 65536, + 2 => 32768, + 4 => 16384, + 8 => 8192, + 12 => 4096, + 16 => 4096, + 24 => 2048, + 28 => 2048, + 32 => 2048, + 40 => 2048, + 64 => 1024, +#if NETCOREAPP3_0_OR_GREATER + _ => InlineCalculateSegmentSize(Unsafe.SizeOf()), +#else + _ => FallbackSegmentHelper.SegmentSize, +#endif + }; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int GetSegmentShift() + { + return Unsafe.SizeOf() switch + { + // Hard code common values since not all versions of the .NET JIT support reducing this computation to a + // constant value at runtime. Values are validated against the reference implementation in + // CalculateSegmentSize in unit tests. + 1 => 16, + 2 => 15, + 4 => 14, + 8 => 13, + 12 => 12, + 16 => 12, + 24 => 11, + 28 => 11, + 32 => 11, + 40 => 11, + 64 => 10, +#if NETCOREAPP3_0_OR_GREATER + _ => InlineCalculateSegmentShift(Unsafe.SizeOf()), +#else + _ => FallbackSegmentHelper.SegmentShift, +#endif + }; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int GetOffsetMask() + { + return Unsafe.SizeOf() switch + { + // Hard code common values since not all versions of the .NET JIT support reducing this computation to a + // constant value at runtime. Values are validated against the reference implementation in + // CalculateSegmentSize in unit tests. + 1 => 65535, + 2 => 32767, + 4 => 16383, + 8 => 8191, + 12 => 4095, + 16 => 4095, + 24 => 2047, + 28 => 2047, + 32 => 2047, + 40 => 2047, + 64 => 1023, +#if NETCOREAPP3_0_OR_GREATER + _ => InlineCalculateOffsetMask(Unsafe.SizeOf()), +#else + _ => FallbackSegmentHelper.OffsetMask, +#endif + }; + } + + /// + /// Calculates the maximum number of elements of size which can fit into an array + /// which has the following characteristics: + /// + /// The array can be allocated in the small object heap. + /// The array length is a power of 2. + /// + /// + /// The size of the elements in the array. + /// The segment size to use for small object heap segmented arrays. + private static int CalculateSegmentSize(int elementSize) + { + // Default Large Object Heap size threshold + // https://github.com/dotnet/runtime/blob/c9d69e38d0e54bea5d188593ef6c3b30139f3ab1/src/coreclr/src/gc/gc.h#L111 + const int Threshold = 85000; + + var segmentSize = 2; + while (ArraySize(elementSize, segmentSize << 1) < Threshold) + { + segmentSize <<= 1; + } + + return segmentSize; + + static int ArraySize(int elementSize, int segmentSize) + { + // Array object header, plus space for the elements + return (2 * IntPtr.Size + 8) + (elementSize * segmentSize); + } + } + + /// + /// Calculates a shift which can be applied to an absolute index to get the page index within a segmented array. + /// + /// The number of elements in each page of the segmented array. Must be a power of 2. + /// The shift to apply to the absolute index to get the page index within a segmented array. + private static int CalculateSegmentShift(int segmentSize) + { + var segmentShift = 0; + while (0 != (segmentSize >>= 1)) + { + segmentShift++; + } + + return segmentShift; + } + + /// + /// Calculates a mask, which can be applied to an absolute index to get the index within a page of a segmented + /// array. + /// + /// The number of elements in each page of the segmented array. Must be a power of 2. + /// The bit mask to obtain the index within a page from an absolute index within a segmented array. + private static int CalculateOffsetMask(int segmentSize) + { + Debug.Assert(segmentSize == 1 || (segmentSize & (segmentSize - 1)) == 0, "Expected size of 1, or a power of 2"); + return segmentSize - 1; + } + + // Faster inline implementation for NETCOREAPP to avoid static constructors and non-inlineable + // generics with runtime lookups +#if NETCOREAPP3_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int InlineCalculateSegmentSize(int elementSize) + { + return 1 << InlineCalculateSegmentShift(elementSize); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int InlineCalculateSegmentShift(int elementSize) + { + // Default Large Object Heap size threshold + // https://github.com/dotnet/runtime/blob/c9d69e38d0e54bea5d188593ef6c3b30139f3ab1/src/coreclr/src/gc/gc.h#L111 + const uint Threshold = 85000; + return System.Numerics.BitOperations.Log2((uint)((Threshold / elementSize) - (2 * Unsafe.SizeOf() + 8))); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int InlineCalculateOffsetMask(int elementSize) + { + return InlineCalculateSegmentSize(elementSize) - 1; + } +#endif + + internal static class TestAccessor + { + public static int CalculateSegmentSize(int elementSize) + => SegmentedArrayHelper.CalculateSegmentSize(elementSize); + + public static int CalculateSegmentShift(int segmentSize) + => SegmentedArrayHelper.CalculateSegmentShift(segmentSize); + + public static int CalculateOffsetMask(int segmentSize) + => SegmentedArrayHelper.CalculateOffsetMask(segmentSize); + } + +#if !NETCOREAPP3_0_OR_GREATER + private static class FallbackSegmentHelper + { + public static readonly int SegmentSize = CalculateSegmentSize(Unsafe.SizeOf()); + public static readonly int SegmentShift = CalculateSegmentShift(SegmentSize); + public static readonly int OffsetMask = CalculateOffsetMask(SegmentSize); + } +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SegmentedArraySegment`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SegmentedArraySegment`1.cs new file mode 100755 index 00000000000..69d490ea85f --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SegmentedArraySegment`1.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal readonly struct SegmentedArraySegment + { + public SegmentedArray Array { get; } + public int Start { get; } + public int Length { get; } + + public SegmentedArraySegment(SegmentedArray array, int start, int length) + { + Array = array; + Start = start; + Length = length; + } + + public ref T this[int index] + { + get + { + if ((uint)index >= (uint)Length) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return ref Array[index + Start]; + } + } + + public SegmentedArraySegment Slice(int start) + { + if ((uint)start >= (uint)Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new SegmentedArraySegment(Array, Start + start, Length - start); + } + + public SegmentedArraySegment Slice(int start, int length) + { + // Since start and length are both 32-bit, their sum can be computed across a 64-bit domain + // without loss of fidelity. The cast to uint before the cast to ulong ensures that the + // extension from 32- to 64-bit is zero-extending rather than sign-extending. The end result + // of this is that if either input is negative or if the input sum overflows past Int32.MaxValue, + // that information is captured correctly in the comparison against the backing _length field. + if ((uint)start + (ulong)(uint)length > (uint)Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new SegmentedArraySegment(Array, Start + start, length); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SegmentedHashSetEqualityComparer`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SegmentedHashSetEqualityComparer`1.cs new file mode 100755 index 00000000000..5946c81f763 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/SegmentedHashSetEqualityComparer`1.cs @@ -0,0 +1,90 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSetEqualityComparer.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + /// Equality comparer for hashsets of hashsets + internal sealed class SegmentedHashSetEqualityComparer : IEqualityComparer?> + { + public bool Equals(SegmentedHashSet? x, SegmentedHashSet? y) + { + // If they're the exact same instance, they're equal. + if (ReferenceEquals(x, y)) + { + return true; + } + + // They're not both null, so if either is null, they're not equal. + if (x == null || y == null) + { + return false; + } + + var defaultComparer = EqualityComparer.Default; + + // If both sets use the same comparer, they're equal if they're the same + // size and one is a "subset" of the other. + if (SegmentedHashSet.EqualityComparersAreEqual(x, y)) + { + return x.Count == y.Count && y.IsSubsetOfHashSetWithSameComparer(x); + } + + // Otherwise, do an O(N^2) match. + // 🐛 This is non-symmetrical, but matches original: https://github.com/dotnet/runtime/issues/69218 + foreach (var yi in y) + { + var found = false; + foreach (var xi in x) + { + if (defaultComparer.Equals(yi, xi)) + { + found = true; + break; + } + } + + if (!found) + { + return false; + } + } + + return true; + } + + public int GetHashCode(SegmentedHashSet? obj) + { + var hashCode = 0; // default to 0 for null/empty set + + if (obj != null) + { + foreach (var t in obj) + { + if (t != null) + { + hashCode ^= t.GetHashCode(); // same hashcode as default comparer + } + } + } + + return hashCode; + } + + // Equals method for the comparer itself. + public override bool Equals([NotNullWhen(true)] object? obj) => obj is SegmentedHashSetEqualityComparer; + + public override int GetHashCode() => EqualityComparer.Default.GetHashCode(); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ThrowHelper.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ThrowHelper.cs new file mode 100755 index 00000000000..994a252a9ce --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Internal/ThrowHelper.cs @@ -0,0 +1,383 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// This file defines an internal class used to throw exceptions in BCL code. +// The main purpose is to reduce code size. +// +// The old way to throw an exception generates quite a lot IL code and assembly code. +// Following is an example: +// C# source +// throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key); +// IL code: +// IL_0003: ldstr "key" +// IL_0008: ldstr "ArgumentNull_Key" +// IL_000d: call string System.Environment::GetResourceString(string) +// IL_0012: newobj instance void System.ArgumentNullException::.ctor(string,string) +// IL_0017: throw +// which is 21bytes in IL. +// +// So we want to get rid of the ldstr and call to Environment.GetResource in IL. +// In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the +// argument name and resource name in a small integer. The source code will be changed to +// ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key); +// +// The IL code will be 7 bytes. +// IL_0008: ldc.i4.4 +// IL_0009: ldc.i4.4 +// IL_000a: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument) +// IL_000f: ldarg.0 +// +// This will also reduce the Jitted code size a lot. +// +// It is very important we do this for generic classes because we can easily generate the same code +// multiple times for different instantiation. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Collections.Internal +{ + internal static class ThrowHelper + { + [DoesNotReturn] + internal static void ThrowIndexOutOfRangeException() + { + throw new IndexOutOfRangeException(); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRangeException() + { + throw new ArgumentOutOfRangeException(); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRange_IndexMustBeLessException() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.index, + ExceptionResource.ArgumentOutOfRange_IndexMustBeLess); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.index, + ExceptionResource.ArgumentOutOfRange_IndexMustBeLessOrEqual); + } + + [DoesNotReturn] + internal static void ThrowArgumentException_BadComparer(object? comparer) + { + throw new ArgumentException(string.Format(SR.Arg_BogusIComparer, comparer)); + } + + [DoesNotReturn] + internal static void ThrowIndexArgumentOutOfRange_NeedNonNegNumException() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.index, + ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + [DoesNotReturn] + internal static void ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.length, + ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + [DoesNotReturn] + internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLessOrEqual() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex, + ExceptionResource.ArgumentOutOfRange_IndexMustBeLessOrEqual); + } + + [DoesNotReturn] + internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex, + ExceptionResource.ArgumentOutOfRange_IndexMustBeLess); + } + + [DoesNotReturn] + internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count() + { + throw GetArgumentOutOfRangeException(ExceptionArgument.count, + ExceptionResource.ArgumentOutOfRange_Count); + } + + [DoesNotReturn] + internal static void ThrowWrongKeyTypeArgumentException(T key, Type targetType) + { + // Generic key to move the boxing to the right hand side of throw + throw GetWrongKeyTypeArgumentException(key, targetType); + } + + [DoesNotReturn] + internal static void ThrowWrongValueTypeArgumentException(T value, Type targetType) + { + // Generic key to move the boxing to the right hand side of throw + throw GetWrongValueTypeArgumentException(value, targetType); + } + + private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object? key) + { + return new ArgumentException(string.Format(SR.Argument_AddingDuplicateWithKey, key)); + } + + [DoesNotReturn] + internal static void ThrowAddingDuplicateWithKeyArgumentException(T key) + { + // Generic key to move the boxing to the right hand side of throw + throw GetAddingDuplicateWithKeyArgumentException(key); + } + + [DoesNotReturn] + internal static void ThrowKeyNotFoundException(T key) + { + // Generic key to move the boxing to the right hand side of throw + throw GetKeyNotFoundException(key); + } + + [DoesNotReturn] + internal static void ThrowArgumentException(ExceptionResource resource) + { + throw GetArgumentException(resource); + } + + private static ArgumentNullException GetArgumentNullException(ExceptionArgument argument) + { + return new ArgumentNullException(GetArgumentName(argument)); + } + + [DoesNotReturn] + internal static void ThrowArgumentNullException(ExceptionArgument argument) + { + throw GetArgumentNullException(argument); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument) + { + throw new ArgumentOutOfRangeException(GetArgumentName(argument)); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) + { + throw GetArgumentOutOfRangeException(argument, resource); + } + + [DoesNotReturn] + internal static void ThrowInvalidOperationException(ExceptionResource resource, Exception e) + { + throw new InvalidOperationException(GetResourceString(resource), e); + } + + [DoesNotReturn] + internal static void ThrowNotSupportedException(ExceptionResource resource) + { + throw new NotSupportedException(GetResourceString(resource)); + } + + [DoesNotReturn] + internal static void ThrowArgumentException_Argument_IncompatibleArrayType() + { + throw new ArgumentException(SR.Argument_IncompatibleArrayType); + } + + [DoesNotReturn] + internal static void ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion() + { + throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + } + + [DoesNotReturn] + internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen() + { + throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); + } + + [DoesNotReturn] + internal static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported() + { + throw new InvalidOperationException(SR.InvalidOperation_ConcurrentOperationsNotSupported); + } + + private static ArgumentException GetArgumentException(ExceptionResource resource) + { + return new ArgumentException(GetResourceString(resource)); + } + + private static ArgumentException GetWrongKeyTypeArgumentException(object? key, Type targetType) + { + return new ArgumentException(string.Format(SR.Arg_WrongType, key, targetType), nameof(key)); + } + + private static ArgumentException GetWrongValueTypeArgumentException(object? value, Type targetType) + { + return new ArgumentException(string.Format(SR.Arg_WrongType, value, targetType), nameof(value)); + } + + private static KeyNotFoundException GetKeyNotFoundException(object? key) + { + return new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, key)); + } + + private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) + { + return new ArgumentOutOfRangeException(GetArgumentName(argument), GetResourceString(resource)); + } + + // Allow nulls for reference types and Nullable, but not for value types. + // Aggressively inline so the jit evaluates the if in place and either drops the call altogether + // Or just leaves null test and call to the Non-returning ThrowHelper.ThrowArgumentNullException + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void IfNullAndNullsAreIllegalThenThrow(object? value, ExceptionArgument argName) + { + // Note that default(T) is not equal to null for value types except when T is Nullable. + if (!(default(T) == null) && value == null) + ThrowHelper.ThrowArgumentNullException(argName); + } + + private static string GetArgumentName(ExceptionArgument argument) + { + switch (argument) + { + case ExceptionArgument.dictionary: + return "dictionary"; + case ExceptionArgument.array: + return "array"; + case ExceptionArgument.info: + return "info"; + case ExceptionArgument.key: + return "key"; + case ExceptionArgument.value: + return "value"; + case ExceptionArgument.startIndex: + return "startIndex"; + case ExceptionArgument.index: + return "index"; + case ExceptionArgument.capacity: + return "capacity"; + case ExceptionArgument.collection: + return "collection"; + case ExceptionArgument.item: + return "item"; + case ExceptionArgument.converter: + return "converter"; + case ExceptionArgument.match: + return "match"; + case ExceptionArgument.count: + return "count"; + case ExceptionArgument.action: + return "action"; + case ExceptionArgument.comparison: + return "comparison"; + case ExceptionArgument.source: + return "source"; + case ExceptionArgument.length: + return "length"; + case ExceptionArgument.destinationArray: + return "destinationArray"; + case ExceptionArgument.other: + return "other"; + default: + Debug.Fail("The enum value is not defined, please check the ExceptionArgument Enum."); + return ""; + } + } + + private static string GetResourceString(ExceptionResource resource) + { + switch (resource) + { + case ExceptionResource.ArgumentOutOfRange_IndexMustBeLessOrEqual: + return SR.ArgumentOutOfRange_IndexMustBeLessOrEqual; + case ExceptionResource.ArgumentOutOfRange_IndexMustBeLess: + return SR.ArgumentOutOfRange_IndexMustBeLess; + case ExceptionResource.ArgumentOutOfRange_Count: + return SR.ArgumentOutOfRange_Count; + case ExceptionResource.Arg_ArrayPlusOffTooSmall: + return SR.Arg_ArrayPlusOffTooSmall; + case ExceptionResource.Arg_RankMultiDimNotSupported: + return SR.Arg_RankMultiDimNotSupported; + case ExceptionResource.Arg_NonZeroLowerBound: + return SR.Arg_NonZeroLowerBound; + case ExceptionResource.ArgumentOutOfRange_ListInsert: + return SR.ArgumentOutOfRange_ListInsert; + case ExceptionResource.ArgumentOutOfRange_NeedNonNegNum: + return SR.ArgumentOutOfRange_NeedNonNegNum; + case ExceptionResource.ArgumentOutOfRange_SmallCapacity: + return SR.ArgumentOutOfRange_SmallCapacity; + case ExceptionResource.Argument_InvalidOffLen: + return SR.Argument_InvalidOffLen; + case ExceptionResource.ArgumentOutOfRange_BiggerThanCollection: + return SR.ArgumentOutOfRange_BiggerThanCollection; + case ExceptionResource.NotSupported_KeyCollectionSet: + return SR.NotSupported_KeyCollectionSet; + case ExceptionResource.NotSupported_ValueCollectionSet: + return SR.NotSupported_ValueCollectionSet; + case ExceptionResource.InvalidOperation_IComparerFailed: + return SR.InvalidOperation_IComparerFailed; + default: + Debug.Fail("The enum value is not defined, please check the ExceptionResource Enum."); + return ""; + } + } + } + + // + // The convention for this enum is using the argument name as the enum name + // + internal enum ExceptionArgument + { + dictionary, + array, + info, + key, + value, + startIndex, + index, + capacity, + collection, + item, + converter, + match, + count, + action, + comparison, + source, + length, + destinationArray, + other, + } + + // + // The convention for this enum is using the resource name as the enum name + // + internal enum ExceptionResource + { + ArgumentOutOfRange_IndexMustBeLessOrEqual, + ArgumentOutOfRange_IndexMustBeLess, + ArgumentOutOfRange_Count, + Arg_ArrayPlusOffTooSmall, + Arg_RankMultiDimNotSupported, + Arg_NonZeroLowerBound, + ArgumentOutOfRange_ListInsert, + ArgumentOutOfRange_NeedNonNegNum, + ArgumentOutOfRange_SmallCapacity, + Argument_InvalidOffLen, + ArgumentOutOfRange_BiggerThanCollection, + NotSupported_KeyCollectionSet, + NotSupported_ValueCollectionSet, + InvalidOperation_IComparerFailed, + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/OneOrMany.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/OneOrMany.cs new file mode 100755 index 00000000000..eaad4dcf1c1 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/OneOrMany.cs @@ -0,0 +1,287 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.PooledObjects; + +namespace Roslyn.Utilities +{ + /// + /// Represents a single item or many items (including none). + /// + /// + /// Used when a collection usually contains a single item but sometimes might contain multiple. + /// + [DebuggerDisplay("{GetDebuggerDisplay(),nq}")] + [DebuggerTypeProxy(typeof(OneOrMany<>.DebuggerProxy))] + internal readonly struct OneOrMany + { + public static readonly OneOrMany Empty = new OneOrMany(ImmutableArray.Empty); + + private readonly T? _one; + private readonly ImmutableArray _many; + + public OneOrMany(T one) + { + _one = one; + _many = default; + } + + public OneOrMany(ImmutableArray many) + { + if (many.IsDefault) + { + throw new ArgumentNullException(nameof(many)); + } + + if (many is [var item]) + { + _one = item; + _many = default; + } + else + { + _one = default; + _many = many; + } + } + + /// + /// True if the collection has a single item. This item is stored in . + /// + [MemberNotNullWhen(true, nameof(_one))] + private bool HasOneItem + => _many.IsDefault; + + public bool IsDefault + => _one == null && _many.IsDefault; + + public T this[int index] + { + get + { + if (HasOneItem) + { + if (index != 0) + { + throw new IndexOutOfRangeException(); + } + + return _one; + } + else + { + return _many[index]; + } + } + } + + public int Count + => HasOneItem ? 1 : _many.Length; + + public bool IsEmpty + => Count == 0; + + public OneOrMany Add(T item) + => HasOneItem ? OneOrMany.Create(_one, item) : + IsEmpty ? OneOrMany.Create(item) : + OneOrMany.Create(_many.Add(item)); + + public void AddRangeTo(ArrayBuilder builder) + { + if (HasOneItem) + { + builder.Add(_one); + } + else + { + builder.AddRange(_many); + } + } + + public bool Contains(T item) + => HasOneItem ? EqualityComparer.Default.Equals(item, _one) : _many.Contains(item); + + public OneOrMany RemoveAll(T item) + { + if (HasOneItem) + { + return EqualityComparer.Default.Equals(item, _one) ? Empty : this; + } + + return OneOrMany.Create(_many.WhereAsArray(static (value, item) => !EqualityComparer.Default.Equals(value, item), item)); + } + + public OneOrMany Select(Func selector) + { + return HasOneItem ? + OneOrMany.Create(selector(_one)) : + OneOrMany.Create(_many.SelectAsArray(selector)); + } + + public OneOrMany Select(Func selector, TArg arg) + { + return HasOneItem ? + OneOrMany.Create(selector(_one, arg)) : + OneOrMany.Create(_many.SelectAsArray(selector, arg)); + } + + public T First() => this[0]; + + public T? FirstOrDefault() + => HasOneItem ? _one : _many.FirstOrDefault(); + + public T? FirstOrDefault(Func predicate) + { + if (HasOneItem) + { + return predicate(_one) ? _one : default; + } + + return _many.FirstOrDefault(predicate); + } + + public T? FirstOrDefault(Func predicate, TArg arg) + { + if (HasOneItem) + { + return predicate(_one, arg) ? _one : default; + } + + return _many.FirstOrDefault(predicate, arg); + } + + public static OneOrMany CastUp(OneOrMany from) where TDerived : class, T + { + return from.HasOneItem + ? new OneOrMany(from._one) + : new OneOrMany(ImmutableArray.CastUp(from._many)); + } + + public bool All(Func predicate) + => HasOneItem ? predicate(_one) : _many.All(predicate); + + public bool All(Func predicate, TArg arg) + => HasOneItem ? predicate(_one, arg) : _many.All(predicate, arg); + + public bool Any() + => !IsEmpty; + + public bool Any(Func predicate) + => HasOneItem ? predicate(_one) : _many.Any(predicate); + + public bool Any(Func predicate, TArg arg) + => HasOneItem ? predicate(_one, arg) : _many.Any(predicate, arg); + + public ImmutableArray ToImmutable() + => HasOneItem ? ImmutableArray.Create(_one) : _many; + + public T[] ToArray() + => HasOneItem ? new[] { _one } : _many.ToArray(); + + public bool SequenceEqual(OneOrMany other, IEqualityComparer? comparer = null) + { + comparer ??= EqualityComparer.Default; + + if (Count != other.Count) + { + return false; + } + + Debug.Assert(HasOneItem == other.HasOneItem); + + return HasOneItem ? comparer.Equals(_one, other._one!) : + System.Linq.ImmutableArrayExtensions.SequenceEqual(_many, other._many, comparer); + } + + public bool SequenceEqual(ImmutableArray other, IEqualityComparer? comparer = null) + => SequenceEqual(OneOrMany.Create(other), comparer); + + public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) + { + comparer ??= EqualityComparer.Default; + + if (!HasOneItem) + { + return _many.SequenceEqual(other, comparer); + } + + var first = true; + foreach (var otherItem in other) + { + if (!first || !comparer.Equals(_one, otherItem)) + { + return false; + } + + first = false; + } + + return true; + } + + public Enumerator GetEnumerator() + => new(this); + + internal struct Enumerator + { + private readonly OneOrMany _collection; + private int _index; + + internal Enumerator(OneOrMany collection) + { + _collection = collection; + _index = -1; + } + + public bool MoveNext() + { + _index++; + return _index < _collection.Count; + } + + public T Current => _collection[_index]; + } + + private sealed class DebuggerProxy(OneOrMany instance) + { + private readonly OneOrMany _instance = instance; + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public T[] Items => _instance.ToArray(); + } + + private string GetDebuggerDisplay() + => "Count = " + Count; + } + + internal static class OneOrMany + { + public static OneOrMany Create(T one) + => new OneOrMany(one); + + public static OneOrMany Create(T one, T two) + => new OneOrMany(ImmutableArray.Create(one, two)); + + public static OneOrMany OneOrNone(T? one) + => one is null ? OneOrMany.Empty : new OneOrMany(one); + + public static OneOrMany Create(ImmutableArray many) + => new OneOrMany(many); + + public static bool SequenceEqual(this ImmutableArray array, OneOrMany other, IEqualityComparer? comparer = null) + => Create(array).SequenceEqual(other, comparer); + + public static bool SequenceEqual(this IEnumerable array, OneOrMany other, IEqualityComparer? comparer = null) + => other.SequenceEqual(array, comparer); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/RoslynEnumerable.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/RoslynEnumerable.cs new file mode 100755 index 00000000000..5edd13ee2e5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/RoslynEnumerable.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; +using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace System.Linq +{ + internal static class RoslynEnumerable + { + public static SegmentedList ToSegmentedList(this IEnumerable source) + { + if (source == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + + return new SegmentedList(source); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/RoslynImmutableInterlocked.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/RoslynImmutableInterlocked.cs new file mode 100755 index 00000000000..ae317798435 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/RoslynImmutableInterlocked.cs @@ -0,0 +1,639 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Threading; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static class RoslynImmutableInterlocked + { + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of value stored by the list. + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, + /// as it may run multiple times when races occur with other threads. + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedList location, Func, ImmutableSegmentedList> transformer) + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedList.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of value stored by the list. + /// The type of argument passed to the . + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, as it may run multiple times + /// when races occur with other threads. + /// The argument to pass to . + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedList location, Func, TArg, ImmutableSegmentedList> transformer, TArg transformerArgument) + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedList.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue, transformerArgument); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Assigns a field or variable containing an immutable list to the specified value and returns the previous + /// value. + /// + /// The type of value stored by the list. + /// The field or local variable to change. + /// The new value to assign. + /// The prior value at the specified . + public static ImmutableSegmentedList InterlockedExchange(ref ImmutableSegmentedList location, ImmutableSegmentedList value) + { + return ImmutableSegmentedList.PrivateMarshal.InterlockedExchange(ref location, value); + } + + /// + /// Assigns a field or variable containing an immutable list to the specified value if it is currently equal to + /// another specified value. Returns the previous value. + /// + /// The type of value stored by the list. + /// The field or local variable to change. + /// The new value to assign. + /// The value to check equality for before assigning. + /// The prior value at the specified . + public static ImmutableSegmentedList InterlockedCompareExchange(ref ImmutableSegmentedList location, ImmutableSegmentedList value, ImmutableSegmentedList comparand) + { + return ImmutableSegmentedList.PrivateMarshal.InterlockedCompareExchange(ref location, value, comparand); + } + + /// + /// Assigns a field or variable containing an immutable list to the specified value if it is has not yet been + /// initialized. + /// + /// The type of value stored by the list. + /// The field or local variable to change. + /// The new value to assign. + /// if the field was assigned the specified value; otherwise, + /// if it was previously initialized. + public static bool InterlockedInitialize(ref ImmutableSegmentedList location, ImmutableSegmentedList value) + { + return InterlockedCompareExchange(ref location, value, default(ImmutableSegmentedList)).IsDefault; + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of value stored by the set. + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, + /// as it may run multiple times when races occur with other threads. + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedHashSet location, Func, ImmutableSegmentedHashSet> transformer) + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedHashSet.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of value stored by the set. + /// The type of argument passed to the . + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, as it may run multiple times + /// when races occur with other threads. + /// The argument to pass to . + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedHashSet location, Func, TArg, ImmutableSegmentedHashSet> transformer, TArg transformerArgument) + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedHashSet.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue, transformerArgument); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Assigns a field or variable containing an immutable set to the specified value and returns the + /// previous value. + /// + /// The type of value stored by the set. + /// The field or local variable to change. + /// The new value to assign. + /// The prior value at the specified . + public static ImmutableSegmentedHashSet InterlockedExchange(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value) + { + return ImmutableSegmentedHashSet.PrivateMarshal.InterlockedExchange(ref location, value); + } + + /// + /// Assigns a field or variable containing an immutable set to the specified value if it is currently + /// equal to another specified value. Returns the previous value. + /// + /// The type of value stored by the set. + /// The field or local variable to change. + /// The new value to assign. + /// The value to check equality for before assigning. + /// The prior value at the specified . + public static ImmutableSegmentedHashSet InterlockedCompareExchange(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value, ImmutableSegmentedHashSet comparand) + { + return ImmutableSegmentedHashSet.PrivateMarshal.InterlockedCompareExchange(ref location, value, comparand); + } + + /// + /// Assigns a field or variable containing an immutable set to the specified value if it is has not yet + /// been initialized. + /// + /// The type of value stored by the set. + /// The field or local variable to change. + /// The new value to assign. + /// if the field was assigned the specified value; otherwise, + /// if it was previously initialized. + public static bool InterlockedInitialize(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value) + { + return InterlockedCompareExchange(ref location, value, default(ImmutableSegmentedHashSet)).IsDefault; + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, + /// as it may run multiple times when races occur with other threads. + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedDictionary location, Func, ImmutableSegmentedDictionary> transformer) + where TKey : notnull + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation + /// function. The transformation is retried as many times as necessary to win the optimistic locking race. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// The type of argument passed to the . + /// + /// The variable or field to be changed, which may be accessed by multiple threads. + /// + /// + /// A function that mutates the value. This function should be side-effect free, as it may run multiple times + /// when races occur with other threads. + /// The argument to pass to . + /// + /// if the location's value is changed by applying the result of the + /// function; otherwise, if the location's value remained + /// the same because the last invocation of returned the existing value. + /// + public static bool Update(ref ImmutableSegmentedDictionary location, Func, TArg, ImmutableSegmentedDictionary> transformer, TArg transformerArgument) + where TKey : notnull + { + if (transformer is null) + throw new ArgumentNullException(nameof(transformer)); + + var oldValue = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + var newValue = transformer(oldValue, transformerArgument); + if (oldValue == newValue) + { + // No change was actually required. + return false; + } + + var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue); + if (oldValue == interlockedResult) + return true; + + oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Assigns a field or variable containing an immutable dictionary to the specified value and returns the + /// previous value. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// The field or local variable to change. + /// The new value to assign. + /// The prior value at the specified . + public static ImmutableSegmentedDictionary InterlockedExchange(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value) + where TKey : notnull + { + return ImmutableSegmentedDictionary.PrivateMarshal.InterlockedExchange(ref location, value); + } + + /// + /// Assigns a field or variable containing an immutable dictionary to the specified value if it is currently + /// equal to another specified value. Returns the previous value. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// The field or local variable to change. + /// The new value to assign. + /// The value to check equality for before assigning. + /// The prior value at the specified . + public static ImmutableSegmentedDictionary InterlockedCompareExchange(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value, ImmutableSegmentedDictionary comparand) + where TKey : notnull + { + return ImmutableSegmentedDictionary.PrivateMarshal.InterlockedCompareExchange(ref location, value, comparand); + } + + /// + /// Assigns a field or variable containing an immutable dictionary to the specified value if it is has not yet + /// been initialized. + /// + /// The type of key stored by the dictionary. + /// The type of value stored by the dictionary. + /// The field or local variable to change. + /// The new value to assign. + /// if the field was assigned the specified value; otherwise, + /// if it was previously initialized. + public static bool InterlockedInitialize(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value) + where TKey : notnull + { + return InterlockedCompareExchange(ref location, value, default(ImmutableSegmentedDictionary)).IsDefault; + } + + /// + public static TValue GetOrAdd(ref ImmutableSegmentedDictionary location, TKey key, Func valueFactory, TArg factoryArgument) + where TKey : notnull + { + if (valueFactory is null) + throw new ArgumentNullException(nameof(valueFactory)); + + var map = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + if (map.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (map.TryGetValue(key, out var value)) + { + return value; + } + + value = valueFactory(key, factoryArgument); + return GetOrAdd(ref location, key, value); + } + + /// + public static TValue GetOrAdd(ref ImmutableSegmentedDictionary location, TKey key, Func valueFactory) + where TKey : notnull + { + if (valueFactory is null) + throw new ArgumentNullException(nameof(valueFactory)); + + var map = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + if (map.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (map.TryGetValue(key, out var value)) + { + return value; + } + + value = valueFactory(key); + return GetOrAdd(ref location, key, value); + } + + /// + public static TValue GetOrAdd(ref ImmutableSegmentedDictionary location, TKey key, TValue value) + where TKey : notnull + { + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (priorCollection.TryGetValue(key, out var oldValue)) + { + return oldValue; + } + + var updatedCollection = priorCollection.Add(key, value); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + // We won the race-condition and have updated the collection. + // Return the value that is in the collection (as of the Interlocked operation). + return value; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static TValue AddOrUpdate(ref ImmutableSegmentedDictionary location, TKey key, Func addValueFactory, Func updateValueFactory) + where TKey : notnull + { + if (addValueFactory is null) + throw new ArgumentNullException(nameof(addValueFactory)); + if (updateValueFactory is null) + throw new ArgumentNullException(nameof(updateValueFactory)); + + TValue newValue; + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (priorCollection.TryGetValue(key, out var oldValue)) + { + newValue = updateValueFactory(key, oldValue); + } + else + { + newValue = addValueFactory(key); + } + + var updatedCollection = priorCollection.SetItem(key, newValue); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + // We won the race-condition and have updated the collection. + // Return the value that is in the collection (as of the Interlocked operation). + return newValue; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static TValue AddOrUpdate(ref ImmutableSegmentedDictionary location, TKey key, TValue addValue, Func updateValueFactory) + where TKey : notnull + { + if (updateValueFactory is null) + throw new ArgumentNullException(nameof(updateValueFactory)); + + TValue newValue; + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (priorCollection.TryGetValue(key, out var oldValue)) + { + newValue = updateValueFactory(key, oldValue); + } + else + { + newValue = addValue; + } + + var updatedCollection = priorCollection.SetItem(key, newValue); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + // We won the race-condition and have updated the collection. + // Return the value that is in the collection (as of the Interlocked operation). + return newValue; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static bool TryAdd(ref ImmutableSegmentedDictionary location, TKey key, TValue value) + where TKey : notnull + { + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (priorCollection.ContainsKey(key)) + { + return false; + } + + var updatedCollection = priorCollection.Add(key, value); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + return true; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static bool TryUpdate(ref ImmutableSegmentedDictionary location, TKey key, TValue newValue, TValue comparisonValue) + where TKey : notnull + { + var valueComparer = EqualityComparer.Default; + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (!priorCollection.TryGetValue(key, out var priorValue) || !valueComparer.Equals(priorValue, comparisonValue)) + { + // The key isn't in the dictionary, or its current value doesn't match what the caller expected. + return false; + } + + var updatedCollection = priorCollection.SetItem(key, newValue); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + return true; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + public static bool TryRemove(ref ImmutableSegmentedDictionary location, TKey key, [MaybeNullWhen(false)] out TValue value) + where TKey : notnull + { + var priorCollection = ImmutableSegmentedDictionary.PrivateMarshal.VolatileRead(in location); + while (true) + { + if (priorCollection.IsDefault) + throw new ArgumentNullException(nameof(location)); + + if (!priorCollection.TryGetValue(key, out value)) + { + return false; + } + + var updatedCollection = priorCollection.Remove(key); + var interlockedResult = InterlockedCompareExchange(ref location, updatedCollection, priorCollection); + if (priorCollection == interlockedResult) + { + return true; + } + + priorCollection = interlockedResult; // we already have a volatile read that we can reuse for the next loop + } + } + + /// + /// Reads from an ImmutableArray location, ensuring that a read barrier is inserted to prevent any subsequent reads from being reordered before this read. + /// + /// + /// This method is not intended to be used to provide write barriers. + /// + public static ImmutableArray VolatileRead(ref readonly ImmutableArray location) + { + var value = location; + // When Volatile.ReadBarrier() is available in .NET 10, it can be used here. + Interlocked.MemoryBarrier(); + return value; + } + + /// + /// Writes to an ImmutableArray location, ensuring that a write barrier is inserted to prevent any prior writes from being reordered after this write. + /// + /// + /// This method is not intended to be used to provide read barriers. + /// + public static void VolatileWrite(ref ImmutableArray location, ImmutableArray value) + { + // When Volatile.WriteBarrier() is available in .NET 10, it can be used here. + Interlocked.MemoryBarrier(); + location = value; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary.cs new file mode 100755 index 00000000000..70ca2fa8c17 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Provides methods for creating a segmented dictionary that is immutable; meaning it cannot be changed once it is + /// created. + /// + internal static class ImmutableSegmentedDictionary + { + public static ImmutableSegmentedDictionary Create() + where TKey : notnull + => ImmutableSegmentedDictionary.Empty; + + public static ImmutableSegmentedDictionary Create(IEqualityComparer? keyComparer) + where TKey : notnull + => ImmutableSegmentedDictionary.Empty.WithComparer(keyComparer); + + public static ImmutableSegmentedDictionary.Builder CreateBuilder() + where TKey : notnull + => Create().ToBuilder(); + + public static ImmutableSegmentedDictionary.Builder CreateBuilder(IEqualityComparer? keyComparer) + where TKey : notnull + => Create(keyComparer).ToBuilder(); + + public static ImmutableSegmentedDictionary CreateRange(IEnumerable> items) + where TKey : notnull + => ImmutableSegmentedDictionary.Empty.AddRange(items); + + public static ImmutableSegmentedDictionary CreateRange(IEqualityComparer? keyComparer, IEnumerable> items) + where TKey : notnull + => ImmutableSegmentedDictionary.Empty.WithComparer(keyComparer).AddRange(items); + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable> items) + where TKey : notnull + => ToImmutableSegmentedDictionary(items, keyComparer: null); + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this ImmutableSegmentedDictionary.Builder builder) + where TKey : notnull + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + return builder.ToImmutable(); + } + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable> items, IEqualityComparer? keyComparer) + where TKey : notnull + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + if (items is ImmutableSegmentedDictionary existingDictionary) + return existingDictionary.WithComparer(keyComparer); + + return ImmutableSegmentedDictionary.Empty.WithComparer(keyComparer).AddRange(items); + } + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable source, Func keySelector, Func elementSelector) + where TKey : notnull + => ToImmutableSegmentedDictionary(source, keySelector, elementSelector, keyComparer: null); + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? keyComparer) + where TKey : notnull + { + if (source is null) + throw new ArgumentNullException(nameof(source)); + if (keySelector is null) + throw new ArgumentNullException(nameof(keySelector)); + if (elementSelector is null) + throw new ArgumentNullException(nameof(elementSelector)); + + return ImmutableSegmentedDictionary.Empty.WithComparer(keyComparer) + .AddRange(source.Select(element => new KeyValuePair(keySelector(element), elementSelector(element)))); + } + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable source, Func keySelector) + where TKey : notnull + => ToImmutableSegmentedDictionary(source, keySelector, elementSelector: static x => x, keyComparer: null); + + public static ImmutableSegmentedDictionary ToImmutableSegmentedDictionary(this IEnumerable source, Func keySelector, IEqualityComparer? keyComparer) + where TKey : notnull + => ToImmutableSegmentedDictionary(source, keySelector, elementSelector: static x => x, keyComparer); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder+KeyCollection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder+KeyCollection.cs new file mode 100755 index 00000000000..6f406539a72 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder+KeyCollection.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public partial class Builder + { + public readonly struct KeyCollection : ICollection, IReadOnlyCollection, ICollection + { + private readonly ImmutableSegmentedDictionary.Builder _dictionary; + + internal KeyCollection(ImmutableSegmentedDictionary.Builder dictionary) + { + Debug.Assert(dictionary is not null); + _dictionary = dictionary!; + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => false; + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + void ICollection.Add(TKey item) + => throw new NotSupportedException(); + + public void Clear() + => _dictionary.Clear(); + + public bool Contains(TKey item) + => _dictionary.ContainsKey(item); + + public void CopyTo(TKey[] array, int arrayIndex) + => _dictionary.ReadOnlyDictionary.Keys.CopyTo(array, arrayIndex); + + public ImmutableSegmentedDictionary.KeyCollection.Enumerator GetEnumerator() + => new(_dictionary.GetEnumerator()); + + public bool Remove(TKey item) + => _dictionary.Remove(item); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary.ReadOnlyDictionary.Keys).CopyTo(array, index); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder+PrivateMarshal.cs new file mode 100755 index 00000000000..174a53dfc09 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder+PrivateMarshal.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections; + +internal readonly partial struct ImmutableSegmentedDictionary +{ + public partial class Builder + { + /// + /// Private helper class for use only by . + /// + internal static class PrivateMarshal + { + /// + public static ref TValue FindValue(Builder dictionary, TKey key) + => ref SegmentedCollectionsMarshal.GetValueRefOrNullRef(dictionary._builder.GetOrCreateMutableDictionary(), key); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder+ValueCollection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder+ValueCollection.cs new file mode 100755 index 00000000000..bf68f898f0a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder+ValueCollection.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public partial class Builder + { + public readonly struct ValueCollection : ICollection, IReadOnlyCollection, ICollection + { + private readonly ImmutableSegmentedDictionary.Builder _dictionary; + + internal ValueCollection(ImmutableSegmentedDictionary.Builder dictionary) + { + Debug.Assert(dictionary is not null); + _dictionary = dictionary!; + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => false; + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + void ICollection.Add(TValue item) + => throw new NotSupportedException(); + + public void Clear() + => _dictionary.Clear(); + + public bool Contains(TValue item) + => _dictionary.ContainsValue(item); + + public void CopyTo(TValue[] array, int arrayIndex) + => _dictionary.ReadOnlyDictionary.Values.CopyTo(array, arrayIndex); + + public ImmutableSegmentedDictionary.ValueCollection.Enumerator GetEnumerator() + => new(_dictionary.GetEnumerator()); + + bool ICollection.Remove(TValue item) + => throw new NotSupportedException(); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary.ReadOnlyDictionary.Values).CopyTo(array, index); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder.cs new file mode 100755 index 00000000000..a1e438608ac --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Builder.cs @@ -0,0 +1,159 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public sealed partial class Builder : IDictionary, IReadOnlyDictionary, IDictionary + { + /// + /// The private builder implementation. + /// + private ValueBuilder _builder; + + internal Builder(ImmutableSegmentedDictionary dictionary) + => _builder = new ValueBuilder(dictionary); + + public IEqualityComparer KeyComparer + { + get => _builder.KeyComparer; + set => _builder.KeyComparer = value; + } + + public int Count => _builder.Count; + + public KeyCollection Keys => new(this); + + public ValueCollection Values => new(this); + + private SegmentedDictionary ReadOnlyDictionary => _builder.ReadOnlyDictionary; + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Values => Values; + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + bool ICollection>.IsReadOnly => ICollectionCalls>.IsReadOnly(ref _builder); + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + bool IDictionary.IsReadOnly => IDictionaryCalls.IsReadOnly(ref _builder); + + bool IDictionary.IsFixedSize => IDictionaryCalls.IsFixedSize(ref _builder); + + object ICollection.SyncRoot => this; + + bool ICollection.IsSynchronized => ICollectionCalls.IsSynchronized(ref _builder); + + public TValue this[TKey key] + { + get => _builder[key]; + set => _builder[key] = value; + } + + object? IDictionary.this[object key] + { + get => IDictionaryCalls.GetItem(ref _builder, key); + set => IDictionaryCalls.SetItem(ref _builder, key, value); + } + + public void Add(TKey key, TValue value) + => _builder.Add(key, value); + + public void Add(KeyValuePair item) + => _builder.Add(item); + + public void AddRange(IEnumerable> items) + => _builder.AddRange(items); + + public void Clear() + => _builder.Clear(); + + public bool Contains(KeyValuePair item) + => _builder.Contains(item); + + public bool ContainsKey(TKey key) + => _builder.ContainsKey(key); + + public bool ContainsValue(TValue value) + => _builder.ContainsValue(value); + + public Enumerator GetEnumerator() + => _builder.GetEnumerator(); + + public TValue? GetValueOrDefault(TKey key) + => _builder.GetValueOrDefault(key); + + public TValue GetValueOrDefault(TKey key, TValue defaultValue) + => _builder.GetValueOrDefault(key, defaultValue); + + public bool Remove(TKey key) + => _builder.Remove(key); + + public bool Remove(KeyValuePair item) + => _builder.Remove(item); + + public void RemoveRange(IEnumerable keys) + => _builder.RemoveRange(keys); + + public bool TryGetKey(TKey equalKey, out TKey actualKey) + => _builder.TryGetKey(equalKey, out actualKey); + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + => _builder.TryGetValue(key, out value); + + public ImmutableSegmentedDictionary ToImmutable() + => _builder.ToImmutable(); + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + => ICollectionCalls>.CopyTo(ref _builder, array, arrayIndex); + + IEnumerator> IEnumerable>.GetEnumerator() + => IEnumerableCalls>.GetEnumerator(ref _builder); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + + bool IDictionary.Contains(object key) + => IDictionaryCalls.Contains(ref _builder, key); + + void IDictionary.Add(object key, object? value) + => IDictionaryCalls.Add(ref _builder, key, value); + + IDictionaryEnumerator IDictionary.GetEnumerator() + => IDictionaryCalls.GetEnumerator(ref _builder); + + void IDictionary.Remove(object key) + => IDictionaryCalls.Remove(ref _builder, key); + + void ICollection.CopyTo(Array array, int index) + => ICollectionCalls.CopyTo(ref _builder, array, index); + + internal TestAccessor GetTestAccessor() + => new TestAccessor(this); + + internal readonly struct TestAccessor(Builder instance) + { + internal SegmentedDictionary GetOrCreateMutableDictionary() + => instance._builder.GetOrCreateMutableDictionary(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Enumerator.cs new file mode 100755 index 00000000000..5513c12bbc7 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+Enumerator.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public struct Enumerator : IEnumerator>, IDictionaryEnumerator + { + private readonly SegmentedDictionary _dictionary; + private readonly ReturnType _returnType; + private SegmentedDictionary.Enumerator _enumerator; + + internal Enumerator(SegmentedDictionary dictionary, ReturnType returnType) + { + _dictionary = dictionary; + _returnType = returnType; + _enumerator = dictionary.GetEnumerator(); + } + + internal enum ReturnType + { + /// + /// The return value from the implementation of is + /// . This is the return value for most instances of this + /// enumerator. + /// + KeyValuePair, + + /// + /// The return value from the implementation of is + /// . This is the return value for instances of this + /// enumerator created by the implementation in + /// . + /// + DictionaryEntry, + } + + public readonly KeyValuePair Current => _enumerator.Current; + + readonly object IEnumerator.Current => _returnType == ReturnType.DictionaryEntry ? ((IDictionaryEnumerator)this).Entry : Current; + + readonly DictionaryEntry IDictionaryEnumerator.Entry => new(Current.Key, Current.Value); + + readonly object IDictionaryEnumerator.Key => Current.Key; + + readonly object? IDictionaryEnumerator.Value => Current.Value; + + public readonly void Dispose() + => _enumerator.Dispose(); + + public bool MoveNext() + => _enumerator.MoveNext(); + + public void Reset() + { + _enumerator = _dictionary.GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection+Enumerator.cs new file mode 100755 index 00000000000..d4a04d85269 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection+Enumerator.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public partial struct KeyCollection + { + public struct Enumerator : IEnumerator + { + private ImmutableSegmentedDictionary.Enumerator _enumerator; + + internal Enumerator(ImmutableSegmentedDictionary.Enumerator enumerator) + { + _enumerator = enumerator; + } + + public readonly TKey Current => _enumerator.Current.Key; + + readonly object IEnumerator.Current => Current; + + public readonly void Dispose() + => _enumerator.Dispose(); + + public bool MoveNext() + => _enumerator.MoveNext(); + + public void Reset() + => _enumerator.Reset(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection.cs new file mode 100755 index 00000000000..dbdbd4e515d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+KeyCollection.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public readonly partial struct KeyCollection : IReadOnlyCollection, ICollection, ICollection + { + private readonly ImmutableSegmentedDictionary _dictionary; + + internal KeyCollection(ImmutableSegmentedDictionary dictionary) + { + _dictionary = dictionary; + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => true; + + bool ICollection.IsSynchronized => true; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + public Enumerator GetEnumerator() + => new(_dictionary.GetEnumerator()); + + public bool Contains(TKey item) + => _dictionary.ContainsKey(item); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + void ICollection.CopyTo(TKey[] array, int arrayIndex) + => _dictionary._dictionary.Keys.CopyTo(array, arrayIndex); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary._dictionary.Keys).CopyTo(array, index); + + void ICollection.Add(TKey item) + => throw new NotSupportedException(); + + void ICollection.Clear() + => throw new NotSupportedException(); + + bool ICollection.Remove(TKey item) + => throw new NotSupportedException(); + + public bool All(Func predicate, TArg arg) + { + foreach (var item in this) + { + if (!predicate(item, arg)) + { + return false; + } + } + + return true; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+PrivateMarshal.cs new file mode 100755 index 00000000000..3b6ee1c382d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+PrivateMarshal.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + /// + /// Private helper class for use only by and + /// . + /// + internal static class PrivateMarshal + { + internal static ImmutableSegmentedDictionary VolatileRead(in ImmutableSegmentedDictionary location) + { + var dictionary = Volatile.Read(ref Unsafe.AsRef(in location._dictionary)); + if (dictionary is null) + return default; + + return new ImmutableSegmentedDictionary(dictionary); + } + + internal static ImmutableSegmentedDictionary InterlockedExchange(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value) + { + var dictionary = Interlocked.Exchange(ref Unsafe.AsRef(in location._dictionary), value._dictionary); + if (dictionary is null) + return default; + + return new ImmutableSegmentedDictionary(dictionary); + } + + internal static ImmutableSegmentedDictionary InterlockedCompareExchange(ref ImmutableSegmentedDictionary location, ImmutableSegmentedDictionary value, ImmutableSegmentedDictionary comparand) + { + var dictionary = Interlocked.CompareExchange(ref Unsafe.AsRef(in location._dictionary), value._dictionary, comparand._dictionary); + if (dictionary is null) + return default; + + return new ImmutableSegmentedDictionary(dictionary); + } + + /// + public static ref readonly TValue FindValue(ImmutableSegmentedDictionary dictionary, TKey key) + => ref SegmentedCollectionsMarshal.GetValueRefOrNullRef(dictionary._dictionary, key); + + /// + internal static ImmutableSegmentedDictionary AsImmutableSegmentedDictionary(SegmentedDictionary? dictionary) + => dictionary is not null ? new ImmutableSegmentedDictionary(dictionary) : default; + + /// + internal static SegmentedDictionary? AsSegmentedDictionary(ImmutableSegmentedDictionary dictionary) + => dictionary._dictionary; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+ValueBuilder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+ValueBuilder.cs new file mode 100755 index 00000000000..f57337bbd1d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+ValueBuilder.cs @@ -0,0 +1,261 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + private struct ValueBuilder : IDictionary, IReadOnlyDictionary, IDictionary + { + /// + /// The immutable collection this builder is based on. + /// + private ImmutableSegmentedDictionary _dictionary; + + /// + /// The current mutable collection this builder is operating on. This field is initialized to a copy of + /// the first time a change is made. + /// + private SegmentedDictionary? _mutableDictionary; + + internal ValueBuilder(ImmutableSegmentedDictionary dictionary) + { + _dictionary = dictionary; + _mutableDictionary = null; + } + + public IEqualityComparer KeyComparer + { + readonly get + { + return ReadOnlyDictionary.Comparer; + } + + set + { + if (value is null) + throw new ArgumentNullException(nameof(value)); + + if (value != KeyComparer) + { + // Rewrite the mutable dictionary using a new comparer + var valuesToAdd = ReadOnlyDictionary; + _mutableDictionary = new SegmentedDictionary(value); + _dictionary = default; + AddRange(valuesToAdd); + } + } + } + + public readonly int Count => ReadOnlyDictionary.Count; + + internal readonly SegmentedDictionary ReadOnlyDictionary => _mutableDictionary ?? _dictionary._dictionary; + + readonly IEnumerable IReadOnlyDictionary.Keys => throw new NotSupportedException(); + + readonly IEnumerable IReadOnlyDictionary.Values => throw new NotSupportedException(); + + readonly ICollection IDictionary.Keys => throw new NotSupportedException(); + + readonly ICollection IDictionary.Values => throw new NotSupportedException(); + + readonly bool ICollection>.IsReadOnly => false; + + readonly ICollection IDictionary.Keys => throw new NotSupportedException(); + + readonly ICollection IDictionary.Values => throw new NotSupportedException(); + + readonly bool IDictionary.IsReadOnly => false; + + readonly bool IDictionary.IsFixedSize => false; + + readonly object ICollection.SyncRoot => throw new NotSupportedException(); + + readonly bool ICollection.IsSynchronized => false; + + public TValue this[TKey key] + { + readonly get => ReadOnlyDictionary[key]; + set => GetOrCreateMutableDictionary()[key] = value; + } + + object? IDictionary.this[object key] + { + readonly get => ((IDictionary)ReadOnlyDictionary)[key]; + set => ((IDictionary)GetOrCreateMutableDictionary())[key] = value; + } + + internal SegmentedDictionary GetOrCreateMutableDictionary() + { + if (_mutableDictionary is null) + { + var originalDictionary = RoslynImmutableInterlocked.InterlockedExchange(ref _dictionary, default); + if (originalDictionary.IsDefault) + throw new InvalidOperationException($"Unexpected concurrent access to {GetType()}"); + + _mutableDictionary = new SegmentedDictionary(originalDictionary._dictionary, originalDictionary.KeyComparer); + } + + return _mutableDictionary; + } + + public void Add(TKey key, TValue value) + { + if (Contains(new KeyValuePair(key, value))) + return; + + GetOrCreateMutableDictionary().Add(key, value); + } + + public void Add(KeyValuePair item) + => Add(item.Key, item.Value); + + public void AddRange(IEnumerable> items) + { + if (items == null) + throw new ArgumentNullException(nameof(items)); + + foreach (var pair in items) + Add(pair.Key, pair.Value); + } + + public void Clear() + { + if (ReadOnlyDictionary.Count != 0) + { + if (_mutableDictionary is null) + { + _mutableDictionary = new SegmentedDictionary(KeyComparer); + _dictionary = default; + } + else + { + _mutableDictionary.Clear(); + } + } + } + + public readonly bool Contains(KeyValuePair item) + { + return TryGetValue(item.Key, out var value) + && EqualityComparer.Default.Equals(value, item.Value); + } + + public readonly bool ContainsKey(TKey key) + => ReadOnlyDictionary.ContainsKey(key); + + public readonly bool ContainsValue(TValue value) + => ReadOnlyDictionary.ContainsValue(value); + + public Enumerator GetEnumerator() + => new(GetOrCreateMutableDictionary(), Enumerator.ReturnType.KeyValuePair); + + public readonly TValue? GetValueOrDefault(TKey key) + { + if (TryGetValue(key, out var value)) + return value; + + return default; + } + + public readonly TValue GetValueOrDefault(TKey key, TValue defaultValue) + { + if (TryGetValue(key, out var value)) + return value; + + return defaultValue; + } + + public bool Remove(TKey key) + { + if (_mutableDictionary is null && !ContainsKey(key)) + return false; + + return GetOrCreateMutableDictionary().Remove(key); + } + + public bool Remove(KeyValuePair item) + { + if (!Contains(item)) + { + return false; + } + + GetOrCreateMutableDictionary().Remove(item.Key); + return true; + } + + public void RemoveRange(IEnumerable keys) + { + if (keys is null) + throw new ArgumentNullException(nameof(keys)); + + foreach (var key in keys) + { + Remove(key); + } + } + +#pragma warning disable IDE0251 // Make member 'readonly' (false positive: https://github.com/dotnet/roslyn/issues/72335) + public bool TryGetKey(TKey equalKey, out TKey actualKey) +#pragma warning restore IDE0251 // Make member 'readonly' + { + foreach (var pair in this) + { + if (KeyComparer.Equals(pair.Key, equalKey)) + { + actualKey = pair.Key; + return true; + } + } + + actualKey = equalKey; + return false; + } + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + public readonly bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + => ReadOnlyDictionary.TryGetValue(key, out value); + + public ImmutableSegmentedDictionary ToImmutable() + { + _dictionary = new ImmutableSegmentedDictionary(ReadOnlyDictionary); + _mutableDictionary = null; + return _dictionary; + } + + readonly void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + => ((ICollection>)ReadOnlyDictionary).CopyTo(array, arrayIndex); + + IEnumerator> IEnumerable>.GetEnumerator() + => new Enumerator(GetOrCreateMutableDictionary(), Enumerator.ReturnType.KeyValuePair); + + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(GetOrCreateMutableDictionary(), Enumerator.ReturnType.KeyValuePair); + + readonly bool IDictionary.Contains(object key) + => ((IDictionary)ReadOnlyDictionary).Contains(key); + + void IDictionary.Add(object key, object? value) + => ((IDictionary)GetOrCreateMutableDictionary()).Add(key, value); + + IDictionaryEnumerator IDictionary.GetEnumerator() + => new Enumerator(GetOrCreateMutableDictionary(), Enumerator.ReturnType.DictionaryEntry); + + void IDictionary.Remove(object key) + => ((IDictionary)GetOrCreateMutableDictionary()).Remove(key); + + readonly void ICollection.CopyTo(Array array, int index) + => ((ICollection)ReadOnlyDictionary).CopyTo(array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection+Enumerator.cs new file mode 100755 index 00000000000..dccb9177d81 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection+Enumerator.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public partial struct ValueCollection + { + public struct Enumerator : IEnumerator + { + private ImmutableSegmentedDictionary.Enumerator _enumerator; + + internal Enumerator(ImmutableSegmentedDictionary.Enumerator enumerator) + { + _enumerator = enumerator; + } + + public readonly TValue Current => _enumerator.Current.Value; + + readonly object? IEnumerator.Current => Current; + + public readonly void Dispose() + => _enumerator.Dispose(); + + public bool MoveNext() + => _enumerator.MoveNext(); + + public void Reset() + => _enumerator.Reset(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection.cs new file mode 100755 index 00000000000..966328f845f --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2+ValueCollection.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedDictionary + { + public readonly partial struct ValueCollection : IReadOnlyCollection, ICollection, ICollection + { + private readonly ImmutableSegmentedDictionary _dictionary; + + internal ValueCollection(ImmutableSegmentedDictionary dictionary) + { + _dictionary = dictionary; + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => true; + + bool ICollection.IsSynchronized => true; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + public Enumerator GetEnumerator() + => new(_dictionary.GetEnumerator()); + + public bool Contains(TValue item) + => _dictionary.ContainsValue(item); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + void ICollection.CopyTo(TValue[] array, int arrayIndex) + => _dictionary._dictionary.Values.CopyTo(array, arrayIndex); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary._dictionary.Values).CopyTo(array, index); + + void ICollection.Add(TValue item) + => throw new NotSupportedException(); + + void ICollection.Clear() + => throw new NotSupportedException(); + + bool ICollection.Remove(TValue item) + => throw new NotSupportedException(); + + public bool All(Func predicate, TArg arg) + { + foreach (var item in this) + { + if (!predicate(item, arg)) + { + return false; + } + } + + return true; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2.cs new file mode 100755 index 00000000000..8898ed1e367 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedDictionary`2.cs @@ -0,0 +1,392 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a segmented dictionary that is immutable; meaning it cannot be changed once it is created. + /// + /// + /// There are different scenarios best for and others + /// best for . + /// + /// In general, is applicable in scenarios most like + /// the scenarios where is applicable, and + /// is applicable in scenarios most like the scenarios where + /// is applicable. + /// + /// The following table summarizes the performance characteristics of + /// : + /// + /// + /// + /// Operation + /// Complexity + /// Complexity + /// Comments + /// + /// + /// Item + /// O(1) + /// O(log n) + /// Directly index into the underlying segmented dictionary + /// + /// + /// Add() + /// O(n) + /// O(log n) + /// Requires creating a new segmented dictionary + /// + /// + /// + /// This type is backed by segmented arrays to avoid using the Large Object Heap without impacting algorithmic + /// complexity. + /// + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + /// + /// This type has a documented contract of being exactly one reference-type field in size. Our own + /// class depends on it, as well as others externally. + /// + /// IMPORTANT NOTICE FOR MAINTAINERS AND REVIEWERS: + /// + /// This type should be thread-safe. As a struct, it cannot protect its own fields from being changed from one + /// thread while its members are executing on other threads because structs can change in place simply by + /// reassigning the field containing this struct. Therefore it is extremely important that ⚠⚠ Every member + /// should only dereference this ONCE ⚠⚠. If a member needs to reference the + /// field, that counts as a dereference of this. Calling other instance members + /// (properties or methods) also counts as dereferencing this. Any member that needs to use this more + /// than once must instead assign this to a local variable and use that for the rest of the code instead. + /// This effectively copies the one field in the struct to a local variable so that it is insulated from other + /// threads. + /// + internal readonly partial struct ImmutableSegmentedDictionary : IImmutableDictionary, IDictionary, IReadOnlyDictionary, IDictionary, IEquatable> + where TKey : notnull + { + public static readonly ImmutableSegmentedDictionary Empty = new(new SegmentedDictionary()); + + private readonly SegmentedDictionary _dictionary; + + private ImmutableSegmentedDictionary(SegmentedDictionary dictionary) + { + _dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary)); + } + + public IEqualityComparer KeyComparer => _dictionary.Comparer; + + public int Count => _dictionary.Count; + + public bool IsEmpty => _dictionary.Count == 0; + + public bool IsDefault => _dictionary == null; + + public bool IsDefaultOrEmpty => _dictionary?.Count is null or 0; + + public KeyCollection Keys => new(this); + + public ValueCollection Values => new(this); + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Values => Values; + + bool ICollection>.IsReadOnly => true; + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + bool IDictionary.IsReadOnly => true; + + bool IDictionary.IsFixedSize => true; + + object ICollection.SyncRoot => _dictionary; + + bool ICollection.IsSynchronized => true; + + public TValue this[TKey key] => _dictionary[key]; + + TValue IDictionary.this[TKey key] + { + get => this[key]; + set => throw new NotSupportedException(); + } + + object? IDictionary.this[object key] + { + get => ((IDictionary)_dictionary)[key]; + set => throw new NotSupportedException(); + } + + public static bool operator ==(ImmutableSegmentedDictionary left, ImmutableSegmentedDictionary right) + => left.Equals(right); + + public static bool operator !=(ImmutableSegmentedDictionary left, ImmutableSegmentedDictionary right) + => !left.Equals(right); + + public static bool operator ==(ImmutableSegmentedDictionary? left, ImmutableSegmentedDictionary? right) + => left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + public static bool operator !=(ImmutableSegmentedDictionary? left, ImmutableSegmentedDictionary? right) + => !left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + public ImmutableSegmentedDictionary Add(TKey key, TValue value) + { + var self = this; + if (self.Contains(new KeyValuePair(key, value))) + return self; + + var builder = ToValueBuilder(); + builder.Add(key, value); + return builder.ToImmutable(); + } + + public ImmutableSegmentedDictionary AddRange(IEnumerable> pairs) + { + var self = this; + + // Optimize the case of adding to an empty collection + if (self.IsEmpty && TryCastToImmutableSegmentedDictionary(pairs, out var other) && self.KeyComparer == other.KeyComparer) + { + return other; + } + + var builder = ToValueBuilder(); + builder.AddRange(pairs); + return builder.ToImmutable(); + } + + public ImmutableSegmentedDictionary Clear() + { + var self = this; + if (self.IsEmpty) + { + return self; + } + + return Empty.WithComparer(self.KeyComparer); + } + + public bool Contains(KeyValuePair pair) + { + return TryGetValue(pair.Key, out var value) + && EqualityComparer.Default.Equals(value, pair.Value); + } + + public bool ContainsKey(TKey key) + => _dictionary.ContainsKey(key); + + public bool ContainsValue(TValue value) + => _dictionary.ContainsValue(value); + + public Enumerator GetEnumerator() + => new(_dictionary, Enumerator.ReturnType.KeyValuePair); + + public ImmutableSegmentedDictionary Remove(TKey key) + { + var self = this; + if (!self._dictionary.ContainsKey(key)) + return self; + + var builder = ToValueBuilder(); + builder.Remove(key); + return builder.ToImmutable(); + } + + public ImmutableSegmentedDictionary RemoveRange(IEnumerable keys) + { + if (keys is null) + throw new ArgumentNullException(nameof(keys)); + + var result = ToValueBuilder(); + result.RemoveRange(keys); + return result.ToImmutable(); + } + + public ImmutableSegmentedDictionary SetItem(TKey key, TValue value) + { + var self = this; + if (self.Contains(new KeyValuePair(key, value))) + { + return self; + } + + var builder = ToValueBuilder(); + builder[key] = value; + return builder.ToImmutable(); + } + + public ImmutableSegmentedDictionary SetItems(IEnumerable> items) + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + var result = ToValueBuilder(); + foreach (var item in items) + { + result[item.Key] = item.Value; + } + + return result.ToImmutable(); + } + + public bool TryGetKey(TKey equalKey, out TKey actualKey) + { + var self = this; + foreach (var key in self.Keys) + { + if (self.KeyComparer.Equals(key, equalKey)) + { + actualKey = key; + return true; + } + } + + actualKey = equalKey; + return false; + } + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + => _dictionary.TryGetValue(key, out value); + + public ImmutableSegmentedDictionary WithComparer(IEqualityComparer? keyComparer) + { + keyComparer ??= EqualityComparer.Default; + + var self = this; + if (self.KeyComparer == keyComparer) + { + // Don't need to reconstruct the dictionary because the key comparer is the same + return self; + } + else if (self.IsEmpty) + { + if (keyComparer == Empty.KeyComparer) + { + return Empty; + } + else + { + return new ImmutableSegmentedDictionary(new SegmentedDictionary(keyComparer)); + } + } + else + { + return ImmutableSegmentedDictionary.CreateRange(keyComparer, self); + } + } + + public Builder ToBuilder() + => new(this); + + private ValueBuilder ToValueBuilder() + => new(this); + + public override int GetHashCode() + => _dictionary?.GetHashCode() ?? 0; + + public override bool Equals(object? obj) + { + return obj is ImmutableSegmentedDictionary other + && Equals(other); + } + + public bool Equals(ImmutableSegmentedDictionary other) + => _dictionary == other._dictionary; + + IImmutableDictionary IImmutableDictionary.Clear() + => Clear(); + + IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) + => Add(key, value); + + IImmutableDictionary IImmutableDictionary.AddRange(IEnumerable> pairs) + => AddRange(pairs); + + IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) + => SetItem(key, value); + + IImmutableDictionary IImmutableDictionary.SetItems(IEnumerable> items) + => SetItems(items); + + IImmutableDictionary IImmutableDictionary.RemoveRange(IEnumerable keys) + => RemoveRange(keys); + + IImmutableDictionary IImmutableDictionary.Remove(TKey key) => Remove(key); + + IEnumerator> IEnumerable>.GetEnumerator() + => new Enumerator(_dictionary, Enumerator.ReturnType.KeyValuePair); + + IDictionaryEnumerator IDictionary.GetEnumerator() + => new Enumerator(_dictionary, Enumerator.ReturnType.DictionaryEntry); + + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(_dictionary, Enumerator.ReturnType.KeyValuePair); + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + => ((ICollection>)_dictionary).CopyTo(array, arrayIndex); + + bool IDictionary.Contains(object key) + => ((IDictionary)_dictionary).Contains(key); + + void ICollection.CopyTo(Array array, int index) + => ((ICollection)_dictionary).CopyTo(array, index); + + void IDictionary.Add(TKey key, TValue value) + => throw new NotSupportedException(); + + bool IDictionary.Remove(TKey key) + => throw new NotSupportedException(); + + void ICollection>.Add(KeyValuePair item) + => throw new NotSupportedException(); + + void ICollection>.Clear() + => throw new NotSupportedException(); + + bool ICollection>.Remove(KeyValuePair item) + => throw new NotSupportedException(); + + void IDictionary.Add(object key, object? value) + => throw new NotSupportedException(); + + void IDictionary.Clear() + => throw new NotSupportedException(); + + void IDictionary.Remove(object key) + => throw new NotSupportedException(); + + private static bool TryCastToImmutableSegmentedDictionary(IEnumerable> pairs, out ImmutableSegmentedDictionary other) + { + if (pairs is ImmutableSegmentedDictionary dictionary) + { + other = dictionary; + return true; + } + + if (pairs is ImmutableSegmentedDictionary.Builder builder) + { + other = builder.ToImmutable(); + return true; + } + + other = default; + return false; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet.cs new file mode 100755 index 00000000000..63e2a1e8969 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static class ImmutableSegmentedHashSet + { + /// + public static ImmutableSegmentedHashSet Create() + => ImmutableSegmentedHashSet.Empty; + + /// + public static ImmutableSegmentedHashSet Create(T item) + => ImmutableSegmentedHashSet.Empty.Add(item); + + /// + public static ImmutableSegmentedHashSet Create(params T[] items) + => ImmutableSegmentedHashSet.Empty.Union(items); + + /// + public static ImmutableSegmentedHashSet Create(IEqualityComparer? equalityComparer) + => ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer); + + /// + public static ImmutableSegmentedHashSet Create(IEqualityComparer? equalityComparer, T item) + => ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).Add(item); + + /// + public static ImmutableSegmentedHashSet Create(IEqualityComparer? equalityComparer, params T[] items) + => ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).Union(items); + + /// + public static ImmutableSegmentedHashSet.Builder CreateBuilder() + => ImmutableSegmentedHashSet.Empty.ToBuilder(); + + /// + public static ImmutableSegmentedHashSet.Builder CreateBuilder(IEqualityComparer? equalityComparer) + => ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).ToBuilder(); + + /// + public static ImmutableSegmentedHashSet CreateRange(IEnumerable items) + { + if (items is ImmutableSegmentedHashSet existingSet) + return existingSet.WithComparer(null); + + return ImmutableSegmentedHashSet.Empty.Union(items); + } + + /// + public static ImmutableSegmentedHashSet CreateRange(IEqualityComparer? equalityComparer, IEnumerable items) + { + if (items is ImmutableSegmentedHashSet existingSet) + return existingSet.WithComparer(equalityComparer); + + return ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).Union(items); + } + + /// + public static ImmutableSegmentedHashSet ToImmutableSegmentedHashSet(this IEnumerable source) + { + if (source is ImmutableSegmentedHashSet existingSet) + return existingSet.WithComparer(null); + + return ImmutableSegmentedHashSet.Empty.Union(source); + } + + /// + public static ImmutableSegmentedHashSet ToImmutableSegmentedHashSet(this IEnumerable source, IEqualityComparer? equalityComparer) + { + if (source is ImmutableSegmentedHashSet existingSet) + return existingSet.WithComparer(equalityComparer); + + return ImmutableSegmentedHashSet.Empty.WithComparer(equalityComparer).Union(source); + } + + /// + public static ImmutableSegmentedHashSet ToImmutableSegmentedHashSet(this ImmutableSegmentedHashSet.Builder builder) + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + return builder.ToImmutable(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+Builder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+Builder.cs new file mode 100755 index 00000000000..d8273f710b8 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+Builder.cs @@ -0,0 +1,130 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedHashSet + { + public sealed class Builder : ISet, IReadOnlyCollection + { + /// + /// The private builder implementation. + /// + private ValueBuilder _builder; + + internal Builder(ImmutableSegmentedHashSet set) + => _builder = new ValueBuilder(set); + + /// + public IEqualityComparer KeyComparer + { + get => _builder.KeyComparer; + set => _builder.KeyComparer = value; + } + + /// + public int Count => _builder.Count; + + bool ICollection.IsReadOnly => ICollectionCalls.IsReadOnly(ref _builder); + + /// + public bool Add(T item) + => _builder.Add(item); + + /// + public void Clear() + => _builder.Clear(); + + /// + public bool Contains(T item) + => _builder.Contains(item); + + /// + public void ExceptWith(IEnumerable other) + { + if (other == this) + { + // The ValueBuilder knows how to optimize for this case by calling Clear, provided it does not need + // to access properties of the wrapping Builder instance. + _builder.ExceptWith(_builder.ReadOnlySet); + } + else + { + _builder.ExceptWith(other); + } + } + + /// + public Enumerator GetEnumerator() + => _builder.GetEnumerator(); + + /// + public void IntersectWith(IEnumerable other) + => _builder.IntersectWith(other); + + /// + public bool IsProperSubsetOf(IEnumerable other) + => _builder.IsProperSubsetOf(other); + + /// + public bool IsProperSupersetOf(IEnumerable other) + => _builder.IsProperSupersetOf(other); + + /// + public bool IsSubsetOf(IEnumerable other) + => _builder.IsSubsetOf(other); + + /// + public bool IsSupersetOf(IEnumerable other) + => _builder.IsSupersetOf(other); + + /// + public bool Overlaps(IEnumerable other) + => _builder.Overlaps(other); + + /// + public bool Remove(T item) + => _builder.Remove(item); + + /// + public bool SetEquals(IEnumerable other) + => _builder.SetEquals(other); + + /// + public void SymmetricExceptWith(IEnumerable other) + => _builder.SymmetricExceptWith(other); + + /// + public bool TryGetValue(T equalValue, out T actualValue) + => _builder.TryGetValue(equalValue, out actualValue); + + /// + public void UnionWith(IEnumerable other) + => _builder.UnionWith(other); + + /// + public ImmutableSegmentedHashSet ToImmutable() + => _builder.ToImmutable(); + + void ICollection.Add(T item) + => ICollectionCalls.Add(ref _builder, item); + + void ICollection.CopyTo(T[] array, int arrayIndex) + => ICollectionCalls.CopyTo(ref _builder, array, arrayIndex); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+Enumerator.cs new file mode 100755 index 00000000000..add645bb303 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+Enumerator.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedHashSet + { + /// + public struct Enumerator : IEnumerator + { + private readonly SegmentedHashSet _set; + private SegmentedHashSet.Enumerator _enumerator; + + internal Enumerator(SegmentedHashSet set) + { + _set = set; + _enumerator = set.GetEnumerator(); + } + + /// + public readonly T Current => _enumerator.Current; + + readonly object? IEnumerator.Current => ((IEnumerator)_enumerator).Current; + + /// + public readonly void Dispose() + => _enumerator.Dispose(); + + /// + public bool MoveNext() + => _enumerator.MoveNext(); + + /// + public void Reset() + { + // Create a new enumerator, since _enumerator.Reset() will fail for cases where the set was mutated + // after enumeration started, and ImmutableSegmentHashSet.Builder allows for this case without error. + _enumerator = _set.GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+PrivateMarshal.cs new file mode 100755 index 00000000000..282cbfb17a5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+PrivateMarshal.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedHashSet + { + /// + /// Private helper class for use only by and + /// . + /// + internal static class PrivateMarshal + { + internal static ImmutableSegmentedHashSet VolatileRead(in ImmutableSegmentedHashSet location) + { + var set = Volatile.Read(ref Unsafe.AsRef(in location._set)); + if (set is null) + return default; + + return new ImmutableSegmentedHashSet(set); + } + + internal static ImmutableSegmentedHashSet InterlockedExchange(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value) + { + var set = Interlocked.Exchange(ref Unsafe.AsRef(in location._set), value._set); + if (set is null) + return default; + + return new ImmutableSegmentedHashSet(set); + } + + internal static ImmutableSegmentedHashSet InterlockedCompareExchange(ref ImmutableSegmentedHashSet location, ImmutableSegmentedHashSet value, ImmutableSegmentedHashSet comparand) + { + var set = Interlocked.CompareExchange(ref Unsafe.AsRef(in location._set), value._set, comparand._set); + if (set is null) + return default; + + return new ImmutableSegmentedHashSet(set); + } + + /// + internal static ImmutableSegmentedHashSet AsImmutableSegmentedHashSet(SegmentedHashSet? set) + => set is not null ? new ImmutableSegmentedHashSet(set) : default; + + /// + internal static SegmentedHashSet? AsSegmentedHashSet(ImmutableSegmentedHashSet set) + => set._set; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+ValueBuilder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+ValueBuilder.cs new file mode 100755 index 00000000000..8c8f2f88690 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1+ValueBuilder.cs @@ -0,0 +1,284 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal readonly partial struct ImmutableSegmentedHashSet + { + private struct ValueBuilder : ISet, IReadOnlyCollection + { + /// + /// The immutable collection this builder is based on. + /// + private ImmutableSegmentedHashSet _set; + + /// + /// The current mutable collection this builder is operating on. This field is initialized to a copy of + /// the first time a change is made. + /// + private SegmentedHashSet? _mutableSet; + + internal ValueBuilder(ImmutableSegmentedHashSet set) + { + _set = set; + _mutableSet = null; + } + + /// + public IEqualityComparer KeyComparer + { + readonly get + { + return ReadOnlySet.Comparer; + } + + set + { + if (Equals(KeyComparer, value ?? EqualityComparer.Default)) + return; + + _mutableSet = new SegmentedHashSet(ReadOnlySet, value ?? EqualityComparer.Default); + _set = default; + } + } + + /// + public readonly int Count => ReadOnlySet.Count; + + internal readonly SegmentedHashSet ReadOnlySet => _mutableSet ?? _set._set; + + readonly bool ICollection.IsReadOnly => false; + + private SegmentedHashSet GetOrCreateMutableSet() + { + if (_mutableSet is null) + { + var originalSet = RoslynImmutableInterlocked.InterlockedExchange(ref _set, default); + if (originalSet.IsDefault) + throw new InvalidOperationException($"Unexpected concurrent access to {GetType()}"); + + _mutableSet = new SegmentedHashSet(originalSet._set, originalSet.KeyComparer); + } + + return _mutableSet; + } + + /// + public bool Add(T item) + { + if (_mutableSet is null && Contains(item)) + return false; + + return GetOrCreateMutableSet().Add(item); + } + + /// + public void Clear() + { + if (ReadOnlySet.Count != 0) + { + if (_mutableSet is null) + { + _mutableSet = new SegmentedHashSet(KeyComparer); + _set = default; + } + else + { + _mutableSet.Clear(); + } + } + } + + /// + public readonly bool Contains(T item) + => ReadOnlySet.Contains(item); + + /// + public void ExceptWith(IEnumerable other) + { + if (other is null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + + if (_mutableSet is not null) + { + _mutableSet.ExceptWith(other); + return; + } + + // ValueBuilder is not a public API, so there shouldn't be any callers trying to pass a boxed instance + // to this method. + Debug.Assert(other is not ValueBuilder); + + if (other == ReadOnlySet) + { + Clear(); + return; + } + else if (other is ImmutableSegmentedHashSet otherSet) + { + if (otherSet == _set) + { + Clear(); + return; + } + else if (otherSet.IsEmpty) + { + // No action required + return; + } + else + { + GetOrCreateMutableSet().ExceptWith(otherSet._set); + return; + } + } + else + { + // Manually enumerate to avoid changes to the builder if 'other' is empty or does not contain any + // items present in the current set. + SegmentedHashSet? mutableSet = null; + foreach (var item in other) + { + if (mutableSet is null) + { + if (!ReadOnlySet.Contains(item)) + continue; + + mutableSet = GetOrCreateMutableSet(); + } + + mutableSet.Remove(item); + } + + return; + } + } + + /// + public Enumerator GetEnumerator() + => new(GetOrCreateMutableSet()); + + /// + public void IntersectWith(IEnumerable other) + => GetOrCreateMutableSet().IntersectWith(other); + + /// + public readonly bool IsProperSubsetOf(IEnumerable other) + => ReadOnlySet.IsProperSubsetOf(other); + + /// + public readonly bool IsProperSupersetOf(IEnumerable other) + => ReadOnlySet.IsProperSupersetOf(other); + + /// + public readonly bool IsSubsetOf(IEnumerable other) + => ReadOnlySet.IsSubsetOf(other); + + /// + public readonly bool IsSupersetOf(IEnumerable other) + => ReadOnlySet.IsSupersetOf(other); + + /// + public readonly bool Overlaps(IEnumerable other) + => ReadOnlySet.Overlaps(other); + + /// + public bool Remove(T item) + { + if (_mutableSet is null && !Contains(item)) + return false; + + return GetOrCreateMutableSet().Remove(item); + } + + /// + public readonly bool SetEquals(IEnumerable other) + => ReadOnlySet.SetEquals(other); + + /// + public void SymmetricExceptWith(IEnumerable other) + => GetOrCreateMutableSet().SymmetricExceptWith(other); + + /// + public readonly bool TryGetValue(T equalValue, out T actualValue) + { + if (ReadOnlySet.TryGetValue(equalValue, out var value)) + { + actualValue = value; + return true; + } + + actualValue = equalValue; + return false; + } + + /// + public void UnionWith(IEnumerable other) + { + if (other is null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + + if (_mutableSet is not null) + { + _mutableSet.UnionWith(other); + return; + } + + if (other is ImmutableSegmentedHashSet { IsEmpty: true }) + { + return; + } + else + { + // Manually enumerate to avoid changes to the builder if 'other' is empty or only contains items + // already present in the current set. + SegmentedHashSet? mutableSet = null; + foreach (var item in other) + { + if (mutableSet is null) + { + if (ReadOnlySet.Contains(item)) + continue; + + mutableSet = GetOrCreateMutableSet(); + } + + mutableSet.Add(item); + } + + return; + } + } + + /// + public ImmutableSegmentedHashSet ToImmutable() + { + _set = new ImmutableSegmentedHashSet(ReadOnlySet); + _mutableSet = null; + return _set; + } + + void ICollection.Add(T item) + => ((ICollection)GetOrCreateMutableSet()).Add(item); + + readonly void ICollection.CopyTo(T[] array, int arrayIndex) + => ((ICollection)ReadOnlySet).CopyTo(array, arrayIndex); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1.cs new file mode 100755 index 00000000000..4728fa7a05b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedHashSet`1.cs @@ -0,0 +1,394 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a segmented hash set that is immutable; meaning it cannot be changed once it is created. + /// + /// + /// There are different scenarios best for and others + /// best for . + /// + /// The following table summarizes the performance characteristics of + /// : + /// + /// + /// + /// Operation + /// Complexity + /// Complexity + /// Comments + /// + /// + /// Contains + /// O(1) + /// O(log n) + /// Directly index into the underlying segmented list + /// + /// + /// Add() + /// O(n) + /// O(log n) + /// Requires creating a new segmented hash set and cloning all impacted segments + /// + /// + /// + /// This type is backed by segmented arrays to avoid using the Large Object Heap without impacting algorithmic + /// complexity. + /// + /// The type of the value in the set. + /// + /// This type has a documented contract of being exactly one reference-type field in size. Our own + /// class depends on it, as well as others externally. + /// + /// IMPORTANT NOTICE FOR MAINTAINERS AND REVIEWERS: + /// + /// This type should be thread-safe. As a struct, it cannot protect its own fields from being changed from one + /// thread while its members are executing on other threads because structs can change in place simply by + /// reassigning the field containing this struct. Therefore it is extremely important that ⚠⚠ Every member + /// should only dereference this ONCE ⚠⚠. If a member needs to reference the + /// field, that counts as a dereference of this. Calling other instance members + /// (properties or methods) also counts as dereferencing this. Any member that needs to use this more + /// than once must instead assign this to a local variable and use that for the rest of the code instead. + /// This effectively copies the one field in the struct to a local variable so that it is insulated from other + /// threads. + /// + internal readonly partial struct ImmutableSegmentedHashSet : IImmutableSet, ISet, ICollection, IEquatable> + { + /// + public static readonly ImmutableSegmentedHashSet Empty = new(new SegmentedHashSet()); + + private readonly SegmentedHashSet _set; + + private ImmutableSegmentedHashSet(SegmentedHashSet set) + { + _set = set; + } + + /// + public IEqualityComparer KeyComparer => _set.Comparer; + + /// + public int Count => _set.Count; + + public bool IsDefault => _set == null; + + /// + public bool IsEmpty => _set.Count == 0; + + bool ICollection.IsReadOnly => true; + + bool ICollection.IsSynchronized => true; + + object ICollection.SyncRoot => _set; + + public static bool operator ==(ImmutableSegmentedHashSet left, ImmutableSegmentedHashSet right) + => left.Equals(right); + + public static bool operator !=(ImmutableSegmentedHashSet left, ImmutableSegmentedHashSet right) + => !left.Equals(right); + + public static bool operator ==(ImmutableSegmentedHashSet? left, ImmutableSegmentedHashSet? right) + => left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + public static bool operator !=(ImmutableSegmentedHashSet? left, ImmutableSegmentedHashSet? right) + => !left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + /// + public ImmutableSegmentedHashSet Add(T value) + { + var self = this; + + if (self.IsEmpty) + { + var set = new SegmentedHashSet(self.KeyComparer) { value }; + return new ImmutableSegmentedHashSet(set); + } + else if (self.Contains(value)) + { + return self; + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.Add(value); + return builder.ToImmutable(); + } + } + + /// + public ImmutableSegmentedHashSet Clear() + { + var self = this; + + if (self.IsEmpty) + { + return self; + } + + return Empty.WithComparer(self.KeyComparer); + } + + /// + public bool Contains(T value) + => _set.Contains(value); + + /// + public ImmutableSegmentedHashSet Except(IEnumerable other) + { + var self = this; + + if (other is ImmutableSegmentedHashSet { IsEmpty: true }) + { + return self; + } + else if (self.IsEmpty) + { + // Enumerate the argument to match behavior of ImmutableHashSet + foreach (var _ in other) + { + // Intentionally empty + } + + return self; + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.ExceptWith(other); + return builder.ToImmutable(); + } + } + + /// + public Enumerator GetEnumerator() + => new(_set); + + /// + public ImmutableSegmentedHashSet Intersect(IEnumerable other) + { + var self = this; + + if (self.IsEmpty || other is ImmutableSegmentedHashSet { IsEmpty: true }) + { + return self.Clear(); + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.IntersectWith(other); + return builder.ToImmutable(); + } + } + + /// + public bool IsProperSubsetOf(IEnumerable other) + => _set.IsProperSubsetOf(other); + + /// + public bool IsProperSupersetOf(IEnumerable other) + => _set.IsProperSupersetOf(other); + + /// + public bool IsSubsetOf(IEnumerable other) + => _set.IsSubsetOf(other); + + /// + public bool IsSupersetOf(IEnumerable other) + => _set.IsSupersetOf(other); + + /// + public bool Overlaps(IEnumerable other) + => _set.Overlaps(other); + + /// + public ImmutableSegmentedHashSet Remove(T value) + { + var self = this; + + if (!self.Contains(value)) + { + return self; + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.Remove(value); + return builder.ToImmutable(); + } + } + + /// + public bool SetEquals(IEnumerable other) + => _set.SetEquals(other); + + /// + public ImmutableSegmentedHashSet SymmetricExcept(IEnumerable other) + { + var self = this; + + if (other is ImmutableSegmentedHashSet otherSet) + { + if (otherSet.IsEmpty) + return self; + else if (self.IsEmpty) + return otherSet.WithComparer(self.KeyComparer); + } + + if (self.IsEmpty) + { + return ImmutableSegmentedHashSet.CreateRange(self.KeyComparer, other); + } + else + { + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.SymmetricExceptWith(other); + return builder.ToImmutable(); + } + } + + /// + public bool TryGetValue(T equalValue, out T actualValue) + { + if (_set.TryGetValue(equalValue, out var value)) + { + actualValue = value; + return true; + } + + actualValue = equalValue; + return false; + } + + /// + public ImmutableSegmentedHashSet Union(IEnumerable other) + { + var self = this; + + if (other is ImmutableSegmentedHashSet otherSet) + { + if (otherSet.IsEmpty) + return self; + else if (self.IsEmpty) + return otherSet.WithComparer(self.KeyComparer); + } + + // TODO: Reuse all pages with no changes + var builder = self.ToValueBuilder(); + builder.UnionWith(other); + return builder.ToImmutable(); + } + + /// + public Builder ToBuilder() + => new(this); + + private ValueBuilder ToValueBuilder() + => new ValueBuilder(this); + + /// + public ImmutableSegmentedHashSet WithComparer(IEqualityComparer? equalityComparer) + { + var self = this; + + equalityComparer ??= EqualityComparer.Default; + if (Equals(self.KeyComparer, equalityComparer)) + return self; + + return new ImmutableSegmentedHashSet(new SegmentedHashSet(self._set, equalityComparer)); + } + + public override int GetHashCode() + => _set?.GetHashCode() ?? 0; + + public override bool Equals(object? obj) + => obj is ImmutableSegmentedHashSet other && Equals(other); + + public bool Equals(ImmutableSegmentedHashSet other) + => _set == other._set; + + IImmutableSet IImmutableSet.Clear() + => Clear(); + + IImmutableSet IImmutableSet.Add(T value) + => Add(value); + + IImmutableSet IImmutableSet.Remove(T value) + => Remove(value); + + IImmutableSet IImmutableSet.Intersect(IEnumerable other) + => Intersect(other); + + IImmutableSet IImmutableSet.Except(IEnumerable other) + => Except(other); + + IImmutableSet IImmutableSet.SymmetricExcept(IEnumerable other) + => SymmetricExcept(other); + + IImmutableSet IImmutableSet.Union(IEnumerable other) + => Union(other); + + void ICollection.CopyTo(T[] array, int arrayIndex) + => _set.CopyTo(array, arrayIndex); + + void ICollection.CopyTo(Array array, int index) + { + if (array is null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (array.Length < index + Count) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + + foreach (var item in this) + { + array.SetValue(item, index++); + } + } + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + bool ISet.Add(T item) + => throw new NotSupportedException(); + + void ISet.UnionWith(IEnumerable other) + => throw new NotSupportedException(); + + void ISet.IntersectWith(IEnumerable other) + => throw new NotSupportedException(); + + void ISet.ExceptWith(IEnumerable other) + => throw new NotSupportedException(); + + void ISet.SymmetricExceptWith(IEnumerable other) + => throw new NotSupportedException(); + + void ICollection.Add(T item) + => throw new NotSupportedException(); + + void ICollection.Clear() + => throw new NotSupportedException(); + + bool ICollection.Remove(T item) + => throw new NotSupportedException(); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList.cs new file mode 100755 index 00000000000..9272bfb5976 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static class ImmutableSegmentedList + { + /// + public static ImmutableSegmentedList Create() + => ImmutableSegmentedList.Empty; + + /// + public static ImmutableSegmentedList Create(T item) + => ImmutableSegmentedList.Empty.Add(item); + + /// + public static ImmutableSegmentedList Create(params T[] items) + => ImmutableSegmentedList.Empty.AddRange(items); + + /// + public static ImmutableSegmentedList.Builder CreateBuilder() + => ImmutableSegmentedList.Empty.ToBuilder(); + + /// + public static ImmutableSegmentedList CreateRange(IEnumerable items) + => ImmutableSegmentedList.Empty.AddRange(items); + + /// + public static ImmutableSegmentedList ToImmutableSegmentedList(this IEnumerable source) + { + if (source is ImmutableSegmentedList existingList) + return existingList; + + return ImmutableSegmentedList.Empty.AddRange(source); + } + + /// + public static ImmutableSegmentedList ToImmutableSegmentedList(this ImmutableSegmentedList.Builder builder) + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + return builder.ToImmutable(); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedListExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedListExtensions.cs new file mode 100755 index 00000000000..a7675a069b7 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedListExtensions.cs @@ -0,0 +1,120 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; +using Microsoft.CodeAnalysis.Collections; + +#pragma warning disable RS0001 // Use 'SpecializedCollections.EmptyEnumerable()' + +namespace System.Linq +{ + /// + internal static class ImmutableSegmentedListExtensions + { + public static bool All(this ImmutableSegmentedList immutableList, Func predicate) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + if (predicate is null) + throw new ArgumentNullException(nameof(predicate)); + + foreach (var item in immutableList) + { + if (!predicate(item)) + return false; + } + + return true; + } + + public static bool Any(this ImmutableSegmentedList immutableList) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + + return !immutableList.IsEmpty; + } + + public static bool Any(this ImmutableSegmentedList.Builder builder) + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + return builder.Count > 0; + } + + public static bool Any(this ImmutableSegmentedList immutableList, Func predicate) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + if (predicate is null) + throw new ArgumentNullException(nameof(predicate)); + + foreach (var item in immutableList) + { + if (predicate(item)) + return true; + } + + return false; + } + + public static T Last(this ImmutableSegmentedList immutableList) + { + // In the event of an empty list, generate the same exception + // that the linq extension method would. + return immutableList.Count > 0 + ? immutableList[immutableList.Count - 1] + : Enumerable.Last(immutableList); + } + + public static T Last(this ImmutableSegmentedList.Builder builder) + { + if (builder is null) + throw new ArgumentNullException(nameof(builder)); + + // In the event of an empty list, generate the same exception + // that the linq extension method would. + return builder.Count > 0 + ? builder[builder.Count - 1] + : Enumerable.Last(builder); + } + + public static T Last(this ImmutableSegmentedList immutableList, Func predicate) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + if (predicate is null) + throw new ArgumentNullException(nameof(predicate)); + + for (var i = immutableList.Count - 1; i >= 0; i--) + { + if (predicate(immutableList[i])) + return immutableList[i]; + } + + // Throw the same exception that LINQ would. + return Enumerable.Empty().Last(); + } + + public static IEnumerable Select(this ImmutableSegmentedList immutableList, Func selector) + { + if (immutableList.IsDefault) + throw new ArgumentNullException(nameof(immutableList)); + if (selector is null) + throw new ArgumentNullException(nameof(selector)); + + if (immutableList.IsEmpty) + { + return Enumerable.Empty(); + } + else + { + return Enumerable.Select(immutableList, selector); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+Builder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+Builder.cs new file mode 100755 index 00000000000..6ffd557d665 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+Builder.cs @@ -0,0 +1,251 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial struct ImmutableSegmentedList + { + public sealed class Builder : IList, IReadOnlyList, IList + { + /// + /// The private builder implementation. + /// + private ValueBuilder _builder; + + internal Builder(ImmutableSegmentedList list) + => _builder = new ValueBuilder(list); + + public int Count => _builder.Count; + + bool ICollection.IsReadOnly => ICollectionCalls.IsReadOnly(ref _builder); + + bool IList.IsFixedSize => IListCalls.IsFixedSize(ref _builder); + + bool IList.IsReadOnly => IListCalls.IsReadOnly(ref _builder); + + bool ICollection.IsSynchronized => ICollectionCalls.IsSynchronized(ref _builder); + + object ICollection.SyncRoot => this; + + public T this[int index] + { + get => _builder[index]; + set => _builder[index] = value; + } + + object? IList.this[int index] + { + get => IListCalls.GetItem(ref _builder, index); + set => IListCalls.SetItem(ref _builder, index, value); + } + + /// + public ref readonly T ItemRef(int index) + => ref _builder.ItemRef(index); + + public void Add(T item) + => _builder.Add(item); + + /// + public void AddRange(IEnumerable items) + => _builder.AddRange(items); + + /// + public int BinarySearch(T item) + => _builder.BinarySearch(item); + + /// + public int BinarySearch(T item, IComparer? comparer) + => _builder.BinarySearch(item, comparer); + + /// + public int BinarySearch(int index, int count, T item, IComparer? comparer) + => _builder.BinarySearch(index, count, item, comparer); + + public void Clear() + => _builder.Clear(); + + public bool Contains(T item) + => _builder.Contains(item); + + /// + public ImmutableSegmentedList ConvertAll(Converter converter) + => _builder.ConvertAll(converter); + + /// + public void CopyTo(T[] array) + => _builder.CopyTo(array); + + public void CopyTo(T[] array, int arrayIndex) + => _builder.CopyTo(array, arrayIndex); + + /// + public void CopyTo(int index, T[] array, int arrayIndex, int count) + => _builder.CopyTo(index, array, arrayIndex, count); + + /// + public bool Exists(Predicate match) + => _builder.Exists(match); + + /// + public T? Find(Predicate match) + => _builder.Find(match); + + /// + public ImmutableSegmentedList FindAll(Predicate match) + => _builder.FindAll(match); + + /// + public int FindIndex(Predicate match) + => _builder.FindIndex(match); + + /// + public int FindIndex(int startIndex, Predicate match) + => _builder.FindIndex(startIndex, match); + + /// + public int FindIndex(int startIndex, int count, Predicate match) + => _builder.FindIndex(startIndex, count, match); + + /// + public T? FindLast(Predicate match) + => _builder.FindLast(match); + + /// + public int FindLastIndex(Predicate match) + => _builder.FindLastIndex(match); + + /// + public int FindLastIndex(int startIndex, Predicate match) + => _builder.FindLastIndex(startIndex, match); + + /// + public int FindLastIndex(int startIndex, int count, Predicate match) + => _builder.FindLastIndex(startIndex, count, match); + + /// + public void ForEach(Action action) + => _builder.ForEach(action); + + /// + public Enumerator GetEnumerator() + => _builder.GetEnumerator(); + + /// + public ImmutableSegmentedList GetRange(int index, int count) + => _builder.GetRange(index, count); + + public int IndexOf(T item) + => _builder.IndexOf(item); + + /// + public int IndexOf(T item, int index) + => _builder.IndexOf(item, index); + + /// + public int IndexOf(T item, int index, int count) + => _builder.IndexOf(item, index, count); + + /// + public int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) + => _builder.IndexOf(item, index, count, equalityComparer); + + public void Insert(int index, T item) + => _builder.Insert(index, item); + + /// + public void InsertRange(int index, IEnumerable items) + => _builder.InsertRange(index, items); + + /// + public int LastIndexOf(T item) + => _builder.LastIndexOf(item); + + /// + public int LastIndexOf(T item, int startIndex) + => _builder.LastIndexOf(item, startIndex); + + /// + public int LastIndexOf(T item, int startIndex, int count) + => _builder.LastIndexOf(item, startIndex, count); + + /// + public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer? equalityComparer) + => _builder.LastIndexOf(item, startIndex, count, equalityComparer); + + public bool Remove(T item) + => _builder.Remove(item); + + /// + public int RemoveAll(Predicate match) + => _builder.RemoveAll(match); + + public void RemoveAt(int index) + => _builder.RemoveAt(index); + + /// + public void Reverse() + => _builder.Reverse(); + + /// + public void Reverse(int index, int count) + => _builder.Reverse(index, count); + + /// + public void Sort() + => _builder.Sort(); + + /// + public void Sort(IComparer? comparer) + => _builder.Sort(comparer); + + /// + public void Sort(Comparison comparison) + => _builder.Sort(comparison); + + /// + public void Sort(int index, int count, IComparer? comparer) + => _builder.Sort(index, count, comparer); + + /// + public ImmutableSegmentedList ToImmutable() + => _builder.ToImmutable(); + + /// + public bool TrueForAll(Predicate match) + => _builder.TrueForAll(match); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + + IEnumerator IEnumerable.GetEnumerator() + => IEnumerableCalls.GetEnumerator(ref _builder); + + int IList.Add(object? value) + => IListCalls.Add(ref _builder, value); + + bool IList.Contains(object? value) + => IListCalls.Contains(ref _builder, value); + + int IList.IndexOf(object? value) + => IListCalls.IndexOf(ref _builder, value); + + void IList.Insert(int index, object? value) + => IListCalls.Insert(ref _builder, index, value); + + void IList.Remove(object? value) + => IListCalls.Remove(ref _builder, value); + + void ICollection.CopyTo(Array array, int index) + => ICollectionCalls.CopyTo(ref _builder, array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+Enumerator.cs new file mode 100755 index 00000000000..6d61c3a3178 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+Enumerator.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial struct ImmutableSegmentedList + { + public struct Enumerator : IEnumerator + { + private readonly SegmentedList _list; + private SegmentedList.Enumerator _enumerator; + + internal Enumerator(SegmentedList list) + { + _list = list; + _enumerator = list.GetEnumerator(); + } + + public readonly T Current => _enumerator.Current; + + readonly object? IEnumerator.Current => ((IEnumerator)_enumerator).Current; + + public readonly void Dispose() + => _enumerator.Dispose(); + + public bool MoveNext() + => _enumerator.MoveNext(); + + public void Reset() + { + // Create a new enumerator, since _enumerator.Reset() will fail for cases where the list was mutated + // after enumeration started, and ImmutableSegmentList.Builder allows for this case without error. + _enumerator = _list.GetEnumerator(); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+PrivateMarshal.cs new file mode 100755 index 00000000000..1b9cae87e4a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+PrivateMarshal.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial struct ImmutableSegmentedList + { + /// + /// Private helper class for use only by and + /// . + /// + internal static class PrivateMarshal + { + internal static ImmutableSegmentedList VolatileRead(in ImmutableSegmentedList location) + { + var list = Volatile.Read(ref Unsafe.AsRef(in location._list)); + if (list is null) + return default; + + return new ImmutableSegmentedList(list); + } + + internal static ImmutableSegmentedList InterlockedExchange(ref ImmutableSegmentedList location, ImmutableSegmentedList value) + { + var list = Interlocked.Exchange(ref Unsafe.AsRef(in location._list), value._list); + if (list is null) + return default; + + return new ImmutableSegmentedList(list); + } + + internal static ImmutableSegmentedList InterlockedCompareExchange(ref ImmutableSegmentedList location, ImmutableSegmentedList value, ImmutableSegmentedList comparand) + { + var list = Interlocked.CompareExchange(ref Unsafe.AsRef(in location._list), value._list, comparand._list); + if (list is null) + return default; + + return new ImmutableSegmentedList(list); + } + + /// + internal static ImmutableSegmentedList AsImmutableSegmentedList(SegmentedList? list) + => list is not null ? new ImmutableSegmentedList(list) : default; + + /// + internal static SegmentedList? AsSegmentedList(ImmutableSegmentedList list) + => list._list; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+ValueBuilder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+ValueBuilder.cs new file mode 100755 index 00000000000..f71b14da7f5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1+ValueBuilder.cs @@ -0,0 +1,360 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial struct ImmutableSegmentedList + { + private struct ValueBuilder : IList, IReadOnlyList, IList + { + /// + /// The immutable collection this builder is based on. + /// + private ImmutableSegmentedList _list; + + /// + /// The current mutable collection this builder is operating on. This field is initialized to a copy of + /// the first time a change is made. + /// + private SegmentedList? _mutableList; + + internal ValueBuilder(ImmutableSegmentedList list) + { + _list = list; + _mutableList = null; + } + + public readonly int Count => ReadOnlyList.Count; + + private readonly SegmentedList ReadOnlyList => _mutableList ?? _list._list; + + readonly bool ICollection.IsReadOnly => false; + + readonly bool IList.IsFixedSize => false; + + readonly bool IList.IsReadOnly => false; + + readonly bool ICollection.IsSynchronized => false; + + readonly object ICollection.SyncRoot => throw new NotSupportedException(); + + public T this[int index] + { + readonly get => ReadOnlyList[index]; + set => GetOrCreateMutableList()[index] = value; + } + + object? IList.this[int index] + { + readonly get => ((IList)ReadOnlyList)[index]; + set => ((IList)GetOrCreateMutableList())[index] = value; + } + + public readonly ref readonly T ItemRef(int index) + { + // Following trick can reduce the range check by one + if ((uint)index >= (uint)ReadOnlyList.Count) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + + return ref ReadOnlyList._items[index]; + } + + private SegmentedList GetOrCreateMutableList() + { + if (_mutableList is null) + { + var originalList = RoslynImmutableInterlocked.InterlockedExchange(ref _list, default); + if (originalList.IsDefault) + throw new InvalidOperationException($"Unexpected concurrent access to {GetType()}"); + + _mutableList = new SegmentedList(originalList._list); + } + + return _mutableList; + } + + public void Add(T item) + => GetOrCreateMutableList().Add(item); + + public void AddRange(IEnumerable items) + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + GetOrCreateMutableList().AddRange(items); + } + + public readonly int BinarySearch(T item) + => ReadOnlyList.BinarySearch(item); + + public readonly int BinarySearch(T item, IComparer? comparer) + => ReadOnlyList.BinarySearch(item, comparer); + + public readonly int BinarySearch(int index, int count, T item, IComparer? comparer) + => ReadOnlyList.BinarySearch(index, count, item, comparer); + + public void Clear() + { + if (ReadOnlyList.Count != 0) + { + if (_mutableList is null) + { + _mutableList = new SegmentedList(); + _list = default; + } + else + { + _mutableList.Clear(); + } + } + } + + public readonly bool Contains(T item) + => ReadOnlyList.Contains(item); + + public readonly ImmutableSegmentedList ConvertAll(Converter converter) + => new ImmutableSegmentedList(ReadOnlyList.ConvertAll(converter)); + + public readonly void CopyTo(T[] array) + => ReadOnlyList.CopyTo(array); + + public readonly void CopyTo(T[] array, int arrayIndex) + => ReadOnlyList.CopyTo(array, arrayIndex); + + public readonly void CopyTo(int index, T[] array, int arrayIndex, int count) + => ReadOnlyList.CopyTo(index, array, arrayIndex, count); + + public readonly bool Exists(Predicate match) + => ReadOnlyList.Exists(match); + + public readonly T? Find(Predicate match) + => ReadOnlyList.Find(match); + + public readonly ImmutableSegmentedList FindAll(Predicate match) + => new ImmutableSegmentedList(ReadOnlyList.FindAll(match)); + + public readonly int FindIndex(Predicate match) + => ReadOnlyList.FindIndex(match); + + public readonly int FindIndex(int startIndex, Predicate match) + => ReadOnlyList.FindIndex(startIndex, match); + + public readonly int FindIndex(int startIndex, int count, Predicate match) + => ReadOnlyList.FindIndex(startIndex, count, match); + + public readonly T? FindLast(Predicate match) + => ReadOnlyList.FindLast(match); + + public readonly int FindLastIndex(Predicate match) + => ReadOnlyList.FindLastIndex(match); + + public readonly int FindLastIndex(int startIndex, Predicate match) + { + if (startIndex == 0 && Count == 0) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return ReadOnlyList.FindLastIndex(startIndex, match); + } + + public readonly int FindLastIndex(int startIndex, int count, Predicate match) + { + if (count == 0 && startIndex == 0 && Count == 0) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return ReadOnlyList.FindLastIndex(startIndex, count, match); + } + + public readonly void ForEach(Action action) + => ReadOnlyList.ForEach(action); + + public Enumerator GetEnumerator() + => new Enumerator(GetOrCreateMutableList()); + + public ImmutableSegmentedList GetRange(int index, int count) + { + if (index == 0 && count == Count) + return ToImmutable(); + + return new ImmutableSegmentedList(ReadOnlyList.GetRange(index, count)); + } + + public readonly int IndexOf(T item) + => ReadOnlyList.IndexOf(item); + + public readonly int IndexOf(T item, int index) + => ReadOnlyList.IndexOf(item, index); + + public readonly int IndexOf(T item, int index, int count) + => ReadOnlyList.IndexOf(item, index, count); + + public readonly int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) + => ReadOnlyList.IndexOf(item, index, count, equalityComparer); + + public void Insert(int index, T item) + => GetOrCreateMutableList().Insert(index, item); + + public void InsertRange(int index, IEnumerable items) + => GetOrCreateMutableList().InsertRange(index, items); + + public readonly int LastIndexOf(T item) + => ReadOnlyList.LastIndexOf(item); + + public readonly int LastIndexOf(T item, int startIndex) + { + if (startIndex == 0 && Count == 0) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return ReadOnlyList.LastIndexOf(item, startIndex); + } + + public readonly int LastIndexOf(T item, int startIndex, int count) + { + if (count == 0 && startIndex == 0 && Count == 0) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return ReadOnlyList.LastIndexOf(item, startIndex, count); + } + + public readonly int LastIndexOf(T item, int startIndex, int count, IEqualityComparer? equalityComparer) + { + if (startIndex < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (count < 0 || count > Count) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count); + if (startIndex - count + 1 < 0) + throw new ArgumentException(); + + return ReadOnlyList.LastIndexOf(item, startIndex, count, equalityComparer); + } + + public bool Remove(T item) + { + if (_mutableList is null) + { + var index = IndexOf(item); + if (index < 0) + return false; + + RemoveAt(index); + return true; + } + else + { + return _mutableList.Remove(item); + } + } + + public int RemoveAll(Predicate match) + => GetOrCreateMutableList().RemoveAll(match); + + public void RemoveAt(int index) + => GetOrCreateMutableList().RemoveAt(index); + + public void RemoveRange(int index, int count) + => GetOrCreateMutableList().RemoveRange(index, count); + + public void Reverse() + { + if (Count < 2) + return; + + GetOrCreateMutableList().Reverse(); + } + + public void Reverse(int index, int count) + => GetOrCreateMutableList().Reverse(index, count); + + public void Sort() + { + if (Count < 2) + return; + + GetOrCreateMutableList().Sort(); + } + + public void Sort(IComparer? comparer) + { + if (Count < 2) + return; + + GetOrCreateMutableList().Sort(comparer); + } + + public void Sort(Comparison comparison) + { + if (comparison == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); + } + + if (Count < 2) + return; + + GetOrCreateMutableList().Sort(comparison); + } + + public void Sort(int index, int count, IComparer? comparer) + => GetOrCreateMutableList().Sort(index, count, comparer); + + public ImmutableSegmentedList ToImmutable() + { + _list = new ImmutableSegmentedList(ReadOnlyList); + _mutableList = null; + return _list; + } + + public readonly bool TrueForAll(Predicate match) + => ReadOnlyList.TrueForAll(match); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + int IList.Add(object? value) + => ((IList)GetOrCreateMutableList()).Add(value); + + readonly bool IList.Contains(object? value) + => ((IList)ReadOnlyList).Contains(value); + + readonly int IList.IndexOf(object? value) + => ((IList)ReadOnlyList).IndexOf(value); + + void IList.Insert(int index, object? value) + => ((IList)GetOrCreateMutableList()).Insert(index, value); + + void IList.Remove(object? value) + => ((IList)GetOrCreateMutableList()).Remove(value); + + readonly void ICollection.CopyTo(Array array, int index) + => ((ICollection)ReadOnlyList).CopyTo(array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1.cs new file mode 100755 index 00000000000..41a5c8473f2 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/ImmutableSegmentedList`1.cs @@ -0,0 +1,693 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a segmented list that is immutable; meaning it cannot be changed once it is created. + /// + /// + /// There are different scenarios best for and others + /// best for . + /// + /// The following table summarizes the performance characteristics of + /// : + /// + /// + /// + /// Operation + /// Complexity + /// Complexity + /// Comments + /// + /// + /// Item + /// O(1) + /// O(log n) + /// Directly index into the underlying segmented list + /// + /// + /// Add() + /// Currently O(n), but could be O(1) with a relatively large constant + /// O(log n) + /// Currently requires creating a new segmented list, but could be modified to only clone the segments with changes + /// + /// + /// Insert() + /// O(n) + /// O(log n) + /// Requires creating a new segmented list and cloning all impacted segments + /// + /// + /// + /// This type is backed by segmented arrays to avoid using the Large Object Heap without impacting algorithmic + /// complexity. + /// + /// The type of the value in the list. + /// + /// This type has a documented contract of being exactly one reference-type field in size. Our own + /// class depends on it, as well as others externally. + /// + /// IMPORTANT NOTICE FOR MAINTAINERS AND REVIEWERS: + /// + /// This type should be thread-safe. As a struct, it cannot protect its own fields from being changed from one + /// thread while its members are executing on other threads because structs can change in place simply by + /// reassigning the field containing this struct. Therefore it is extremely important that ⚠⚠ Every member + /// should only dereference this ONCE ⚠⚠. If a member needs to reference the + /// field, that counts as a dereference of this. Calling other instance members + /// (properties or methods) also counts as dereferencing this. Any member that needs to use this more + /// than once must instead assign this to a local variable and use that for the rest of the code instead. + /// This effectively copies the one field in the struct to a local variable so that it is insulated from other + /// threads. + /// + internal readonly partial struct ImmutableSegmentedList : IImmutableList, IReadOnlyList, IList, IList, IEquatable> + { + /// + public static readonly ImmutableSegmentedList Empty = new(new SegmentedList()); + + private readonly SegmentedList _list; + + private ImmutableSegmentedList(SegmentedList list) + => _list = list; + + public int Count => _list.Count; + + public bool IsDefault => _list == null; + + /// + public bool IsEmpty => _list.Count == 0; + + bool ICollection.IsReadOnly => true; + + bool IList.IsFixedSize => true; + + bool IList.IsReadOnly => true; + + bool ICollection.IsSynchronized => true; + + object ICollection.SyncRoot => _list; + + public T this[int index] => _list[index]; + + T IList.this[int index] + { + get => _list[index]; + set => throw new NotSupportedException(); + } + + object? IList.this[int index] + { + get => _list[index]; + set => throw new NotSupportedException(); + } + + public static bool operator ==(ImmutableSegmentedList left, ImmutableSegmentedList right) + => left.Equals(right); + + public static bool operator !=(ImmutableSegmentedList left, ImmutableSegmentedList right) + => !left.Equals(right); + + public static bool operator ==(ImmutableSegmentedList? left, ImmutableSegmentedList? right) + => left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + public static bool operator !=(ImmutableSegmentedList? left, ImmutableSegmentedList? right) + => !left.GetValueOrDefault().Equals(right.GetValueOrDefault()); + + /// + public ref readonly T ItemRef(int index) + { + var self = this; + + // Following trick can reduce the number of range comparison operations by one + if (unchecked((uint)index) >= (uint)self.Count) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + + return ref self._list._items[index]; + } + + /// + public ImmutableSegmentedList Add(T value) + { + var self = this; + + if (self.IsEmpty) + { + var list = new SegmentedList { value }; + return new ImmutableSegmentedList(list); + } + else + { + // TODO: Optimize this to share all segments except for the last one + // TODO: Only resize the last page the minimum amount necessary + var builder = self.ToValueBuilder(); + builder.Add(value); + return builder.ToImmutable(); + } + } + + /// + public ImmutableSegmentedList AddRange(IEnumerable items) + { + var self = this; + + if (items is ICollection { Count: 0 }) + { + return self; + } + else if (self.IsEmpty) + { + if (items is ImmutableSegmentedList immutableList) + return immutableList; + else if (items is ImmutableSegmentedList.Builder builder) + return builder.ToImmutable(); + + var list = new SegmentedList(items); + return new ImmutableSegmentedList(list); + } + else + { + // TODO: Optimize this to share all segments except for the last one + var builder = self.ToValueBuilder(); + builder.AddRange(items); + return builder.ToImmutable(); + } + } + + /// + public int BinarySearch(T item) + => _list.BinarySearch(item); + + /// + public int BinarySearch(T item, IComparer? comparer) + => _list.BinarySearch(item, comparer); + + /// + public int BinarySearch(int index, int count, T item, IComparer? comparer) + => _list.BinarySearch(index, count, item, comparer); + + /// + public ImmutableSegmentedList Clear() + => Empty; + + public bool Contains(T value) + => _list.Contains(value); + + /// + public ImmutableSegmentedList ConvertAll(Converter converter) + => new ImmutableSegmentedList(_list.ConvertAll(converter)); + + /// + public void CopyTo(T[] array) + => _list.CopyTo(array); + + public void CopyTo(T[] array, int arrayIndex) + => _list.CopyTo(array, arrayIndex); + + /// + public void CopyTo(int index, T[] array, int arrayIndex, int count) + => _list.CopyTo(index, array, arrayIndex, count); + + /// + public bool Exists(Predicate match) + => _list.Exists(match); + + /// + public T? Find(Predicate match) + => _list.Find(match); + + /// + public ImmutableSegmentedList FindAll(Predicate match) + => new ImmutableSegmentedList(_list.FindAll(match)); + + /// + public int FindIndex(Predicate match) + => _list.FindIndex(match); + + /// + public int FindIndex(int startIndex, Predicate match) + => _list.FindIndex(startIndex, match); + + /// + public int FindIndex(int startIndex, int count, Predicate match) + => _list.FindIndex(startIndex, count, match); + + /// + public T? FindLast(Predicate match) + => _list.FindLast(match); + + /// + public int FindLastIndex(Predicate match) + => _list.FindLastIndex(match); + + /// + public int FindLastIndex(int startIndex, Predicate match) + { + var self = this; + + if (startIndex == 0 && self.IsEmpty) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return self._list.FindLastIndex(startIndex, match); + } + + /// + public int FindLastIndex(int startIndex, int count, Predicate match) + { + var self = this; + + if (count == 0 && startIndex == 0 && self.IsEmpty) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return self._list.FindLastIndex(startIndex, count, match); + } + + /// + public void ForEach(Action action) + => _list.ForEach(action); + + /// + public Enumerator GetEnumerator() + => new(_list); + + /// + public ImmutableSegmentedList GetRange(int index, int count) + { + var self = this; + + if (index == 0 && count == self.Count) + return self; + + return new ImmutableSegmentedList(self._list.GetRange(index, count)); + } + + public int IndexOf(T value) + => _list.IndexOf(value); + + public int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) + => _list.IndexOf(item, index, count, equalityComparer); + + /// + public ImmutableSegmentedList Insert(int index, T item) + { + var self = this; + + if (index == self.Count) + return self.Add(item); + + // TODO: Optimize this to share all segments prior to index + // TODO: Only resize the last page the minimum amount necessary + var builder = self.ToValueBuilder(); + builder.Insert(index, item); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList InsertRange(int index, IEnumerable items) + { + var self = this; + + if (index == self.Count) + return self.AddRange(items); + + // TODO: Optimize this to share all segments prior to index + // TODO: Only resize the last page the minimum amount necessary + var builder = self.ToValueBuilder(); + builder.InsertRange(index, items); + return builder.ToImmutable(); + } + + public int LastIndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) + { + var self = this; + + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (count < 0 || count > self.Count) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count); + if (index - count + 1 < 0) + throw new ArgumentException(); + + if (count == 0 && index == 0 && self.IsEmpty) + { + // SegmentedList doesn't allow starting at index 0 for an empty list, but IImmutableList does. + // Handle it explicitly to avoid an exception. + return -1; + } + + return self._list.LastIndexOf(item, index, count, equalityComparer); + } + + /// + public ImmutableSegmentedList Remove(T value) + { + var self = this; + + var index = self.IndexOf(value); + if (index < 0) + return self; + + return self.RemoveAt(index); + } + + /// + public ImmutableSegmentedList Remove(T value, IEqualityComparer? equalityComparer) + { + var self = this; + + var index = self.IndexOf(value, 0, Count, equalityComparer); + if (index < 0) + return self; + + return self.RemoveAt(index); + } + + /// + public ImmutableSegmentedList RemoveAll(Predicate match) + { + // TODO: Optimize this to avoid allocations if no items are removed + // TODO: Optimize this to share pages prior to the first removed item + var builder = ToValueBuilder(); + builder.RemoveAll(match); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList RemoveAt(int index) + { + // TODO: Optimize this to share pages prior to the removed item + var builder = ToValueBuilder(); + builder.RemoveAt(index); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList RemoveRange(IEnumerable items) + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + var self = this; + + if (self.IsEmpty) + return self; + + var builder = ToValueBuilder(); + foreach (var item in items) + { + var index = builder.IndexOf(item); + if (index < 0) + continue; + + builder.RemoveAt(index); + } + + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList RemoveRange(IEnumerable items, IEqualityComparer? equalityComparer) + { + if (items is null) + throw new ArgumentNullException(nameof(items)); + + var self = this; + + if (self.IsEmpty) + return self; + + var builder = ToValueBuilder(); + foreach (var item in items) + { + var index = builder.IndexOf(item, 0, builder.Count, equalityComparer); + if (index < 0) + continue; + + builder.RemoveAt(index); + } + + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList RemoveRange(int index, int count) + { + var self = this; + + if (count == 0 && index >= 0 && index <= self.Count) + { + return self; + } + + // TODO: Optimize this to share pages prior to the first removed item + var builder = self.ToValueBuilder(); + builder.RemoveRange(index, count); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Replace(T oldValue, T newValue) + { + var self = this; + + var index = self.IndexOf(oldValue); + if (index < 0) + { + throw new ArgumentException(SR.CannotFindOldValue, nameof(oldValue)); + } + + return self.SetItem(index, newValue); + } + + /// + public ImmutableSegmentedList Replace(T oldValue, T newValue, IEqualityComparer? equalityComparer) + { + var self = this; + + var index = self.IndexOf(oldValue, equalityComparer); + if (index < 0) + { + throw new ArgumentException(SR.CannotFindOldValue, nameof(oldValue)); + } + + return self.SetItem(index, newValue); + } + + /// + public ImmutableSegmentedList Reverse() + { + var self = this; + if (self.Count < 2) + return self; + + var builder = self.ToValueBuilder(); + builder.Reverse(); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Reverse(int index, int count) + { + var builder = ToValueBuilder(); + builder.Reverse(index, count); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList SetItem(int index, T value) + { + // TODO: Optimize this to share all pages except the one with 'index' + var builder = ToValueBuilder(); + builder[index] = value; + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Sort() + { + var self = this; + + if (self.Count < 2) + return self; + + // TODO: Optimize this to avoid allocations if the list is already sorted + var builder = self.ToValueBuilder(); + builder.Sort(); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Sort(IComparer? comparer) + { + var self = this; + + if (self.Count < 2) + return self; + + // TODO: Optimize this to avoid allocations if the list is already sorted + var builder = self.ToValueBuilder(); + builder.Sort(comparer); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Sort(Comparison comparison) + { + if (comparison == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); + } + + var self = this; + + if (self.Count < 2) + return self; + + // TODO: Optimize this to avoid allocations if the list is already sorted + var builder = self.ToValueBuilder(); + builder.Sort(comparison); + return builder.ToImmutable(); + } + + /// + public ImmutableSegmentedList Sort(int index, int count, IComparer? comparer) + { + // TODO: Optimize this to avoid allocations if the list is already sorted + var builder = ToValueBuilder(); + builder.Sort(index, count, comparer); + return builder.ToImmutable(); + } + + /// + public Builder ToBuilder() + => new Builder(this); + + private ValueBuilder ToValueBuilder() + => new ValueBuilder(this); + + public override int GetHashCode() + => _list?.GetHashCode() ?? 0; + + public override bool Equals(object? obj) + { + return obj is ImmutableSegmentedList other + && Equals(other); + } + + public bool Equals(ImmutableSegmentedList other) + => _list == other._list; + + /// + public bool TrueForAll(Predicate match) + => _list.TrueForAll(match); + + IImmutableList IImmutableList.Clear() + => Clear(); + + IImmutableList IImmutableList.Add(T value) + => Add(value); + + IImmutableList IImmutableList.AddRange(IEnumerable items) + => AddRange(items); + + IImmutableList IImmutableList.Insert(int index, T element) + => Insert(index, element); + + IImmutableList IImmutableList.InsertRange(int index, IEnumerable items) + => InsertRange(index, items); + + IImmutableList IImmutableList.Remove(T value, IEqualityComparer? equalityComparer) + => Remove(value, equalityComparer); + + IImmutableList IImmutableList.RemoveAll(Predicate match) + => RemoveAll(match); + + IImmutableList IImmutableList.RemoveRange(IEnumerable items, IEqualityComparer? equalityComparer) + => RemoveRange(items, equalityComparer); + + IImmutableList IImmutableList.RemoveRange(int index, int count) + => RemoveRange(index, count); + + IImmutableList IImmutableList.RemoveAt(int index) + => RemoveAt(index); + + IImmutableList IImmutableList.SetItem(int index, T value) + => SetItem(index, value); + + IImmutableList IImmutableList.Replace(T oldValue, T newValue, IEqualityComparer? equalityComparer) + => Replace(oldValue, newValue, equalityComparer); + + IEnumerator IEnumerable.GetEnumerator() + => IsEmpty ? Enumerable.Empty().GetEnumerator() : GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => ((IEnumerable)this).GetEnumerator(); + + void IList.Insert(int index, T item) + => throw new NotSupportedException(); + + void IList.RemoveAt(int index) + => throw new NotSupportedException(); + + void ICollection.Add(T item) + => throw new NotSupportedException(); + + void ICollection.Clear() + => throw new NotSupportedException(); + + bool ICollection.Remove(T item) + => throw new NotSupportedException(); + + int IList.Add(object? value) + => throw new NotSupportedException(); + + void IList.Clear() + => throw new NotSupportedException(); + + bool IList.Contains(object? value) + { + IList backingList = _list; + return backingList.Contains(value); + } + + int IList.IndexOf(object? value) + { + IList backingList = _list; + return backingList.IndexOf(value); + } + + void IList.Insert(int index, object? value) + => throw new NotSupportedException(); + + void IList.Remove(object? value) + => throw new NotSupportedException(); + + void IList.RemoveAt(int index) + => throw new NotSupportedException(); + + void ICollection.CopyTo(Array array, int index) + { + IList backingList = _list; + backingList.CopyTo(array, index); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedArray.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedArray.cs new file mode 100755 index 00000000000..56301f0c088 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedArray.cs @@ -0,0 +1,802 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static class SegmentedArray + { +#if NET6_0_OR_GREATER + /// +#endif + internal static void Clear(SegmentedArray array) + => Clear(array, 0, array.Length); + + /// + internal static void Clear(SegmentedArray array, int index, int length) + { + foreach (var memory in array.GetSegments(index, length)) + { + memory.Span.Clear(); + } + } + + /// + internal static void Copy(SegmentedArray sourceArray, SegmentedArray destinationArray, int length) + { + if (length == 0) + return; + + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length)); + if (length > sourceArray.Length) + throw new ArgumentException(SR.Arg_LongerThanSrcArray, nameof(sourceArray)); + if (length > destinationArray.Length) + throw new ArgumentException(SR.Arg_LongerThanDestArray, nameof(destinationArray)); + + foreach (var (first, second) in GetSegments(sourceArray, destinationArray, length)) + { + first.CopyTo(second); + } + } + + public static void Copy(SegmentedArray sourceArray, Array destinationArray, int length) + { + if (destinationArray is null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.destinationArray); + if (length == 0) + return; + + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length)); + if (length > sourceArray.Length) + throw new ArgumentException(SR.Arg_LongerThanSrcArray, nameof(sourceArray)); + if (length > destinationArray.Length) + throw new ArgumentException(SR.Arg_LongerThanDestArray, nameof(destinationArray)); + + var copied = 0; + foreach (var memory in sourceArray.GetSegments(0, length)) + { + if (!MemoryMarshal.TryGetArray(memory, out var segment)) + { + throw new NotSupportedException(); + } + + Array.Copy(segment.Array!, sourceIndex: segment.Offset, destinationArray: destinationArray, destinationIndex: copied, length: segment.Count); + copied += segment.Count; + } + } + + public static void Copy(SegmentedArray sourceArray, int sourceIndex, SegmentedArray destinationArray, int destinationIndex, int length) + { + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum); + if (sourceIndex < 0) + throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_ArrayLB); + if (destinationIndex < 0) + throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_ArrayLB); + if ((uint)(sourceIndex + length) > sourceArray.Length) + throw new ArgumentException(SR.Arg_LongerThanSrcArray, nameof(sourceArray)); + if ((uint)(destinationIndex + length) > destinationArray.Length) + throw new ArgumentException(SR.Arg_LongerThanDestArray, nameof(destinationArray)); + + if (length == 0) + return; + + if (SegmentedCollectionsMarshal.AsSegments(sourceArray) == SegmentedCollectionsMarshal.AsSegments(destinationArray) + && sourceIndex + length > destinationIndex) + { + // We are copying in the same array with overlap + CopyOverlapped(sourceArray, sourceIndex, destinationIndex, length); + } + else + { + foreach (var (first, second) in GetSegmentsUnaligned(sourceArray, sourceIndex, destinationArray, destinationIndex, length)) + { + first.CopyTo(second); + } + } + } + + // PERF: Avoid inlining this path in Copy + [MethodImpl(MethodImplOptions.NoInlining)] + private static void CopyOverlapped(SegmentedArray array, int sourceIndex, int destinationIndex, int length) + { + Debug.Assert(length > 0); + Debug.Assert(sourceIndex >= 0); + Debug.Assert(destinationIndex >= 0); + Debug.Assert((uint)(sourceIndex + length) <= array.Length); + Debug.Assert((uint)(destinationIndex + length) <= array.Length); + + var unalignedEnumerator = GetSegmentsUnaligned(array, sourceIndex, array, destinationIndex, length); + if (sourceIndex < destinationIndex) + { + // We are copying forward in the same array with overlap + foreach (var (first, second) in unalignedEnumerator.Reverse()) + { + first.CopyTo(second); + } + } + else + { + foreach (var (first, second) in unalignedEnumerator) + { + first.CopyTo(second); + } + } + } + + public static void Copy(SegmentedArray sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length) + { + if (destinationArray == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.destinationArray); + + if (typeof(T[]) != destinationArray.GetType() && destinationArray.Rank != 1) + throw new RankException(SR.Rank_MustMatch); + + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum); + if (sourceIndex < 0) + throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_ArrayLB); + + var dstLB = destinationArray.GetLowerBound(0); + if (destinationIndex < dstLB || destinationIndex - dstLB < 0) + throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_ArrayLB); + destinationIndex -= dstLB; + + if ((uint)(sourceIndex + length) > sourceArray.Length) + throw new ArgumentException(SR.Arg_LongerThanSrcArray, nameof(sourceArray)); + if ((uint)(destinationIndex + length) > (nuint)destinationArray.LongLength) + throw new ArgumentException(SR.Arg_LongerThanDestArray, nameof(destinationArray)); + + var copied = 0; + foreach (var memory in sourceArray.GetSegments(sourceIndex, length)) + { + if (!MemoryMarshal.TryGetArray(memory, out var segment)) + { + throw new NotSupportedException(); + } + + Array.Copy(segment.Array!, sourceIndex: segment.Offset, destinationArray: destinationArray, destinationIndex: destinationIndex + copied, length: segment.Count); + copied += segment.Count; + } + } + + public static int BinarySearch(SegmentedArray array, T value) + { + return BinarySearch(array, 0, array.Length, value, comparer: null); + } + + public static int BinarySearch(SegmentedArray array, T value, IComparer? comparer) + { + return BinarySearch(array, 0, array.Length, value, comparer); + } + + public static int BinarySearch(SegmentedArray array, int index, int length, T value) + { + return BinarySearch(array, index, length, value, comparer: null); + } + + public static int BinarySearch(SegmentedArray array, int index, int length, T value, IComparer? comparer) + { + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (length < 0) + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); + if (array.Length - index < length) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + return SegmentedArraySortHelper.BinarySearch(array, index, length, value, comparer); + } + + public static int IndexOf(SegmentedArray array, T value) + { + return IndexOf(array, value, 0, array.Length, comparer: null); + } + + public static int IndexOf(SegmentedArray array, T value, int startIndex) + { + return IndexOf(array, value, startIndex, array.Length - startIndex, comparer: null); + } + + public static int IndexOf(SegmentedArray array, T value, int startIndex, int count) + { + return IndexOf(array, value, startIndex, count, comparer: null); + } + + public static int IndexOf(SegmentedArray array, T value, int startIndex, int count, IEqualityComparer? comparer) + { + if ((uint)startIndex > (uint)array.Length) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLessOrEqual(); + } + + if ((uint)count > (uint)(array.Length - startIndex)) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + var offset = startIndex; + foreach (var memory in array.GetSegments(startIndex, count)) + { + if (!MemoryMarshal.TryGetArray(memory, out var segment)) + { + throw new NotSupportedException(); + } + + int index; + if (comparer is null || comparer == EqualityComparer.Default) + { + index = Array.IndexOf(segment.Array!, value, segment.Offset, segment.Count); + } + else + { + index = -1; + var endIndex = segment.Offset + segment.Count; + for (var i = segment.Offset; i < endIndex; i++) + { + if (comparer.Equals(array[i], value)) + { + index = i; + break; + } + } + } + + if (index >= 0) + { + return index + offset - segment.Offset; + } + + offset += segment.Count; + } + + return -1; + } + + public static int LastIndexOf(SegmentedArray array, T value) + { + return LastIndexOf(array, value, array.Length - 1, array.Length, comparer: null); + } + + public static int LastIndexOf(SegmentedArray array, T value, int startIndex) + { + return LastIndexOf(array, value, startIndex, array.Length == 0 ? 0 : startIndex + 1, comparer: null); + } + + public static int LastIndexOf(SegmentedArray array, T value, int startIndex, int count) + { + return LastIndexOf(array, value, startIndex, count, comparer: null); + } + + public static int LastIndexOf(SegmentedArray array, T value, int startIndex, int count, IEqualityComparer? comparer) + { + if (array.Length == 0) + { + // Special case for 0 length List + // accept -1 and 0 as valid startIndex for compatibility reason. + if (startIndex is not (-1) and not 0) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); + } + + // only 0 is a valid value for count if array is empty + if (count != 0) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + return -1; + } + + // Make sure we're not out of range + if ((uint)startIndex >= (uint)array.Length) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); + } + + // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. + if (count < 0 || startIndex - count + 1 < 0) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + if (comparer is null || comparer == EqualityComparer.Default) + { + var endIndex = startIndex - count + 1; + for (var i = startIndex; i >= endIndex; i--) + { + if (EqualityComparer.Default.Equals(array[i], value)) + return i; + } + } + else + { + var endIndex = startIndex - count + 1; + for (var i = startIndex; i >= endIndex; i--) + { + if (comparer.Equals(array[i], value)) + return i; + } + } + + return -1; + } + + public static void Reverse(SegmentedArray array) + { + Reverse(array, 0, array.Length); + } + + public static void Reverse(SegmentedArray array, int index, int length) + { + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (length < 0) + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); + if (array.Length - index < length) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (length <= 1) + return; + + var firstIndex = index; + var lastIndex = index + length - 1; + do + { + var temp = array[firstIndex]; + array[firstIndex] = array[lastIndex]; + array[lastIndex] = temp; + firstIndex++; + lastIndex--; + } while (firstIndex < lastIndex); + } + + public static void Sort(SegmentedArray array) + { + if (array.Length > 1) + { + var segment = new SegmentedArraySegment(array, 0, array.Length); + SegmentedArraySortHelper.Sort(segment, (IComparer?)null); + } + } + + public static void Sort(SegmentedArray array, int index, int length) + { + Sort(array, index, length, comparer: null); + } + + public static void Sort(SegmentedArray array, IComparer? comparer) + { + Sort(array, 0, array.Length, comparer); + } + + public static void Sort(SegmentedArray array, int index, int length, IComparer? comparer) + { + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (length < 0) + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); + if (array.Length - index < length) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (length > 1) + { + var segment = new SegmentedArraySegment(array, index, length); + SegmentedArraySortHelper.Sort(segment, comparer); + } + } + + public static void Sort(SegmentedArray array, Comparison comparison) + { + if (comparison is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); + } + + if (array.Length > 1) + { + var segment = new SegmentedArraySegment(array, 0, array.Length); + SegmentedArraySortHelper.Sort(segment, comparison); + } + } + + private static SegmentEnumerable GetSegments(this SegmentedArray array, int offset, int length) + => new(array, offset, length); + + private static AlignedSegmentEnumerable GetSegments(SegmentedArray first, SegmentedArray second, int length) + => new(first, second, length); + +#pragma warning disable IDE0051 // Remove unused private members (will be used in follow-up) + private static AlignedSegmentEnumerable GetSegmentsAligned(SegmentedArray first, int firstOffset, SegmentedArray second, int secondOffset, int length) + => new(first, firstOffset, second, secondOffset, length); +#pragma warning restore IDE0051 // Remove unused private members + + private static UnalignedSegmentEnumerable GetSegmentsUnaligned(SegmentedArray first, int firstOffset, SegmentedArray second, int secondOffset, int length) + => new(first, firstOffset, second, secondOffset, length); + + private readonly struct AlignedSegmentEnumerable + { + private readonly SegmentedArray _first; + private readonly int _firstOffset; + private readonly SegmentedArray _second; + private readonly int _secondOffset; + private readonly int _length; + + public AlignedSegmentEnumerable(SegmentedArray first, SegmentedArray second, int length) + : this(first, 0, second, 0, length) + { + } + + public AlignedSegmentEnumerable(SegmentedArray first, int firstOffset, SegmentedArray second, int secondOffset, int length) + { + _first = first; + _firstOffset = firstOffset; + _second = second; + _secondOffset = secondOffset; + _length = length; + } + + public AlignedSegmentEnumerator GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_first), _firstOffset, SegmentedCollectionsMarshal.AsSegments(_second), _secondOffset, _length); + } + + private struct AlignedSegmentEnumerator + { + private readonly T[][] _firstSegments; + private readonly int _firstOffset; + private readonly T[][] _secondSegments; + private readonly int _secondOffset; + private readonly int _length; + + private int _completed; + private (Memory first, Memory second) _current; + + public AlignedSegmentEnumerator(T[][] firstSegments, int firstOffset, T[][] secondSegments, int secondOffset, int length) + { + _firstSegments = firstSegments; + _firstOffset = firstOffset; + _secondSegments = secondSegments; + _secondOffset = secondOffset; + _length = length; + + _completed = 0; + _current = (Memory.Empty, Memory.Empty); + } + + public readonly (Memory first, Memory second) Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = (Memory.Empty, Memory.Empty); + return false; + } + + if (_completed == 0) + { + var initialFirstSegment = _firstOffset >> SegmentedArrayHelper.GetSegmentShift(); + var initialSecondSegment = _secondOffset >> SegmentedArrayHelper.GetSegmentShift(); + var offset = _firstOffset & SegmentedArrayHelper.GetOffsetMask(); + Debug.Assert(offset == (_secondOffset & SegmentedArrayHelper.GetOffsetMask()), "Aligned views must start at the same segment offset"); + + var firstSegment = _firstSegments[initialFirstSegment]; + var secondSegment = _secondSegments[initialSecondSegment]; + var remainingInSegment = firstSegment.Length - offset; + var currentSegmentLength = Math.Min(remainingInSegment, _length); + _current = (firstSegment.AsMemory().Slice(offset, currentSegmentLength), secondSegment.AsMemory().Slice(offset, currentSegmentLength)); + _completed = currentSegmentLength; + return true; + } + else + { + var firstSegment = _firstSegments[(_completed + _firstOffset) >> SegmentedArrayHelper.GetSegmentShift()]; + var secondSegment = _secondSegments[(_completed + _secondOffset) >> SegmentedArrayHelper.GetSegmentShift()]; + var currentSegmentLength = Math.Min(SegmentedArrayHelper.GetSegmentSize(), _length - _completed); + _current = (firstSegment.AsMemory().Slice(0, currentSegmentLength), secondSegment.AsMemory().Slice(0, currentSegmentLength)); + _completed += currentSegmentLength; + return true; + } + } + } + + private readonly struct UnalignedSegmentEnumerable + { + private readonly SegmentedArray _first; + private readonly int _firstOffset; + private readonly SegmentedArray _second; + private readonly int _secondOffset; + private readonly int _length; + + public UnalignedSegmentEnumerable(SegmentedArray first, SegmentedArray second, int length) + : this(first, 0, second, 0, length) + { + } + + public UnalignedSegmentEnumerable(SegmentedArray first, int firstOffset, SegmentedArray second, int secondOffset, int length) + { + _first = first; + _firstOffset = firstOffset; + _second = second; + _secondOffset = secondOffset; + _length = length; + } + + public UnalignedSegmentEnumerator GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_first), _firstOffset, SegmentedCollectionsMarshal.AsSegments(_second), _secondOffset, _length); + + public ReverseEnumerable Reverse() + => new(this); + + public readonly struct ReverseEnumerable + { + private readonly UnalignedSegmentEnumerable _enumerable; + + public ReverseEnumerable(UnalignedSegmentEnumerable enumerable) + { + _enumerable = enumerable; + } + + public UnalignedSegmentEnumerator.Reverse GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_enumerable._first), _enumerable._firstOffset, SegmentedCollectionsMarshal.AsSegments(_enumerable._second), _enumerable._secondOffset, _enumerable._length); + + public UnalignedSegmentEnumerable Reverse() + => _enumerable; + } + } + + private struct UnalignedSegmentEnumerator + { + private readonly T[][] _firstSegments; + private readonly int _firstOffset; + private readonly T[][] _secondSegments; + private readonly int _secondOffset; + private readonly int _length; + + private int _completed; + private (Memory first, Memory second) _current; + + public UnalignedSegmentEnumerator(T[][] firstSegments, int firstOffset, T[][] secondSegments, int secondOffset, int length) + { + _firstSegments = firstSegments; + _firstOffset = firstOffset; + _secondSegments = secondSegments; + _secondOffset = secondOffset; + _length = length; + + _completed = 0; + _current = (Memory.Empty, Memory.Empty); + } + + public readonly (Memory first, Memory second) Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = (Memory.Empty, Memory.Empty); + return false; + } + + var initialFirstSegment = (_completed + _firstOffset) >> SegmentedArrayHelper.GetSegmentShift(); + var initialSecondSegment = (_completed + _secondOffset) >> SegmentedArrayHelper.GetSegmentShift(); + var firstOffset = (_completed + _firstOffset) & SegmentedArrayHelper.GetOffsetMask(); + var secondOffset = (_completed + _secondOffset) & SegmentedArrayHelper.GetOffsetMask(); + + var firstSegment = _firstSegments[initialFirstSegment]; + var secondSegment = _secondSegments[initialSecondSegment]; + var remainingInFirstSegment = firstSegment.Length - firstOffset; + var remainingInSecondSegment = secondSegment.Length - secondOffset; + var currentSegmentLength = Math.Min(Math.Min(remainingInFirstSegment, remainingInSecondSegment), _length - _completed); + _current = (firstSegment.AsMemory().Slice(firstOffset, currentSegmentLength), secondSegment.AsMemory().Slice(secondOffset, currentSegmentLength)); + _completed += currentSegmentLength; + return true; + } + + public struct Reverse + { + private readonly T[][] _firstSegments; + private readonly int _firstOffset; + private readonly T[][] _secondSegments; + private readonly int _secondOffset; + private readonly int _length; + + private int _completed; + private (Memory first, Memory second) _current; + + public Reverse(T[][] firstSegments, int firstOffset, T[][] secondSegments, int secondOffset, int length) + { + _firstSegments = firstSegments; + _firstOffset = firstOffset; + _secondSegments = secondSegments; + _secondOffset = secondOffset; + _length = length; + + _completed = 0; + _current = (Memory.Empty, Memory.Empty); + } + + public readonly (Memory first, Memory second) Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = (Memory.Empty, Memory.Empty); + return false; + } + + var initialFirstSegment = (_firstOffset + _length - _completed - 1) >> SegmentedArrayHelper.GetSegmentShift(); + var initialSecondSegment = (_secondOffset + _length - _completed - 1) >> SegmentedArrayHelper.GetSegmentShift(); + var firstOffset = (_firstOffset + _length - _completed - 1) & SegmentedArrayHelper.GetOffsetMask(); + var secondOffset = (_secondOffset + _length - _completed - 1) & SegmentedArrayHelper.GetOffsetMask(); + + var firstSegment = _firstSegments[initialFirstSegment]; + var secondSegment = _secondSegments[initialSecondSegment]; + var remainingInFirstSegment = firstOffset + 1; + var remainingInSecondSegment = secondOffset + 1; + var currentSegmentLength = Math.Min(Math.Min(remainingInFirstSegment, remainingInSecondSegment), _length - _completed); + _current = (firstSegment.AsMemory().Slice(firstOffset - currentSegmentLength + 1, currentSegmentLength), secondSegment.AsMemory().Slice(secondOffset - currentSegmentLength + 1, currentSegmentLength)); + _completed += currentSegmentLength; + return true; + } + } + } + + private readonly struct SegmentEnumerable + { + private readonly SegmentedArray _array; + private readonly int _offset; + private readonly int _length; + + public SegmentEnumerable(SegmentedArray array) + { + _array = array; + _offset = 0; + _length = array.Length; + } + + public SegmentEnumerable(SegmentedArray array, int offset, int length) + { + if (offset < 0 || length < 0 || (uint)(offset + length) > (uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + _array = array; + _offset = offset; + _length = length; + } + + public SegmentEnumerator GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_array), _offset, _length); + + public ReverseEnumerable Reverse() + => new(this); + + public readonly struct ReverseEnumerable + { + private readonly SegmentEnumerable _enumerable; + + public ReverseEnumerable(SegmentEnumerable enumerable) + { + _enumerable = enumerable; + } + + public SegmentEnumerator.Reverse GetEnumerator() + => new(SegmentedCollectionsMarshal.AsSegments(_enumerable._array), _enumerable._offset, _enumerable._length); + + public SegmentEnumerable Reverse() + => _enumerable; + } + } + + private struct SegmentEnumerator + { + private readonly T[][] _segments; + private readonly int _offset; + private readonly int _length; + + private int _completed; + private Memory _current; + + public SegmentEnumerator(T[][] segments, int offset, int length) + { + _segments = segments; + _offset = offset; + _length = length; + + _completed = 0; + _current = Memory.Empty; + } + + public readonly Memory Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = Memory.Empty; + return false; + } + + if (_completed == 0) + { + var firstSegment = _offset >> SegmentedArrayHelper.GetSegmentShift(); + var offset = _offset & SegmentedArrayHelper.GetOffsetMask(); + + var segment = _segments[firstSegment]; + var remainingInSegment = segment.Length - offset; + _current = segment.AsMemory().Slice(offset, Math.Min(remainingInSegment, _length)); + _completed = _current.Length; + return true; + } + else + { + var segment = _segments[(_completed + _offset) >> SegmentedArrayHelper.GetSegmentShift()]; + _current = segment.AsMemory().Slice(0, Math.Min(SegmentedArrayHelper.GetSegmentSize(), _length - _completed)); + _completed += _current.Length; + return true; + } + } + + public struct Reverse + { + private readonly T[][] _segments; + private readonly int _offset; + private readonly int _length; + + private int _completed; + private Memory _current; + + public Reverse(T[][] segments, int offset, int length) + { + _segments = segments; + _offset = offset; + _length = length; + + _completed = 0; + _current = Memory.Empty; + } + + public readonly Memory Current => _current; + + public bool MoveNext() + { + if (_completed == _length) + { + _current = Memory.Empty; + return false; + } + + if (_completed == 0) + { + var firstSegment = _offset >> SegmentedArrayHelper.GetSegmentShift(); + var offset = _offset & SegmentedArrayHelper.GetOffsetMask(); + + var segment = _segments[firstSegment]; + var remainingInSegment = segment.Length - offset; + _current = segment.AsMemory().Slice(offset, Math.Min(remainingInSegment, _length)); + _completed = _current.Length; + return true; + } + else + { + var segment = _segments[(_completed + _offset) >> SegmentedArrayHelper.GetSegmentShift()]; + _current = segment.AsMemory().Slice(0, Math.Min(SegmentedArrayHelper.GetSegmentSize(), _length - _completed)); + _completed += _current.Length; + return true; + } + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedArray`1+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedArray`1+PrivateMarshal.cs new file mode 100755 index 00000000000..54bb94d2ffa --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedArray`1+PrivateMarshal.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections; + +internal readonly partial struct SegmentedArray +{ + /// + /// Private helper class for use only by . + /// + internal static class PrivateMarshal + { + /// + public static T[][] AsSegments(SegmentedArray array) + => array._items; + + public static SegmentedArray AsSegmentedArray(int length, T[][] segments) + => new SegmentedArray(length, segments); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedArray`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedArray`1.cs new file mode 100755 index 00000000000..c544295a66a --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedArray`1.cs @@ -0,0 +1,426 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Defines a fixed-size collection with the same API surface and behavior as an "SZArray", which is a + /// single-dimensional zero-based array commonly represented in C# as T[]. The implementation of this + /// collection uses segmented arrays to avoid placing objects on the Large Object Heap. + /// + /// The type of elements stored in the array. + internal readonly partial struct SegmentedArray : ICloneable, IList, IStructuralComparable, IStructuralEquatable, IList, IReadOnlyList, IEquatable> + { + /// + /// The number of elements in each page of the segmented array of type . + /// + /// + /// The segment size is calculated according to , performs the IL operation + /// defined by . ECMA-335 defines this operation with the following note: + /// + /// sizeof returns the total size that would be occupied by each element in an array of this type – + /// including any padding the implementation chooses to add. Specifically, array elements lie sizeof + /// bytes apart. + /// + private static int SegmentSize + { + get + { + return SegmentedArrayHelper.GetSegmentSize(); + } + } + + /// + /// The bit shift to apply to an array index to get the page index within . + /// + private static int SegmentShift + { + get + { + return SegmentedArrayHelper.GetSegmentShift(); + } + } + + /// + /// The bit mask to apply to an array index to get the index within a page of . + /// + private static int OffsetMask + { + get + { + return SegmentedArrayHelper.GetOffsetMask(); + } + } + + private readonly int _length; + private readonly T[][] _items; + + public SegmentedArray(int length) + { + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + if (length == 0) + { + _items = Array.Empty(); + _length = 0; + } + else + { + _items = new T[(length + SegmentSize - 1) >> SegmentShift][]; + for (var i = 0; i < _items.Length - 1; i++) + { + _items[i] = new T[SegmentSize]; + } + + // Make sure the last page only contains the number of elements required for the desired length. This + // collection is not resizeable so any additional padding would be a waste of space. + // + // Avoid using (length & s_offsetMask) because it doesn't handle a last page size of s_segmentSize. + var lastPageSize = length - ((_items.Length - 1) << SegmentShift); + + _items[_items.Length - 1] = new T[lastPageSize]; + _length = length; + } + } + + private SegmentedArray(int length, T[][] items) + { + _length = length; + _items = items; + } + + public bool IsFixedSize => true; + + public bool IsReadOnly => true; + + public bool IsSynchronized => false; + + public int Length => _length; + + public object SyncRoot => _items; + + public ref T this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref _items[index >> SegmentShift][index & OffsetMask]; + } + } + + int ICollection.Count => Length; + + int ICollection.Count => Length; + + int IReadOnlyCollection.Count => Length; + + T IReadOnlyList.this[int index] => this[index]; + + T IList.this[int index] + { + get => this[index]; + set => this[index] = value; + } + + object? IList.this[int index] + { + get => this[index]; + set => this[index] = (T)value!; + } + + public object Clone() + { + var items = (T[][])_items.Clone(); + for (var i = 0; i < items.Length; i++) + { + items[i] = (T[])items[i].Clone(); + } + + return new SegmentedArray(Length, items); + } + + public void CopyTo(Array array, int index) + { + for (var i = 0; i < _items.Length; i++) + { + _items[i].CopyTo(array, index + (i * SegmentSize)); + } + } + + void ICollection.CopyTo(T[] array, int arrayIndex) + { + for (var i = 0; i < _items.Length; i++) + { + ICollection collection = _items[i]; + collection.CopyTo(array, arrayIndex + (i * SegmentSize)); + } + } + + public Enumerator GetEnumerator() + => new(this); + + public override bool Equals(object? obj) + { + return obj is SegmentedArray other + && Equals(other); + } + + public override int GetHashCode() + { + return _items.GetHashCode(); + } + + public bool Equals(SegmentedArray other) + { + return _items == other._items; + } + + int IList.Add(object? value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void ICollection.Add(T value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.Clear() + { + // Matches System.Array + // https://github.com/dotnet/runtime/blob/e0ec035994179e8ebd6ccf081711ee11d4c5491b/src/libraries/System.Private.CoreLib/src/System/Array.cs#L279-L282 + foreach (IList list in _items) + { + list.Clear(); + } + } + + void ICollection.Clear() + { + // Matches `((ICollection)new T[1]).Clear()` + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + bool IList.Contains(object? value) + { + foreach (IList list in _items) + { + if (list.Contains(value)) + return true; + } + + return false; + } + + bool ICollection.Contains(T value) + { + foreach (ICollection collection in _items) + { + if (collection.Contains(value)) + return true; + } + + return false; + } + + int IList.IndexOf(object? value) + { + for (var i = 0; i < _items.Length; i++) + { + IList list = _items[i]; + var index = list.IndexOf(value); + if (index >= 0) + { + return index + i * SegmentSize; + } + } + + return -1; + } + + int IList.IndexOf(T value) + { + for (var i = 0; i < _items.Length; i++) + { + IList list = _items[i]; + var index = list.IndexOf(value); + if (index >= 0) + { + return index + i * SegmentSize; + } + } + + return -1; + } + + void IList.Insert(int index, object? value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.Insert(int index, T value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.Remove(object? value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + bool ICollection.Remove(T value) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.RemoveAt(int index) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + void IList.RemoveAt(int index) + { + throw new NotSupportedException(SR.NotSupported_FixedSizeCollection); + } + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + int IStructuralComparable.CompareTo(object? other, IComparer comparer) + { + if (other is null) + return 1; + + // Matches System.Array + // https://github.com/dotnet/runtime/blob/e0ec035994179e8ebd6ccf081711ee11d4c5491b/src/libraries/System.Private.CoreLib/src/System/Array.cs#L320-L323 + if (other is not SegmentedArray o + || Length != o.Length) + { + throw new ArgumentException(SR.ArgumentException_OtherNotArrayOfCorrectLength, nameof(other)); + } + + for (var i = 0; i < Length; i++) + { + var result = comparer.Compare(this[i], o[i]); + if (result != 0) + return result; + } + + return 0; + } + + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) + { + if (other is null) + return false; + + if (other is not SegmentedArray o) + return false; + + if (ReferenceEquals(_items, o._items)) + return true; + + if (Length != o.Length) + return false; + + for (var i = 0; i < Length; i++) + { + if (!comparer.Equals(this[i], o[i])) + return false; + } + + return true; + } + + int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) + { + _ = comparer ?? throw new ArgumentNullException(nameof(comparer)); + + // Matches System.Array + // https://github.com/dotnet/runtime/blob/e0ec035994179e8ebd6ccf081711ee11d4c5491b/src/libraries/System.Private.CoreLib/src/System/Array.cs#L380-L383 + var ret = 0; + for (var i = Length >= 8 ? Length - 8 : 0; i < Length; i++) + { +#if NET + ret = HashCode.Combine(comparer.GetHashCode(this[i]!), ret); +#else + ret = unchecked((ret * (int)0xA5555529) + comparer.GetHashCode(this[i]!)); +#endif + } + + return ret; + } + + public struct Enumerator : IEnumerator + { + private readonly T[][] _items; + private int _nextItemSegment; + private int _nextItemIndex; + private T _current; + + public Enumerator(SegmentedArray array) + { + _items = array._items; + _nextItemSegment = 0; + _nextItemIndex = 0; + _current = default!; + } + + public readonly T Current => _current; + readonly object? IEnumerator.Current => Current; + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + if (_items.Length == 0) + return false; + + if (_nextItemIndex == _items[_nextItemSegment].Length) + { + if (_nextItemSegment == _items.Length - 1) + { + return false; + } + + _nextItemSegment++; + _nextItemIndex = 0; + } + + _current = _items[_nextItemSegment][_nextItemIndex]; + _nextItemIndex++; + return true; + } + + public void Reset() + { + _nextItemSegment = 0; + _nextItemIndex = 0; + _current = default!; + } + } + + internal static class TestAccessor + { + public static int SegmentSize => SegmentedArray.SegmentSize; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedCollectionsMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedCollectionsMarshal.cs new file mode 100755 index 00000000000..56c6f38b5e1 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedCollectionsMarshal.cs @@ -0,0 +1,226 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections; + +/// +/// An unsafe class that provides a set of methods to access the underlying data representations of immutable segmented +/// collections. +/// +internal static class SegmentedCollectionsMarshal +{ + /// + /// Gets the backing storage array for a . + /// + /// The type of elements stored in the array. + /// The segmented array. + /// The backing storage array for the segmented array. Note that replacing segments within the returned + /// value will invalidate the data structure. + public static T[][] AsSegments(SegmentedArray array) + => SegmentedArray.PrivateMarshal.AsSegments(array); + + /// + /// Gets a value wrapping the input T[][]. + /// + /// The type of elements in the input. + /// The combined length of the input arrays + /// The input array to wrap in the returned value. + /// A value wrapping . + /// + /// + /// When using this method, callers should take extra care to ensure that they're the sole owners of the input + /// array, and that it won't be modified once the returned value starts + /// being used. Doing so might cause undefined behavior in code paths which don't expect the contents of a given + /// values to change outside their control. + /// + /// + /// Thrown when is + public static SegmentedArray AsSegmentedArray(int length, T[][] segments) + => SegmentedArray.PrivateMarshal.AsSegmentedArray(length, segments); + + /// + /// Gets either a ref to a in the or a + /// ref null if it does not exist in the . + /// + /// The dictionary to get the ref to from. + /// The key used for lookup. + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + /// + /// Items should not be added or removed from the while the ref + /// is in use. The ref null can be detected using . + /// + [SuppressMessage("Documentation", "CA1200", Justification = "Not all targets can resolve the documented method reference.")] + public static ref TValue GetValueRefOrNullRef(SegmentedDictionary dictionary, TKey key) + where TKey : notnull + => ref SegmentedDictionary.PrivateMarshal.FindValue(dictionary, key); + + /// + /// Gets either a read-only ref to a in the + /// or a ref null if it does not exist in the . + /// + /// The dictionary to get the ref to from. + /// The key used for lookup. + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + /// + /// The ref null can be detected using . + /// + [SuppressMessage("Documentation", "CA1200", Justification = "Not all targets can resolve the documented method reference.")] + public static ref readonly TValue GetValueRefOrNullRef(ImmutableSegmentedDictionary dictionary, TKey key) + where TKey : notnull + => ref ImmutableSegmentedDictionary.PrivateMarshal.FindValue(dictionary, key); + + /// + /// Gets either a ref to a in the + /// or a ref null if it does not exist in the . + /// + /// The dictionary to get the ref to from. + /// The key used for lookup. + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + /// + /// Items should not be added or removed from the + /// while the ref is in use. The ref null can be detected using + /// . + /// + [SuppressMessage("Documentation", "CA1200", Justification = "Not all targets can resolve the documented method reference.")] + public static ref TValue GetValueRefOrNullRef(ImmutableSegmentedDictionary.Builder dictionary, TKey key) + where TKey : notnull + => ref ImmutableSegmentedDictionary.Builder.PrivateMarshal.FindValue(dictionary, key); + + /// + /// Gets an value wrapping the input . + /// + /// The type of elements in the input segmented list. + /// The input segmented list to wrap in the returned value. + /// An value wrapping . + /// + /// + /// When using this method, callers should take extra care to ensure that they're the sole owners of the input + /// list, and that it won't be modified once the returned value starts + /// being used. Doing so might cause undefined behavior in code paths which don't expect the contents of a given + /// values to change after its creation. + /// + /// + /// If is , the returned value + /// will be uninitialized (i.e. its property will be + /// ). + /// + /// + public static ImmutableSegmentedList AsImmutableSegmentedList(SegmentedList? list) + => ImmutableSegmentedList.PrivateMarshal.AsImmutableSegmentedList(list); + + /// + /// Gets the underlying for an input value. + /// + /// The type of elements in the input value. + /// The input value to get the underlying from. + /// The underlying for , if present; otherwise, . + /// + /// + /// When using this method, callers should make sure to not pass the resulting underlying list to methods that + /// might mutate it. Doing so might cause undefined behavior in code paths using which + /// don't expect the contents of the value to change. + /// + /// + /// If is uninitialized (i.e. its property is + /// ), the resulting will be . + /// + /// + public static SegmentedList? AsSegmentedList(ImmutableSegmentedList list) + => ImmutableSegmentedList.PrivateMarshal.AsSegmentedList(list); + + /// + /// Gets an value wrapping the input . + /// + /// The type of elements in the input segmented hash set. + /// The input segmented hash set to wrap in the returned value. + /// An value wrapping . + /// + /// + /// When using this method, callers should take extra care to ensure that they're the sole owners of the input + /// set, and that it won't be modified once the returned value starts + /// being used. Doing so might cause undefined behavior in code paths which don't expect the contents of a given + /// values to change after its creation. + /// + /// + /// If is , the returned + /// value will be uninitialized (i.e. its property will be + /// ). + /// + /// + public static ImmutableSegmentedHashSet AsImmutableSegmentedHashSet(SegmentedHashSet? set) + => ImmutableSegmentedHashSet.PrivateMarshal.AsImmutableSegmentedHashSet(set); + + /// + /// Gets the underlying for an input value. + /// + /// The type of elements in the input value. + /// The input value to get the underlying from. + /// The underlying for , if present; otherwise, . + /// + /// + /// When using this method, callers should make sure to not pass the resulting underlying hash set to methods that + /// might mutate it. Doing so might cause undefined behavior in code paths using which + /// don't expect the contents of the value to change. + /// + /// + /// If is uninitialized (i.e. its + /// property is ), the resulting will be . + /// + /// + public static SegmentedHashSet? AsSegmentedHashSet(ImmutableSegmentedHashSet set) + => ImmutableSegmentedHashSet.PrivateMarshal.AsSegmentedHashSet(set); + + /// + /// Gets an value wrapping the input . + /// + /// The type of keys in the input segmented dictionary. + /// The type of values in the input segmented dictionary. + /// The input segmented dictionary to wrap in the returned value. + /// An value wrapping . + /// + /// + /// When using this method, callers should take extra care to ensure that they're the sole owners of the input + /// dictionary, and that it won't be modified once the returned + /// value starts being used. Doing so might cause undefined behavior in code paths which don't expect the contents + /// of a given values to change after its creation. + /// + /// + /// If is , the returned + /// value will be uninitialized (i.e. its + /// property will be ). + /// + /// + public static ImmutableSegmentedDictionary AsImmutableSegmentedDictionary(SegmentedDictionary? dictionary) + where TKey : notnull + => ImmutableSegmentedDictionary.PrivateMarshal.AsImmutableSegmentedDictionary(dictionary); + + /// + /// Gets the underlying for an input value. + /// + /// The type of keys in the input value. + /// The type of values in the input value. + /// The input value to get the underlying from. + /// The underlying for , if present; otherwise, . + /// + /// + /// When using this method, callers should make sure to not pass the resulting underlying dictionary to methods that + /// might mutate it. Doing so might cause undefined behavior in code paths using which + /// don't expect the contents of the value to change. + /// + /// + /// If is uninitialized (i.e. its + /// property is ), the resulting will be . + /// + /// + public static SegmentedDictionary? AsSegmentedDictionary(ImmutableSegmentedDictionary dictionary) + where TKey : notnull + => ImmutableSegmentedDictionary.PrivateMarshal.AsSegmentedDictionary(dictionary); +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedDictionary`2+PrivateMarshal.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedDictionary`2+PrivateMarshal.cs new file mode 100755 index 00000000000..d29131abc2b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedDictionary`2+PrivateMarshal.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections; + +internal sealed partial class SegmentedDictionary +{ + /// + /// Private helper class for use only by . + /// + internal static class PrivateMarshal + { + /// + public static ref TValue FindValue(SegmentedDictionary dictionary, TKey key) + => ref dictionary.FindValue(key); + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedDictionary`2.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedDictionary`2.cs new file mode 100755 index 00000000000..0a9302a05e6 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedDictionary`2.cs @@ -0,0 +1,1707 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a collection of keys and values. + /// + /// + /// This collection has the same performance characteristics as , but + /// uses segmented arrays to avoid allocations in the Large Object Heap. + /// + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + [DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))] + [DebuggerDisplay("Count = {Count}")] + internal sealed partial class SegmentedDictionary : IDictionary, IDictionary, IReadOnlyDictionary + where TKey : notnull + { + private const bool SupportsComparerDevirtualization +#if NET + = true; +#else + = false; +#endif + + private static IEnumerator>? s_emptyEnumerator; + + private SegmentedArray _buckets; + private SegmentedArray _entries; + private ulong _fastModMultiplier; + private int _count; + private int _freeList; + private int _freeCount; + private int _version; +#if NET + private readonly IEqualityComparer? _comparer; +#else + /// + /// doesn't devirtualize on .NET Framework, so we always ensure + /// is initialized to a non- value. + /// + private readonly IEqualityComparer _comparer; +#endif + private KeyCollection? _keys; + private ValueCollection? _values; + private const int StartOfFreeList = -3; + + public SegmentedDictionary() + : this(0, null) + { + } + + public SegmentedDictionary(int capacity) + : this(capacity, null) + { + } + + public SegmentedDictionary(IEqualityComparer? comparer) + : this(0, comparer) + { + } + + public SegmentedDictionary(int capacity, IEqualityComparer? comparer) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + if (capacity > 0) + { + Initialize(capacity); + } + + // For reference types, we always want to store a comparer instance, either + // the one provided, or if one wasn't provided, the default (accessing + // EqualityComparer.Default with shared generics on every dictionary + // access can add measurable overhead). For value types, if no comparer is + // provided, or if the default is provided, we'd prefer to use + // EqualityComparer.Default.Equals on every use, enabling the JIT to + // devirtualize and possibly inline the operation. + if (!typeof(TKey).IsValueType) + { + _comparer = comparer ?? EqualityComparer.Default; + } + else if (comparer is not null && // first check for null to avoid forcing default comparer instantiation unnecessarily + comparer != EqualityComparer.Default) + { + _comparer = comparer; + } + +#if !NETCOREAPP + // .NET Framework doesn't support devirtualization, so we always initialize comparer to a non-null value + _comparer ??= EqualityComparer.Default; +#endif + } + + public SegmentedDictionary(IDictionary dictionary) + : this(dictionary, null) + { + } + + public SegmentedDictionary(IDictionary dictionary, IEqualityComparer? comparer) + : this(dictionary?.Count ?? 0, comparer) + { + if (dictionary == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); + } + + AddRange(dictionary); + } + + public SegmentedDictionary(IEnumerable> collection) + : this(collection, null) + { + } + + public SegmentedDictionary(IEnumerable> collection, IEqualityComparer? comparer) + : this((collection as ICollection>)?.Count ?? 0, comparer) + { + if (collection == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + + AddRange(collection); + } + + private void AddRange(IEnumerable> enumerable) + { + // It is likely that the passed-in enumerable is SegmentedDictionary. When this is the case, + // avoid the enumerator allocation and overhead by looping through the entries array directly. + // We only do this when dictionary is SegmentedDictionary and not a subclass, to maintain + // back-compat with subclasses that may have overridden the enumerator behavior. + if (enumerable.GetType() == typeof(SegmentedDictionary)) + { + var source = (SegmentedDictionary)enumerable; + + if (source.Count == 0) + { + // Nothing to copy, all done + return; + } + + // This is not currently a true .AddRange as it needs to be an initialized dictionary + // of the correct size, and also an empty dictionary with no current entities (and no argument checks). + Debug.Assert(_entries.Length >= source.Count); + Debug.Assert(_count == 0); + + var oldEntries = source._entries; + if (source._comparer == _comparer) + { + // If comparers are the same, we can copy _entries without rehashing. + CopyEntries(oldEntries, source._count); + return; + } + + // Comparers differ need to rehash all the entries via Add + var count = source._count; + for (var i = 0; i < count; i++) + { + // Only copy if an entry + if (oldEntries[i]._next >= -1) + { + Add(oldEntries[i]._key, oldEntries[i]._value); + } + } + return; + } + + // We similarly special-case KVP<>[] and List>, as they're commonly used to seed dictionaries, and + // we want to avoid the enumerator costs (e.g. allocation) for them as well. Extract a span if possible. + ReadOnlySpan> span; + if (enumerable is KeyValuePair[] array) + { + span = array; + } +#if NET5_0_OR_GREATER + else if (enumerable.GetType() == typeof(List>)) + { + span = CollectionsMarshal.AsSpan((List>)enumerable); + } +#endif + else + { + // Fallback path for all other enumerables + foreach (var pair in enumerable) + { + Add(pair.Key, pair.Value); + } + return; + } + + // We got a span. Add the elements to the dictionary. + foreach (var pair in span) + { + Add(pair.Key, pair.Value); + } + } + + public IEqualityComparer Comparer + { + get + { + return _comparer ?? EqualityComparer.Default; + } + } + + public int Count => _count - _freeCount; + + public KeyCollection Keys => _keys ??= new KeyCollection(this); + + ICollection IDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + public ValueCollection Values => _values ??= new ValueCollection(this); + + ICollection IDictionary.Values => Values; + + IEnumerable IReadOnlyDictionary.Values => Values; + + public TValue this[TKey key] + { + get + { + ref var value = ref FindValue(key); + if (!RoslynUnsafe.IsNullRef(ref value)) + { + return value; + } + + ThrowHelper.ThrowKeyNotFoundException(key); + return default; + } + set + { + var modified = TryInsert(key, value, InsertionBehavior.OverwriteExisting); + Debug.Assert(modified); + } + } + + public void Add(TKey key, TValue value) + { + var modified = TryInsert(key, value, InsertionBehavior.ThrowOnExisting); + Debug.Assert(modified); // If there was an existing key and the Add failed, an exception will already have been thrown. + } + + void ICollection>.Add(KeyValuePair keyValuePair) + => Add(keyValuePair.Key, keyValuePair.Value); + + bool ICollection>.Contains(KeyValuePair keyValuePair) + { + ref var value = ref FindValue(keyValuePair.Key); + if (!RoslynUnsafe.IsNullRef(ref value) && EqualityComparer.Default.Equals(value, keyValuePair.Value)) + { + return true; + } + + return false; + } + + bool ICollection>.Remove(KeyValuePair keyValuePair) + { + ref var value = ref FindValue(keyValuePair.Key); + if (!RoslynUnsafe.IsNullRef(ref value) && EqualityComparer.Default.Equals(value, keyValuePair.Value)) + { + Remove(keyValuePair.Key); + return true; + } + + return false; + } + + public void Clear() + { + var count = _count; + if (count > 0) + { + Debug.Assert(_buckets.Length > 0, "_buckets should be non-empty"); + Debug.Assert(_entries.Length > 0, "_entries should be non-empty"); + + SegmentedArray.Clear(_buckets); + + _count = 0; + _freeList = -1; + _freeCount = 0; + SegmentedArray.Clear(_entries, 0, count); + } + } + + public bool ContainsKey(TKey key) + => !RoslynUnsafe.IsNullRef(ref FindValue(key)); + + public bool ContainsValue(TValue value) + { + var entries = _entries; + if (value == null) + { + for (var i = 0; i < _count; i++) + { + if (entries[i]._next >= -1 && entries[i]._value == null) + { + return true; + } + } + } + else if (SupportsComparerDevirtualization && typeof(TValue).IsValueType) + { + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + for (var i = 0; i < _count; i++) + { + if (entries[i]._next >= -1 && EqualityComparer.Default.Equals(entries[i]._value, value)) + { + return true; + } + } + } + else + { + // Object type: Shared Generic, EqualityComparer.Default won't devirtualize + // https://github.com/dotnet/runtime/issues/10050 + // So cache in a local rather than get EqualityComparer per loop iteration + var defaultComparer = EqualityComparer.Default; + for (var i = 0; i < _count; i++) + { + if (entries[i]._next >= -1 && defaultComparer.Equals(entries[i]._value, value)) + { + return true; + } + } + } + + return false; + } + + private void CopyTo(KeyValuePair[] array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if ((uint)index > (uint)array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + var count = _count; + var entries = _entries; + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + { + array[index++] = new KeyValuePair(entries[i]._key, entries[i]._value); + } + } + } + + public Enumerator GetEnumerator() + => new(this, Enumerator.KeyValuePair); + + IEnumerator> IEnumerable>.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + private static IEnumerator> GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedDictionary(), Enumerator.KeyValuePair))!; + } + + private ref TValue FindValue(TKey key) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + ref var entry = ref RoslynUnsafe.NullRef(); + if (_buckets.Length > 0) + { + Debug.Assert(_entries.Length > 0, "expected entries to be non-empty"); + var comparer = _comparer; + if (SupportsComparerDevirtualization + && typeof(TKey).IsValueType // comparer can only be null for value types; enable JIT to eliminate entire if block for ref types + && comparer == null) + { + var hashCode = (uint)key.GetHashCode(); + var i = GetBucket(hashCode); + var entries = _entries; + uint collisionCount = 0; + + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + i--; // Value in _buckets is 1-based; subtract 1 from i. We do it here so it fuses with the following conditional. + do + { + // Should be a while loop https://github.com/dotnet/runtime/issues/9422 + // Test in if to drop range check for following array access + if ((uint)i >= (uint)entries.Length) + { + goto ReturnNotFound; + } + + entry = ref entries[i]; + if (entry._hashCode == hashCode && EqualityComparer.Default.Equals(entry._key, key)) + { + goto ReturnFound; + } + + i = entry._next; + + collisionCount++; + } while (collisionCount <= (uint)entries.Length); + + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + goto ConcurrentOperation; + } + else + { + Debug.Assert(comparer is not null); + var hashCode = (uint)comparer!.GetHashCode(key); + var i = GetBucket(hashCode); + var entries = _entries; + uint collisionCount = 0; + i--; // Value in _buckets is 1-based; subtract 1 from i. We do it here so it fuses with the following conditional. + do + { + // Should be a while loop https://github.com/dotnet/runtime/issues/9422 + // Test in if to drop range check for following array access + if ((uint)i >= (uint)entries.Length) + { + goto ReturnNotFound; + } + + entry = ref entries[i]; + if (entry._hashCode == hashCode && comparer.Equals(entry._key, key)) + { + goto ReturnFound; + } + + i = entry._next; + + collisionCount++; + } while (collisionCount <= (uint)entries.Length); + + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + goto ConcurrentOperation; + } + } + + goto ReturnNotFound; + +ConcurrentOperation: + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); +ReturnFound: + ref TValue value = ref entry._value; +Return: + return ref value; +ReturnNotFound: + value = ref RoslynUnsafe.NullRef(); + goto Return; + } + + private int Initialize(int capacity) + { + var size = HashHelpers.GetPrime(capacity); + var buckets = new SegmentedArray(size); + var entries = new SegmentedArray(size); + + // Assign member variables after both arrays allocated to guard against corruption from OOM if second fails + _freeList = -1; + _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)size); + _buckets = buckets; + _entries = entries; + + return size; + } + + private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + if (_buckets.Length == 0) + { + Initialize(0); + } + Debug.Assert(_buckets.Length > 0); + + var entries = _entries; + Debug.Assert(entries.Length > 0, "expected entries to be non-empty"); + + var comparer = _comparer; + Debug.Assert(comparer is not null || (SupportsComparerDevirtualization && typeof(TKey).IsValueType)); + var hashCode = (uint)((SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null) ? key.GetHashCode() : comparer!.GetHashCode(key)); + + uint collisionCount = 0; + ref var bucket = ref GetBucket(hashCode); + var i = bucket - 1; // Value in _buckets is 1-based + + if (SupportsComparerDevirtualization + && typeof(TKey).IsValueType // comparer can only be null for value types; enable JIT to eliminate entire if block for ref types + && comparer == null) + { + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + while (true) + { + // Should be a while loop https://github.com/dotnet/runtime/issues/9422 + // Test uint in if rather than loop condition to drop range check for following array access + if ((uint)i >= (uint)entries.Length) + { + break; + } + + if (entries[i]._hashCode == hashCode && EqualityComparer.Default.Equals(entries[i]._key, key)) + { + if (behavior == InsertionBehavior.OverwriteExisting) + { + entries[i]._value = value; + return true; + } + + if (behavior == InsertionBehavior.ThrowOnExisting) + { + ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key); + } + + return false; + } + + i = entries[i]._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + else + { + Debug.Assert(comparer is not null); + while (true) + { + // Should be a while loop https://github.com/dotnet/runtime/issues/9422 + // Test uint in if rather than loop condition to drop range check for following array access + if ((uint)i >= (uint)entries.Length) + { + break; + } + + if (entries[i]._hashCode == hashCode && comparer!.Equals(entries[i]._key, key)) + { + if (behavior == InsertionBehavior.OverwriteExisting) + { + entries[i]._value = value; + return true; + } + + if (behavior == InsertionBehavior.ThrowOnExisting) + { + ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key); + } + + return false; + } + + i = entries[i]._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + + int index; + if (_freeCount > 0) + { + index = _freeList; + Debug.Assert((StartOfFreeList - entries[_freeList]._next) >= -1, "shouldn't overflow because `next` cannot underflow"); + _freeList = StartOfFreeList - entries[_freeList]._next; + _freeCount--; + } + else + { + var count = _count; + if (count == entries.Length) + { + Resize(); + bucket = ref GetBucket(hashCode); + } + index = count; + _count = count + 1; + entries = _entries; + } + + ref var entry = ref entries![index]; + entry._hashCode = hashCode; + entry._next = bucket - 1; // Value in _buckets is 1-based + entry._key = key; + entry._value = value; + bucket = index + 1; // Value in _buckets is 1-based + _version++; + return true; + } + + private void Resize() + => Resize(HashHelpers.ExpandPrime(_count)); + + private void Resize(int newSize) + { + Debug.Assert(_entries.Length > 0, "_entries should be non-empty"); + Debug.Assert(newSize >= _entries.Length); + + var count = _count; + + // Rather than creating a copy of _entries, instead reuse as much of it's data as possible. + var entries = CreateNewSegmentedArrayReusingOldSegments(_entries, newSize); + + // Assign member variables after both arrays allocated to guard against corruption from OOM if second fails + _buckets = new SegmentedArray(newSize); + _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)newSize); + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + { + ref var bucket = ref GetBucket(entries[i]._hashCode); + entries[i]._next = bucket - 1; // Value in _buckets is 1-based + bucket = i + 1; + } + } + + _entries = entries; + } + + private static SegmentedArray CreateNewSegmentedArrayReusingOldSegments(SegmentedArray oldArray, int newSize) + { + var segments = SegmentedCollectionsMarshal.AsSegments(oldArray); + + var oldSegmentCount = segments.Length; + var newSegmentCount = (newSize + SegmentedArrayHelper.GetSegmentSize() - 1) >> SegmentedArrayHelper.GetSegmentShift(); + + // Grow the array of segments, if necessary + Array.Resize(ref segments, newSegmentCount); + + // Resize all segments to full segment size from the last old segment to the next to last + // new segment. + for (var i = oldSegmentCount - 1; i < newSegmentCount - 1; i++) + Array.Resize(ref segments[i], SegmentedArrayHelper.GetSegmentSize()); + + // Resize the last segment + var lastSegmentSize = newSize - ((newSegmentCount - 1) << SegmentedArrayHelper.GetSegmentShift()); + Array.Resize(ref segments[newSegmentCount - 1], lastSegmentSize); + + return SegmentedCollectionsMarshal.AsSegmentedArray(newSize, segments); + } + + public bool Remove(TKey key) + { + // The overload Remove(TKey key, out TValue value) is a copy of this method with one additional + // statement to copy the value for entry being removed into the output parameter. + // Code has been intentionally duplicated for performance reasons. + + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + if (_buckets.Length > 0) + { + Debug.Assert(_entries.Length > 0, "entries should be non-empty"); + uint collisionCount = 0; + + var comparer = _comparer; + Debug.Assert((SupportsComparerDevirtualization && typeof(TKey).IsValueType) || comparer is not null); + var hashCode = (uint)(SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null ? key.GetHashCode() : comparer!.GetHashCode(key)); + + ref var bucket = ref GetBucket(hashCode); + var entries = _entries; + var last = -1; + var i = bucket - 1; // Value in buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + + if (entry._hashCode == hashCode && + (SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null ? EqualityComparer.Default.Equals(entry._key, key) : comparer!.Equals(entry._key, key))) + { + if (last < 0) + { + bucket = entry._next + 1; // Value in buckets is 1-based + } + else + { + entries[last]._next = entry._next; + } + + Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646"); + entry._next = StartOfFreeList - _freeList; + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._key = default!; + } + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._value = default!; + } + + _freeList = i; + _freeCount++; + return true; + } + + last = i; + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + return false; + } + + public bool Remove(TKey key, [MaybeNullWhen(false)] out TValue value) + { + // This overload is a copy of the overload Remove(TKey key) with one additional + // statement to copy the value for entry being removed into the output parameter. + // Code has been intentionally duplicated for performance reasons. + + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + if (_buckets.Length > 0) + { + Debug.Assert(_entries.Length > 0, "entries should be non-empty"); + uint collisionCount = 0; + + var comparer = _comparer; + Debug.Assert((SupportsComparerDevirtualization && typeof(TKey).IsValueType) || comparer is not null); + var hashCode = (uint)(SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null ? key.GetHashCode() : comparer!.GetHashCode(key)); + + ref var bucket = ref GetBucket(hashCode); + var entries = _entries; + var last = -1; + var i = bucket - 1; // Value in buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + + if (entry._hashCode == hashCode && + (SupportsComparerDevirtualization && typeof(TKey).IsValueType && comparer == null ? EqualityComparer.Default.Equals(entry._key, key) : comparer!.Equals(entry._key, key))) + { + if (last < 0) + { + bucket = entry._next + 1; // Value in buckets is 1-based + } + else + { + entries[last]._next = entry._next; + } + + value = entry._value; + + Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646"); + entry._next = StartOfFreeList - _freeList; + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._key = default!; + } + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._value = default!; + } + + _freeList = i; + _freeCount++; + return true; + } + + last = i; + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + + value = default; + return false; + } + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + { + ref var valRef = ref FindValue(key); + if (!RoslynUnsafe.IsNullRef(ref valRef)) + { + value = valRef; + return true; + } + + value = default; + return false; + } + + public bool TryAdd(TKey key, TValue value) + => TryInsert(key, value, InsertionBehavior.None); + + bool ICollection>.IsReadOnly => false; + + void ICollection>.CopyTo(KeyValuePair[] array, int index) + => CopyTo(array, index); + + void ICollection.CopyTo(Array array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (array.Rank != 1) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); + } + + if (array.GetLowerBound(0) != 0) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); + } + + if ((uint)index > (uint)array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + if (array is KeyValuePair[] pairs) + { + CopyTo(pairs, index); + } + else if (array is DictionaryEntry[] dictEntryArray) + { + var entries = _entries; + for (var i = 0; i < _count; i++) + { + if (entries[i]._next >= -1) + { + dictEntryArray[index++] = new DictionaryEntry(entries[i]._key, entries[i]._value); + } + } + } + else + { + var objects = array as object[]; + if (objects == null) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + + try + { + var count = _count; + var entries = _entries; + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + { + objects[index++] = new KeyValuePair(entries[i]._key, entries[i]._value); + } + } + } + catch (ArrayTypeMismatchException) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + } + } + + IEnumerator IEnumerable.GetEnumerator() + => ((IEnumerable>)this).GetEnumerator(); + + /// + /// Ensures that the dictionary can hold up to 'capacity' entries without any further expansion of its backing storage + /// + public int EnsureCapacity(int capacity) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + var currentCapacity = _entries.Length; + if (currentCapacity >= capacity) + { + return currentCapacity; + } + + _version++; + + if (_buckets.Length == 0) + { + return Initialize(capacity); + } + + var newSize = HashHelpers.GetPrime(capacity); + Resize(newSize); + return newSize; + } + + /// + /// Sets the capacity of this dictionary to what it would be if it had been originally initialized with all its entries + /// + /// + /// This method can be used to minimize the memory overhead + /// once it is known that no new elements will be added. + /// + /// To allocate minimum size storage array, execute the following statements: + /// + /// dictionary.Clear(); + /// dictionary.TrimExcess(); + /// + public void TrimExcess() + => TrimExcess(Count); + + /// + /// Sets the capacity of this dictionary to hold up 'capacity' entries without any further expansion of its backing storage + /// + /// + /// This method can be used to minimize the memory overhead + /// once it is known that no new elements will be added. + /// + public void TrimExcess(int capacity) + { + if (capacity < Count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + var newSize = HashHelpers.GetPrime(capacity); + var oldEntries = _entries; + var currentCapacity = oldEntries.Length; + if (newSize >= currentCapacity) + { + return; + } + + var oldCount = _count; + _version++; + Initialize(newSize); + + CopyEntries(oldEntries, oldCount); + } + + private void CopyEntries(SegmentedArray entries, int count) + { + var newEntries = _entries; + var newCount = 0; + for (var i = 0; i < count; i++) + { + var hashCode = entries[i]._hashCode; + if (entries[i]._next >= -1) + { + ref var entry = ref newEntries[newCount]; + entry = entries[i]; + ref var bucket = ref GetBucket(hashCode); + entry._next = bucket - 1; // Value in _buckets is 1-based + bucket = newCount + 1; + newCount++; + } + } + + _count = newCount; + _freeCount = 0; + } + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => this; + + bool IDictionary.IsFixedSize => false; + + bool IDictionary.IsReadOnly => false; + + ICollection IDictionary.Keys => Keys; + + ICollection IDictionary.Values => Values; + + object? IDictionary.this[object key] + { + get + { + if (IsCompatibleKey(key)) + { + ref var value = ref FindValue((TKey)key); + if (!RoslynUnsafe.IsNullRef(ref value)) + { + return value; + } + } + + return null; + } + set + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(value, ExceptionArgument.value); + + try + { + var tempKey = (TKey)key; + try + { + this[tempKey] = (TValue)value!; + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue)); + } + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey)); + } + } + } + + private static bool IsCompatibleKey(object key) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + return key is TKey; + } + + void IDictionary.Add(object key, object? value) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(value, ExceptionArgument.value); + + try + { + var tempKey = (TKey)key; + + try + { + Add(tempKey, (TValue)value!); + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue)); + } + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey)); + } + } + + bool IDictionary.Contains(object key) + { + if (IsCompatibleKey(key)) + { + return ContainsKey((TKey)key); + } + + return false; + } + + IDictionaryEnumerator IDictionary.GetEnumerator() + => new Enumerator(this, Enumerator.DictEntry); + + void IDictionary.Remove(object key) + { + if (IsCompatibleKey(key)) + { + Remove((TKey)key); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private ref int GetBucket(uint hashCode) + { + var buckets = _buckets; + return ref buckets[(int)HashHelpers.FastMod(hashCode, (uint)buckets.Length, _fastModMultiplier)]; + } + + private struct Entry + { + public uint _hashCode; + /// + /// 0-based index of next entry in chain: -1 means end of chain + /// also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3, + /// so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc. + /// + public int _next; + public TKey _key; // Key of entry + public TValue _value; // Value of entry + } + + public struct Enumerator : IEnumerator>, IDictionaryEnumerator + { + private readonly SegmentedDictionary _dictionary; + private readonly int _version; + private int _index; + private KeyValuePair _current; + private readonly int _getEnumeratorRetType; // What should Enumerator.Current return? + + internal const int DictEntry = 1; + internal const int KeyValuePair = 2; + + internal Enumerator(SegmentedDictionary dictionary, int getEnumeratorRetType) + { + _dictionary = dictionary; + _version = dictionary._version; + _index = 0; + _getEnumeratorRetType = getEnumeratorRetType; + _current = default; + } + + public bool MoveNext() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. + // dictionary.count+1 could be negative if dictionary.count is int.MaxValue + while ((uint)_index < (uint)_dictionary._count) + { + ref var entry = ref _dictionary._entries[_index++]; + + if (entry._next >= -1) + { + _current = new KeyValuePair(entry._key, entry._value); + return true; + } + } + + _index = _dictionary._count + 1; + _current = default; + return false; + } + + public readonly KeyValuePair Current => _current; + + public readonly void Dispose() + { + } + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + if (_getEnumeratorRetType == DictEntry) + { + return new DictionaryEntry(_current.Key, _current.Value); + } + + return new KeyValuePair(_current.Key, _current.Value); + } + } + + void IEnumerator.Reset() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _current = default; + } + + readonly DictionaryEntry IDictionaryEnumerator.Entry + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return new DictionaryEntry(_current.Key, _current.Value); + } + } + + readonly object IDictionaryEnumerator.Key + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _current.Key; + } + } + + readonly object? IDictionaryEnumerator.Value + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _current.Value; + } + } + } + + [DebuggerTypeProxy(typeof(DictionaryKeyCollectionDebugView<,>))] + [DebuggerDisplay("Count = {Count}")] + public sealed class KeyCollection : ICollection, ICollection, IReadOnlyCollection + { + private static IEnumerator? s_emptyEnumerator; + + private readonly SegmentedDictionary _dictionary; + + public KeyCollection(SegmentedDictionary dictionary) + { + if (dictionary == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); + } + + _dictionary = dictionary; + } + + public Enumerator GetEnumerator() + => new Enumerator(_dictionary); + + public void CopyTo(TKey[] array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (index < 0 || index > array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < _dictionary.Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + var count = _dictionary._count; + var entries = _dictionary._entries; + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + array[index++] = entries[i]._key; + } + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => true; + + void ICollection.Add(TKey item) + => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet); + + void ICollection.Clear() + => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet); + + public bool Contains(TKey item) + => _dictionary.ContainsKey(item); + + bool ICollection.Remove(TKey item) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet); + return false; + } + + IEnumerator IEnumerable.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + private static IEnumerator GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedDictionary()))!; + } + + IEnumerator IEnumerable.GetEnumerator() + => ((IEnumerable)this).GetEnumerator(); + + void ICollection.CopyTo(Array array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (array.Rank != 1) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); + } + + if (array.GetLowerBound(0) != 0) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); + } + + if ((uint)index > (uint)array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < _dictionary.Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + if (array is TKey[] keys) + { + CopyTo(keys, index); + } + else + { + var objects = array as object[]; + if (objects == null) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + + var count = _dictionary._count; + var entries = _dictionary._entries; + try + { + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + objects[index++] = entries[i]._key; + } + } + catch (ArrayTypeMismatchException) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + } + } + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + public struct Enumerator : IEnumerator, IEnumerator + { + private readonly SegmentedDictionary _dictionary; + private int _index; + private readonly int _version; + private TKey? _currentKey; + + internal Enumerator(SegmentedDictionary dictionary) + { + _dictionary = dictionary; + _version = dictionary._version; + _index = 0; + _currentKey = default; + } + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + while ((uint)_index < (uint)_dictionary._count) + { + ref var entry = ref _dictionary._entries[_index++]; + + if (entry._next >= -1) + { + _currentKey = entry._key; + return true; + } + } + + _index = _dictionary._count + 1; + _currentKey = default; + return false; + } + + public readonly TKey Current => _currentKey!; + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _currentKey; + } + } + + void IEnumerator.Reset() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _currentKey = default; + } + } + } + + [DebuggerTypeProxy(typeof(DictionaryValueCollectionDebugView<,>))] + [DebuggerDisplay("Count = {Count}")] + public sealed class ValueCollection : ICollection, ICollection, IReadOnlyCollection + { + private static IEnumerator? s_emptyEnumerator; + + private readonly SegmentedDictionary _dictionary; + + public ValueCollection(SegmentedDictionary dictionary) + { + if (dictionary == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); + } + + _dictionary = dictionary; + } + + public Enumerator GetEnumerator() + => new Enumerator(_dictionary); + + public void CopyTo(TValue[] array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if ((uint)index > array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < _dictionary.Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + var count = _dictionary._count; + var entries = _dictionary._entries; + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + array[index++] = entries[i]._value; + } + } + + public int Count => _dictionary.Count; + + bool ICollection.IsReadOnly => true; + + void ICollection.Add(TValue item) + => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet); + + bool ICollection.Remove(TValue item) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet); + return false; + } + + void ICollection.Clear() + => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet); + + bool ICollection.Contains(TValue item) + => _dictionary.ContainsValue(item); + + IEnumerator IEnumerable.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + private static IEnumerator GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedDictionary()))!; + } + + IEnumerator IEnumerable.GetEnumerator() + => ((IEnumerable)this).GetEnumerator(); + + void ICollection.CopyTo(Array array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (array.Rank != 1) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); + } + + if (array.GetLowerBound(0) != 0) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); + } + + if ((uint)index > (uint)array.Length) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < _dictionary.Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + if (array is TValue[] values) + { + CopyTo(values, index); + } + else + { + var objects = array as object[]; + if (objects == null) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + + var count = _dictionary._count; + var entries = _dictionary._entries; + try + { + for (var i = 0; i < count; i++) + { + if (entries[i]._next >= -1) + objects[index++] = entries[i]._value!; + } + } + catch (ArrayTypeMismatchException) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + } + } + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot; + + public struct Enumerator : IEnumerator, IEnumerator + { + private readonly SegmentedDictionary _dictionary; + private int _index; + private readonly int _version; + private TValue? _currentValue; + + internal Enumerator(SegmentedDictionary dictionary) + { + _dictionary = dictionary; + _version = dictionary._version; + _index = 0; + _currentValue = default; + } + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + while ((uint)_index < (uint)_dictionary._count) + { + ref var entry = ref _dictionary._entries[_index++]; + + if (entry._next >= -1) + { + _currentValue = entry._value; + return true; + } + } + _index = _dictionary._count + 1; + _currentValue = default; + return false; + } + + public readonly TValue Current => _currentValue!; + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || (_index == _dictionary._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _currentValue; + } + } + + void IEnumerator.Reset() + { + if (_version != _dictionary._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _currentValue = default; + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedHashSet`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedHashSet`1.cs new file mode 100755 index 00000000000..59d4528bc6d --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedHashSet`1.cs @@ -0,0 +1,1456 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Threading; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + [DebuggerTypeProxy(typeof(ICollectionDebugView<>))] + [DebuggerDisplay("Count = {Count}")] + internal class SegmentedHashSet : ICollection, ISet, IReadOnlyCollection +#if NET5_0_OR_GREATER + , IReadOnlySet +#endif + { + private const bool SupportsComparerDevirtualization +#if NET + = true; +#else + = false; +#endif + + // This uses the same array-based implementation as Dictionary. + + /// Cutoff point for stackallocs. This corresponds to the number of ints. + private const int StackAllocThreshold = 100; + + /// + /// When constructing a hashset from an existing collection, it may contain duplicates, + /// so this is used as the max acceptable excess ratio of capacity to count. Note that + /// this is only used on the ctor and not to automatically shrink if the hashset has, e.g, + /// a lot of adds followed by removes. Users must explicitly shrink by calling TrimExcess. + /// This is set to 3 because capacity is acceptable as 2x rounded up to nearest prime. + /// + private const int ShrinkThreshold = 3; + private const int StartOfFreeList = -3; + + private static IEnumerator? s_emptyEnumerator; + + private SegmentedArray _buckets; + private SegmentedArray _entries; + private ulong _fastModMultiplier; + private int _count; + private int _freeList; + private int _freeCount; + private int _version; +#if NET + private readonly IEqualityComparer? _comparer; +#else + /// + /// doesn't devirtualize on .NET Framework, so we always ensure + /// is initialized to a non- value. + /// + private readonly IEqualityComparer _comparer; +#endif + + #region Constructors + + public SegmentedHashSet() : this((IEqualityComparer?)null) { } + + public SegmentedHashSet(IEqualityComparer? comparer) + { + // For reference types, we always want to store a comparer instance, either + // the one provided, or if one wasn't provided, the default (accessing + // EqualityComparer.Default with shared generics on every dictionary + // access can add measurable overhead). For value types, if no comparer is + // provided, or if the default is provided, we'd prefer to use + // EqualityComparer.Default.Equals on every use, enabling the JIT to + // devirtualize and possibly inline the operation. + if (!typeof(T).IsValueType) + { + _comparer = comparer ?? EqualityComparer.Default; + } + else if (comparer is not null && // first check for null to avoid forcing default comparer instantiation unnecessarily + comparer != EqualityComparer.Default) + { + _comparer = comparer; + } + +#if !NETCOREAPP + // .NET Framework doesn't support devirtualization, so we always initialize comparer to a non-null value + _comparer ??= EqualityComparer.Default; +#endif + } + + public SegmentedHashSet(int capacity) : this(capacity, null) { } + + public SegmentedHashSet(IEnumerable collection) : this(collection, null) { } + + public SegmentedHashSet(IEnumerable collection, IEqualityComparer? comparer) : this(comparer) + { + if (collection == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + + if (collection is SegmentedHashSet otherAsHashSet && EqualityComparersAreEqual(this, otherAsHashSet)) + { + ConstructFrom(otherAsHashSet); + } + else + { + // To avoid excess resizes, first set size based on collection's count. The collection may + // contain duplicates, so call TrimExcess if resulting SegmentedHashSet is larger than the threshold. + if (collection is ICollection coll) + { + var count = coll.Count; + if (count > 0) + { + Initialize(count); + } + } + + UnionWith(collection); + + if (_count > 0 && _entries.Length / _count > ShrinkThreshold) + { + TrimExcess(); + } + } + } + + public SegmentedHashSet(int capacity, IEqualityComparer? comparer) : this(comparer) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + if (capacity > 0) + { + Initialize(capacity); + } + } + + /// Initializes the SegmentedHashSet from another SegmentedHashSet with the same element type and equality comparer. + private void ConstructFrom(SegmentedHashSet source) + { + if (source.Count == 0) + { + // As well as short-circuiting on the rest of the work done, + // this avoids errors from trying to access source._buckets + // or source._entries when they aren't initialized. + return; + } + + var capacity = source._buckets.Length; + var threshold = HashHelpers.ExpandPrime(source.Count + 1); + + if (threshold >= capacity) + { + _buckets = (SegmentedArray)source._buckets.Clone(); + _entries = (SegmentedArray)source._entries.Clone(); + _freeList = source._freeList; + _freeCount = source._freeCount; + _count = source._count; + _fastModMultiplier = source._fastModMultiplier; + } + else + { + Initialize(source.Count); + + var entries = source._entries; + for (var i = 0; i < source._count; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + AddIfNotPresent(entry._value, out _); + } + } + } + + Debug.Assert(Count == source.Count); + } + + #endregion + + #region ICollection methods + + void ICollection.Add(T item) => AddIfNotPresent(item, out _); + + /// Removes all elements from the object. + public void Clear() + { + var count = _count; + if (count > 0) + { + Debug.Assert(_buckets.Length > 0, "_buckets should be non-empty"); + Debug.Assert(_entries.Length > 0, "_entries should be non-empty"); + + SegmentedArray.Clear(_buckets); + _count = 0; + _freeList = -1; + _freeCount = 0; + SegmentedArray.Clear(_entries, 0, count); + } + } + + /// Determines whether the contains the specified element. + /// The element to locate in the object. + /// true if the object contains the specified element; otherwise, false. + public bool Contains(T item) => FindItemIndex(item) >= 0; + + /// Gets the index of the item in , or -1 if it's not in the set. + private int FindItemIndex(T item) + { + var buckets = _buckets; + if (buckets.Length > 0) + { + var entries = _entries; + Debug.Assert(entries.Length > 0, "Expected _entries to be initialized"); + + uint collisionCount = 0; + var comparer = _comparer; + + if (SupportsComparerDevirtualization && + typeof(T).IsValueType && // comparer can only be null for value types; enable JIT to eliminate entire if block for ref types + comparer == null) + { + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + var hashCode = item!.GetHashCode(); + var i = GetBucketRef(hashCode) - 1; // Value in _buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + if (entry._hashCode == hashCode && EqualityComparer.Default.Equals(entry._value, item)) + { + return i; + } + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop, which means a concurrent update has happened. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + else + { + Debug.Assert(comparer is not null); + var hashCode = item != null ? comparer!.GetHashCode(item) : 0; + var i = GetBucketRef(hashCode) - 1; // Value in _buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + if (entry._hashCode == hashCode && comparer!.Equals(entry._value, item)) + { + return i; + } + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop, which means a concurrent update has happened. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + } + + return -1; + } + + /// Gets a reference to the specified hashcode's bucket, containing an index into . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private ref int GetBucketRef(int hashCode) + { + var buckets = _buckets; + return ref buckets[(int)HashHelpers.FastMod((uint)hashCode, (uint)buckets.Length, _fastModMultiplier)]; + } + + public bool Remove(T item) + { + if (_buckets.Length > 0) + { + var entries = _entries; + Debug.Assert(entries.Length > 0, "entries should be non-empty"); + + uint collisionCount = 0; + var last = -1; + + IEqualityComparer? comparer = _comparer; + Debug.Assert((SupportsComparerDevirtualization && typeof(T).IsValueType) || comparer is not null); + int hashCode = + SupportsComparerDevirtualization && typeof(T).IsValueType && comparer == null ? item!.GetHashCode() : + item is not null ? comparer!.GetHashCode(item) : + 0; + + ref var bucket = ref GetBucketRef(hashCode); + var i = bucket - 1; // Value in buckets is 1-based + + while (i >= 0) + { + ref var entry = ref entries[i]; + + if (entry._hashCode == hashCode && (comparer?.Equals(entry._value, item) ?? EqualityComparer.Default.Equals(entry._value, item))) + { + if (last < 0) + { + bucket = entry._next + 1; // Value in buckets is 1-based + } + else + { + entries[last]._next = entry._next; + } + + Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646"); + entry._next = StartOfFreeList - _freeList; + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + entry._value = default!; + } + + _freeList = i; + _freeCount++; + return true; + } + + last = i; + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + + return false; + } + + /// Gets the number of elements that are contained in the set. + public int Count => _count - _freeCount; + + bool ICollection.IsReadOnly => false; + + #endregion + + #region IEnumerable methods + + public Enumerator GetEnumerator() => new(this); + + IEnumerator IEnumerable.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this).GetEnumerator(); + + private static IEnumerator GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedHashSet()))!; + } + + #endregion + + #region SegmentedHashSet methods + + /// Adds the specified element to the . + /// The element to add to the set. + /// true if the element is added to the object; false if the element is already present. + public bool Add(T item) => AddIfNotPresent(item, out _); + + /// Searches the set for a given value and returns the equal value it finds, if any. + /// The value to search for. + /// The value from the set that the search found, or the default value of when the search yielded no match. + /// A value indicating whether the search was successful. + /// + /// This can be useful when you want to reuse a previously stored reference instead of + /// a newly constructed one (so that more sharing of references can occur) or to look up + /// a value that has more complete data than the value you currently have, although their + /// comparer functions indicate they are equal. + /// + public bool TryGetValue(T equalValue, [MaybeNullWhen(false)] out T actualValue) + { + if (_buckets.Length > 0) + { + var index = FindItemIndex(equalValue); + if (index >= 0) + { + actualValue = _entries[index]._value; + return true; + } + } + + actualValue = default; + return false; + } + + /// Modifies the current object to contain all elements that are present in itself, the specified collection, or both. + /// The collection to compare to the current object. + public void UnionWith(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + foreach (var item in other) + { + AddIfNotPresent(item, out _); + } + } + + /// Modifies the current object to contain only elements that are present in that object and in the specified collection. + /// The collection to compare to the current object. + public void IntersectWith(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // Intersection of anything with empty set is empty set, so return if count is 0. + // Same if the set intersecting with itself is the same set. + if (Count == 0 || other == this) + { + return; + } + + // If other is known to be empty, intersection is empty set; remove all elements, and we're done. + if (other is ICollection otherAsCollection) + { + if (otherAsCollection.Count == 0) + { + Clear(); + return; + } + + // Faster if other is a hashset using same equality comparer; so check + // that other is a hashset using the same equality comparer. + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + IntersectWithHashSetWithSameComparer(otherAsSet); + return; + } + } + + IntersectWithEnumerable(other); + } + + /// Removes all elements in the specified collection from the current object. + /// The collection to compare to the current object. + public void ExceptWith(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // This is already the empty set; return. + if (Count == 0) + { + return; + } + + // Special case if other is this; a set minus itself is the empty set. + if (other == this) + { + Clear(); + return; + } + + // Remove every element in other from this. + foreach (var element in other) + { + Remove(element); + } + } + + /// Modifies the current object to contain only elements that are present either in that object or in the specified collection, but not both. + /// The collection to compare to the current object. + public void SymmetricExceptWith(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // If set is empty, then symmetric difference is other. + if (Count == 0) + { + UnionWith(other); + return; + } + + // Special-case this; the symmetric difference of a set with itself is the empty set. + if (other == this) + { + Clear(); + return; + } + + // If other is a SegmentedHashSet, it has unique elements according to its equality comparer, + // but if they're using different equality comparers, then assumption of uniqueness + // will fail. So first check if other is a hashset using the same equality comparer; + // symmetric except is a lot faster and avoids bit array allocations if we can assume + // uniqueness. + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + SymmetricExceptWithUniqueHashSet(otherAsSet); + } + else + { + SymmetricExceptWithEnumerable(other); + } + } + + /// Determines whether a object is a subset of the specified collection. + /// The collection to compare to the current object. + /// true if the object is a subset of ; otherwise, false. + public bool IsSubsetOf(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // The empty set is a subset of any set, and a set is a subset of itself. + // Set is always a subset of itself + if (Count == 0 || other == this) + { + return true; + } + + // Faster if other has unique elements according to this equality comparer; so check + // that other is a hashset using the same equality comparer. + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + // if this has more elements then it can't be a subset + if (Count > otherAsSet.Count) + { + return false; + } + + // already checked that we're using same equality comparer. simply check that + // each element in this is contained in other. + return IsSubsetOfHashSetWithSameComparer(otherAsSet); + } + + (var uniqueCount, var unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: false); + return uniqueCount == Count && unfoundCount >= 0; + } + + /// Determines whether a object is a proper subset of the specified collection. + /// The collection to compare to the current object. + /// true if the object is a proper subset of ; otherwise, false. + public bool IsProperSubsetOf(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // No set is a proper subset of itself. + if (other == this) + { + return false; + } + + if (other is ICollection otherAsCollection) + { + // No set is a proper subset of an empty set. + if (otherAsCollection.Count == 0) + { + return false; + } + + // The empty set is a proper subset of anything but the empty set. + if (Count == 0) + { + return otherAsCollection.Count > 0; + } + + // Faster if other is a hashset (and we're using same equality comparer). + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + if (Count >= otherAsSet.Count) + { + return false; + } + + // This has strictly less than number of items in other, so the following + // check suffices for proper subset. + return IsSubsetOfHashSetWithSameComparer(otherAsSet); + } + } + + (var uniqueCount, var unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: false); + return uniqueCount == Count && unfoundCount > 0; + } + + /// Determines whether a object is a proper superset of the specified collection. + /// The collection to compare to the current object. + /// true if the object is a superset of ; otherwise, false. + public bool IsSupersetOf(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // A set is always a superset of itself. + if (other == this) + { + return true; + } + + // Try to fall out early based on counts. + if (other is ICollection otherAsCollection) + { + // If other is the empty set then this is a superset. + if (otherAsCollection.Count == 0) + { + return true; + } + + // Try to compare based on counts alone if other is a hashset with same equality comparer. + if (other is SegmentedHashSet otherAsSet && + EqualityComparersAreEqual(this, otherAsSet) && + otherAsSet.Count > Count) + { + return false; + } + } + + foreach (T element in other) + { + if (!Contains(element)) + { + return false; + } + } + + return true; + } + + /// Determines whether a object is a proper superset of the specified collection. + /// The collection to compare to the current object. + /// true if the object is a proper superset of ; otherwise, false. + public bool IsProperSupersetOf(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // The empty set isn't a proper superset of any set, and a set is never a strict superset of itself. + if (Count == 0 || other == this) + { + return false; + } + + if (other is ICollection otherAsCollection) + { + // If other is the empty set then this is a superset. + if (otherAsCollection.Count == 0) + { + // Note that this has at least one element, based on above check. + return true; + } + + // Faster if other is a hashset with the same equality comparer + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + if (otherAsSet.Count >= Count) + { + return false; + } + + // Now perform element check. + return otherAsSet.IsSubsetOfHashSetWithSameComparer(this); + } + } + + // Couldn't fall out in the above cases; do it the long way + (var uniqueCount, var unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: true); + return uniqueCount < Count && unfoundCount == 0; + } + + /// Determines whether the current object and a specified collection share common elements. + /// The collection to compare to the current object. + /// true if the object and share at least one common element; otherwise, false. + public bool Overlaps(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + if (Count == 0) + { + return false; + } + + // Set overlaps itself + if (other == this) + { + return true; + } + + foreach (var element in other) + { + if (Contains(element)) + { + return true; + } + } + + return false; + } + + /// Determines whether a object and the specified collection contain the same elements. + /// The collection to compare to the current object. + /// true if the object is equal to ; otherwise, false. + public bool SetEquals(IEnumerable other) + { + if (other == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); + } + + // A set is equal to itself. + if (other == this) + { + return true; + } + + // Faster if other is a hashset and we're using same equality comparer. + if (other is SegmentedHashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) + { + // Attempt to return early: since both contain unique elements, if they have + // different counts, then they can't be equal. + if (Count != otherAsSet.Count) + { + return false; + } + + // Already confirmed that the sets have the same number of distinct elements, so if + // one is a subset of the other then they must be equal. + return IsSubsetOfHashSetWithSameComparer(otherAsSet); + } + else + { + // If this count is 0 but other contains at least one element, they can't be equal. + if (Count == 0 && + other is ICollection otherAsCollection && + otherAsCollection.Count > 0) + { + return false; + } + + (var uniqueCount, var unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: true); + return uniqueCount == Count && unfoundCount == 0; + } + } + + public void CopyTo(T[] array) => CopyTo(array, 0, Count); + + /// Copies the elements of a object to an array, starting at the specified array index. + /// The destination array. + /// The zero-based index in array at which copying begins. + public void CopyTo(T[] array, int arrayIndex) => CopyTo(array, arrayIndex, Count); + + public void CopyTo(T[] array, int arrayIndex, int count) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + +#if NET8_0_OR_GREATER + ArgumentOutOfRangeException.ThrowIfNegative(arrayIndex); + ArgumentOutOfRangeException.ThrowIfNegative(count); +#else + // Check array index valid index into array. + if (arrayIndex < 0) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex), arrayIndex, SR.ArgumentOutOfRange_NeedNonNegNum); + } + + // Also throw if count less than 0. + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), count, SR.ArgumentOutOfRange_NeedNonNegNum); + } +#endif + + // Will the array, starting at arrayIndex, be able to hold elements? Note: not + // checking arrayIndex >= array.Length (consistency with list of allowing + // count of 0; subsequent check takes care of the rest) + if (arrayIndex > array.Length || count > array.Length - arrayIndex) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + var entries = _entries; + for (var i = 0; i < _count && count != 0; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + array[arrayIndex++] = entry._value; + count--; + } + } + } + + /// Removes all elements that match the conditions defined by the specified predicate from a collection. + public int RemoveWhere(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + var entries = _entries; + var numRemoved = 0; + for (var i = 0; i < _count; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + // Cache value in case delegate removes it + var value = entry._value; + if (match(value)) + { + // Check again that remove actually removed it. + if (Remove(value)) + { + numRemoved++; + } + } + } + } + + return numRemoved; + } + + /// Gets the object that is used to determine equality for the values in the set. + public IEqualityComparer Comparer + { + get + { + return _comparer ?? EqualityComparer.Default; + } + } + + /// Ensures that this hash set can hold the specified number of elements without growing. + public int EnsureCapacity(int capacity) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + var currentCapacity = _entries.Length; + if (currentCapacity >= capacity) + { + return currentCapacity; + } + + if (_buckets.Length == 0) + { + return Initialize(capacity); + } + + var newSize = HashHelpers.GetPrime(capacity); + Resize(newSize); + return newSize; + } + + private void Resize() => Resize(HashHelpers.ExpandPrime(_count)); + + private void Resize(int newSize) + { + Debug.Assert(_entries.Length > 0, "_entries should be non-empty"); + Debug.Assert(newSize >= _entries.Length); + + var count = _count; + + // Rather than creating a copy of _entries, instead reuse as much of it's data as possible. + var entries = CreateNewSegmentedArrayReusingOldSegments(_entries, newSize); + + // Assign member variables after both arrays allocated to guard against corruption from OOM if second fails + _buckets = new SegmentedArray(newSize); + _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)newSize); + for (var i = 0; i < count; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + ref var bucket = ref GetBucketRef(entry._hashCode); + entry._next = bucket - 1; // Value in _buckets is 1-based + bucket = i + 1; + } + } + + _entries = entries; + } + + private static SegmentedArray CreateNewSegmentedArrayReusingOldSegments(SegmentedArray oldArray, int newSize) + { + var segments = SegmentedCollectionsMarshal.AsSegments(oldArray); + + var oldSegmentCount = segments.Length; + var newSegmentCount = (newSize + SegmentedArrayHelper.GetSegmentSize() - 1) >> SegmentedArrayHelper.GetSegmentShift(); + + // Grow the array of segments, if necessary + Array.Resize(ref segments, newSegmentCount); + + // Resize all segments to full segment size from the last old segment to the next to last + // new segment. + for (var i = oldSegmentCount - 1; i < newSegmentCount - 1; i++) + Array.Resize(ref segments[i], SegmentedArrayHelper.GetSegmentSize()); + + // Resize the last segment + var lastSegmentSize = newSize - ((newSegmentCount - 1) << SegmentedArrayHelper.GetSegmentShift()); + Array.Resize(ref segments[newSegmentCount - 1], lastSegmentSize); + + return SegmentedCollectionsMarshal.AsSegmentedArray(newSize, segments); + } + + /// + /// Sets the capacity of a object to the actual number of elements it contains, + /// rounded up to a nearby, implementation-specific value. + /// + public void TrimExcess() + { + var capacity = Count; + + var newSize = HashHelpers.GetPrime(capacity); + var oldEntries = _entries; + var currentCapacity = oldEntries.Length; + if (newSize >= currentCapacity) + { + return; + } + + var oldCount = _count; + _version++; + Initialize(newSize); + var entries = _entries; + var count = 0; + for (var i = 0; i < oldCount; i++) + { + var hashCode = oldEntries[i]._hashCode; // At this point, we know we have entries. + if (oldEntries[i]._next >= -1) + { + ref var entry = ref entries[count]; + entry = oldEntries[i]; + ref var bucket = ref GetBucketRef(hashCode); + entry._next = bucket - 1; // Value in _buckets is 1-based + bucket = count + 1; + count++; + } + } + + _count = capacity; + _freeCount = 0; + } + + #endregion + + #region Helper methods + + /// Returns an object that can be used for equality testing of a object. + public static IEqualityComparer> CreateSetComparer() => new SegmentedHashSetEqualityComparer(); + + /// + /// Initializes buckets and slots arrays. Uses suggested capacity by finding next prime + /// greater than or equal to capacity. + /// + private int Initialize(int capacity) + { + var size = HashHelpers.GetPrime(capacity); + var buckets = new SegmentedArray(size); + var entries = new SegmentedArray(size); + + // Assign member variables after both arrays are allocated to guard against corruption from OOM if second fails. + _freeList = -1; + _buckets = buckets; + _entries = entries; + _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)size); + + return size; + } + + /// Adds the specified element to the set if it's not already contained. + /// The element to add to the set. + /// The index into of the element. + /// true if the element is added to the object; false if the element is already present. + private bool AddIfNotPresent(T value, out int location) + { + if (_buckets.Length == 0) + { + Initialize(0); + } + Debug.Assert(_buckets.Length > 0); + + var entries = _entries; + Debug.Assert(entries.Length > 0, "expected entries to be non-empty"); + + var comparer = _comparer; + int hashCode; + + uint collisionCount = 0; + ref var bucket = ref RoslynUnsafe.NullRef(); + + if (SupportsComparerDevirtualization && + typeof(T).IsValueType && // comparer can only be null for value types; enable JIT to eliminate entire if block for ref types + comparer == null) + { + hashCode = value!.GetHashCode(); + bucket = ref GetBucketRef(hashCode); + var i = bucket - 1; // Value in _buckets is 1-based + + // ValueType: Devirtualize with EqualityComparer.Default intrinsic + while (i >= 0) + { + ref var entry = ref entries[i]; + if (entry._hashCode == hashCode && EqualityComparer.Default.Equals(entry._value, value)) + { + location = i; + return false; + } + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop, which means a concurrent update has happened. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + else + { + Debug.Assert(comparer is not null); + hashCode = value != null ? comparer!.GetHashCode(value) : 0; + bucket = ref GetBucketRef(hashCode); + var i = bucket - 1; // Value in _buckets is 1-based + while (i >= 0) + { + ref var entry = ref entries[i]; + if (entry._hashCode == hashCode && comparer!.Equals(entry._value, value)) + { + location = i; + return false; + } + i = entry._next; + + collisionCount++; + if (collisionCount > (uint)entries.Length) + { + // The chain of entries forms a loop, which means a concurrent update has happened. + ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported(); + } + } + } + + int index; + if (_freeCount > 0) + { + index = _freeList; + _freeCount--; + Debug.Assert((StartOfFreeList - entries[_freeList]._next) >= -1, "shouldn't overflow because `next` cannot underflow"); + _freeList = StartOfFreeList - entries[_freeList]._next; + } + else + { + var count = _count; + if (count == entries.Length) + { + Resize(); + bucket = ref GetBucketRef(hashCode); + } + index = count; + _count = count + 1; + entries = _entries; + } + + { + ref var entry = ref entries[index]; + entry._hashCode = hashCode; + entry._next = bucket - 1; // Value in _buckets is 1-based + entry._value = value; + bucket = index + 1; + _version++; + location = index; + } + + return true; + } + + /// + /// Implementation Notes: + /// If other is a hashset and is using same equality comparer, then checking subset is + /// faster. Simply check that each element in this is in other. + /// + /// Note: if other doesn't use same equality comparer, then Contains check is invalid, + /// which is why callers must take are of this. + /// + /// If callers are concerned about whether this is a proper subset, they take care of that. + /// + internal bool IsSubsetOfHashSetWithSameComparer(SegmentedHashSet other) + { + foreach (var item in this) + { + if (!other.Contains(item)) + { + return false; + } + } + + return true; + } + + /// + /// If other is a hashset that uses same equality comparer, intersect is much faster + /// because we can use other's Contains + /// + private void IntersectWithHashSetWithSameComparer(SegmentedHashSet other) + { + var entries = _entries; + for (var i = 0; i < _count; i++) + { + ref var entry = ref entries[i]; + if (entry._next >= -1) + { + var item = entry._value; + if (!other.Contains(item)) + { + Remove(item); + } + } + } + } + + /// + /// Iterate over other. If contained in this, mark an element in bit array corresponding to + /// its position in _slots. If anything is unmarked (in bit array), remove it. + /// + /// This attempts to allocate on the stack, if below StackAllocThreshold. + /// + private unsafe void IntersectWithEnumerable(IEnumerable other) + { + Debug.Assert(_buckets.Length > 0, "_buckets shouldn't be empty; callers should check first"); + + // Keep track of current last index; don't want to move past the end of our bit array + // (could happen if another thread is modifying the collection). + var originalCount = _count; + int intArrayLength = BitHelper.ToIntArrayLength(originalCount); + + Span span = stackalloc int[StackAllocThreshold]; + var bitHelper = intArrayLength <= StackAllocThreshold + ? new BitHelper(span.Slice(0, intArrayLength), clear: true) + : new BitHelper(new int[intArrayLength], clear: false); + + // Mark if contains: find index of in slots array and mark corresponding element in bit array. + foreach (var item in other) + { + var index = FindItemIndex(item); + if (index >= 0) + { + bitHelper.MarkBit(index); + } + } + + // If anything unmarked, remove it. Perf can be optimized here if BitHelper had a + // FindFirstUnmarked method. + for (var i = 0; i < originalCount; i++) + { + ref var entry = ref _entries[i]; + if (entry._next >= -1 && !bitHelper.IsMarked(i)) + { + Remove(entry._value); + } + } + } + + /// + /// if other is a set, we can assume it doesn't have duplicate elements, so use this + /// technique: if can't remove, then it wasn't present in this set, so add. + /// + /// As with other methods, callers take care of ensuring that other is a hashset using the + /// same equality comparer. + /// + /// + private void SymmetricExceptWithUniqueHashSet(SegmentedHashSet other) + { + foreach (var item in other) + { + if (!Remove(item)) + { + AddIfNotPresent(item, out _); + } + } + } + + /// + /// Implementation notes: + /// + /// Used for symmetric except when other isn't a SegmentedHashSet. This is more tedious because + /// other may contain duplicates. SegmentedHashSet technique could fail in these situations: + /// 1. Other has a duplicate that's not in this: SegmentedHashSet technique would add then + /// remove it. + /// 2. Other has a duplicate that's in this: SegmentedHashSet technique would remove then add it + /// back. + /// In general, its presence would be toggled each time it appears in other. + /// + /// This technique uses bit marking to indicate whether to add/remove the item. If already + /// present in collection, it will get marked for deletion. If added from other, it will + /// get marked as something not to remove. + /// + /// + /// + private unsafe void SymmetricExceptWithEnumerable(IEnumerable other) + { + var originalCount = _count; + int intArrayLength = BitHelper.ToIntArrayLength(originalCount); + + Span itemsToRemoveSpan = stackalloc int[StackAllocThreshold / 2]; + var itemsToRemove = intArrayLength <= StackAllocThreshold / 2 + ? new BitHelper(itemsToRemoveSpan.Slice(0, intArrayLength), clear: true) + : new BitHelper(new int[intArrayLength], clear: false); + + Span itemsAddedFromOtherSpan = stackalloc int[StackAllocThreshold / 2]; + var itemsAddedFromOther = intArrayLength <= StackAllocThreshold / 2 + ? new BitHelper(itemsAddedFromOtherSpan.Slice(0, intArrayLength), clear: true) + : new BitHelper(new int[intArrayLength], clear: false); + + foreach (var item in other) + { + if (AddIfNotPresent(item, out var location)) + { + // wasn't already present in collection; flag it as something not to remove + // *NOTE* if location is out of range, we should ignore. BitHelper will + // detect that it's out of bounds and not try to mark it. But it's + // expected that location could be out of bounds because adding the item + // will increase _lastIndex as soon as all the free spots are filled. + itemsAddedFromOther.MarkBit(location); + } + else + { + // already there...if not added from other, mark for remove. + // *NOTE* Even though BitHelper will check that location is in range, we want + // to check here. There's no point in checking items beyond originalCount + // because they could not have been in the original collection + if (location < originalCount && !itemsAddedFromOther.IsMarked(location)) + { + itemsToRemove.MarkBit(location); + } + } + } + + // if anything marked, remove it + for (var i = 0; i < originalCount; i++) + { + if (itemsToRemove.IsMarked(i)) + { + Remove(_entries[i]._value); + } + } + } + + /// + /// Determines counts that can be used to determine equality, subset, and superset. This + /// is only used when other is an IEnumerable and not a SegmentedHashSet. If other is a SegmentedHashSet + /// these properties can be checked faster without use of marking because we can assume + /// other has no duplicates. + /// + /// The following count checks are performed by callers: + /// 1. Equals: checks if unfoundCount = 0 and uniqueFoundCount = _count; i.e. everything + /// in other is in this and everything in this is in other + /// 2. Subset: checks if unfoundCount >= 0 and uniqueFoundCount = _count; i.e. other may + /// have elements not in this and everything in this is in other + /// 3. Proper subset: checks if unfoundCount > 0 and uniqueFoundCount = _count; i.e + /// other must have at least one element not in this and everything in this is in other + /// 4. Proper superset: checks if unfound count = 0 and uniqueFoundCount strictly less + /// than _count; i.e. everything in other was in this and this had at least one element + /// not contained in other. + /// + /// An earlier implementation used delegates to perform these checks rather than returning + /// an ElementCount struct; however this was changed due to the perf overhead of delegates. + /// + /// + /// Allows us to finish faster for equals and proper superset + /// because unfoundCount must be 0. + private (int UniqueCount, int UnfoundCount) CheckUniqueAndUnfoundElements(IEnumerable other, bool returnIfUnfound) + { + // Need special case in case this has no elements. + if (_count == 0) + { + var numElementsInOther = 0; + foreach (var item in other) + { + numElementsInOther++; + break; // break right away, all we want to know is whether other has 0 or 1 elements + } + + return (UniqueCount: 0, UnfoundCount: numElementsInOther); + } + + Debug.Assert((_buckets.Length > 0) && (_count > 0), "_buckets was empty but count greater than 0"); + + var originalCount = _count; + int intArrayLength = BitHelper.ToIntArrayLength(originalCount); + + Span span = stackalloc int[StackAllocThreshold]; + var bitHelper = intArrayLength <= StackAllocThreshold + ? new BitHelper(span.Slice(0, intArrayLength), clear: true) + : new BitHelper(new int[intArrayLength], clear: false); + + var unfoundCount = 0; // count of items in other not found in this + var uniqueFoundCount = 0; // count of unique items in other found in this + + foreach (var item in other) + { + var index = FindItemIndex(item); + if (index >= 0) + { + if (!bitHelper.IsMarked(index)) + { + // Item hasn't been seen yet. + bitHelper.MarkBit(index); + uniqueFoundCount++; + } + } + else + { + unfoundCount++; + if (returnIfUnfound) + { + break; + } + } + } + + return (uniqueFoundCount, unfoundCount); + } + + /// + /// Checks if equality comparers are equal. This is used for algorithms that can + /// speed up if it knows the other item has unique elements. I.e. if they're using + /// different equality comparers, then uniqueness assumption between sets break. + /// + internal static bool EqualityComparersAreEqual(SegmentedHashSet set1, SegmentedHashSet set2) => set1.Comparer.Equals(set2.Comparer); + + #endregion + + private struct Entry + { + public int _hashCode; + /// + /// 0-based index of next entry in chain: -1 means end of chain + /// also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3, + /// so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc. + /// + public int _next; + public T _value; + } + + public struct Enumerator : IEnumerator + { + private readonly SegmentedHashSet _hashSet; + private readonly int _version; + private int _index; + private T _current; + + internal Enumerator(SegmentedHashSet hashSet) + { + _hashSet = hashSet; + _version = hashSet._version; + _index = 0; + _current = default!; + } + + public bool MoveNext() + { + if (_version != _hashSet._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. + // dictionary.count+1 could be negative if dictionary.count is int.MaxValue + while ((uint)_index < (uint)_hashSet._count) + { + ref var entry = ref _hashSet._entries[_index++]; + if (entry._next >= -1) + { + _current = entry._value; + return true; + } + } + + _index = _hashSet._count + 1; + _current = default!; + return false; + } + + public readonly T Current => _current; + + public readonly void Dispose() { } + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || (_index == _hashSet._count + 1)) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return _current; + } + } + + void IEnumerator.Reset() + { + if (_version != _hashSet._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _current = default!; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedList`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedList`1.cs new file mode 100755 index 00000000000..407d7925951 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Segmented/SegmentedList`1.cs @@ -0,0 +1,1397 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// NOTE: This code is derived from an implementation originally in dotnet/runtime: +// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs +// +// See the commentary in https://github.com/dotnet/roslyn/pull/50156 for notes on incorporating changes made to the +// reference implementation. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading; +using Microsoft.CodeAnalysis.Collections.Internal; + +namespace Microsoft.CodeAnalysis.Collections +{ + /// + /// Represents a strongly typed list of objects that can be accessed by index. Provides methods to search, sort, and + /// manipulate lists. + /// + /// + /// This collection has the same performance characteristics as , but uses segmented + /// arrays to avoid allocations in the Large Object Heap. + /// + /// The type of elements in the list. + [DebuggerTypeProxy(typeof(ICollectionDebugView<>))] + [DebuggerDisplay("Count = {Count}")] + internal class SegmentedList : IList, IList, IReadOnlyList + { + private const int DefaultCapacity = 4; + private const int MaxLength = 0x7FFFFFC7; + + internal SegmentedArray _items; + internal int _size; + internal int _version; + + private static readonly SegmentedArray s_emptyArray = new(0); + private static IEnumerator? s_emptyEnumerator; + + // Constructs a SegmentedList. The list is initially empty and has a capacity + // of zero. Upon adding the first element to the list the capacity is + // increased to DefaultCapacity, and then increased in multiples of two + // as required. + public SegmentedList() + { + _items = s_emptyArray; + } + + // Constructs a SegmentedList with a given initial capacity. The list is + // initially empty, but will have room for the given number of elements + // before any reallocations are required. + // + public SegmentedList(int capacity) + { + if (capacity < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + + if (capacity == 0) + _items = s_emptyArray; + else + _items = new SegmentedArray(capacity); + } + + // Constructs a SegmentedList, copying the contents of the given collection. The + // size and capacity of the new list will both be equal to the size of the + // given collection. + // + public SegmentedList(IEnumerable collection) + { + if (collection == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + + if (collection is SegmentedList segmentedList) + { + _items = (SegmentedArray)segmentedList._items.Clone(); + _size = segmentedList._size; + return; + } + + if (collection is ICollection c) + { + var count = c.Count; + if (count == 0) + { + _items = s_emptyArray; + return; + } + else + { + _items = new SegmentedArray(count); + if (SegmentedCollectionsMarshal.AsSegments(_items) is { Length: 1 } segments) + { + c.CopyTo(segments[0], 0); + _size = count; + return; + } + } + + // Continue below to add the items + } + else + { + _items = s_emptyArray; + + // Continue below to add the items + } + + using var en = collection.GetEnumerator(); + while (en.MoveNext()) + { + Add(en.Current); + } + } + + // Gets and sets the capacity of this list. The capacity is the size of + // the internal array used to hold items. When set, the internal + // array of the list is reallocated to the given capacity. + // + public int Capacity + { + get => _items.Length; + set + { + if (value < _size) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity); + } + + if (value == _items.Length) + return; + + if (value <= 0) + { + _items = s_emptyArray; + return; + } + + if (_items.Length == 0) + { + // No data from existing array to reuse, just create a new one. + _items = new SegmentedArray(value); + } + else + { + // Rather than creating a copy of _items, instead reuse as much of it's data as possible. + _items = CreateNewSegmentedArrayReusingOldSegments(_items, value); + } + } + } + + private static SegmentedArray CreateNewSegmentedArrayReusingOldSegments(SegmentedArray oldArray, int newSize) + { + var segments = SegmentedCollectionsMarshal.AsSegments(oldArray); + + var oldSegmentCount = segments.Length; + var newSegmentCount = (newSize + SegmentedArrayHelper.GetSegmentSize() - 1) >> SegmentedArrayHelper.GetSegmentShift(); + + // Grow the array of segments, if necessary + Array.Resize(ref segments, newSegmentCount); + + // Resize all segments to full segment size from the last old segment to the next to last + // new segment. + for (var i = oldSegmentCount - 1; i < newSegmentCount - 1; i++) + Array.Resize(ref segments[i], SegmentedArrayHelper.GetSegmentSize()); + + // Resize the last segment + var lastSegmentSize = newSize - ((newSegmentCount - 1) << SegmentedArrayHelper.GetSegmentShift()); + Array.Resize(ref segments[newSegmentCount - 1], lastSegmentSize); + + return SegmentedCollectionsMarshal.AsSegmentedArray(newSize, segments); + } + + // Read-only property describing how many elements are in the SegmentedList. + public int Count => _size; + + bool IList.IsFixedSize => false; + + // Is this SegmentedList read-only? + bool ICollection.IsReadOnly => false; + + bool IList.IsReadOnly => false; + + // Is this SegmentedList synchronized (thread-safe)? + bool ICollection.IsSynchronized => false; + + // Synchronization root for this object. + object ICollection.SyncRoot => this; + + // Sets or Gets the element at the given index. + public T this[int index] + { + get + { + // Following trick can reduce the range check by one + if ((uint)index >= (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + return _items[index]; + } + + set + { + if ((uint)index >= (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + _items[index] = value; + _version++; + } + } + + private static bool IsCompatibleObject(object? value) + { + // Non-null values are fine. Only accept nulls if T is a class or Nullable. + // Note that default(T) is not equal to null for value types except when T is Nullable. + return (value is T) || (value == null && default(T) == null); + } + + object? IList.this[int index] + { + get => this[index]; + set + { + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(value, ExceptionArgument.value); + + try + { + this[index] = (T)value!; + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T)); + } + } + } + + // Adds the given object to the end of this list. The size of the list is + // increased by one. If required, the capacity of the list is doubled + // before adding the new element. + // + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(T item) + { + _version++; + var array = _items; + var size = _size; + if ((uint)size < (uint)array.Length) + { + _size = size + 1; + array[size] = item; + } + else + { + AddWithResize(item); + } + } + + // Non-inline from SegmentedList.Add to improve its code quality as uncommon path + [MethodImpl(MethodImplOptions.NoInlining)] + private void AddWithResize(T item) + { + Debug.Assert(_size == _items.Length); + var size = _size; + Grow(size + 1); + _size = size + 1; + _items[size] = item; + } + + int IList.Add(object? item) + { + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(item, ExceptionArgument.item); + + try + { + Add((T)item!); + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(item, typeof(T)); + } + + return Count - 1; + } + + // Adds the elements of the given collection to the end of this list. If + // required, the capacity of the list is increased to twice the previous + // capacity or the new size, whichever is larger. + // + public void AddRange(IEnumerable collection) + { + if (collection == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + + if (collection is ICollection c) + { + var count = c.Count; + if (count > 0) + { + if (_items.Length - _size < count) + { + Grow(checked(_size + count)); + } + + if (c is SegmentedList list) + { + SegmentedArray.Copy(list._items, 0, _items, _size, list.Count); + } + else if (c is SegmentedArray array) + { + SegmentedArray.Copy(array, 0, _items, _size, array.Length); + } + else + { + var targetIndex = _size; + foreach (var item in c) + _items[targetIndex++] = item; + } + + _size += count; + _version++; + } + } + else + { + using var en = collection.GetEnumerator(); + while (en.MoveNext()) + { + Add(en.Current); + } + } + } + + public ReadOnlyCollection AsReadOnly() + => new(this); + + // Searches a section of the list for a given element using a binary search + // algorithm. Elements of the list are compared to the search value using + // the given IComparer interface. If comparer is null, elements of + // the list are compared to the search value using the IComparable + // interface, which in that case must be implemented by all elements of the + // list and the given search value. This method assumes that the given + // section of the list is already sorted; if this is not the case, the + // result will be incorrect. + // + // The method returns the index of the given value in the list. If the + // list does not contain the given value, the method returns a negative + // integer. The bitwise complement operator (~) can be applied to a + // negative result to produce the index of the first element (if any) that + // is larger than the given search value. This is also the index at which + // the search value should be inserted into the list in order for the list + // to remain sorted. + // + // The method uses the Array.BinarySearch method to perform the + // search. + // + public int BinarySearch(int index, int count, T item, IComparer? comparer) + { + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (count < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + if (_size - index < count) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + return SegmentedArray.BinarySearch(_items, index, count, item, comparer); + } + + public int BinarySearch(T item) + => BinarySearch(0, Count, item, null); + + public int BinarySearch(T item, IComparer? comparer) + => BinarySearch(0, Count, item, comparer); + + // Clears the contents of SegmentedList. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Clear() + { + _version++; +#if NET + if (!RuntimeHelpers.IsReferenceOrContainsReferences()) + { + _size = 0; + return; + } +#endif + + var size = _size; + _size = 0; + if (size > 0) + { + SegmentedArray.Clear(_items, 0, size); // Clear the elements so that the gc can reclaim the references. + } + } + + // Contains returns true if the specified element is in the SegmentedList. + // It does a linear, O(n) search. Equality is determined by calling + // EqualityComparer.Default.Equals(). + // + public bool Contains(T item) + { + // PERF: IndexOf calls Array.IndexOf, which internally + // calls EqualityComparer.Default.IndexOf, which + // is specialized for different types. This + // boosts performance since instead of making a + // virtual method call each iteration of the loop, + // via EqualityComparer.Default.Equals, we + // only make one virtual call to EqualityComparer.IndexOf. + + return _size != 0 && IndexOf(item) >= 0; + } + + bool IList.Contains(object? item) + { + if (IsCompatibleObject(item)) + { + return Contains((T)item!); + } + return false; + } + + public SegmentedList ConvertAll(Converter converter) + { + if (converter == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter); + } + + var list = new SegmentedList(_size); + for (var i = 0; i < _size; i++) + { + list._items[i] = converter(_items[i]); + } + list._size = _size; + return list; + } + + // Copies this SegmentedList into array, which must be of a + // compatible array type. + public void CopyTo(T[] array) + => CopyTo(array, 0); + + // Copies this SegmentedList into array, which must be of a + // compatible array type. + void ICollection.CopyTo(Array array, int arrayIndex) + { + if ((array != null) && (array.Rank != 1)) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); + } + + try + { + // Array.Copy will check for NULL. + SegmentedArray.Copy(_items, 0, array!, arrayIndex, _size); + } + catch (ArrayTypeMismatchException) + { + ThrowHelper.ThrowArgumentException_Argument_IncompatibleArrayType(); + } + } + + // Copies a section of this list to the given array at the given index. + // + // The method uses the Array.Copy method to copy the elements. + // + public void CopyTo(int index, T[] array, int arrayIndex, int count) + { + if (_size - index < count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + } + + // Delegate rest of error checking to Array.Copy. + SegmentedArray.Copy(_items, index, array, arrayIndex, count); + } + + public void CopyTo(T[] array, int arrayIndex) + { + // Delegate rest of error checking to Array.Copy. + SegmentedArray.Copy(_items, 0, array, arrayIndex, _size); + } + + /// + /// Ensures that the capacity of this list is at least the specified . + /// If the current capacity of the list is less than specified , + /// the capacity is increased by continuously twice current capacity until it is at least the specified . + /// + /// The minimum capacity to ensure. + /// The new capacity of this list. + public int EnsureCapacity(int capacity) + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + if (_items.Length < capacity) + { + Grow(capacity); + } + + return _items.Length; + } + + /// + /// Increase the capacity of this list to at least the specified . + /// + /// The minimum capacity to ensure. + internal void Grow(int capacity) + { + Debug.Assert(_items.Length < capacity); + + var newCapacity = 0; + + if (_items.Length < SegmentedArrayHelper.GetSegmentSize() / 2) + { + // The array isn't near the maximum segment size. If the array is empty, the new capacity + // should be DefaultCapacity. Otherwise, the new capacity should be double the current array size. + newCapacity = _items.Length == 0 ? DefaultCapacity : _items.Length * 2; + } + else if (_items.Length < SegmentedArrayHelper.GetSegmentSize()) + { + // There is only a single segment that is over half full. Increase it to a full segment. + newCapacity = SegmentedArrayHelper.GetSegmentSize(); + } + else + { + // If the last segment is fully sized, increase the number of segments by the desired growth rate + if (0 == (_items.Length & SegmentedArrayHelper.GetOffsetMask())) + { + // This value determines the growth rate of the number of segments to use. + // For a value of 3, this means the segment count will grow at a rate of + // 1 + (1 >> 3) or 12.5% + const int segmentGrowthShiftValue = 3; + + var oldSegmentCount = (_items.Length + SegmentedArrayHelper.GetSegmentSize() - 1) >> SegmentedArrayHelper.GetSegmentShift(); + var newSegmentCount = oldSegmentCount + Math.Max(1, oldSegmentCount >> segmentGrowthShiftValue); + + newCapacity = SegmentedArrayHelper.GetSegmentSize() * newSegmentCount; + } + } + + // If the computed capacity is less than specified, set to the original argument. + // Capacities exceeding Array.MaxLength will be surfaced as OutOfMemoryException by Array.Resize. + if (newCapacity < capacity) + newCapacity = capacity; + + if (newCapacity > SegmentedArrayHelper.GetSegmentSize()) + { + // If the last segment isn't fully sized, increase the new capacity such that it will be. + var lastSegmentLength = newCapacity & SegmentedArrayHelper.GetOffsetMask(); + if (lastSegmentLength > 0) + newCapacity = (newCapacity - lastSegmentLength) + SegmentedArrayHelper.GetSegmentSize(); + + // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + if ((uint)newCapacity > MaxLength) + newCapacity = MaxLength; + } + + Capacity = newCapacity; + } + + public bool Exists(Predicate match) + => FindIndex(match) != -1; + + public T? Find(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + for (var i = 0; i < _size; i++) + { + if (match(_items[i])) + { + return _items[i]; + } + } + return default; + } + + public SegmentedList FindAll(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + var list = new SegmentedList(); + for (var i = 0; i < _size; i++) + { + if (match(_items[i])) + { + list.Add(_items[i]); + } + } + return list; + } + + public int FindIndex(Predicate match) + => FindIndex(0, _size, match); + + public int FindIndex(int startIndex, Predicate match) + => FindIndex(startIndex, _size - startIndex, match); + + public int FindIndex(int startIndex, int count, Predicate match) + { + if ((uint)startIndex > (uint)_size) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLessOrEqual(); + } + + if (count < 0 || startIndex > _size - count) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + var endIndex = startIndex + count; + for (var i = startIndex; i < endIndex; i++) + { + if (match(_items[i])) + return i; + } + return -1; + } + + public T? FindLast(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + for (var i = _size - 1; i >= 0; i--) + { + if (match(_items[i])) + { + return _items[i]; + } + } + return default; + } + + public int FindLastIndex(Predicate match) + => FindLastIndex(_size - 1, _size, match); + + public int FindLastIndex(int startIndex, Predicate match) + => FindLastIndex(startIndex, startIndex + 1, match); + + public int FindLastIndex(int startIndex, int count, Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + if (_size == 0) + { + // Special case for 0 length SegmentedList + if (startIndex != -1) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); + } + } + else + { + // Make sure we're not out of range + if ((uint)startIndex >= (uint)_size) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); + } + } + + // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. + if (count < 0 || startIndex - count + 1 < 0) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + var endIndex = startIndex - count; + for (var i = startIndex; i > endIndex; i--) + { + if (match(_items[i])) + { + return i; + } + } + return -1; + } + + public void ForEach(Action action) + { + if (action == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action); + } + + var version = _version; + + for (var i = 0; i < _size; i++) + { + if (version != _version) + { + break; + } + action(_items[i]); + } + + if (version != _version) + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + // Returns an enumerator for this list with the given + // permission for removal of elements. If modifications made to the list + // while an enumeration is in progress, the MoveNext and + // GetObject methods of the enumerator will throw an exception. + // + public Enumerator GetEnumerator() => new(this); + + IEnumerator IEnumerable.GetEnumerator() => + Count == 0 ? GetEmptyEnumerator() : + GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this).GetEnumerator(); + + private static IEnumerator GetEmptyEnumerator() + { + return LazyInitializer.EnsureInitialized(ref s_emptyEnumerator, static () => new Enumerator(new SegmentedList(0)))!; + } + + public SegmentedList GetRange(int index, int count) + { + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_size - index < count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + } + + var list = new SegmentedList(count); + SegmentedArray.Copy(_items, index, list._items, 0, count); + list._size = count; + return list; + } + + /// + /// Creates a shallow copy of a range of elements in the source . + /// + /// The zero-based index at which the range starts. + /// The length of the range. + /// A shallow copy of a range of elements in the source . + /// + /// is less than 0. + /// -or- + /// is less than 0. + /// + /// and do not denote a valid range of elements in the . + public SegmentedList Slice(int start, int length) => GetRange(start, length); + + // Returns the index of the first occurrence of a given value in a range of + // this list. The list is searched forwards from beginning to end. + // The elements of the list are compared to the given value using the + // Object.Equals method. + // + // This method uses the Array.IndexOf method to perform the + // search. + // + public int IndexOf(T item) + => SegmentedArray.IndexOf(_items, item, 0, _size); + + int IList.IndexOf(object? item) + { + if (IsCompatibleObject(item)) + { + return IndexOf((T)item!); + } + return -1; + } + + // Returns the index of the first occurrence of a given value in a range of + // this list. The list is searched forwards, starting at index + // index and ending at count number of elements. The + // elements of the list are compared to the given value using the + // Object.Equals method. + // + // This method uses the Array.IndexOf method to perform the + // search. + // + public int IndexOf(T item, int index) + { + if (index > _size) + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException(); + return SegmentedArray.IndexOf(_items, item, index, _size - index); + } + + // Returns the index of the first occurrence of a given value in a range of + // this list. The list is searched forwards, starting at index + // index and upto count number of elements. The + // elements of the list are compared to the given value using the + // Object.Equals method. + // + // This method uses the Array.IndexOf method to perform the + // search. + // + public int IndexOf(T item, int index, int count) + { + if (index > _size) + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException(); + + if (count < 0 || index > _size - count) + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + + return SegmentedArray.IndexOf(_items, item, index, count); + } + + public int IndexOf(T item, int index, int count, IEqualityComparer? comparer) + { + if (index > _size) + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException(); + + if (count < 0 || index > _size - count) + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + + return SegmentedArray.IndexOf(_items, item, index, count, comparer); + } + + // Inserts an element into this list at a given index. The size of the list + // is increased by one. If required, the capacity of the list is doubled + // before inserting the new element. + // + public void Insert(int index, T item) + { + // Note that insertions at the end are legal. + if ((uint)index > (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert); + } + if (_size == _items.Length) + Grow(_size + 1); + if (index < _size) + { + SegmentedArray.Copy(_items, index, _items, index + 1, _size - index); + } + _items[index] = item; + _size++; + _version++; + } + + void IList.Insert(int index, object? item) + { + ThrowHelper.IfNullAndNullsAreIllegalThenThrow(item, ExceptionArgument.item); + + try + { + Insert(index, (T)item!); + } + catch (InvalidCastException) + { + ThrowHelper.ThrowWrongValueTypeArgumentException(item, typeof(T)); + } + } + + // Inserts the elements of the given collection at a given index. If + // required, the capacity of the list is increased to twice the previous + // capacity or the new size, whichever is larger. Ranges may be added + // to the end of the list by setting index to the SegmentedList's size. + // + public void InsertRange(int index, IEnumerable collection) + { + if (collection == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + + if ((uint)index > (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException(); + } + + if (collection is ICollection c) + { + var count = c.Count; + if (count > 0) + { + if (_items.Length - _size < count) + { + Grow(checked(_size + count)); + } + if (index < _size) + { + SegmentedArray.Copy(_items, index, _items, index + count, _size - index); + } + + // If we're inserting a SegmentedList into itself, we want to be able to deal with that. + if (this == c) + { + // Copy first part of _items to insert location + SegmentedArray.Copy(_items, 0, _items, index, index); + // Copy last part of _items back to inserted location + SegmentedArray.Copy(_items, index + count, _items, index * 2, _size - index); + } + else if (c is SegmentedList list) + { + SegmentedArray.Copy(list._items, 0, _items, index, list.Count); + } + else if (c is SegmentedArray array) + { + SegmentedArray.Copy(array, 0, _items, index, array.Length); + } + else + { + var targetIndex = index; + foreach (var item in c) + _items[targetIndex++] = item; + } + + _size += count; + _version++; + } + } + else + { + using var en = collection.GetEnumerator(); + while (en.MoveNext()) + { + Insert(index++, en.Current); + } + } + } + + // Returns the index of the last occurrence of a given value in a range of + // this list. The list is searched backwards, starting at the end + // and ending at the first element in the list. The elements of the list + // are compared to the given value using the Object.Equals method. + // + // This method uses the Array.LastIndexOf method to perform the + // search. + // + public int LastIndexOf(T item) + { + if (_size == 0) + { // Special case for empty list + return -1; + } + else + { + return LastIndexOf(item, _size - 1, _size); + } + } + + // Returns the index of the last occurrence of a given value in a range of + // this list. The list is searched backwards, starting at index + // index and ending at the first element in the list. The + // elements of the list are compared to the given value using the + // Object.Equals method. + // + // This method uses the Array.LastIndexOf method to perform the + // search. + // + public int LastIndexOf(T item, int index) + { + if (index >= _size) + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + return LastIndexOf(item, index, index + 1); + } + + // Returns the index of the last occurrence of a given value in a range of + // this list. The list is searched backwards, starting at index + // index and upto count elements. The elements of + // the list are compared to the given value using the Object.Equals + // method. + // + // This method uses the Array.LastIndexOf method to perform the + // search. + // + public int LastIndexOf(T item, int index, int count) + { + if (_size == 0) + { + // Special case for empty list + return -1; + } + + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (index >= _size) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection); + } + + if (count > index + 1) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection); + } + + return SegmentedArray.LastIndexOf(_items, item, index, count); + } + + public int LastIndexOf(T item, int index, int count, IEqualityComparer? comparer) + { + if (_size == 0) + { + // Special case for empty list + return -1; + } + + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (index >= _size) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection); + } + + if (count > index + 1) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection); + } + + return SegmentedArray.LastIndexOf(_items, item, index, count, comparer); + } + + // Removes the first occurrence of the given element, if found. + // The size of the list is decreased by one if successful. + public bool Remove(T item) + { + var index = IndexOf(item); + if (index >= 0) + { + RemoveAt(index); + return true; + } + + return false; + } + + void IList.Remove(object? item) + { + if (IsCompatibleObject(item)) + { + Remove((T)item!); + } + } + + // This method removes all items which matches the predicate. + // The complexity is O(n). + public int RemoveAll(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + var freeIndex = 0; // the first free slot in items array + + // Find the first item which needs to be removed. + while (freeIndex < _size && !match(_items[freeIndex])) + freeIndex++; + if (freeIndex >= _size) + return 0; + + var current = freeIndex + 1; + while (current < _size) + { + // Find the first item which needs to be kept. + while (current < _size && match(_items[current])) + current++; + + if (current < _size) + { + // copy item to the free slot. + _items[freeIndex++] = _items[current++]; + } + } + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + SegmentedArray.Clear(_items, freeIndex, _size - freeIndex); // Clear the elements so that the gc can reclaim the references. + } + + var result = _size - freeIndex; + _size = freeIndex; + _version++; + return result; + } + + // Removes the element at the given index. The size of the list is + // decreased by one. + public void RemoveAt(int index) + { + if ((uint)index >= (uint)_size) + { + ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException(); + } + _size--; + if (index < _size) + { + SegmentedArray.Copy(_items, index + 1, _items, index, _size - index); + } +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + _items[_size] = default!; + } + _version++; + } + + // Removes a range of elements from this list. + public void RemoveRange(int index, int count) + { + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_size - index < count) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (count > 0) + { + _size -= count; + if (index < _size) + { + SegmentedArray.Copy(_items, index + count, _items, index, _size - index); + } + + _version++; +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + SegmentedArray.Clear(_items, _size, count); + } + } + } + + // Reverses the elements in this list. + public void Reverse() + => Reverse(0, Count); + + // Reverses the elements in a range of this list. Following a call to this + // method, an element in the range given by index and count + // which was previously located at index i will now be located at + // index index + (index + count - i - 1). + // + public void Reverse(int index, int count) + { + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_size - index < count) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (count > 1) + { + SegmentedArray.Reverse(_items, index, count); + } + _version++; + } + + // Sorts the elements in this list. Uses the default comparer and + // Array.Sort. + public void Sort() + => Sort(0, Count, null); + + // Sorts the elements in this list. Uses Array.Sort with the + // provided comparer. + public void Sort(IComparer? comparer) + => Sort(0, Count, comparer); + + // Sorts the elements in a section of this list. The sort compares the + // elements to each other using the given IComparer interface. If + // comparer is null, the elements are compared to each other using + // the IComparable interface, which in that case must be implemented by all + // elements of the list. + // + // This method uses the Array.Sort method to sort the elements. + // + public void Sort(int index, int count, IComparer? comparer) + { + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_size - index < count) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + + if (count > 1) + { + SegmentedArray.Sort(_items, index, count, comparer); + } + _version++; + } + + public void Sort(Comparison comparison) + { + if (comparison == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); + } + + if (_size > 1) + { + var segment = new SegmentedArraySegment(_items, 0, _size); + SegmentedArraySortHelper.Sort(segment, comparison); + } + _version++; + } + + // ToArray returns an array containing the contents of the SegmentedList. + // This requires copying the SegmentedList, which is an O(n) operation. + public T[] ToArray() + { + if (_size == 0) + { + return Array.Empty(); + } + + var array = new T[_size]; + SegmentedArray.Copy(_items, array, _size); + return array; + } + + // Sets the capacity of this list to the size of the list. This method can + // be used to minimize a list's memory overhead once it is known that no + // new elements will be added to the list. To completely clear a list and + // release all memory referenced by the list, execute the following + // statements: + // + // list.Clear(); + // list.TrimExcess(); + // + public void TrimExcess() + { + var threshold = (int)(_items.Length * 0.9); + if (_size < threshold) + { + Capacity = _size; + } + } + + public bool TrueForAll(Predicate match) + { + if (match == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + } + + for (var i = 0; i < _size; i++) + { + if (!match(_items[i])) + { + return false; + } + } + return true; + } + + public struct Enumerator : IEnumerator, IEnumerator + { + private readonly SegmentedList _list; + private int _index; + private readonly int _version; + private T? _current; + + internal Enumerator(SegmentedList list) + { + _list = list; + _index = 0; + _version = list._version; + _current = default; + } + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + var localList = _list; + + if (_version == localList._version && ((uint)_index < (uint)localList._size)) + { + _current = localList._items[_index]; + _index++; + return true; + } + return MoveNextRare(); + } + + private bool MoveNextRare() + { + if (_version != _list._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = _list._size + 1; + _current = default; + return false; + } + + public readonly T Current => _current!; + + readonly object? IEnumerator.Current + { + get + { + if (_index == 0 || _index == _list._size + 1) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + return Current; + } + } + + void IEnumerator.Reset() + { + if (_version != _list._version) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + } + + _index = 0; + _current = default; + } + } + + internal TestAccessor GetTestAccessor() + => new TestAccessor(this); + + internal readonly struct TestAccessor(SegmentedList instance) + { + public ref SegmentedArray Items => ref instance._items; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Collection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Collection.cs new file mode 100755 index 00000000000..4885f9d0d14 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Collection.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static partial class SpecializedCollections + { + private static partial class Empty + { + internal class Collection : Enumerable, ICollection + { + public static readonly ICollection Instance = new Collection(); + + protected Collection() + { + } + + public void Add(T item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(T item) + { + return false; + } + + public void CopyTo(T[] array, int arrayIndex) + { + } + + public int Count => 0; + + public bool IsReadOnly => true; + + public bool Remove(T item) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Dictionary.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Dictionary.cs new file mode 100755 index 00000000000..98164c6c405 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Dictionary.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Dictionary +#nullable disable + // Note: if the interfaces we implement weren't oblivious, then we'd warn about the `[MaybeNullWhen(false)] out TValue value` parameter below + // We can remove this once `IDictionary` is annotated with `[MaybeNullWhen(false)]` + : Collection>, IDictionary, IReadOnlyDictionary +#nullable enable + where TKey : notnull + { + public static new readonly Dictionary Instance = new(); + + private Dictionary() + { + } + + public void Add(TKey key, TValue value) + { + throw new NotSupportedException(); + } + + public bool ContainsKey(TKey key) + { + return false; + } + + public ICollection Keys + { + get + { + return Collection.Instance; + } + } + + IEnumerable IReadOnlyDictionary.Keys => Keys; + IEnumerable IReadOnlyDictionary.Values => Values; + + public bool Remove(TKey key) + { + throw new NotSupportedException(); + } + + public bool TryGetValue(TKey key, [MaybeNullWhen(returnValue: false)] out TValue value) + { + value = default!; + return false; + } + + public ICollection Values + { + get + { + return Collection.Instance; + } + } + + public TValue this[TKey key] + { + get + { + throw new NotSupportedException(); + } + + set + { + throw new NotSupportedException(); + } + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Enumerable.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Enumerable.cs new file mode 100755 index 00000000000..9db162535cd --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Enumerable.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Enumerable : IEnumerable + { + // PERF: cache the instance of enumerator. + // accessing a generic static field is kinda slow from here, + // but since empty enumerables are singletons, there is no harm in having + // one extra instance field + private readonly IEnumerator _enumerator = Enumerator.Instance; + + public IEnumerator GetEnumerator() + { + return _enumerator; + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Enumerator.cs new file mode 100755 index 00000000000..dfb79c7028b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Enumerator.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Enumerator : IEnumerator + { + public static readonly IEnumerator Instance = new Enumerator(); + + protected Enumerator() + { + } + + public object? Current => throw new InvalidOperationException(); + + public bool MoveNext() + { + return false; + } + + public void Reset() + { + throw new InvalidOperationException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Enumerator`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Enumerator`1.cs new file mode 100755 index 00000000000..3e253bae606 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Enumerator`1.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Enumerator : Enumerator, IEnumerator + { + public static new readonly IEnumerator Instance = new Enumerator(); + + protected Enumerator() + { + } + + public new T Current => throw new InvalidOperationException(); + + public void Dispose() + { + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.List.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.List.cs new file mode 100755 index 00000000000..57e4cdd8d8e --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.List.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal static class BoxedImmutableArray + { + // empty boxed immutable array + public static readonly IReadOnlyList Instance = ImmutableArray.Empty; + } + + internal class List : Collection, IList, IReadOnlyList + { + public static new readonly List Instance = new(); + + protected List() + { + } + + public int IndexOf(T item) + { + return -1; + } + + public void Insert(int index, T item) + { + throw new NotSupportedException(); + } + + public void RemoveAt(int index) + { + throw new NotSupportedException(); + } + + public T this[int index] + { + get + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + set + { + throw new NotSupportedException(); + } + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Set.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Set.cs new file mode 100755 index 00000000000..be9f0dd34d9 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.Set.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Linq; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class Empty + { + internal class Set : Collection, ISet, IReadOnlySet + { + public static new readonly Set Instance = new(); + + protected Set() + { + } + + public new bool Add(T item) + { + throw new NotSupportedException(); + } + + public void ExceptWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public void IntersectWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public bool IsProperSubsetOf(IEnumerable other) + { + return other.Any(); + } + + public bool IsProperSupersetOf(IEnumerable other) + { + return false; + } + + public bool IsSubsetOf(IEnumerable other) + { + return true; + } + + public bool IsSupersetOf(IEnumerable other) + { + return !other.Any(); + } + + public bool Overlaps(IEnumerable other) + { + return false; + } + + public bool SetEquals(IEnumerable other) + { + return !other.Any(); + } + + public void SymmetricExceptWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public void UnionWith(IEnumerable other) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.cs new file mode 100755 index 00000000000..84fcd89e5f2 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Empty.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private static partial class Empty + { + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Collection.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Collection.cs new file mode 100755 index 00000000000..f9a15d99ab9 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Collection.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private static partial class ReadOnly + { + internal class Collection : Enumerable, ICollection + where TUnderlying : ICollection + { + public Collection(TUnderlying underlying) + : base(underlying) + { + } + + public void Add(T item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(T item) + { + return this.Underlying.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + this.Underlying.CopyTo(array, arrayIndex); + } + + public int Count + { + get + { + return this.Underlying.Count; + } + } + + public bool IsReadOnly => true; + + public bool Remove(T item) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`1.cs new file mode 100755 index 00000000000..54741cb4ed6 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`1.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class ReadOnly + { + internal class Enumerable : IEnumerable + where TUnderlying : IEnumerable + { + protected readonly TUnderlying Underlying; + + public Enumerable(TUnderlying underlying) + { + this.Underlying = underlying; + } + + public IEnumerator GetEnumerator() + { + return this.Underlying.GetEnumerator(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`2.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`2.cs new file mode 100755 index 00000000000..de762618c35 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Enumerable`2.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class ReadOnly + { + internal class Enumerable : Enumerable, IEnumerable + where TUnderlying : IEnumerable + { + public Enumerable(TUnderlying underlying) + : base(underlying) + { + } + + public new IEnumerator GetEnumerator() + { + return this.Underlying.GetEnumerator(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Set.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Set.cs new file mode 100755 index 00000000000..1a52178fc55 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.ReadOnly.Set.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal partial class SpecializedCollections + { + private partial class ReadOnly + { + internal class Set : Collection, ISet, IReadOnlySet + where TUnderlying : ISet + { + public Set(TUnderlying underlying) + : base(underlying) + { + } + + public new bool Add(T item) + { + throw new NotSupportedException(); + } + + public void ExceptWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public void IntersectWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public bool IsProperSubsetOf(IEnumerable other) + { + return Underlying.IsProperSubsetOf(other); + } + + public bool IsProperSupersetOf(IEnumerable other) + { + return Underlying.IsProperSupersetOf(other); + } + + public bool IsSubsetOf(IEnumerable other) + { + return Underlying.IsSubsetOf(other); + } + + public bool IsSupersetOf(IEnumerable other) + { + return Underlying.IsSupersetOf(other); + } + + public bool Overlaps(IEnumerable other) + { + return Underlying.Overlaps(other); + } + + public bool SetEquals(IEnumerable other) + { + return Underlying.SetEquals(other); + } + + public void SymmetricExceptWith(IEnumerable other) + { + throw new NotSupportedException(); + } + + public void UnionWith(IEnumerable other) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Singleton.Collection`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Singleton.Collection`1.cs new file mode 100755 index 00000000000..17e8e2709f2 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Singleton.Collection`1.cs @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static partial class SpecializedCollections + { + private static partial class Singleton + { + internal sealed class List : IReadOnlyList, IList, IReadOnlyCollection + { + private readonly T _loneValue; + + public List(T value) + { + _loneValue = value; + } + + public void Add(T item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(T item) + { + return EqualityComparer.Default.Equals(_loneValue, item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + array[arrayIndex] = _loneValue; + } + + public int Count => 1; + + public bool IsReadOnly => true; + + public bool Remove(T item) + { + throw new NotSupportedException(); + } + + public IEnumerator GetEnumerator() + { + return new Enumerator(_loneValue); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public T this[int index] + { + get + { + if (index != 0) + { + throw new IndexOutOfRangeException(); + } + + return _loneValue; + } + + set + { + throw new NotSupportedException(); + } + } + + public int IndexOf(T item) + { + if (Equals(_loneValue, item)) + { + return 0; + } + + return -1; + } + + public void Insert(int index, T item) + { + throw new NotSupportedException(); + } + + public void RemoveAt(int index) + { + throw new NotSupportedException(); + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Singleton.Enumerator`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Singleton.Enumerator`1.cs new file mode 100755 index 00000000000..d061ebd4039 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.Singleton.Enumerator`1.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static partial class SpecializedCollections + { + private static partial class Singleton + { + internal class Enumerator : IEnumerator + { + private readonly T _loneValue; + private bool _moveNextCalled; + + public Enumerator(T value) + { + _loneValue = value; + _moveNextCalled = false; + } + + public T Current => _loneValue; + + object? IEnumerator.Current => _loneValue; + + public void Dispose() + { + } + + public bool MoveNext() + { + if (!_moveNextCalled) + { + _moveNextCalled = true; + return true; + } + + return false; + } + + public void Reset() + { + _moveNextCalled = false; + } + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.cs new file mode 100755 index 00000000000..a37cac03076 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Specialized/SpecializedCollections.cs @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.Collections +{ + internal static partial class SpecializedCollections + { + public static IEnumerator EmptyEnumerator() + { + return Empty.Enumerator.Instance; + } + + public static IEnumerable EmptyEnumerable() + { + return Empty.List.Instance; + } + + public static ICollection EmptyCollection() + { + return Empty.List.Instance; + } + + public static IList EmptyList() + { + return Empty.List.Instance; + } + + public static IReadOnlyList EmptyBoxedImmutableArray() + { + return Empty.BoxedImmutableArray.Instance; + } + + public static IReadOnlyList EmptyReadOnlyList() + { + return Empty.List.Instance; + } + + public static ISet EmptySet() + { + return Empty.Set.Instance; + } + + public static IReadOnlySet EmptyReadOnlySet() + { + return Empty.Set.Instance; + } + + public static IDictionary EmptyDictionary() + where TKey : notnull + { + return Empty.Dictionary.Instance; + } + + public static IReadOnlyDictionary EmptyReadOnlyDictionary() + where TKey : notnull + { + return Empty.Dictionary.Instance; + } + + public static IEnumerable SingletonEnumerable(T value) + { + return new Singleton.List(value); + } + + public static ICollection SingletonCollection(T value) + { + return new Singleton.List(value); + } + + public static IEnumerator SingletonEnumerator(T value) + { + return new Singleton.Enumerator(value); + } + + public static IReadOnlyList SingletonReadOnlyList(T value) + { + return new Singleton.List(value); + } + + public static IList SingletonList(T value) + { + return new Singleton.List(value); + } + + public static IEnumerable ReadOnlyEnumerable(IEnumerable values) + { + return new ReadOnly.Enumerable, T>(values); + } + + public static ICollection ReadOnlyCollection(ICollection? collection) + { + return collection == null || collection.Count == 0 + ? EmptyCollection() + : new ReadOnly.Collection, T>(collection); + } + + public static ISet ReadOnlySet(ISet? set) + { + return set == null || set.Count == 0 + ? EmptySet() + : new ReadOnly.Set, T>(set); + } + + public static IReadOnlySet StronglyTypedReadOnlySet(ISet? set) + { + return set == null || set.Count == 0 + ? EmptyReadOnlySet() + : new ReadOnly.Set, T>(set); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/TemporaryArrayExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/TemporaryArrayExtensions.cs new file mode 100755 index 00000000000..df57c3f899b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/TemporaryArrayExtensions.cs @@ -0,0 +1,158 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Shared.Collections +{ + internal static class TemporaryArrayExtensions + { + /// + /// Gets a mutable reference to a stored in a using variable. + /// + /// + /// This supporting method allows , a non-copyable + /// implementing , to be used with using statements while still allowing them to + /// be passed by reference in calls. The following two calls are equivalent: + /// + /// + /// using var array = TemporaryArray<T>.Empty; + /// + /// // Using the 'Unsafe.AsRef' method + /// Method(ref Unsafe.AsRef(in array)); + /// + /// // Using this helper method + /// Method(ref array.AsRef()); + /// + /// + /// ⚠ Do not move or rename this method without updating the corresponding + /// RS0049 + /// analyzer. + /// + /// The type of element stored in the temporary array. + /// A read-only reference to a temporary array which is part of a using statement. + /// A mutable reference to the temporary array. + public static ref TemporaryArray AsRef(this in TemporaryArray array) +#pragma warning disable RS0042 // https://github.com/dotnet/roslyn-analyzers/issues/7128 + => ref Unsafe.AsRef(in array); +#pragma warning restore RS0042 + + public static bool Any(this in TemporaryArray array, Func predicate) + { + foreach (var item in array) + { + if (predicate(item)) + return true; + } + + return false; + } + + public static bool All(this in TemporaryArray array, Func predicate) + { + foreach (var item in array) + { + if (!predicate(item)) + return false; + } + + return true; + } + + private static void ThrowSequenceContainsMoreThanOneElement() + => new[] { 0, 0 }.Single(); + + public static T? SingleOrDefault(this in TemporaryArray array, Func predicate) + { + var first = true; + T? result = default; + foreach (var item in array) + { + if (predicate(item)) + { + if (!first) + { + ThrowSequenceContainsMoreThanOneElement(); + } + + first = false; + result = item; + } + } + + return result; + } + + public static T? SingleOrDefault(this in TemporaryArray array, Func predicate, TArg arg) + { + var first = true; + T? result = default; + foreach (var item in array) + { + if (predicate(item, arg)) + { + if (!first) + { + ThrowSequenceContainsMoreThanOneElement(); + } + + first = false; + result = item; + } + } + + return result; + } + + public static T? FirstOrDefault(this in TemporaryArray array) + => array.Count > 0 ? array[0] : default; + + public static T? FirstOrDefault(this in TemporaryArray array, Func predicate, TArg arg) + { + foreach (var item in array) + { + if (predicate(item, arg)) + return item; + } + + return default; + } + + public static int IndexOf(this in TemporaryArray array, Func predicate, TArg arg) + { + var index = 0; + foreach (var item in array) + { + if (predicate(item, arg)) + return index; + + index++; + } + + return -1; + } + + public static void AddIfNotNull(this ref TemporaryArray array, T? value) + where T : struct + { + if (value is not null) + { + array.Add(value.Value); + } + } + + public static void AddIfNotNull(this ref TemporaryArray array, T? value) + where T : class + { + if (value is not null) + { + array.Add(value); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/TemporaryArray`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/TemporaryArray`1.cs new file mode 100755 index 00000000000..8f1856e4a58 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/TemporaryArray`1.cs @@ -0,0 +1,488 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Shared.Collections +{ + /// + /// Provides temporary storage for a collection of elements. This type is optimized for handling of small + /// collections, particularly for cases where the collection will eventually be discarded or used to produce an + /// . + /// + /// + /// This type stores small collections on the stack, with the ability to transition to dynamic storage if/when + /// larger number of elements are added. + /// + /// The type of elements stored in the collection. + [NonCopyable] + [StructLayout(LayoutKind.Sequential)] + internal struct TemporaryArray : IDisposable + { + /// + /// The number of elements the temporary can store inline. Storing more than this many elements requires the + /// array transition to dynamic storage. + /// + private const int InlineCapacity = 4; + + /// + /// The first inline element. + /// + /// + /// This field is only used when is . In other words, this type + /// stores elements inline or stores them in , but does not use both approaches + /// at the same time. + /// + private T _item0; + + /// + /// The second inline element. + /// + /// + private T _item1; + + /// + /// The third inline element. + /// + /// + private T _item2; + + /// + /// The fourth inline element. + /// + /// + private T _item3; + + /// + /// The number of inline elements held in the array. This value is only used when is + /// . + /// + private int _count; + + /// + /// A builder used for dynamic storage of collections that may exceed the limit for inline elements. + /// + /// + /// This field is initialized to non- the first time the + /// needs to store more than four elements. From that point, is used instead of inline + /// elements, even if items are removed to make the result smaller than four elements. + /// + private ArrayBuilder? _builder; + + private TemporaryArray(in TemporaryArray array) + { + // Intentional copy used for creating an enumerator +#pragma warning disable RS0042 // Do not copy value + this = array; +#pragma warning restore RS0042 // Do not copy value + } + + public static TemporaryArray GetInstance(int capacity) + { + // Capacity <= 4 is already supported by the Empty array value. so can just return that without allocating anything. + if (capacity <= InlineCapacity) + return Empty; + + return new TemporaryArray() + { + _builder = ArrayBuilder.GetInstance(capacity) + }; + } + + public static TemporaryArray Empty => default; + + public readonly int Count => _builder?.Count ?? _count; + + public T this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get + { + if (_builder is not null) + return _builder[index]; + + if ((uint)index >= _count) + ThrowIndexOutOfRangeException(); + + return index switch + { + 0 => _item0, + 1 => _item1, + 2 => _item2, + _ => _item3, + }; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + if (_builder is not null) + { + _builder[index] = value; + return; + } + + if ((uint)index >= _count) + ThrowIndexOutOfRangeException(); + + _ = index switch + { + 0 => _item0 = value, + 1 => _item1 = value, + 2 => _item2 = value, + _ => _item3 = value, + }; + } + } + + public void Dispose() + { + // Return _builder to the pool if necessary. There is no need to release inline storage since the majority + // case for this type is stack-allocated storage and the GC is already able to reclaim objects from the + // stack after the last use of a reference to them. + Interlocked.Exchange(ref _builder, null)?.Free(); + } + + public void Add(T item) + { + if (_builder is not null) + { + _builder.Add(item); + } + else if (_count < InlineCapacity) + { + // Increase _count before assigning a value since the indexer has a bounds check. + _count++; + this[_count - 1] = item; + } + else + { + Debug.Assert(_count == InlineCapacity); + MoveInlineToBuilder(); + _builder.Add(item); + } + } + + public void AddRange(ImmutableArray items) + { + if (_builder is not null) + { + _builder.AddRange(items); + } + else if (_count + items.Length <= InlineCapacity) + { + foreach (var item in items) + { + // Increase _count before assigning values since the indexer has a bounds check. + _count++; + this[_count - 1] = item; + } + } + else + { + MoveInlineToBuilder(); + _builder.AddRange(items); + } + } + + public void AddRange(in TemporaryArray items) + { + if (_count + items.Count <= InlineCapacity) + { + foreach (var item in items) + { + // Increase _count before assigning values since the indexer has a bounds check. + _count++; + this[_count - 1] = item; + } + } + else + { + MoveInlineToBuilder(); + foreach (var item in items) + _builder.Add(item); + } + } + + public void Clear() + { + if (_builder is not null) + { + // Keep using a builder even if we now fit in inline storage to avoid churn in the object pools. + _builder.Clear(); + } + else + { + this = Empty; + } + } + + public T RemoveLast() + { + var count = this.Count; + + var last = this[count - 1]; + this[count - 1] = default!; + + if (_builder != null) + { + _builder.Count--; + } + else + { + _count--; + } + + return last; + } + + public readonly bool Contains(T value, IEqualityComparer? equalityComparer = null) + => IndexOf(value, equalityComparer) >= 0; + + public readonly int IndexOf(T value, IEqualityComparer? equalityComparer = null) + { + equalityComparer ??= EqualityComparer.Default; + + if (_builder != null) + return _builder.IndexOf(value, equalityComparer); + + var index = 0; + foreach (var v in this) + { + if (equalityComparer.Equals(v, value)) + return index; + + index++; + } + + return -1; + } + + public readonly Enumerator GetEnumerator() + { + return new Enumerator(in this); + } + + /// + /// Create an with the elements currently held in the temporary array, and clear the + /// array. + /// + public OneOrMany ToOneOrManyAndClear() + { + switch (this.Count) + { + case 0: + return OneOrMany.Empty; + case 1: + var result = OneOrMany.Create(this[0]); + this.Clear(); + return result; + default: + return new(this.ToImmutableAndClear()); + } + } + + /// + /// Create an with the elements currently held in the temporary array, and clear + /// the array. + /// + public ImmutableArray ToImmutableAndClear() + { + if (_builder is not null) + { + return _builder.ToImmutableAndClear(); + } + else + { + var result = _count switch + { + 0 => ImmutableArray.Empty, + 1 => ImmutableArray.Create(_item0), + 2 => ImmutableArray.Create(_item0, _item1), + 3 => ImmutableArray.Create(_item0, _item1, _item2), + 4 => ImmutableArray.Create(_item0, _item1, _item2, _item3), + _ => throw ExceptionUtilities.Unreachable(), + }; + + // Since _builder is null on this path, we can overwrite the whole structure to Empty to reset all + // inline elements to their default value and the _count to 0. + this = Empty; + + return result; + } + } + + /// + /// Transitions the current from inline storage to dynamic storage storage. An + /// instance is taken from the shared pool, and all elements currently in inline + /// storage are added to it. After this point, dynamic storage will be used instead of inline storage. + /// + [MemberNotNull(nameof(_builder))] + private void MoveInlineToBuilder() + { + Debug.Assert(_builder is null); + + var builder = ArrayBuilder.GetInstance(); + for (var i = 0; i < _count; i++) + { + builder.Add(this[i]); + +#if NET + if (RuntimeHelpers.IsReferenceOrContainsReferences()) +#endif + { + this[i] = default!; + } + } + + _count = 0; + _builder = builder; + } + + public void ReverseContents() + { + if (_builder is not null) + { + _builder.ReverseContents(); + return; + } + + switch (_count) + { + case <= 1: + // if we have one or zero items, we're already reversed. + return; + case 2: + (_item0, _item1) = (_item1, _item0); + return; + case 3: + // Just need to swap the first and last items. The middle one stays where it is. + (_item0, _item2) = (_item2, _item0); + return; + case 4: + (_item0, _item1, _item2, _item3) = (_item3, _item2, _item1, _item0); + return; + default: + throw ExceptionUtilities.Unreachable(); + } + } + + public void Sort(Comparison compare) + { + if (_builder is not null) + { + _builder.Sort(compare); + return; + } + + switch (_count) + { + case <= 1: + return; + case 2: + if (compare(_item0, _item1) > 0) + { + (_item0, _item1) = (_item1, _item0); + } + return; + case 3: + if (compare(_item0, _item1) > 0) + (_item0, _item1) = (_item1, _item0); + + if (compare(_item1, _item2) > 0) + { + (_item1, _item2) = (_item2, _item1); + + if (compare(_item0, _item1) > 0) + (_item0, _item1) = (_item1, _item0); + } + return; + case 4: + + if (compare(_item0, _item1) > 0) + (_item0, _item1) = (_item1, _item0); + + if (compare(_item2, _item3) > 0) + (_item2, _item3) = (_item3, _item2); + + if (compare(_item0, _item2) > 0) + (_item0, _item2) = (_item2, _item0); + + if (compare(_item1, _item3) > 0) + (_item1, _item3) = (_item3, _item1); + + if (compare(_item1, _item2) > 0) + (_item1, _item2) = (_item2, _item1); + + return; + default: + throw ExceptionUtilities.Unreachable(); + } + } + + /// + /// Throws . + /// + /// + /// This helper improves the ability of the JIT to inline callers. + /// + private static void ThrowIndexOutOfRangeException() + => throw new IndexOutOfRangeException(); + + [NonCopyable] + public struct Enumerator + { + private readonly TemporaryArray _array; + + private T _current; + private int _nextIndex; + + public Enumerator(in TemporaryArray array) + { + // Enumerate a copy of the original + _array = new TemporaryArray(in array); + _current = default!; + _nextIndex = 0; + } + + public T Current => _current; + + public bool MoveNext() + { + if (_nextIndex >= _array.Count) + { + return false; + } + else + { + _current = _array[_nextIndex]; + _nextIndex++; + return true; + } + } + } + + internal static class TestAccessor + { + public static int InlineCapacity => TemporaryArray.InlineCapacity; + + public static bool HasDynamicStorage(in TemporaryArray array) + => array._builder is not null; + + public static int InlineCount(in TemporaryArray array) + => array._count; + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/microsoft.codeanalysis.collections.5.0.0-1.25277.114.csproj b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/microsoft.codeanalysis.collections.5.0.0-1.25277.114.csproj new file mode 100644 index 00000000000..b5415561983 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/microsoft.codeanalysis.collections.5.0.0-1.25277.114.csproj @@ -0,0 +1,23 @@ + + + + net9.0;netstandard2.0 + 5.0.0-1.25277.114 + Microsoft.CodeAnalysis.Collections + + + + + + + + + + + + + + + + + diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/microsoft.codeanalysis.collections.nuspec b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/microsoft.codeanalysis.collections.nuspec new file mode 100644 index 00000000000..c1b4d7928de --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/5.0.0-1.25277.114/microsoft.codeanalysis.collections.nuspec @@ -0,0 +1,193 @@ + + + + Microsoft.CodeAnalysis.Collections + 5.0.0-1.25277.114 + Microsoft + true + MIT + https://licenses.nuget.org/MIT + https://github.com/dotnet/roslyn + Package containing sources of Microsoft .NET Compiler Platform ("Roslyn") collections. + + + The source code included in this package is subject to arbitrary changes in future versions. + Updating a reference to this package to a newer version of the package may require changes in the referencing project. + No compatibility guarantees are provided. + + More details at https://aka.ms/roslyn-packages + This package was built from the source at https://github.com/dotnet/dotnet/commit/ddf39a1b4690fbe23aea79c78da67004a5c31094. + © Microsoft Corporation. All rights reserved. + Roslyn CodeAnalysis Compiler CSharp VB VisualBasic Parser Scanner Lexer Emit CodeGeneration Metadata IL Compilation Scripting Syntax Semantics + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/Icon.png b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/Icon.png new file mode 100755 index 00000000000..fb00ecf91e4 Binary files /dev/null and b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/Icon.png differ diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/ThirdPartyNotices.rtf b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/ThirdPartyNotices.rtf new file mode 100755 index 00000000000..1e4323dea60 Binary files /dev/null and b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/ThirdPartyNotices.rtf differ diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/build/Microsoft.CodeAnalysis.Contracts.targets b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/build/Microsoft.CodeAnalysis.Contracts.targets new file mode 100755 index 00000000000..45d642e29b6 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/build/Microsoft.CodeAnalysis.Contracts.targets @@ -0,0 +1,19 @@ + + + + + <_PackageCompileItems Remove="@(_PackageCompileItems)"/> + <_PackageCompileItems Include="%(Compile.RootDir)%(Compile.Directory)" Condition="'%(Compile.NuGetPackageId)' == 'Microsoft.CodeAnalysis.Contracts'" /> + + + + <_PackageCompileItem>@(_PackageCompileItems) + <_PackageCompileItem Condition="'$(_PackageCompileItem)' != ''">$(_PackageCompileItem.Split(';')[0]) + + + + + + + diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/.editorconfig b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/.editorconfig new file mode 100755 index 00000000000..e10491047f5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/.editorconfig @@ -0,0 +1,18 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +# We don't want any analyzer diagnostics to be reported for people consuming this as a source package. +dotnet_analyzer_diagnostic.severity = none + +generated_code = true + +# The above configurations don't apply to compiler warnings. Requiring all params to be documented +# is not something we require for this project, so suppressing it directly here. +dotnet_diagnostic.CS1573.severity = none + +# As above, we need to specifically disable compiler warnings that we don't want to break downstream +# builds +dotnet_diagnostic.IDE0005.severity = none \ No newline at end of file diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/CollectionBuilderAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/CollectionBuilderAttribute.cs new file mode 100755 index 00000000000..dc4da52e89f --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/CollectionBuilderAttribute.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !NET8_0_OR_GREATER + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)] + internal sealed class CollectionBuilderAttribute : Attribute + { + public CollectionBuilderAttribute(Type builderType, string methodName) + { + BuilderType = builderType; + MethodName = methodName; + } + + public Type BuilderType { get; } + public string MethodName { get; } + } +} + +#else + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(CollectionBuilderAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/CompilerFeatureRequiredAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/CompilerFeatureRequiredAttribute.cs new file mode 100755 index 00000000000..18d182764b3 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/CompilerFeatureRequiredAttribute.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/fdd104ec5e1d0d2aa24a6723995a98d0124f724b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CompilerFeatureRequiredAttribute.cs + +#if NET8_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(CompilerFeatureRequiredAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Runtime.CompilerServices +{ + /// + /// Indicates that compiler support for a particular feature is required for the location where this attribute is applied. + /// + [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] + internal sealed class CompilerFeatureRequiredAttribute : Attribute + { + public CompilerFeatureRequiredAttribute(string featureName) + { + FeatureName = featureName; + } + + /// + /// The name of the compiler feature. + /// + public string FeatureName { get; } + + /// + /// If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand . + /// + public bool IsOptional { get; init; } + + /// + /// The used for the ref structs C# feature. + /// + public const string RefStructs = nameof(RefStructs); + + /// + /// The used for the required members C# feature. + /// + public const string RequiredMembers = nameof(RequiredMembers); + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Contract.InterpolatedStringHandlers.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Contract.InterpolatedStringHandlers.cs new file mode 100755 index 00000000000..89b969dc5c6 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Contract.InterpolatedStringHandlers.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_CONTRACT + +using System.Runtime.CompilerServices; +using System.Text; + +#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/58168 + +namespace Microsoft.CodeAnalysis; + +internal static partial class Contract +{ + [InterpolatedStringHandler] + public readonly struct ThrowIfTrueInterpolatedStringHandler + { + private readonly StringBuilder _stringBuilder; + + public ThrowIfTrueInterpolatedStringHandler(int literalLength, int formattedCount, bool condition, out bool success) + { + _stringBuilder = condition ? new StringBuilder(capacity: literalLength) : null!; + success = condition; + } + + public void AppendLiteral(string value) => _stringBuilder.Append(value); + + public void AppendFormatted(T value) => _stringBuilder.Append(value?.ToString()); + + public string GetFormattedText() => _stringBuilder.ToString(); + } + + [InterpolatedStringHandler] + public readonly struct ThrowIfFalseInterpolatedStringHandler + { + private readonly StringBuilder _stringBuilder; + + public ThrowIfFalseInterpolatedStringHandler(int literalLength, int formattedCount, bool condition, out bool success) + { + _stringBuilder = condition ? null! : new StringBuilder(capacity: literalLength); + success = !condition; + } + + public void AppendLiteral(string value) => _stringBuilder.Append(value); + + public void AppendFormatted(T value) => _stringBuilder.Append(value?.ToString()); + + public string GetFormattedText() => _stringBuilder.ToString(); + } + + [InterpolatedStringHandler] + public readonly struct ThrowIfNullInterpolatedStringHandler + { + private readonly StringBuilder _stringBuilder; + + public ThrowIfNullInterpolatedStringHandler(int literalLength, int formattedCount, T? value, out bool success) + { + _stringBuilder = value is null ? new StringBuilder(capacity: literalLength) : null!; + success = value is null; + } + + public void AppendLiteral(string value) => _stringBuilder.Append(value); + + public void AppendFormatted(T2 value) => _stringBuilder.Append(value?.ToString()); + + public string GetFormattedText() => _stringBuilder.ToString(); + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Contract.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Contract.cs new file mode 100755 index 00000000000..28da2af8377 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Contract.cs @@ -0,0 +1,165 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_CONTRACT + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis; + +internal static partial class Contract +{ + // Guidance on inlining: + // ThrowXxx methods are used heavily across the code base. + // Inline their implementation of condition checking but don't inline the code that is only executed on failure. + // This approach makes the common path efficient (both execution time and code size) + // while keeping the rarely executed code in a separate method. + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T value, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) where T : class? + { + if (value is null) + { + Fail("Unexpected null", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T? value, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) where T : struct + { + if (value is null) + { + Fail("Unexpected null", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T value, string message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (value is null) + { + Fail(message, lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T value, [InterpolatedStringHandlerArgument("value")] ThrowIfNullInterpolatedStringHandler message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (value is null) + { + Fail(message.GetFormattedText(), lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is false. This method executes + /// in all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfFalse([DoesNotReturnIf(parameterValue: false)] bool condition, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (!condition) + { + Fail("Unexpected false", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is false. This method executes + /// in all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfFalse([DoesNotReturnIf(parameterValue: false)] bool condition, string message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (!condition) + { + Fail(message, lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is false. This method executes + /// in all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfFalse([DoesNotReturnIf(parameterValue: false)] bool condition, [InterpolatedStringHandlerArgument("condition")] ThrowIfFalseInterpolatedStringHandler message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (!condition) + { + Fail(message.GetFormattedText(), lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is true. This method executes in + /// all builds. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfTrue([DoesNotReturnIf(parameterValue: true)] bool condition, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (condition) + { + Fail("Unexpected true", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is true. This method executes in + /// all builds. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfTrue([DoesNotReturnIf(parameterValue: true)] bool condition, string message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (condition) + { + Fail(message, lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is true. This method executes in + /// all builds. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfTrue([DoesNotReturnIf(parameterValue: true)] bool condition, [InterpolatedStringHandlerArgument("condition")] ThrowIfTrueInterpolatedStringHandler message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (condition) + { + Fail(message.GetFormattedText(), lineNumber, filePath); + } + } + + [DebuggerHidden] + [DoesNotReturn] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Fail(string message = "Unexpected", [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + var fileName = filePath is null ? null : Path.GetFileName(filePath); + throw new InvalidOperationException($"{message} - file {fileName} line {lineNumber}"); + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ErrorReporting/FailFast.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ErrorReporting/FailFast.cs new file mode 100755 index 00000000000..437b36788cf --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ErrorReporting/FailFast.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_ERROR_REPORTING + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.ErrorReporting +{ + internal static class FailFast + { + /// + /// A pre-created delegate to assign to if needed. + /// + internal static readonly FatalError.ErrorReporterHandler Handler = static (e, _, _) => OnFatalException(e); + + [DebuggerHidden] + [DoesNotReturn] + [MethodImpl(MethodImplOptions.Synchronized)] + internal static void OnFatalException(Exception exception) + { + // EDMAURER Now using the managed API to fail fast so as to default + // to the managed VS debug engine and hopefully get great + // Watson bucketing. Before vanishing trigger anyone listening. + if (Debugger.IsAttached) + { + Debugger.Break(); + } + + // don't fail fast with an aggregate exception that is masking true exception + if (exception is AggregateException aggregate && aggregate.InnerExceptions.Count == 1) + { + exception = aggregate.InnerExceptions[0]; + } + + DumpStackTrace(exception: exception); + + Environment.FailFast(exception.ToString(), exception); + throw ExceptionUtilities.Unreachable(); // to satisfy [DoesNotReturn] + } + + [DebuggerHidden] + [DoesNotReturn] + [MethodImpl(MethodImplOptions.Synchronized)] + internal static void Fail(string message) + { + DumpStackTrace(message: message); + Environment.FailFast(message); + throw ExceptionUtilities.Unreachable(); // to satisfy [DoesNotReturn] + } + + /// + /// Dumps the stack trace of the exception and the handler to the console. This is useful + /// for debugging unit tests that hit a fatal exception + /// + [Conditional("DEBUG")] + internal static void DumpStackTrace(Exception? exception = null, string? message = null) + { + Console.WriteLine("Dumping info before call to failfast"); + if (message is object) + { + Console.WriteLine(message); + } + + if (exception is object) + { + Console.WriteLine("Exception info"); + for (Exception? current = exception; current is object; current = current.InnerException) + { + Console.WriteLine(current.Message); + Console.WriteLine(current.StackTrace); + } + } + + Console.WriteLine("Stack trace of handler"); + var stackTrace = new StackTrace(); + Console.WriteLine(stackTrace.ToString()); + + Console.Out.Flush(); + } + + /// + /// Checks for the given ; if the is true, + /// immediately terminates the process without running any pending finally blocks or finalizers + /// and causes a crash dump to be collected (if the system is configured to do so). + /// Otherwise, the process continues normally. + /// + /// The conditional expression to evaluate. + /// An optional message to be recorded in the dump in case of failure. Can be null. + [Conditional("DEBUG")] + [DebuggerHidden] + internal static void Assert([DoesNotReturnIf(false)] bool condition, string? message = null) + { + if (condition) + { + return; + } + + if (Debugger.IsAttached) + { + Debugger.Break(); + } + + Fail("ASSERT FAILED" + Environment.NewLine + message); + } + } +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ErrorReporting/FatalError.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ErrorReporting/FatalError.cs new file mode 100755 index 00000000000..25ab0683431 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ErrorReporting/FatalError.cs @@ -0,0 +1,340 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_ERROR_REPORTING + +using System; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.CodeAnalysis.ErrorReporting +{ + /// + /// Thrown when async code must cancel the current execution but does not have access to the of the passed to the code. + /// Should be used in very rare cases where the is out of our control (e.g. owned but not exposed by JSON RPC in certain call-back scenarios). + /// + internal sealed class OperationCanceledIgnoringCallerTokenException : OperationCanceledException + { + public OperationCanceledIgnoringCallerTokenException(Exception innerException) + : base(innerException.Message, innerException) + { + } + } + + internal static class FatalError + { + public delegate void ErrorReporterHandler(Exception exception, ErrorSeverity severity, bool forceDump); + + private static ErrorReporterHandler? s_handler; + private static ErrorReporterHandler? s_nonFatalHandler; + +#pragma warning disable IDE0052 // Remove unread private members - We want to hold onto last exception to make investigation easier + private static Exception? s_reportedException; + private static string? s_reportedExceptionMessage; +#pragma warning restore IDE0052 + + /// + /// Set by the host to handle an error report; this may crash the process or report telemetry. + /// + /// A handler that will not crash the process when called. Used when calling + public static void SetHandlers(ErrorReporterHandler handler, ErrorReporterHandler? nonFatalHandler) + { + if (s_handler != handler) + { + Debug.Assert(s_handler == null, "Handler already set"); + s_handler = handler; + s_nonFatalHandler = nonFatalHandler; + } + } + + /// + /// Same as setting the Handler property except that it avoids the assert. This is useful in + /// test code which needs to verify the handler is called in specific cases and will continually + /// overwrite this value. + /// + public static void OverwriteHandler(ErrorReporterHandler? value) + { + s_handler = value; + } + + /// + /// Copies the handler in this instance to the linked copy of this type in this other assembly. + /// + /// + /// This file is in linked into multiple layers, but we want to ensure that all layers have the same copy. + /// This lets us copy the handler in this instance into the same in another instance. + /// + public static void CopyHandlersTo(Assembly assembly) + { + copyHandlerTo(assembly, s_handler, nameof(s_handler)); + copyHandlerTo(assembly, s_nonFatalHandler, nameof(s_nonFatalHandler)); + + static void copyHandlerTo(Assembly assembly, ErrorReporterHandler? handler, string handlerName) + { + var targetType = assembly.GetType(typeof(FatalError).FullName!, throwOnError: true)!; + var targetHandlerProperty = targetType.GetField(handlerName, BindingFlags.Static | BindingFlags.NonPublic)!; + if (handler is not null) + { + // We need to convert the delegate type to the type in the linked copy since they won't have identity. + var convertedDelegate = Delegate.CreateDelegate(targetHandlerProperty.FieldType, handler.Target, handler.Method); + targetHandlerProperty.SetValue(obj: null, value: convertedDelegate); + } + else + { + targetHandlerProperty.SetValue(obj: null, value: null); + } + } + } + + /// + /// Use in an exception filter to report an error without catching the exception. + /// The error is reported by calling . + /// + /// to avoid catching the exception. + [DebuggerHidden] + public static bool ReportAndPropagate(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + Report(exception, severity); + return false; + } + + /// + /// Use in an exception filter to report an error (by calling ), unless the + /// operation has been cancelled. The exception is never caught. + /// + /// to avoid catching the exception. + [DebuggerHidden] + public static bool ReportAndPropagateUnlessCanceled(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (exception is OperationCanceledException) + { + return false; + } + + return ReportAndPropagate(exception, severity); + } + + /// + /// Use in an exception filter to report an error (by calling ), unless the + /// operation has been cancelled at the request of . The exception is + /// never caught. + /// + /// Cancellable operations are only expected to throw if the + /// applicable indicates cancellation is requested by setting + /// . Unexpected cancellation, i.e. an + /// which occurs without + /// requesting cancellation, is treated as an error by this method. + /// + /// This method does not require to match + /// , provided cancellation is expected per the previous + /// paragraph. + /// + /// A which will have + /// set if cancellation is expected. + /// to avoid catching the exception. + [DebuggerHidden] + public static bool ReportAndPropagateUnlessCanceled(Exception exception, CancellationToken contextCancellationToken, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (ExceptionUtilities.IsCurrentOperationBeingCancelled(exception, contextCancellationToken) || exception is OperationCanceledIgnoringCallerTokenException) + { + return false; + } + + return ReportAndPropagate(exception, severity); + } + + /// + /// Report an error. + /// Calls and doesn't pass the exception through (the method returns true). + /// This is generally expected to be used within an exception filter as that allows us to + /// capture data at the point the exception is thrown rather than when it is handled. + /// However, it can also be used outside of an exception filter. If the exception has not + /// already been thrown the method will throw and catch it itself to ensure we get a useful + /// stack trace. + /// + /// True to catch the exception. + [DebuggerHidden] + public static bool ReportAndCatch(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + Report(exception, severity); + return true; + } + + // Since the command line compiler has no way to catch exceptions, report them, and march on, we + // simply don't offer such a mechanism here to avoid accidental swallowing of exceptions. + +#if !COMPILERCORE + + [DebuggerHidden] + public static bool ReportWithDumpAndCatch(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + Report(exception, severity, forceDump: true); + return true; + } + + /// + /// Use in an exception filter to report an error (by calling ) and catch + /// the exception, unless the operation was cancelled. + /// + /// to catch the exception if the error was reported; otherwise, + /// to propagate the exception if the operation was cancelled. + [DebuggerHidden] + public static bool ReportAndCatchUnlessCanceled(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (exception is OperationCanceledException) + { + return false; + } + + return ReportAndCatch(exception, severity); + } + + /// + /// Use in an exception filter to report an error (by calling ) and + /// catch the exception, unless the operation was cancelled at the request of + /// . + /// + /// Cancellable operations are only expected to throw if the + /// applicable indicates cancellation is requested by setting + /// . Unexpected cancellation, i.e. an + /// which occurs without + /// requesting cancellation, is treated as an error by this method. + /// + /// This method does not require to match + /// , provided cancellation is expected per the previous + /// paragraph. + /// + /// A which will have + /// set if cancellation is expected. + /// to catch the exception if the error was reported; otherwise, + /// to propagate the exception if the operation was cancelled. + [DebuggerHidden] + public static bool ReportAndCatchUnlessCanceled(Exception exception, CancellationToken contextCancellationToken, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (ExceptionUtilities.IsCurrentOperationBeingCancelled(exception, contextCancellationToken) || exception is OperationCanceledIgnoringCallerTokenException) + { + return false; + } + + return ReportAndCatch(exception, severity); + } + + public static Task ReportNonFatalErrorAsync(this Task task) + { + _ = task.ContinueWith(p => ReportAndCatchUnlessCanceled(p.Exception!), + CancellationToken.None, + TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + + return task; + } + + public static Task ReportNonFatalErrorUnlessCancelledAsync(this Task task, CancellationToken cancellationToken) + { + _ = task.ContinueWith(p => ReportAndCatchUnlessCanceled(p.Exception!, cancellationToken), + CancellationToken.None, + TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + + return task; + } +#endif + + // We use a Guid for the marker because it is used as a key in an exceptions Data dictionary, so we must make sure + // it's serializable if the exception crosses an RPC boundary. In particular System.Text.Json doesn't like plain + // object dictionary keys. + private static readonly object s_reportedMarker = Guid.NewGuid(); + + // Do not allow this method to be inlined. That way when we have a dump we can see this frame in the stack and + // can examine things like s_reportedExceptionMessage. Without this, it's a lot trickier as FatalError is linked + // into many assemblies and finding the right type can be much harder. + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Report(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized, bool forceDump = false) + { + ReportException(exception, severity, forceDump, s_handler); + } + + /// + /// Used to report a non-fatal-watson (when possible) to report an exception. The exception is not caught. Does + /// nothing if no non-fatal error handler is registered. See the second argument to . + /// + [MethodImpl(MethodImplOptions.NoInlining)] + public static void ReportNonFatalError(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized, bool forceDump = false) + { + ReportException(exception, severity, forceDump, s_nonFatalHandler); + } + + private static void ReportException(Exception exception, ErrorSeverity severity, bool forceDump, ErrorReporterHandler? handler) + { + // hold onto last exception to make investigation easier + s_reportedException = exception; + s_reportedExceptionMessage = exception.ToString(); + + if (handler == null) + { + return; + } + + // only report exception once + if (exception.Data[s_reportedMarker] != null) + { + return; + } + + if (exception is AggregateException aggregate && aggregate.InnerExceptions.Count == 1 && aggregate.InnerExceptions[0].Data[s_reportedMarker] != null) + { + return; + } + + if (!exception.Data.IsReadOnly) + { + exception.Data[s_reportedMarker] = s_reportedMarker; + } + + handler(exception, severity, forceDump); + } + } + + /// + /// The severity of the error, see the enum members for a description of when to use each. This is metadata that's included + /// in a non-fatal fault report, which we can take advantage of on the backend to automatically triage bugs. For example, + /// a critical severity issue we can open with a lower bug count compared to a low priority one. + /// + internal enum ErrorSeverity + { + /// + /// The severity hasn't been categorized. Don't use this in new code. + /// + Uncategorized, + + /// + /// Something failed, but the user is unlikely to notice. Especially useful for background things that we can silently recover + /// from, like bugs in caching systems. + /// + Diagnostic, + + /// + /// Something failed, and the user might notice, but they're still likely able to carry on. For example, if the user + /// asked for some information from the IDE (find references, completion, etc.) and we were able to give partial results. + /// + General, + + /// + /// Something failed, and the user likely noticed. For example, the user pressed a button to do an action, and + /// we threw an exception so we completely failed to do that in an unrecoverable way. This may also be used + /// for back-end systems where a failure is going to result in a highly broken experience, for example if parsing a file + /// catastrophically failed. + /// + Critical + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ExceptionUtilities.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ExceptionUtilities.cs new file mode 100755 index 00000000000..cfc71b0c9ea --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ExceptionUtilities.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis +{ + internal static class ExceptionUtilities + { + /// + /// Creates an with information about an unexpected value. + /// + /// The unexpected value. + /// The , which should be thrown by the caller. + internal static Exception UnexpectedValue(object? o) + { + string output = string.Format("Unexpected value '{0}' of type '{1}'", o, (o != null) ? o.GetType().FullName : ""); + Debug.Assert(false, output); + + // We do not throw from here because we don't want all Watson reports to be bucketed to this call. + return new InvalidOperationException(output); + } + + internal static Exception Unreachable([CallerFilePath] string? path = null, [CallerLineNumber] int line = 0) + => new InvalidOperationException($"This program location is thought to be unreachable. File='{path}' Line={line}"); + + /// + /// Determine if an exception was an , and that the provided token caused the cancellation. + /// + /// The exception to test. + /// Checked to see if the provided token was cancelled. + /// if the exception was an and the token was canceled. + internal static bool IsCurrentOperationBeingCancelled(Exception exception, CancellationToken cancellationToken) + => exception is OperationCanceledException && cancellationToken.IsCancellationRequested; + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ExperimentalAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ExperimentalAttribute.cs new file mode 100755 index 00000000000..867f4636326 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/ExperimentalAttribute.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// This was copied from https://github.com/dotnet/runtime/blob/815953a12c822847095a843d69c610a9f895ae3f/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs +// and updated to have the scope of the attributes be internal. + +#if NET8_0_OR_GREATER + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(ExperimentalAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Indicates that an API is experimental and it may change in the future. + /// + /// + /// This attribute allows call sites to be flagged with a diagnostic that indicates that an experimental + /// feature is used. Authors can use this attribute to ship preview features in their assemblies. + /// + [AttributeUsage(AttributeTargets.Assembly | + AttributeTargets.Module | + AttributeTargets.Class | + AttributeTargets.Struct | + AttributeTargets.Enum | + AttributeTargets.Constructor | + AttributeTargets.Method | + AttributeTargets.Property | + AttributeTargets.Field | + AttributeTargets.Event | + AttributeTargets.Interface | + AttributeTargets.Delegate, Inherited = false)] + internal sealed class ExperimentalAttribute : Attribute + { + /// + /// Initializes a new instance of the class, specifying the ID that the compiler will use + /// when reporting a use of the API the attribute applies to. + /// + /// The ID that the compiler will use when reporting a use of the API the attribute applies to. + public ExperimentalAttribute(string diagnosticId) + { + DiagnosticId = diagnosticId; + } + + /// + /// Gets the ID that the compiler will use when reporting a use of the API the attribute applies to. + /// + /// The unique diagnostic ID. + /// + /// The diagnostic ID is shown in build output for warnings and errors. + /// This property represents the unique ID that can be used to suppress the warnings or errors, if needed. + /// + public string DiagnosticId { get; } + + /// + /// Gets or sets the URL for corresponding documentation. + /// The API accepts a format string instead of an actual URL, creating a generic URL that includes the diagnostic ID. + /// + /// The format string that represents a URL to corresponding documentation. + /// An example format string is https://contoso.com/obsoletion-warnings/{0}. + public string? UrlFormat { get; set; } + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/IReadOnlySet.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/IReadOnlySet.cs new file mode 100755 index 00000000000..23d96d1b0c0 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/IReadOnlySet.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(System.Collections.Generic.IReadOnlySet<>))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Collections.Generic; + +/// +/// Provides a readonly abstraction of a set. +/// +/// The type of elements in the set. +internal interface IReadOnlySet : IReadOnlyCollection +{ + /// + /// Determines if the set contains a specific item + /// + /// The item to check if the set contains. + /// if found; otherwise . + bool Contains(T item); + + /// + /// Determines whether the current set is a proper (strict) subset of a specified collection. + /// + /// The collection to compare to the current set. + /// if the current set is a proper subset of other; otherwise . + /// other is . + bool IsProperSubsetOf(IEnumerable other); + + /// + /// Determines whether the current set is a proper (strict) superset of a specified collection. + /// + /// The collection to compare to the current set. + /// if the collection is a proper superset of other; otherwise . + /// other is . + bool IsProperSupersetOf(IEnumerable other); + + /// + /// Determine whether the current set is a subset of a specified collection. + /// + /// The collection to compare to the current set. + /// if the current set is a subset of other; otherwise . + /// other is . + bool IsSubsetOf(IEnumerable other); + + /// + /// Determine whether the current set is a super set of a specified collection. + /// + /// The collection to compare to the current set + /// if the current set is a subset of other; otherwise . + /// other is . + bool IsSupersetOf(IEnumerable other); + + /// + /// Determines whether the current set overlaps with the specified collection. + /// + /// The collection to compare to the current set. + /// if the current set and other share at least one common element; otherwise, . + /// other is . + bool Overlaps(IEnumerable other); + + /// + /// Determines whether the current set and the specified collection contain the same elements. + /// + /// The collection to compare to the current set. + /// if the current set is equal to other; otherwise, . + /// other is . + bool SetEquals(IEnumerable other); +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Index.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Index.cs new file mode 100755 index 00000000000..21489812989 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Index.cs @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Index))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +using System.Runtime.CompilerServices; + +namespace System +{ + /// Represent a type can be used to index a collection either from the start or the end. + /// + /// Index is used by the C# compiler to support the new index syntax + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; + /// int lastElement = someArray[^1]; // lastElement = 5 + /// + /// + internal readonly struct Index : IEquatable + { + private readonly int _value; + + /// Construct an Index using a value and indicating if the index is from the start or from the end. + /// The index value. it has to be zero or positive number. + /// Indicating if the index is from the start or from the end. + /// + /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Index(int value, bool fromEnd = false) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Non-negative number required."); + } + + if (fromEnd) + _value = ~value; + else + _value = value; + } + + // The following private constructors mainly created for perf reason to avoid the checks + private Index(int value) + { + _value = value; + } + + /// Create an Index pointing at first element. + public static Index Start => new Index(0); + + /// Create an Index pointing at beyond last element. + public static Index End => new Index(~0); + + /// Create an Index from the start at the position indicated by the value. + /// The index value from the start. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromStart(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Non-negative number required."); + } + + return new Index(value); + } + + /// Create an Index from the end at the position indicated by the value. + /// The index value from the end. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromEnd(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Non-negative number required."); + } + + return new Index(~value); + } + + /// Returns the index value. + public int Value + { + get + { + if (_value < 0) + return ~_value; + else + return _value; + } + } + + /// Indicates whether the index is from the start or the end. + public bool IsFromEnd => _value < 0; + + /// Calculate the offset from the start using the giving collection length. + /// The length of the collection that the Index will be used with. length has to be a positive value + /// + /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. + /// we don't validate either the returned offset is greater than the input length. + /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and + /// then used to index a collection will get out of range exception which will be same affect as the validation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetOffset(int length) + { + int offset = _value; + if (IsFromEnd) + { + // offset = length - (~value) + // offset = length + (~(~value) + 1) + // offset = length + value + 1 + + offset += length + 1; + } + return offset; + } + + /// Indicates whether the current Index object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value; + + /// Indicates whether the current Index object is equal to another Index object. + /// An object to compare with this object + public bool Equals(Index other) => _value == other._value; + + /// Returns the hash code for this instance. + public override int GetHashCode() => _value; + + /// Converts integer number to an Index. + public static implicit operator Index(int value) => FromStart(value); + + /// Converts the value of the current Index object to its equivalent string representation. + public override string ToString() + { + if (IsFromEnd) + return $"^{((uint)Value).ToString()}"; + + return ((uint)Value).ToString(); + } + } +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/InterpolatedStringHandlerArgumentAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/InterpolatedStringHandlerArgumentAttribute.cs new file mode 100755 index 00000000000..a8df29ce946 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/InterpolatedStringHandlerArgumentAttribute.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(InterpolatedStringHandlerArgumentAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +#pragma warning disable CA1019 // Add a public read-only property accessor for positional argument argument of Attribute + +namespace System.Runtime.CompilerServices +{ + /// Indicates which arguments to a method involving an interpolated string handler should be passed to that handler. + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute + { + /// Initializes a new instance of the class. + /// The name of the argument that should be passed to the handler. + /// may be used as the name of the receiver in an instance method. + public InterpolatedStringHandlerArgumentAttribute(string argument) => Arguments = new string[] { argument }; + /// Initializes a new instance of the class. + /// The names of the arguments that should be passed to the handler. + /// may be used as the name of the receiver in an instance method. + public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) => Arguments = arguments; + /// Gets the names of the arguments that should be passed to the handler. + /// may be used as the name of the receiver in an instance method. + public string[] Arguments { get; } + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/InterpolatedStringHandlerAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/InterpolatedStringHandlerAttribute.cs new file mode 100755 index 00000000000..1ac03f50fab --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/InterpolatedStringHandlerAttribute.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(InterpolatedStringHandlerAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Runtime.CompilerServices +{ + /// Indicates the attributed type is to be used as an interpolated string handler. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] + internal sealed class InterpolatedStringHandlerAttribute : Attribute + { + /// Initializes the . + public InterpolatedStringHandlerAttribute() { } + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/IsExternalInit.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/IsExternalInit.cs new file mode 100755 index 00000000000..cf6d665f0f4 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/IsExternalInit.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/218ef0f7776c2c20f6c594e3475b80f1fe2d7d08/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/IsExternalInit.cs + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(IsExternalInit))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +using System.ComponentModel; + +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit + { + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/NonCopyableAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/NonCopyableAttribute.cs new file mode 100755 index 00000000000..a83373ef6a5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/NonCopyableAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; + +namespace Microsoft.CodeAnalysis; + +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.GenericParameter)] +internal sealed class NonCopyableAttribute : Attribute +{ +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/NonDefaultableAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/NonDefaultableAttribute.cs new file mode 100755 index 00000000000..bddbc3f3807 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/NonDefaultableAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; + +namespace Microsoft.CodeAnalysis; + +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.GenericParameter)] +internal sealed class NonDefaultableAttribute : Attribute +{ +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/NullableAttributes.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/NullableAttributes.cs new file mode 100755 index 00000000000..b6eefd30184 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/NullableAttributes.cs @@ -0,0 +1,153 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// This was copied from https://github.com/dotnet/runtime/blob/39b9607807f29e48cae4652cd74735182b31182e/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs +// and updated to have the scope of the attributes be internal. + +namespace System.Diagnostics.CodeAnalysis +{ +#if !NETCOREAPP + + /// Specifies that null is allowed as an input even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class AllowNullAttribute : Attribute { } + + /// Specifies that null is disallowed as an input even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class DisallowNullAttribute : Attribute { } + + /// Specifies that an output may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class MaybeNullAttribute : Attribute { } + + /// Specifies that an output will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class NotNullAttribute : Attribute { } + + /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class MaybeNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter may be null. + /// + public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class NotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that the output will be non-null if the named parameter is non-null. + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] + internal sealed class NotNullIfNotNullAttribute : Attribute + { + /// Initializes the attribute with the associated parameter name. + /// + /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. + /// + public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + + /// Gets the associated parameter name. + public string ParameterName { get; } + } + + /// Applied to a method that will never return under any circumstance. + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + internal sealed class DoesNotReturnAttribute : Attribute { } + + /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class DoesNotReturnIfAttribute : Attribute + { + /// Initializes the attribute with the specified parameter value. + /// + /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + /// the associated parameter matches this value. + /// + public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + + /// Gets the condition parameter value. + public bool ParameterValue { get; } + } + +#endif + +#if !NETCOREAPP + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullAttribute : Attribute + { + /// Initializes the attribute with a field or property member. + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullAttribute(string member) => Members = new[] { member }; + + /// Initializes the attribute with the list of field and property members. + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullAttribute(params string[] members) => Members = members; + + /// Gets field or property member names. + public string[] Members { get; } + } + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition and a field or property member. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = new[] { member }; + } + + /// Initializes the attribute with the specified return value condition and list of field and property members. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// Gets the return value condition. + public bool ReturnValue { get; } + + /// Gets field or property member names. + public string[] Members { get; } + } + +#endif +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Range.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Range.cs new file mode 100755 index 00000000000..1f4ac6e0bf5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/Range.cs @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Range))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else +using System.Runtime.CompilerServices; + +namespace System +{ + /// Represent a range has start and end indexes. + /// + /// Range is used by the C# compiler to support the range syntax. + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; + /// int[] subArray1 = someArray[0..2]; // { 1, 2 } + /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } + /// + /// + internal readonly struct Range : IEquatable + { + /// Represent the inclusive start index of the Range. + public Index Start { get; } + + /// Represent the exclusive end index of the Range. + public Index End { get; } + + /// Construct a Range object using the start and end indexes. + /// Represent the inclusive start index of the range. + /// Represent the exclusive end index of the range. + public Range(Index start, Index end) + { + Start = start; + End = end; + } + + /// Indicates whether the current Range object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => + value is Range r && + r.Start.Equals(Start) && + r.End.Equals(End); + + /// Indicates whether the current Range object is equal to another Range object. + /// An object to compare with this object + public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); + + /// Returns the hash code for this instance. + public override int GetHashCode() + => unchecked(Start.GetHashCode() * (int)0xA5555529 + End.GetHashCode()); + + /// Converts the value of the current Range object to its equivalent string representation. + public override string ToString() + { + return $"{getFromEndSpecifier(Start)}{toString(Start)}..{getFromEndSpecifier(End)}{toString(End)}"; + + static string getFromEndSpecifier(Index index) => index.IsFromEnd ? "^" : string.Empty; + static string toString(Index index) => ((uint)index.Value).ToString(); + } + + /// Create a Range object starting from start index to the end of the collection. + public static Range StartAt(Index start) => new Range(start, Index.End); + + /// Create a Range object starting from first element in the collection to the end Index. + public static Range EndAt(Index end) => new Range(Index.Start, end); + + /// Create a Range object starting from first element to the end. + public static Range All => new Range(Index.Start, Index.End); + +#if !NO_VALUE_TUPLE // workaround for https://github.com/dotnet/roslyn/issues/78392 + + /// Calculate the start offset and length of range object using a collection length. + /// The length of the collection that the range will be used with. length has to be a positive value. + /// + /// For performance reason, we don't validate the input length parameter against negative values. + /// It is expected Range will be used with collections which always have non negative length/count. + /// We validate the range is inside the length scope though. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public (int Offset, int Length) GetOffsetAndLength(int length) + { + int start; + Index startIndex = Start; + if (startIndex.IsFromEnd) + start = length - startIndex.Value; + else + start = startIndex.Value; + + int end; + Index endIndex = End; + if (endIndex.IsFromEnd) + end = length - endIndex.Value; + else + end = endIndex.Value; + + if ((uint)end > (uint)length || (uint)start > (uint)end) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + return (start, end - start); + } +#endif + } +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/RequiredMemberAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/RequiredMemberAttribute.cs new file mode 100755 index 00000000000..7004bd75265 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/RequiredMemberAttribute.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/fdd104ec5e1d0d2aa24a6723995a98d0124f724b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RequiredMemberAttribute.cs + +#if NET8_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(RequiredMemberAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Runtime.CompilerServices +{ + /// Specifies that a type has required members or that a member is required. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + internal sealed class RequiredMemberAttribute : Attribute + { + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/SetsRequiredMembersAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/SetsRequiredMembersAttribute.cs new file mode 100755 index 00000000000..891d50f2859 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net8.0/SetsRequiredMembersAttribute.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/fdd104ec5e1d0d2aa24a6723995a98d0124f724b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs + +#if NET8_0_OR_GREATER + +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(SetsRequiredMembersAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Specifies that this constructor sets all required members for the current type, and callers + /// do not need to set any required members themselves. + /// + [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] + internal sealed class SetsRequiredMembersAttribute : Attribute + { + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/.editorconfig b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/.editorconfig new file mode 100755 index 00000000000..e10491047f5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/.editorconfig @@ -0,0 +1,18 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +# We don't want any analyzer diagnostics to be reported for people consuming this as a source package. +dotnet_analyzer_diagnostic.severity = none + +generated_code = true + +# The above configurations don't apply to compiler warnings. Requiring all params to be documented +# is not something we require for this project, so suppressing it directly here. +dotnet_diagnostic.CS1573.severity = none + +# As above, we need to specifically disable compiler warnings that we don't want to break downstream +# builds +dotnet_diagnostic.IDE0005.severity = none \ No newline at end of file diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/CollectionBuilderAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/CollectionBuilderAttribute.cs new file mode 100755 index 00000000000..dc4da52e89f --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/CollectionBuilderAttribute.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !NET8_0_OR_GREATER + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)] + internal sealed class CollectionBuilderAttribute : Attribute + { + public CollectionBuilderAttribute(Type builderType, string methodName) + { + BuilderType = builderType; + MethodName = methodName; + } + + public Type BuilderType { get; } + public string MethodName { get; } + } +} + +#else + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(CollectionBuilderAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/CompilerFeatureRequiredAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/CompilerFeatureRequiredAttribute.cs new file mode 100755 index 00000000000..18d182764b3 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/CompilerFeatureRequiredAttribute.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/fdd104ec5e1d0d2aa24a6723995a98d0124f724b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CompilerFeatureRequiredAttribute.cs + +#if NET8_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(CompilerFeatureRequiredAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Runtime.CompilerServices +{ + /// + /// Indicates that compiler support for a particular feature is required for the location where this attribute is applied. + /// + [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] + internal sealed class CompilerFeatureRequiredAttribute : Attribute + { + public CompilerFeatureRequiredAttribute(string featureName) + { + FeatureName = featureName; + } + + /// + /// The name of the compiler feature. + /// + public string FeatureName { get; } + + /// + /// If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand . + /// + public bool IsOptional { get; init; } + + /// + /// The used for the ref structs C# feature. + /// + public const string RefStructs = nameof(RefStructs); + + /// + /// The used for the required members C# feature. + /// + public const string RequiredMembers = nameof(RequiredMembers); + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Contract.InterpolatedStringHandlers.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Contract.InterpolatedStringHandlers.cs new file mode 100755 index 00000000000..89b969dc5c6 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Contract.InterpolatedStringHandlers.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_CONTRACT + +using System.Runtime.CompilerServices; +using System.Text; + +#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/58168 + +namespace Microsoft.CodeAnalysis; + +internal static partial class Contract +{ + [InterpolatedStringHandler] + public readonly struct ThrowIfTrueInterpolatedStringHandler + { + private readonly StringBuilder _stringBuilder; + + public ThrowIfTrueInterpolatedStringHandler(int literalLength, int formattedCount, bool condition, out bool success) + { + _stringBuilder = condition ? new StringBuilder(capacity: literalLength) : null!; + success = condition; + } + + public void AppendLiteral(string value) => _stringBuilder.Append(value); + + public void AppendFormatted(T value) => _stringBuilder.Append(value?.ToString()); + + public string GetFormattedText() => _stringBuilder.ToString(); + } + + [InterpolatedStringHandler] + public readonly struct ThrowIfFalseInterpolatedStringHandler + { + private readonly StringBuilder _stringBuilder; + + public ThrowIfFalseInterpolatedStringHandler(int literalLength, int formattedCount, bool condition, out bool success) + { + _stringBuilder = condition ? null! : new StringBuilder(capacity: literalLength); + success = !condition; + } + + public void AppendLiteral(string value) => _stringBuilder.Append(value); + + public void AppendFormatted(T value) => _stringBuilder.Append(value?.ToString()); + + public string GetFormattedText() => _stringBuilder.ToString(); + } + + [InterpolatedStringHandler] + public readonly struct ThrowIfNullInterpolatedStringHandler + { + private readonly StringBuilder _stringBuilder; + + public ThrowIfNullInterpolatedStringHandler(int literalLength, int formattedCount, T? value, out bool success) + { + _stringBuilder = value is null ? new StringBuilder(capacity: literalLength) : null!; + success = value is null; + } + + public void AppendLiteral(string value) => _stringBuilder.Append(value); + + public void AppendFormatted(T2 value) => _stringBuilder.Append(value?.ToString()); + + public string GetFormattedText() => _stringBuilder.ToString(); + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Contract.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Contract.cs new file mode 100755 index 00000000000..28da2af8377 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Contract.cs @@ -0,0 +1,165 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_CONTRACT + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis; + +internal static partial class Contract +{ + // Guidance on inlining: + // ThrowXxx methods are used heavily across the code base. + // Inline their implementation of condition checking but don't inline the code that is only executed on failure. + // This approach makes the common path efficient (both execution time and code size) + // while keeping the rarely executed code in a separate method. + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T value, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) where T : class? + { + if (value is null) + { + Fail("Unexpected null", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T? value, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) where T : struct + { + if (value is null) + { + Fail("Unexpected null", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T value, string message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (value is null) + { + Fail(message, lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T value, [InterpolatedStringHandlerArgument("value")] ThrowIfNullInterpolatedStringHandler message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (value is null) + { + Fail(message.GetFormattedText(), lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is false. This method executes + /// in all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfFalse([DoesNotReturnIf(parameterValue: false)] bool condition, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (!condition) + { + Fail("Unexpected false", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is false. This method executes + /// in all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfFalse([DoesNotReturnIf(parameterValue: false)] bool condition, string message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (!condition) + { + Fail(message, lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is false. This method executes + /// in all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfFalse([DoesNotReturnIf(parameterValue: false)] bool condition, [InterpolatedStringHandlerArgument("condition")] ThrowIfFalseInterpolatedStringHandler message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (!condition) + { + Fail(message.GetFormattedText(), lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is true. This method executes in + /// all builds. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfTrue([DoesNotReturnIf(parameterValue: true)] bool condition, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (condition) + { + Fail("Unexpected true", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is true. This method executes in + /// all builds. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfTrue([DoesNotReturnIf(parameterValue: true)] bool condition, string message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (condition) + { + Fail(message, lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is true. This method executes in + /// all builds. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfTrue([DoesNotReturnIf(parameterValue: true)] bool condition, [InterpolatedStringHandlerArgument("condition")] ThrowIfTrueInterpolatedStringHandler message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (condition) + { + Fail(message.GetFormattedText(), lineNumber, filePath); + } + } + + [DebuggerHidden] + [DoesNotReturn] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Fail(string message = "Unexpected", [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + var fileName = filePath is null ? null : Path.GetFileName(filePath); + throw new InvalidOperationException($"{message} - file {fileName} line {lineNumber}"); + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ErrorReporting/FailFast.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ErrorReporting/FailFast.cs new file mode 100755 index 00000000000..437b36788cf --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ErrorReporting/FailFast.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_ERROR_REPORTING + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.ErrorReporting +{ + internal static class FailFast + { + /// + /// A pre-created delegate to assign to if needed. + /// + internal static readonly FatalError.ErrorReporterHandler Handler = static (e, _, _) => OnFatalException(e); + + [DebuggerHidden] + [DoesNotReturn] + [MethodImpl(MethodImplOptions.Synchronized)] + internal static void OnFatalException(Exception exception) + { + // EDMAURER Now using the managed API to fail fast so as to default + // to the managed VS debug engine and hopefully get great + // Watson bucketing. Before vanishing trigger anyone listening. + if (Debugger.IsAttached) + { + Debugger.Break(); + } + + // don't fail fast with an aggregate exception that is masking true exception + if (exception is AggregateException aggregate && aggregate.InnerExceptions.Count == 1) + { + exception = aggregate.InnerExceptions[0]; + } + + DumpStackTrace(exception: exception); + + Environment.FailFast(exception.ToString(), exception); + throw ExceptionUtilities.Unreachable(); // to satisfy [DoesNotReturn] + } + + [DebuggerHidden] + [DoesNotReturn] + [MethodImpl(MethodImplOptions.Synchronized)] + internal static void Fail(string message) + { + DumpStackTrace(message: message); + Environment.FailFast(message); + throw ExceptionUtilities.Unreachable(); // to satisfy [DoesNotReturn] + } + + /// + /// Dumps the stack trace of the exception and the handler to the console. This is useful + /// for debugging unit tests that hit a fatal exception + /// + [Conditional("DEBUG")] + internal static void DumpStackTrace(Exception? exception = null, string? message = null) + { + Console.WriteLine("Dumping info before call to failfast"); + if (message is object) + { + Console.WriteLine(message); + } + + if (exception is object) + { + Console.WriteLine("Exception info"); + for (Exception? current = exception; current is object; current = current.InnerException) + { + Console.WriteLine(current.Message); + Console.WriteLine(current.StackTrace); + } + } + + Console.WriteLine("Stack trace of handler"); + var stackTrace = new StackTrace(); + Console.WriteLine(stackTrace.ToString()); + + Console.Out.Flush(); + } + + /// + /// Checks for the given ; if the is true, + /// immediately terminates the process without running any pending finally blocks or finalizers + /// and causes a crash dump to be collected (if the system is configured to do so). + /// Otherwise, the process continues normally. + /// + /// The conditional expression to evaluate. + /// An optional message to be recorded in the dump in case of failure. Can be null. + [Conditional("DEBUG")] + [DebuggerHidden] + internal static void Assert([DoesNotReturnIf(false)] bool condition, string? message = null) + { + if (condition) + { + return; + } + + if (Debugger.IsAttached) + { + Debugger.Break(); + } + + Fail("ASSERT FAILED" + Environment.NewLine + message); + } + } +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ErrorReporting/FatalError.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ErrorReporting/FatalError.cs new file mode 100755 index 00000000000..25ab0683431 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ErrorReporting/FatalError.cs @@ -0,0 +1,340 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_ERROR_REPORTING + +using System; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.CodeAnalysis.ErrorReporting +{ + /// + /// Thrown when async code must cancel the current execution but does not have access to the of the passed to the code. + /// Should be used in very rare cases where the is out of our control (e.g. owned but not exposed by JSON RPC in certain call-back scenarios). + /// + internal sealed class OperationCanceledIgnoringCallerTokenException : OperationCanceledException + { + public OperationCanceledIgnoringCallerTokenException(Exception innerException) + : base(innerException.Message, innerException) + { + } + } + + internal static class FatalError + { + public delegate void ErrorReporterHandler(Exception exception, ErrorSeverity severity, bool forceDump); + + private static ErrorReporterHandler? s_handler; + private static ErrorReporterHandler? s_nonFatalHandler; + +#pragma warning disable IDE0052 // Remove unread private members - We want to hold onto last exception to make investigation easier + private static Exception? s_reportedException; + private static string? s_reportedExceptionMessage; +#pragma warning restore IDE0052 + + /// + /// Set by the host to handle an error report; this may crash the process or report telemetry. + /// + /// A handler that will not crash the process when called. Used when calling + public static void SetHandlers(ErrorReporterHandler handler, ErrorReporterHandler? nonFatalHandler) + { + if (s_handler != handler) + { + Debug.Assert(s_handler == null, "Handler already set"); + s_handler = handler; + s_nonFatalHandler = nonFatalHandler; + } + } + + /// + /// Same as setting the Handler property except that it avoids the assert. This is useful in + /// test code which needs to verify the handler is called in specific cases and will continually + /// overwrite this value. + /// + public static void OverwriteHandler(ErrorReporterHandler? value) + { + s_handler = value; + } + + /// + /// Copies the handler in this instance to the linked copy of this type in this other assembly. + /// + /// + /// This file is in linked into multiple layers, but we want to ensure that all layers have the same copy. + /// This lets us copy the handler in this instance into the same in another instance. + /// + public static void CopyHandlersTo(Assembly assembly) + { + copyHandlerTo(assembly, s_handler, nameof(s_handler)); + copyHandlerTo(assembly, s_nonFatalHandler, nameof(s_nonFatalHandler)); + + static void copyHandlerTo(Assembly assembly, ErrorReporterHandler? handler, string handlerName) + { + var targetType = assembly.GetType(typeof(FatalError).FullName!, throwOnError: true)!; + var targetHandlerProperty = targetType.GetField(handlerName, BindingFlags.Static | BindingFlags.NonPublic)!; + if (handler is not null) + { + // We need to convert the delegate type to the type in the linked copy since they won't have identity. + var convertedDelegate = Delegate.CreateDelegate(targetHandlerProperty.FieldType, handler.Target, handler.Method); + targetHandlerProperty.SetValue(obj: null, value: convertedDelegate); + } + else + { + targetHandlerProperty.SetValue(obj: null, value: null); + } + } + } + + /// + /// Use in an exception filter to report an error without catching the exception. + /// The error is reported by calling . + /// + /// to avoid catching the exception. + [DebuggerHidden] + public static bool ReportAndPropagate(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + Report(exception, severity); + return false; + } + + /// + /// Use in an exception filter to report an error (by calling ), unless the + /// operation has been cancelled. The exception is never caught. + /// + /// to avoid catching the exception. + [DebuggerHidden] + public static bool ReportAndPropagateUnlessCanceled(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (exception is OperationCanceledException) + { + return false; + } + + return ReportAndPropagate(exception, severity); + } + + /// + /// Use in an exception filter to report an error (by calling ), unless the + /// operation has been cancelled at the request of . The exception is + /// never caught. + /// + /// Cancellable operations are only expected to throw if the + /// applicable indicates cancellation is requested by setting + /// . Unexpected cancellation, i.e. an + /// which occurs without + /// requesting cancellation, is treated as an error by this method. + /// + /// This method does not require to match + /// , provided cancellation is expected per the previous + /// paragraph. + /// + /// A which will have + /// set if cancellation is expected. + /// to avoid catching the exception. + [DebuggerHidden] + public static bool ReportAndPropagateUnlessCanceled(Exception exception, CancellationToken contextCancellationToken, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (ExceptionUtilities.IsCurrentOperationBeingCancelled(exception, contextCancellationToken) || exception is OperationCanceledIgnoringCallerTokenException) + { + return false; + } + + return ReportAndPropagate(exception, severity); + } + + /// + /// Report an error. + /// Calls and doesn't pass the exception through (the method returns true). + /// This is generally expected to be used within an exception filter as that allows us to + /// capture data at the point the exception is thrown rather than when it is handled. + /// However, it can also be used outside of an exception filter. If the exception has not + /// already been thrown the method will throw and catch it itself to ensure we get a useful + /// stack trace. + /// + /// True to catch the exception. + [DebuggerHidden] + public static bool ReportAndCatch(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + Report(exception, severity); + return true; + } + + // Since the command line compiler has no way to catch exceptions, report them, and march on, we + // simply don't offer such a mechanism here to avoid accidental swallowing of exceptions. + +#if !COMPILERCORE + + [DebuggerHidden] + public static bool ReportWithDumpAndCatch(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + Report(exception, severity, forceDump: true); + return true; + } + + /// + /// Use in an exception filter to report an error (by calling ) and catch + /// the exception, unless the operation was cancelled. + /// + /// to catch the exception if the error was reported; otherwise, + /// to propagate the exception if the operation was cancelled. + [DebuggerHidden] + public static bool ReportAndCatchUnlessCanceled(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (exception is OperationCanceledException) + { + return false; + } + + return ReportAndCatch(exception, severity); + } + + /// + /// Use in an exception filter to report an error (by calling ) and + /// catch the exception, unless the operation was cancelled at the request of + /// . + /// + /// Cancellable operations are only expected to throw if the + /// applicable indicates cancellation is requested by setting + /// . Unexpected cancellation, i.e. an + /// which occurs without + /// requesting cancellation, is treated as an error by this method. + /// + /// This method does not require to match + /// , provided cancellation is expected per the previous + /// paragraph. + /// + /// A which will have + /// set if cancellation is expected. + /// to catch the exception if the error was reported; otherwise, + /// to propagate the exception if the operation was cancelled. + [DebuggerHidden] + public static bool ReportAndCatchUnlessCanceled(Exception exception, CancellationToken contextCancellationToken, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (ExceptionUtilities.IsCurrentOperationBeingCancelled(exception, contextCancellationToken) || exception is OperationCanceledIgnoringCallerTokenException) + { + return false; + } + + return ReportAndCatch(exception, severity); + } + + public static Task ReportNonFatalErrorAsync(this Task task) + { + _ = task.ContinueWith(p => ReportAndCatchUnlessCanceled(p.Exception!), + CancellationToken.None, + TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + + return task; + } + + public static Task ReportNonFatalErrorUnlessCancelledAsync(this Task task, CancellationToken cancellationToken) + { + _ = task.ContinueWith(p => ReportAndCatchUnlessCanceled(p.Exception!, cancellationToken), + CancellationToken.None, + TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + + return task; + } +#endif + + // We use a Guid for the marker because it is used as a key in an exceptions Data dictionary, so we must make sure + // it's serializable if the exception crosses an RPC boundary. In particular System.Text.Json doesn't like plain + // object dictionary keys. + private static readonly object s_reportedMarker = Guid.NewGuid(); + + // Do not allow this method to be inlined. That way when we have a dump we can see this frame in the stack and + // can examine things like s_reportedExceptionMessage. Without this, it's a lot trickier as FatalError is linked + // into many assemblies and finding the right type can be much harder. + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Report(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized, bool forceDump = false) + { + ReportException(exception, severity, forceDump, s_handler); + } + + /// + /// Used to report a non-fatal-watson (when possible) to report an exception. The exception is not caught. Does + /// nothing if no non-fatal error handler is registered. See the second argument to . + /// + [MethodImpl(MethodImplOptions.NoInlining)] + public static void ReportNonFatalError(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized, bool forceDump = false) + { + ReportException(exception, severity, forceDump, s_nonFatalHandler); + } + + private static void ReportException(Exception exception, ErrorSeverity severity, bool forceDump, ErrorReporterHandler? handler) + { + // hold onto last exception to make investigation easier + s_reportedException = exception; + s_reportedExceptionMessage = exception.ToString(); + + if (handler == null) + { + return; + } + + // only report exception once + if (exception.Data[s_reportedMarker] != null) + { + return; + } + + if (exception is AggregateException aggregate && aggregate.InnerExceptions.Count == 1 && aggregate.InnerExceptions[0].Data[s_reportedMarker] != null) + { + return; + } + + if (!exception.Data.IsReadOnly) + { + exception.Data[s_reportedMarker] = s_reportedMarker; + } + + handler(exception, severity, forceDump); + } + } + + /// + /// The severity of the error, see the enum members for a description of when to use each. This is metadata that's included + /// in a non-fatal fault report, which we can take advantage of on the backend to automatically triage bugs. For example, + /// a critical severity issue we can open with a lower bug count compared to a low priority one. + /// + internal enum ErrorSeverity + { + /// + /// The severity hasn't been categorized. Don't use this in new code. + /// + Uncategorized, + + /// + /// Something failed, but the user is unlikely to notice. Especially useful for background things that we can silently recover + /// from, like bugs in caching systems. + /// + Diagnostic, + + /// + /// Something failed, and the user might notice, but they're still likely able to carry on. For example, if the user + /// asked for some information from the IDE (find references, completion, etc.) and we were able to give partial results. + /// + General, + + /// + /// Something failed, and the user likely noticed. For example, the user pressed a button to do an action, and + /// we threw an exception so we completely failed to do that in an unrecoverable way. This may also be used + /// for back-end systems where a failure is going to result in a highly broken experience, for example if parsing a file + /// catastrophically failed. + /// + Critical + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ExceptionUtilities.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ExceptionUtilities.cs new file mode 100755 index 00000000000..cfc71b0c9ea --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ExceptionUtilities.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis +{ + internal static class ExceptionUtilities + { + /// + /// Creates an with information about an unexpected value. + /// + /// The unexpected value. + /// The , which should be thrown by the caller. + internal static Exception UnexpectedValue(object? o) + { + string output = string.Format("Unexpected value '{0}' of type '{1}'", o, (o != null) ? o.GetType().FullName : ""); + Debug.Assert(false, output); + + // We do not throw from here because we don't want all Watson reports to be bucketed to this call. + return new InvalidOperationException(output); + } + + internal static Exception Unreachable([CallerFilePath] string? path = null, [CallerLineNumber] int line = 0) + => new InvalidOperationException($"This program location is thought to be unreachable. File='{path}' Line={line}"); + + /// + /// Determine if an exception was an , and that the provided token caused the cancellation. + /// + /// The exception to test. + /// Checked to see if the provided token was cancelled. + /// if the exception was an and the token was canceled. + internal static bool IsCurrentOperationBeingCancelled(Exception exception, CancellationToken cancellationToken) + => exception is OperationCanceledException && cancellationToken.IsCancellationRequested; + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ExperimentalAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ExperimentalAttribute.cs new file mode 100755 index 00000000000..867f4636326 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/ExperimentalAttribute.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// This was copied from https://github.com/dotnet/runtime/blob/815953a12c822847095a843d69c610a9f895ae3f/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs +// and updated to have the scope of the attributes be internal. + +#if NET8_0_OR_GREATER + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(ExperimentalAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Indicates that an API is experimental and it may change in the future. + /// + /// + /// This attribute allows call sites to be flagged with a diagnostic that indicates that an experimental + /// feature is used. Authors can use this attribute to ship preview features in their assemblies. + /// + [AttributeUsage(AttributeTargets.Assembly | + AttributeTargets.Module | + AttributeTargets.Class | + AttributeTargets.Struct | + AttributeTargets.Enum | + AttributeTargets.Constructor | + AttributeTargets.Method | + AttributeTargets.Property | + AttributeTargets.Field | + AttributeTargets.Event | + AttributeTargets.Interface | + AttributeTargets.Delegate, Inherited = false)] + internal sealed class ExperimentalAttribute : Attribute + { + /// + /// Initializes a new instance of the class, specifying the ID that the compiler will use + /// when reporting a use of the API the attribute applies to. + /// + /// The ID that the compiler will use when reporting a use of the API the attribute applies to. + public ExperimentalAttribute(string diagnosticId) + { + DiagnosticId = diagnosticId; + } + + /// + /// Gets the ID that the compiler will use when reporting a use of the API the attribute applies to. + /// + /// The unique diagnostic ID. + /// + /// The diagnostic ID is shown in build output for warnings and errors. + /// This property represents the unique ID that can be used to suppress the warnings or errors, if needed. + /// + public string DiagnosticId { get; } + + /// + /// Gets or sets the URL for corresponding documentation. + /// The API accepts a format string instead of an actual URL, creating a generic URL that includes the diagnostic ID. + /// + /// The format string that represents a URL to corresponding documentation. + /// An example format string is https://contoso.com/obsoletion-warnings/{0}. + public string? UrlFormat { get; set; } + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/IReadOnlySet.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/IReadOnlySet.cs new file mode 100755 index 00000000000..23d96d1b0c0 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/IReadOnlySet.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(System.Collections.Generic.IReadOnlySet<>))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Collections.Generic; + +/// +/// Provides a readonly abstraction of a set. +/// +/// The type of elements in the set. +internal interface IReadOnlySet : IReadOnlyCollection +{ + /// + /// Determines if the set contains a specific item + /// + /// The item to check if the set contains. + /// if found; otherwise . + bool Contains(T item); + + /// + /// Determines whether the current set is a proper (strict) subset of a specified collection. + /// + /// The collection to compare to the current set. + /// if the current set is a proper subset of other; otherwise . + /// other is . + bool IsProperSubsetOf(IEnumerable other); + + /// + /// Determines whether the current set is a proper (strict) superset of a specified collection. + /// + /// The collection to compare to the current set. + /// if the collection is a proper superset of other; otherwise . + /// other is . + bool IsProperSupersetOf(IEnumerable other); + + /// + /// Determine whether the current set is a subset of a specified collection. + /// + /// The collection to compare to the current set. + /// if the current set is a subset of other; otherwise . + /// other is . + bool IsSubsetOf(IEnumerable other); + + /// + /// Determine whether the current set is a super set of a specified collection. + /// + /// The collection to compare to the current set + /// if the current set is a subset of other; otherwise . + /// other is . + bool IsSupersetOf(IEnumerable other); + + /// + /// Determines whether the current set overlaps with the specified collection. + /// + /// The collection to compare to the current set. + /// if the current set and other share at least one common element; otherwise, . + /// other is . + bool Overlaps(IEnumerable other); + + /// + /// Determines whether the current set and the specified collection contain the same elements. + /// + /// The collection to compare to the current set. + /// if the current set is equal to other; otherwise, . + /// other is . + bool SetEquals(IEnumerable other); +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Index.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Index.cs new file mode 100755 index 00000000000..21489812989 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Index.cs @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Index))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +using System.Runtime.CompilerServices; + +namespace System +{ + /// Represent a type can be used to index a collection either from the start or the end. + /// + /// Index is used by the C# compiler to support the new index syntax + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; + /// int lastElement = someArray[^1]; // lastElement = 5 + /// + /// + internal readonly struct Index : IEquatable + { + private readonly int _value; + + /// Construct an Index using a value and indicating if the index is from the start or from the end. + /// The index value. it has to be zero or positive number. + /// Indicating if the index is from the start or from the end. + /// + /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Index(int value, bool fromEnd = false) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Non-negative number required."); + } + + if (fromEnd) + _value = ~value; + else + _value = value; + } + + // The following private constructors mainly created for perf reason to avoid the checks + private Index(int value) + { + _value = value; + } + + /// Create an Index pointing at first element. + public static Index Start => new Index(0); + + /// Create an Index pointing at beyond last element. + public static Index End => new Index(~0); + + /// Create an Index from the start at the position indicated by the value. + /// The index value from the start. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromStart(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Non-negative number required."); + } + + return new Index(value); + } + + /// Create an Index from the end at the position indicated by the value. + /// The index value from the end. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromEnd(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Non-negative number required."); + } + + return new Index(~value); + } + + /// Returns the index value. + public int Value + { + get + { + if (_value < 0) + return ~_value; + else + return _value; + } + } + + /// Indicates whether the index is from the start or the end. + public bool IsFromEnd => _value < 0; + + /// Calculate the offset from the start using the giving collection length. + /// The length of the collection that the Index will be used with. length has to be a positive value + /// + /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. + /// we don't validate either the returned offset is greater than the input length. + /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and + /// then used to index a collection will get out of range exception which will be same affect as the validation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetOffset(int length) + { + int offset = _value; + if (IsFromEnd) + { + // offset = length - (~value) + // offset = length + (~(~value) + 1) + // offset = length + value + 1 + + offset += length + 1; + } + return offset; + } + + /// Indicates whether the current Index object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value; + + /// Indicates whether the current Index object is equal to another Index object. + /// An object to compare with this object + public bool Equals(Index other) => _value == other._value; + + /// Returns the hash code for this instance. + public override int GetHashCode() => _value; + + /// Converts integer number to an Index. + public static implicit operator Index(int value) => FromStart(value); + + /// Converts the value of the current Index object to its equivalent string representation. + public override string ToString() + { + if (IsFromEnd) + return $"^{((uint)Value).ToString()}"; + + return ((uint)Value).ToString(); + } + } +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/InterpolatedStringHandlerArgumentAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/InterpolatedStringHandlerArgumentAttribute.cs new file mode 100755 index 00000000000..a8df29ce946 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/InterpolatedStringHandlerArgumentAttribute.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(InterpolatedStringHandlerArgumentAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +#pragma warning disable CA1019 // Add a public read-only property accessor for positional argument argument of Attribute + +namespace System.Runtime.CompilerServices +{ + /// Indicates which arguments to a method involving an interpolated string handler should be passed to that handler. + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute + { + /// Initializes a new instance of the class. + /// The name of the argument that should be passed to the handler. + /// may be used as the name of the receiver in an instance method. + public InterpolatedStringHandlerArgumentAttribute(string argument) => Arguments = new string[] { argument }; + /// Initializes a new instance of the class. + /// The names of the arguments that should be passed to the handler. + /// may be used as the name of the receiver in an instance method. + public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) => Arguments = arguments; + /// Gets the names of the arguments that should be passed to the handler. + /// may be used as the name of the receiver in an instance method. + public string[] Arguments { get; } + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/InterpolatedStringHandlerAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/InterpolatedStringHandlerAttribute.cs new file mode 100755 index 00000000000..1ac03f50fab --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/InterpolatedStringHandlerAttribute.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(InterpolatedStringHandlerAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Runtime.CompilerServices +{ + /// Indicates the attributed type is to be used as an interpolated string handler. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] + internal sealed class InterpolatedStringHandlerAttribute : Attribute + { + /// Initializes the . + public InterpolatedStringHandlerAttribute() { } + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/IsExternalInit.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/IsExternalInit.cs new file mode 100755 index 00000000000..cf6d665f0f4 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/IsExternalInit.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/218ef0f7776c2c20f6c594e3475b80f1fe2d7d08/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/IsExternalInit.cs + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(IsExternalInit))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +using System.ComponentModel; + +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit + { + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/NonCopyableAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/NonCopyableAttribute.cs new file mode 100755 index 00000000000..a83373ef6a5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/NonCopyableAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; + +namespace Microsoft.CodeAnalysis; + +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.GenericParameter)] +internal sealed class NonCopyableAttribute : Attribute +{ +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/NonDefaultableAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/NonDefaultableAttribute.cs new file mode 100755 index 00000000000..bddbc3f3807 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/NonDefaultableAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; + +namespace Microsoft.CodeAnalysis; + +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.GenericParameter)] +internal sealed class NonDefaultableAttribute : Attribute +{ +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/NullableAttributes.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/NullableAttributes.cs new file mode 100755 index 00000000000..b6eefd30184 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/NullableAttributes.cs @@ -0,0 +1,153 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// This was copied from https://github.com/dotnet/runtime/blob/39b9607807f29e48cae4652cd74735182b31182e/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs +// and updated to have the scope of the attributes be internal. + +namespace System.Diagnostics.CodeAnalysis +{ +#if !NETCOREAPP + + /// Specifies that null is allowed as an input even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class AllowNullAttribute : Attribute { } + + /// Specifies that null is disallowed as an input even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class DisallowNullAttribute : Attribute { } + + /// Specifies that an output may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class MaybeNullAttribute : Attribute { } + + /// Specifies that an output will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class NotNullAttribute : Attribute { } + + /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class MaybeNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter may be null. + /// + public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class NotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that the output will be non-null if the named parameter is non-null. + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] + internal sealed class NotNullIfNotNullAttribute : Attribute + { + /// Initializes the attribute with the associated parameter name. + /// + /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. + /// + public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + + /// Gets the associated parameter name. + public string ParameterName { get; } + } + + /// Applied to a method that will never return under any circumstance. + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + internal sealed class DoesNotReturnAttribute : Attribute { } + + /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class DoesNotReturnIfAttribute : Attribute + { + /// Initializes the attribute with the specified parameter value. + /// + /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + /// the associated parameter matches this value. + /// + public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + + /// Gets the condition parameter value. + public bool ParameterValue { get; } + } + +#endif + +#if !NETCOREAPP + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullAttribute : Attribute + { + /// Initializes the attribute with a field or property member. + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullAttribute(string member) => Members = new[] { member }; + + /// Initializes the attribute with the list of field and property members. + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullAttribute(params string[] members) => Members = members; + + /// Gets field or property member names. + public string[] Members { get; } + } + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition and a field or property member. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = new[] { member }; + } + + /// Initializes the attribute with the specified return value condition and list of field and property members. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// Gets the return value condition. + public bool ReturnValue { get; } + + /// Gets field or property member names. + public string[] Members { get; } + } + +#endif +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Range.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Range.cs new file mode 100755 index 00000000000..1f4ac6e0bf5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/Range.cs @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Range))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else +using System.Runtime.CompilerServices; + +namespace System +{ + /// Represent a range has start and end indexes. + /// + /// Range is used by the C# compiler to support the range syntax. + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; + /// int[] subArray1 = someArray[0..2]; // { 1, 2 } + /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } + /// + /// + internal readonly struct Range : IEquatable + { + /// Represent the inclusive start index of the Range. + public Index Start { get; } + + /// Represent the exclusive end index of the Range. + public Index End { get; } + + /// Construct a Range object using the start and end indexes. + /// Represent the inclusive start index of the range. + /// Represent the exclusive end index of the range. + public Range(Index start, Index end) + { + Start = start; + End = end; + } + + /// Indicates whether the current Range object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => + value is Range r && + r.Start.Equals(Start) && + r.End.Equals(End); + + /// Indicates whether the current Range object is equal to another Range object. + /// An object to compare with this object + public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); + + /// Returns the hash code for this instance. + public override int GetHashCode() + => unchecked(Start.GetHashCode() * (int)0xA5555529 + End.GetHashCode()); + + /// Converts the value of the current Range object to its equivalent string representation. + public override string ToString() + { + return $"{getFromEndSpecifier(Start)}{toString(Start)}..{getFromEndSpecifier(End)}{toString(End)}"; + + static string getFromEndSpecifier(Index index) => index.IsFromEnd ? "^" : string.Empty; + static string toString(Index index) => ((uint)index.Value).ToString(); + } + + /// Create a Range object starting from start index to the end of the collection. + public static Range StartAt(Index start) => new Range(start, Index.End); + + /// Create a Range object starting from first element in the collection to the end Index. + public static Range EndAt(Index end) => new Range(Index.Start, end); + + /// Create a Range object starting from first element to the end. + public static Range All => new Range(Index.Start, Index.End); + +#if !NO_VALUE_TUPLE // workaround for https://github.com/dotnet/roslyn/issues/78392 + + /// Calculate the start offset and length of range object using a collection length. + /// The length of the collection that the range will be used with. length has to be a positive value. + /// + /// For performance reason, we don't validate the input length parameter against negative values. + /// It is expected Range will be used with collections which always have non negative length/count. + /// We validate the range is inside the length scope though. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public (int Offset, int Length) GetOffsetAndLength(int length) + { + int start; + Index startIndex = Start; + if (startIndex.IsFromEnd) + start = length - startIndex.Value; + else + start = startIndex.Value; + + int end; + Index endIndex = End; + if (endIndex.IsFromEnd) + end = length - endIndex.Value; + else + end = endIndex.Value; + + if ((uint)end > (uint)length || (uint)start > (uint)end) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + return (start, end - start); + } +#endif + } +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/RequiredMemberAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/RequiredMemberAttribute.cs new file mode 100755 index 00000000000..7004bd75265 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/RequiredMemberAttribute.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/fdd104ec5e1d0d2aa24a6723995a98d0124f724b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RequiredMemberAttribute.cs + +#if NET8_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(RequiredMemberAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Runtime.CompilerServices +{ + /// Specifies that a type has required members or that a member is required. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + internal sealed class RequiredMemberAttribute : Attribute + { + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/SetsRequiredMembersAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/SetsRequiredMembersAttribute.cs new file mode 100755 index 00000000000..891d50f2859 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/net9.0/SetsRequiredMembersAttribute.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/fdd104ec5e1d0d2aa24a6723995a98d0124f724b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs + +#if NET8_0_OR_GREATER + +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(SetsRequiredMembersAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Specifies that this constructor sets all required members for the current type, and callers + /// do not need to set any required members themselves. + /// + [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] + internal sealed class SetsRequiredMembersAttribute : Attribute + { + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/.editorconfig b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/.editorconfig new file mode 100755 index 00000000000..e10491047f5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/.editorconfig @@ -0,0 +1,18 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +# We don't want any analyzer diagnostics to be reported for people consuming this as a source package. +dotnet_analyzer_diagnostic.severity = none + +generated_code = true + +# The above configurations don't apply to compiler warnings. Requiring all params to be documented +# is not something we require for this project, so suppressing it directly here. +dotnet_diagnostic.CS1573.severity = none + +# As above, we need to specifically disable compiler warnings that we don't want to break downstream +# builds +dotnet_diagnostic.IDE0005.severity = none \ No newline at end of file diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/CollectionBuilderAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/CollectionBuilderAttribute.cs new file mode 100755 index 00000000000..dc4da52e89f --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/CollectionBuilderAttribute.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !NET8_0_OR_GREATER + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)] + internal sealed class CollectionBuilderAttribute : Attribute + { + public CollectionBuilderAttribute(Type builderType, string methodName) + { + BuilderType = builderType; + MethodName = methodName; + } + + public Type BuilderType { get; } + public string MethodName { get; } + } +} + +#else + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(CollectionBuilderAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/CompilerFeatureRequiredAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/CompilerFeatureRequiredAttribute.cs new file mode 100755 index 00000000000..18d182764b3 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/CompilerFeatureRequiredAttribute.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/fdd104ec5e1d0d2aa24a6723995a98d0124f724b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CompilerFeatureRequiredAttribute.cs + +#if NET8_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(CompilerFeatureRequiredAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Runtime.CompilerServices +{ + /// + /// Indicates that compiler support for a particular feature is required for the location where this attribute is applied. + /// + [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] + internal sealed class CompilerFeatureRequiredAttribute : Attribute + { + public CompilerFeatureRequiredAttribute(string featureName) + { + FeatureName = featureName; + } + + /// + /// The name of the compiler feature. + /// + public string FeatureName { get; } + + /// + /// If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand . + /// + public bool IsOptional { get; init; } + + /// + /// The used for the ref structs C# feature. + /// + public const string RefStructs = nameof(RefStructs); + + /// + /// The used for the required members C# feature. + /// + public const string RequiredMembers = nameof(RequiredMembers); + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Contract.InterpolatedStringHandlers.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Contract.InterpolatedStringHandlers.cs new file mode 100755 index 00000000000..89b969dc5c6 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Contract.InterpolatedStringHandlers.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_CONTRACT + +using System.Runtime.CompilerServices; +using System.Text; + +#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/58168 + +namespace Microsoft.CodeAnalysis; + +internal static partial class Contract +{ + [InterpolatedStringHandler] + public readonly struct ThrowIfTrueInterpolatedStringHandler + { + private readonly StringBuilder _stringBuilder; + + public ThrowIfTrueInterpolatedStringHandler(int literalLength, int formattedCount, bool condition, out bool success) + { + _stringBuilder = condition ? new StringBuilder(capacity: literalLength) : null!; + success = condition; + } + + public void AppendLiteral(string value) => _stringBuilder.Append(value); + + public void AppendFormatted(T value) => _stringBuilder.Append(value?.ToString()); + + public string GetFormattedText() => _stringBuilder.ToString(); + } + + [InterpolatedStringHandler] + public readonly struct ThrowIfFalseInterpolatedStringHandler + { + private readonly StringBuilder _stringBuilder; + + public ThrowIfFalseInterpolatedStringHandler(int literalLength, int formattedCount, bool condition, out bool success) + { + _stringBuilder = condition ? null! : new StringBuilder(capacity: literalLength); + success = !condition; + } + + public void AppendLiteral(string value) => _stringBuilder.Append(value); + + public void AppendFormatted(T value) => _stringBuilder.Append(value?.ToString()); + + public string GetFormattedText() => _stringBuilder.ToString(); + } + + [InterpolatedStringHandler] + public readonly struct ThrowIfNullInterpolatedStringHandler + { + private readonly StringBuilder _stringBuilder; + + public ThrowIfNullInterpolatedStringHandler(int literalLength, int formattedCount, T? value, out bool success) + { + _stringBuilder = value is null ? new StringBuilder(capacity: literalLength) : null!; + success = value is null; + } + + public void AppendLiteral(string value) => _stringBuilder.Append(value); + + public void AppendFormatted(T2 value) => _stringBuilder.Append(value?.ToString()); + + public string GetFormattedText() => _stringBuilder.ToString(); + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Contract.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Contract.cs new file mode 100755 index 00000000000..28da2af8377 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Contract.cs @@ -0,0 +1,165 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_CONTRACT + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis; + +internal static partial class Contract +{ + // Guidance on inlining: + // ThrowXxx methods are used heavily across the code base. + // Inline their implementation of condition checking but don't inline the code that is only executed on failure. + // This approach makes the common path efficient (both execution time and code size) + // while keeping the rarely executed code in a separate method. + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T value, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) where T : class? + { + if (value is null) + { + Fail("Unexpected null", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T? value, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) where T : struct + { + if (value is null) + { + Fail("Unexpected null", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T value, string message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (value is null) + { + Fail(message, lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is null. This method executes in + /// all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] T value, [InterpolatedStringHandlerArgument("value")] ThrowIfNullInterpolatedStringHandler message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (value is null) + { + Fail(message.GetFormattedText(), lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is false. This method executes + /// in all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfFalse([DoesNotReturnIf(parameterValue: false)] bool condition, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (!condition) + { + Fail("Unexpected false", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is false. This method executes + /// in all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfFalse([DoesNotReturnIf(parameterValue: false)] bool condition, string message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (!condition) + { + Fail(message, lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is false. This method executes + /// in all builds + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfFalse([DoesNotReturnIf(parameterValue: false)] bool condition, [InterpolatedStringHandlerArgument("condition")] ThrowIfFalseInterpolatedStringHandler message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (!condition) + { + Fail(message.GetFormattedText(), lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is true. This method executes in + /// all builds. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfTrue([DoesNotReturnIf(parameterValue: true)] bool condition, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (condition) + { + Fail("Unexpected true", lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is true. This method executes in + /// all builds. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfTrue([DoesNotReturnIf(parameterValue: true)] bool condition, string message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (condition) + { + Fail(message, lineNumber, filePath); + } + } + + /// + /// Throws a non-accessible exception if the provided value is true. This method executes in + /// all builds. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfTrue([DoesNotReturnIf(parameterValue: true)] bool condition, [InterpolatedStringHandlerArgument("condition")] ThrowIfTrueInterpolatedStringHandler message, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + if (condition) + { + Fail(message.GetFormattedText(), lineNumber, filePath); + } + } + + [DebuggerHidden] + [DoesNotReturn] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Fail(string message = "Unexpected", [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string? filePath = null) + { + var fileName = filePath is null ? null : Path.GetFileName(filePath); + throw new InvalidOperationException($"{message} - file {fileName} line {lineNumber}"); + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ErrorReporting/FailFast.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ErrorReporting/FailFast.cs new file mode 100755 index 00000000000..437b36788cf --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ErrorReporting/FailFast.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_ERROR_REPORTING + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.ErrorReporting +{ + internal static class FailFast + { + /// + /// A pre-created delegate to assign to if needed. + /// + internal static readonly FatalError.ErrorReporterHandler Handler = static (e, _, _) => OnFatalException(e); + + [DebuggerHidden] + [DoesNotReturn] + [MethodImpl(MethodImplOptions.Synchronized)] + internal static void OnFatalException(Exception exception) + { + // EDMAURER Now using the managed API to fail fast so as to default + // to the managed VS debug engine and hopefully get great + // Watson bucketing. Before vanishing trigger anyone listening. + if (Debugger.IsAttached) + { + Debugger.Break(); + } + + // don't fail fast with an aggregate exception that is masking true exception + if (exception is AggregateException aggregate && aggregate.InnerExceptions.Count == 1) + { + exception = aggregate.InnerExceptions[0]; + } + + DumpStackTrace(exception: exception); + + Environment.FailFast(exception.ToString(), exception); + throw ExceptionUtilities.Unreachable(); // to satisfy [DoesNotReturn] + } + + [DebuggerHidden] + [DoesNotReturn] + [MethodImpl(MethodImplOptions.Synchronized)] + internal static void Fail(string message) + { + DumpStackTrace(message: message); + Environment.FailFast(message); + throw ExceptionUtilities.Unreachable(); // to satisfy [DoesNotReturn] + } + + /// + /// Dumps the stack trace of the exception and the handler to the console. This is useful + /// for debugging unit tests that hit a fatal exception + /// + [Conditional("DEBUG")] + internal static void DumpStackTrace(Exception? exception = null, string? message = null) + { + Console.WriteLine("Dumping info before call to failfast"); + if (message is object) + { + Console.WriteLine(message); + } + + if (exception is object) + { + Console.WriteLine("Exception info"); + for (Exception? current = exception; current is object; current = current.InnerException) + { + Console.WriteLine(current.Message); + Console.WriteLine(current.StackTrace); + } + } + + Console.WriteLine("Stack trace of handler"); + var stackTrace = new StackTrace(); + Console.WriteLine(stackTrace.ToString()); + + Console.Out.Flush(); + } + + /// + /// Checks for the given ; if the is true, + /// immediately terminates the process without running any pending finally blocks or finalizers + /// and causes a crash dump to be collected (if the system is configured to do so). + /// Otherwise, the process continues normally. + /// + /// The conditional expression to evaluate. + /// An optional message to be recorded in the dump in case of failure. Can be null. + [Conditional("DEBUG")] + [DebuggerHidden] + internal static void Assert([DoesNotReturnIf(false)] bool condition, string? message = null) + { + if (condition) + { + return; + } + + if (Debugger.IsAttached) + { + Debugger.Break(); + } + + Fail("ASSERT FAILED" + Environment.NewLine + message); + } + } +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ErrorReporting/FatalError.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ErrorReporting/FatalError.cs new file mode 100755 index 00000000000..25ab0683431 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ErrorReporting/FatalError.cs @@ -0,0 +1,340 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_CONTRACTS_NO_ERROR_REPORTING + +using System; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.CodeAnalysis.ErrorReporting +{ + /// + /// Thrown when async code must cancel the current execution but does not have access to the of the passed to the code. + /// Should be used in very rare cases where the is out of our control (e.g. owned but not exposed by JSON RPC in certain call-back scenarios). + /// + internal sealed class OperationCanceledIgnoringCallerTokenException : OperationCanceledException + { + public OperationCanceledIgnoringCallerTokenException(Exception innerException) + : base(innerException.Message, innerException) + { + } + } + + internal static class FatalError + { + public delegate void ErrorReporterHandler(Exception exception, ErrorSeverity severity, bool forceDump); + + private static ErrorReporterHandler? s_handler; + private static ErrorReporterHandler? s_nonFatalHandler; + +#pragma warning disable IDE0052 // Remove unread private members - We want to hold onto last exception to make investigation easier + private static Exception? s_reportedException; + private static string? s_reportedExceptionMessage; +#pragma warning restore IDE0052 + + /// + /// Set by the host to handle an error report; this may crash the process or report telemetry. + /// + /// A handler that will not crash the process when called. Used when calling + public static void SetHandlers(ErrorReporterHandler handler, ErrorReporterHandler? nonFatalHandler) + { + if (s_handler != handler) + { + Debug.Assert(s_handler == null, "Handler already set"); + s_handler = handler; + s_nonFatalHandler = nonFatalHandler; + } + } + + /// + /// Same as setting the Handler property except that it avoids the assert. This is useful in + /// test code which needs to verify the handler is called in specific cases and will continually + /// overwrite this value. + /// + public static void OverwriteHandler(ErrorReporterHandler? value) + { + s_handler = value; + } + + /// + /// Copies the handler in this instance to the linked copy of this type in this other assembly. + /// + /// + /// This file is in linked into multiple layers, but we want to ensure that all layers have the same copy. + /// This lets us copy the handler in this instance into the same in another instance. + /// + public static void CopyHandlersTo(Assembly assembly) + { + copyHandlerTo(assembly, s_handler, nameof(s_handler)); + copyHandlerTo(assembly, s_nonFatalHandler, nameof(s_nonFatalHandler)); + + static void copyHandlerTo(Assembly assembly, ErrorReporterHandler? handler, string handlerName) + { + var targetType = assembly.GetType(typeof(FatalError).FullName!, throwOnError: true)!; + var targetHandlerProperty = targetType.GetField(handlerName, BindingFlags.Static | BindingFlags.NonPublic)!; + if (handler is not null) + { + // We need to convert the delegate type to the type in the linked copy since they won't have identity. + var convertedDelegate = Delegate.CreateDelegate(targetHandlerProperty.FieldType, handler.Target, handler.Method); + targetHandlerProperty.SetValue(obj: null, value: convertedDelegate); + } + else + { + targetHandlerProperty.SetValue(obj: null, value: null); + } + } + } + + /// + /// Use in an exception filter to report an error without catching the exception. + /// The error is reported by calling . + /// + /// to avoid catching the exception. + [DebuggerHidden] + public static bool ReportAndPropagate(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + Report(exception, severity); + return false; + } + + /// + /// Use in an exception filter to report an error (by calling ), unless the + /// operation has been cancelled. The exception is never caught. + /// + /// to avoid catching the exception. + [DebuggerHidden] + public static bool ReportAndPropagateUnlessCanceled(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (exception is OperationCanceledException) + { + return false; + } + + return ReportAndPropagate(exception, severity); + } + + /// + /// Use in an exception filter to report an error (by calling ), unless the + /// operation has been cancelled at the request of . The exception is + /// never caught. + /// + /// Cancellable operations are only expected to throw if the + /// applicable indicates cancellation is requested by setting + /// . Unexpected cancellation, i.e. an + /// which occurs without + /// requesting cancellation, is treated as an error by this method. + /// + /// This method does not require to match + /// , provided cancellation is expected per the previous + /// paragraph. + /// + /// A which will have + /// set if cancellation is expected. + /// to avoid catching the exception. + [DebuggerHidden] + public static bool ReportAndPropagateUnlessCanceled(Exception exception, CancellationToken contextCancellationToken, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (ExceptionUtilities.IsCurrentOperationBeingCancelled(exception, contextCancellationToken) || exception is OperationCanceledIgnoringCallerTokenException) + { + return false; + } + + return ReportAndPropagate(exception, severity); + } + + /// + /// Report an error. + /// Calls and doesn't pass the exception through (the method returns true). + /// This is generally expected to be used within an exception filter as that allows us to + /// capture data at the point the exception is thrown rather than when it is handled. + /// However, it can also be used outside of an exception filter. If the exception has not + /// already been thrown the method will throw and catch it itself to ensure we get a useful + /// stack trace. + /// + /// True to catch the exception. + [DebuggerHidden] + public static bool ReportAndCatch(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + Report(exception, severity); + return true; + } + + // Since the command line compiler has no way to catch exceptions, report them, and march on, we + // simply don't offer such a mechanism here to avoid accidental swallowing of exceptions. + +#if !COMPILERCORE + + [DebuggerHidden] + public static bool ReportWithDumpAndCatch(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + Report(exception, severity, forceDump: true); + return true; + } + + /// + /// Use in an exception filter to report an error (by calling ) and catch + /// the exception, unless the operation was cancelled. + /// + /// to catch the exception if the error was reported; otherwise, + /// to propagate the exception if the operation was cancelled. + [DebuggerHidden] + public static bool ReportAndCatchUnlessCanceled(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (exception is OperationCanceledException) + { + return false; + } + + return ReportAndCatch(exception, severity); + } + + /// + /// Use in an exception filter to report an error (by calling ) and + /// catch the exception, unless the operation was cancelled at the request of + /// . + /// + /// Cancellable operations are only expected to throw if the + /// applicable indicates cancellation is requested by setting + /// . Unexpected cancellation, i.e. an + /// which occurs without + /// requesting cancellation, is treated as an error by this method. + /// + /// This method does not require to match + /// , provided cancellation is expected per the previous + /// paragraph. + /// + /// A which will have + /// set if cancellation is expected. + /// to catch the exception if the error was reported; otherwise, + /// to propagate the exception if the operation was cancelled. + [DebuggerHidden] + public static bool ReportAndCatchUnlessCanceled(Exception exception, CancellationToken contextCancellationToken, ErrorSeverity severity = ErrorSeverity.Uncategorized) + { + if (ExceptionUtilities.IsCurrentOperationBeingCancelled(exception, contextCancellationToken) || exception is OperationCanceledIgnoringCallerTokenException) + { + return false; + } + + return ReportAndCatch(exception, severity); + } + + public static Task ReportNonFatalErrorAsync(this Task task) + { + _ = task.ContinueWith(p => ReportAndCatchUnlessCanceled(p.Exception!), + CancellationToken.None, + TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + + return task; + } + + public static Task ReportNonFatalErrorUnlessCancelledAsync(this Task task, CancellationToken cancellationToken) + { + _ = task.ContinueWith(p => ReportAndCatchUnlessCanceled(p.Exception!, cancellationToken), + CancellationToken.None, + TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + + return task; + } +#endif + + // We use a Guid for the marker because it is used as a key in an exceptions Data dictionary, so we must make sure + // it's serializable if the exception crosses an RPC boundary. In particular System.Text.Json doesn't like plain + // object dictionary keys. + private static readonly object s_reportedMarker = Guid.NewGuid(); + + // Do not allow this method to be inlined. That way when we have a dump we can see this frame in the stack and + // can examine things like s_reportedExceptionMessage. Without this, it's a lot trickier as FatalError is linked + // into many assemblies and finding the right type can be much harder. + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Report(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized, bool forceDump = false) + { + ReportException(exception, severity, forceDump, s_handler); + } + + /// + /// Used to report a non-fatal-watson (when possible) to report an exception. The exception is not caught. Does + /// nothing if no non-fatal error handler is registered. See the second argument to . + /// + [MethodImpl(MethodImplOptions.NoInlining)] + public static void ReportNonFatalError(Exception exception, ErrorSeverity severity = ErrorSeverity.Uncategorized, bool forceDump = false) + { + ReportException(exception, severity, forceDump, s_nonFatalHandler); + } + + private static void ReportException(Exception exception, ErrorSeverity severity, bool forceDump, ErrorReporterHandler? handler) + { + // hold onto last exception to make investigation easier + s_reportedException = exception; + s_reportedExceptionMessage = exception.ToString(); + + if (handler == null) + { + return; + } + + // only report exception once + if (exception.Data[s_reportedMarker] != null) + { + return; + } + + if (exception is AggregateException aggregate && aggregate.InnerExceptions.Count == 1 && aggregate.InnerExceptions[0].Data[s_reportedMarker] != null) + { + return; + } + + if (!exception.Data.IsReadOnly) + { + exception.Data[s_reportedMarker] = s_reportedMarker; + } + + handler(exception, severity, forceDump); + } + } + + /// + /// The severity of the error, see the enum members for a description of when to use each. This is metadata that's included + /// in a non-fatal fault report, which we can take advantage of on the backend to automatically triage bugs. For example, + /// a critical severity issue we can open with a lower bug count compared to a low priority one. + /// + internal enum ErrorSeverity + { + /// + /// The severity hasn't been categorized. Don't use this in new code. + /// + Uncategorized, + + /// + /// Something failed, but the user is unlikely to notice. Especially useful for background things that we can silently recover + /// from, like bugs in caching systems. + /// + Diagnostic, + + /// + /// Something failed, and the user might notice, but they're still likely able to carry on. For example, if the user + /// asked for some information from the IDE (find references, completion, etc.) and we were able to give partial results. + /// + General, + + /// + /// Something failed, and the user likely noticed. For example, the user pressed a button to do an action, and + /// we threw an exception so we completely failed to do that in an unrecoverable way. This may also be used + /// for back-end systems where a failure is going to result in a highly broken experience, for example if parsing a file + /// catastrophically failed. + /// + Critical + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ExceptionUtilities.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ExceptionUtilities.cs new file mode 100755 index 00000000000..cfc71b0c9ea --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ExceptionUtilities.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.CodeAnalysis +{ + internal static class ExceptionUtilities + { + /// + /// Creates an with information about an unexpected value. + /// + /// The unexpected value. + /// The , which should be thrown by the caller. + internal static Exception UnexpectedValue(object? o) + { + string output = string.Format("Unexpected value '{0}' of type '{1}'", o, (o != null) ? o.GetType().FullName : ""); + Debug.Assert(false, output); + + // We do not throw from here because we don't want all Watson reports to be bucketed to this call. + return new InvalidOperationException(output); + } + + internal static Exception Unreachable([CallerFilePath] string? path = null, [CallerLineNumber] int line = 0) + => new InvalidOperationException($"This program location is thought to be unreachable. File='{path}' Line={line}"); + + /// + /// Determine if an exception was an , and that the provided token caused the cancellation. + /// + /// The exception to test. + /// Checked to see if the provided token was cancelled. + /// if the exception was an and the token was canceled. + internal static bool IsCurrentOperationBeingCancelled(Exception exception, CancellationToken cancellationToken) + => exception is OperationCanceledException && cancellationToken.IsCancellationRequested; + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ExperimentalAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ExperimentalAttribute.cs new file mode 100755 index 00000000000..867f4636326 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ExperimentalAttribute.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// This was copied from https://github.com/dotnet/runtime/blob/815953a12c822847095a843d69c610a9f895ae3f/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs +// and updated to have the scope of the attributes be internal. + +#if NET8_0_OR_GREATER + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(ExperimentalAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Indicates that an API is experimental and it may change in the future. + /// + /// + /// This attribute allows call sites to be flagged with a diagnostic that indicates that an experimental + /// feature is used. Authors can use this attribute to ship preview features in their assemblies. + /// + [AttributeUsage(AttributeTargets.Assembly | + AttributeTargets.Module | + AttributeTargets.Class | + AttributeTargets.Struct | + AttributeTargets.Enum | + AttributeTargets.Constructor | + AttributeTargets.Method | + AttributeTargets.Property | + AttributeTargets.Field | + AttributeTargets.Event | + AttributeTargets.Interface | + AttributeTargets.Delegate, Inherited = false)] + internal sealed class ExperimentalAttribute : Attribute + { + /// + /// Initializes a new instance of the class, specifying the ID that the compiler will use + /// when reporting a use of the API the attribute applies to. + /// + /// The ID that the compiler will use when reporting a use of the API the attribute applies to. + public ExperimentalAttribute(string diagnosticId) + { + DiagnosticId = diagnosticId; + } + + /// + /// Gets the ID that the compiler will use when reporting a use of the API the attribute applies to. + /// + /// The unique diagnostic ID. + /// + /// The diagnostic ID is shown in build output for warnings and errors. + /// This property represents the unique ID that can be used to suppress the warnings or errors, if needed. + /// + public string DiagnosticId { get; } + + /// + /// Gets or sets the URL for corresponding documentation. + /// The API accepts a format string instead of an actual URL, creating a generic URL that includes the diagnostic ID. + /// + /// The format string that represents a URL to corresponding documentation. + /// An example format string is https://contoso.com/obsoletion-warnings/{0}. + public string? UrlFormat { get; set; } + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/IReadOnlySet.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/IReadOnlySet.cs new file mode 100755 index 00000000000..23d96d1b0c0 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/IReadOnlySet.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(System.Collections.Generic.IReadOnlySet<>))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Collections.Generic; + +/// +/// Provides a readonly abstraction of a set. +/// +/// The type of elements in the set. +internal interface IReadOnlySet : IReadOnlyCollection +{ + /// + /// Determines if the set contains a specific item + /// + /// The item to check if the set contains. + /// if found; otherwise . + bool Contains(T item); + + /// + /// Determines whether the current set is a proper (strict) subset of a specified collection. + /// + /// The collection to compare to the current set. + /// if the current set is a proper subset of other; otherwise . + /// other is . + bool IsProperSubsetOf(IEnumerable other); + + /// + /// Determines whether the current set is a proper (strict) superset of a specified collection. + /// + /// The collection to compare to the current set. + /// if the collection is a proper superset of other; otherwise . + /// other is . + bool IsProperSupersetOf(IEnumerable other); + + /// + /// Determine whether the current set is a subset of a specified collection. + /// + /// The collection to compare to the current set. + /// if the current set is a subset of other; otherwise . + /// other is . + bool IsSubsetOf(IEnumerable other); + + /// + /// Determine whether the current set is a super set of a specified collection. + /// + /// The collection to compare to the current set + /// if the current set is a subset of other; otherwise . + /// other is . + bool IsSupersetOf(IEnumerable other); + + /// + /// Determines whether the current set overlaps with the specified collection. + /// + /// The collection to compare to the current set. + /// if the current set and other share at least one common element; otherwise, . + /// other is . + bool Overlaps(IEnumerable other); + + /// + /// Determines whether the current set and the specified collection contain the same elements. + /// + /// The collection to compare to the current set. + /// if the current set is equal to other; otherwise, . + /// other is . + bool SetEquals(IEnumerable other); +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Index.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Index.cs new file mode 100755 index 00000000000..21489812989 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Index.cs @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Index))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +using System.Runtime.CompilerServices; + +namespace System +{ + /// Represent a type can be used to index a collection either from the start or the end. + /// + /// Index is used by the C# compiler to support the new index syntax + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; + /// int lastElement = someArray[^1]; // lastElement = 5 + /// + /// + internal readonly struct Index : IEquatable + { + private readonly int _value; + + /// Construct an Index using a value and indicating if the index is from the start or from the end. + /// The index value. it has to be zero or positive number. + /// Indicating if the index is from the start or from the end. + /// + /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Index(int value, bool fromEnd = false) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Non-negative number required."); + } + + if (fromEnd) + _value = ~value; + else + _value = value; + } + + // The following private constructors mainly created for perf reason to avoid the checks + private Index(int value) + { + _value = value; + } + + /// Create an Index pointing at first element. + public static Index Start => new Index(0); + + /// Create an Index pointing at beyond last element. + public static Index End => new Index(~0); + + /// Create an Index from the start at the position indicated by the value. + /// The index value from the start. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromStart(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Non-negative number required."); + } + + return new Index(value); + } + + /// Create an Index from the end at the position indicated by the value. + /// The index value from the end. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromEnd(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Non-negative number required."); + } + + return new Index(~value); + } + + /// Returns the index value. + public int Value + { + get + { + if (_value < 0) + return ~_value; + else + return _value; + } + } + + /// Indicates whether the index is from the start or the end. + public bool IsFromEnd => _value < 0; + + /// Calculate the offset from the start using the giving collection length. + /// The length of the collection that the Index will be used with. length has to be a positive value + /// + /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. + /// we don't validate either the returned offset is greater than the input length. + /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and + /// then used to index a collection will get out of range exception which will be same affect as the validation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetOffset(int length) + { + int offset = _value; + if (IsFromEnd) + { + // offset = length - (~value) + // offset = length + (~(~value) + 1) + // offset = length + value + 1 + + offset += length + 1; + } + return offset; + } + + /// Indicates whether the current Index object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value; + + /// Indicates whether the current Index object is equal to another Index object. + /// An object to compare with this object + public bool Equals(Index other) => _value == other._value; + + /// Returns the hash code for this instance. + public override int GetHashCode() => _value; + + /// Converts integer number to an Index. + public static implicit operator Index(int value) => FromStart(value); + + /// Converts the value of the current Index object to its equivalent string representation. + public override string ToString() + { + if (IsFromEnd) + return $"^{((uint)Value).ToString()}"; + + return ((uint)Value).ToString(); + } + } +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/InterpolatedStringHandlerArgumentAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/InterpolatedStringHandlerArgumentAttribute.cs new file mode 100755 index 00000000000..a8df29ce946 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/InterpolatedStringHandlerArgumentAttribute.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(InterpolatedStringHandlerArgumentAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +#pragma warning disable CA1019 // Add a public read-only property accessor for positional argument argument of Attribute + +namespace System.Runtime.CompilerServices +{ + /// Indicates which arguments to a method involving an interpolated string handler should be passed to that handler. + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute + { + /// Initializes a new instance of the class. + /// The name of the argument that should be passed to the handler. + /// may be used as the name of the receiver in an instance method. + public InterpolatedStringHandlerArgumentAttribute(string argument) => Arguments = new string[] { argument }; + /// Initializes a new instance of the class. + /// The names of the arguments that should be passed to the handler. + /// may be used as the name of the receiver in an instance method. + public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) => Arguments = arguments; + /// Gets the names of the arguments that should be passed to the handler. + /// may be used as the name of the receiver in an instance method. + public string[] Arguments { get; } + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/InterpolatedStringHandlerAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/InterpolatedStringHandlerAttribute.cs new file mode 100755 index 00000000000..1ac03f50fab --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/InterpolatedStringHandlerAttribute.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(InterpolatedStringHandlerAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Runtime.CompilerServices +{ + /// Indicates the attributed type is to be used as an interpolated string handler. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] + internal sealed class InterpolatedStringHandlerAttribute : Attribute + { + /// Initializes the . + public InterpolatedStringHandlerAttribute() { } + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/IsExternalInit.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/IsExternalInit.cs new file mode 100755 index 00000000000..cf6d665f0f4 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/IsExternalInit.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/218ef0f7776c2c20f6c594e3475b80f1fe2d7d08/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/IsExternalInit.cs + +#if NET6_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(IsExternalInit))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +using System.ComponentModel; + +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit + { + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/NonCopyableAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/NonCopyableAttribute.cs new file mode 100755 index 00000000000..a83373ef6a5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/NonCopyableAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; + +namespace Microsoft.CodeAnalysis; + +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.GenericParameter)] +internal sealed class NonCopyableAttribute : Attribute +{ +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/NonDefaultableAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/NonDefaultableAttribute.cs new file mode 100755 index 00000000000..bddbc3f3807 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/NonDefaultableAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; + +namespace Microsoft.CodeAnalysis; + +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.GenericParameter)] +internal sealed class NonDefaultableAttribute : Attribute +{ +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/NullableAttributes.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/NullableAttributes.cs new file mode 100755 index 00000000000..b6eefd30184 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/NullableAttributes.cs @@ -0,0 +1,153 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// This was copied from https://github.com/dotnet/runtime/blob/39b9607807f29e48cae4652cd74735182b31182e/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs +// and updated to have the scope of the attributes be internal. + +namespace System.Diagnostics.CodeAnalysis +{ +#if !NETCOREAPP + + /// Specifies that null is allowed as an input even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class AllowNullAttribute : Attribute { } + + /// Specifies that null is disallowed as an input even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class DisallowNullAttribute : Attribute { } + + /// Specifies that an output may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class MaybeNullAttribute : Attribute { } + + /// Specifies that an output will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class NotNullAttribute : Attribute { } + + /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class MaybeNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter may be null. + /// + public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class NotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that the output will be non-null if the named parameter is non-null. + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] + internal sealed class NotNullIfNotNullAttribute : Attribute + { + /// Initializes the attribute with the associated parameter name. + /// + /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. + /// + public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + + /// Gets the associated parameter name. + public string ParameterName { get; } + } + + /// Applied to a method that will never return under any circumstance. + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + internal sealed class DoesNotReturnAttribute : Attribute { } + + /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class DoesNotReturnIfAttribute : Attribute + { + /// Initializes the attribute with the specified parameter value. + /// + /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + /// the associated parameter matches this value. + /// + public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + + /// Gets the condition parameter value. + public bool ParameterValue { get; } + } + +#endif + +#if !NETCOREAPP + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullAttribute : Attribute + { + /// Initializes the attribute with a field or property member. + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullAttribute(string member) => Members = new[] { member }; + + /// Initializes the attribute with the list of field and property members. + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullAttribute(params string[] members) => Members = members; + + /// Gets field or property member names. + public string[] Members { get; } + } + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition and a field or property member. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = new[] { member }; + } + + /// Initializes the attribute with the specified return value condition and list of field and property members. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// Gets the return value condition. + public bool ReturnValue { get; } + + /// Gets field or property member names. + public string[] Members { get; } + } + +#endif +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Range.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Range.cs new file mode 100755 index 00000000000..1f4ac6e0bf5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/Range.cs @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if NET + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Range))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else +using System.Runtime.CompilerServices; + +namespace System +{ + /// Represent a range has start and end indexes. + /// + /// Range is used by the C# compiler to support the range syntax. + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; + /// int[] subArray1 = someArray[0..2]; // { 1, 2 } + /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } + /// + /// + internal readonly struct Range : IEquatable + { + /// Represent the inclusive start index of the Range. + public Index Start { get; } + + /// Represent the exclusive end index of the Range. + public Index End { get; } + + /// Construct a Range object using the start and end indexes. + /// Represent the inclusive start index of the range. + /// Represent the exclusive end index of the range. + public Range(Index start, Index end) + { + Start = start; + End = end; + } + + /// Indicates whether the current Range object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => + value is Range r && + r.Start.Equals(Start) && + r.End.Equals(End); + + /// Indicates whether the current Range object is equal to another Range object. + /// An object to compare with this object + public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); + + /// Returns the hash code for this instance. + public override int GetHashCode() + => unchecked(Start.GetHashCode() * (int)0xA5555529 + End.GetHashCode()); + + /// Converts the value of the current Range object to its equivalent string representation. + public override string ToString() + { + return $"{getFromEndSpecifier(Start)}{toString(Start)}..{getFromEndSpecifier(End)}{toString(End)}"; + + static string getFromEndSpecifier(Index index) => index.IsFromEnd ? "^" : string.Empty; + static string toString(Index index) => ((uint)index.Value).ToString(); + } + + /// Create a Range object starting from start index to the end of the collection. + public static Range StartAt(Index start) => new Range(start, Index.End); + + /// Create a Range object starting from first element in the collection to the end Index. + public static Range EndAt(Index end) => new Range(Index.Start, end); + + /// Create a Range object starting from first element to the end. + public static Range All => new Range(Index.Start, Index.End); + +#if !NO_VALUE_TUPLE // workaround for https://github.com/dotnet/roslyn/issues/78392 + + /// Calculate the start offset and length of range object using a collection length. + /// The length of the collection that the range will be used with. length has to be a positive value. + /// + /// For performance reason, we don't validate the input length parameter against negative values. + /// It is expected Range will be used with collections which always have non negative length/count. + /// We validate the range is inside the length scope though. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public (int Offset, int Length) GetOffsetAndLength(int length) + { + int start; + Index startIndex = Start; + if (startIndex.IsFromEnd) + start = length - startIndex.Value; + else + start = startIndex.Value; + + int end; + Index endIndex = End; + if (endIndex.IsFromEnd) + end = length - endIndex.Value; + else + end = endIndex.Value; + + if ((uint)end > (uint)length || (uint)start > (uint)end) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + return (start, end - start); + } +#endif + } +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/RequiredMemberAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/RequiredMemberAttribute.cs new file mode 100755 index 00000000000..7004bd75265 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/RequiredMemberAttribute.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/fdd104ec5e1d0d2aa24a6723995a98d0124f724b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RequiredMemberAttribute.cs + +#if NET8_0_OR_GREATER + +using System.Runtime.CompilerServices; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(RequiredMemberAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Runtime.CompilerServices +{ + /// Specifies that a type has required members or that a member is required. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + internal sealed class RequiredMemberAttribute : Attribute + { + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/SetsRequiredMembersAttribute.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/SetsRequiredMembersAttribute.cs new file mode 100755 index 00000000000..891d50f2859 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/SetsRequiredMembersAttribute.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// Copied from: +// https://github.com/dotnet/runtime/blob/fdd104ec5e1d0d2aa24a6723995a98d0124f724b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs + +#if NET8_0_OR_GREATER + +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API) +[assembly: TypeForwardedTo(typeof(SetsRequiredMembersAttribute))] +#pragma warning restore RS0016 // Add public types and members to the declared API + +#else + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Specifies that this constructor sets all required members for the current type, and callers + /// do not need to set any required members themselves. + /// + [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] + internal sealed class SetsRequiredMembersAttribute : Attribute + { + } +} + +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/microsoft.codeanalysis.contracts.5.0.0-1.25277.114.csproj b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/microsoft.codeanalysis.contracts.5.0.0-1.25277.114.csproj new file mode 100644 index 00000000000..715871ea63b --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/microsoft.codeanalysis.contracts.5.0.0-1.25277.114.csproj @@ -0,0 +1,25 @@ + + + + net8.0;net9.0;netstandard2.0 + 5.0.0-1.25277.114 + Microsoft.CodeAnalysis.Contracts + + + + + + + + + + + + + + + + + + + diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/microsoft.codeanalysis.contracts.nuspec b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/microsoft.codeanalysis.contracts.nuspec new file mode 100644 index 00000000000..a7233edcc6c --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.contracts/5.0.0-1.25277.114/microsoft.codeanalysis.contracts.nuspec @@ -0,0 +1,102 @@ + + + + Microsoft.CodeAnalysis.Contracts + 5.0.0-1.25277.114 + Microsoft + true + MIT + https://licenses.nuget.org/MIT + https://github.com/dotnet/roslyn + Package containing sources of Microsoft .NET Compiler Platform ("Roslyn") contract and polyfill types. + + + The source code included in this package is subject to arbitrary changes in future versions. + Updating a reference to this package to a newer version of the package may require changes in the referencing project. + No compatibility guarantees are provided. + + More details at https://aka.ms/roslyn-packages + This package was built from the source at https://github.com/dotnet/dotnet/commit/ddf39a1b4690fbe23aea79c78da67004a5c31094. + © Microsoft Corporation. All rights reserved. + Roslyn CodeAnalysis Compiler CSharp VB VisualBasic Parser Scanner Lexer Emit CodeGeneration Metadata IL Compilation Scripting Syntax Semantics + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/Icon.png b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/Icon.png new file mode 100755 index 00000000000..fb00ecf91e4 Binary files /dev/null and b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/Icon.png differ diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/ThirdPartyNotices.rtf b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/ThirdPartyNotices.rtf new file mode 100755 index 00000000000..1e4323dea60 Binary files /dev/null and b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/ThirdPartyNotices.rtf differ diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/build/Microsoft.CodeAnalysis.PooledObjects.targets b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/build/Microsoft.CodeAnalysis.PooledObjects.targets new file mode 100755 index 00000000000..34ba1e60c89 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/build/Microsoft.CodeAnalysis.PooledObjects.targets @@ -0,0 +1,19 @@ + + + + + <_PackageCompileItems Remove="@(_PackageCompileItems)"/> + <_PackageCompileItems Include="%(Compile.RootDir)%(Compile.Directory)" Condition="'%(Compile.NuGetPackageId)' == 'Microsoft.CodeAnalysis.PooledObjects'" /> + + + + <_PackageCompileItem>@(_PackageCompileItems) + <_PackageCompileItem Condition="'$(_PackageCompileItem)' != ''">$(_PackageCompileItem.Split(';')[0]) + + + + + + + diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/.editorconfig b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/.editorconfig new file mode 100755 index 00000000000..e10491047f5 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/.editorconfig @@ -0,0 +1,18 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +# We don't want any analyzer diagnostics to be reported for people consuming this as a source package. +dotnet_analyzer_diagnostic.severity = none + +generated_code = true + +# The above configurations don't apply to compiler warnings. Requiring all params to be documented +# is not something we require for this project, so suppressing it directly here. +dotnet_diagnostic.CS1573.severity = none + +# As above, we need to specifically disable compiler warnings that we don't want to break downstream +# builds +dotnet_diagnostic.IDE0005.severity = none \ No newline at end of file diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ArrayBuilder.Enumerator.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ArrayBuilder.Enumerator.cs new file mode 100755 index 00000000000..94bfba790f9 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ArrayBuilder.Enumerator.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.PooledObjects +{ + internal partial class ArrayBuilder + { + /// + /// struct enumerator used in foreach. + /// + internal struct Enumerator + { + private readonly ArrayBuilder _builder; + private int _index; + + public Enumerator(ArrayBuilder builder) + { + _builder = builder; + _index = -1; + } + + public readonly T Current + { + get + { + return _builder[_index]; + } + } + + public bool MoveNext() + { + _index++; + return _index < _builder.Count; + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ArrayBuilder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ArrayBuilder.cs new file mode 100755 index 00000000000..80ebb45f367 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ArrayBuilder.cs @@ -0,0 +1,981 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.PooledObjects +{ + [DebuggerDisplay("Count = {Count,nq}")] + [DebuggerTypeProxy(typeof(ArrayBuilder<>.DebuggerProxy))] + internal sealed partial class ArrayBuilder : IReadOnlyCollection, IReadOnlyList, ICollection +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + , IPooled +#endif + { + /// + /// See for an explanation of this constant value. + /// + public const int PooledArrayLengthLimitExclusive = 128; + + #region DebuggerProxy + + private sealed class DebuggerProxy + { + private readonly ArrayBuilder _builder; + + public DebuggerProxy(ArrayBuilder builder) + { + _builder = builder; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public T[] A + { + get + { + var result = new T[_builder.Count]; + for (var i = 0; i < result.Length; i++) + { + result[i] = _builder[i]; + } + + return result; + } + } + } + + #endregion + + private readonly ImmutableArray.Builder _builder; + + private readonly ObjectPool>? _pool; + + public ArrayBuilder(int size) + { + _builder = ImmutableArray.CreateBuilder(size); + } + + public ArrayBuilder() + : this(8) + { } + + private ArrayBuilder(ObjectPool> pool) + : this() + { + _pool = pool; + } + + /// + /// Realizes the array. + /// + public ImmutableArray ToImmutable() + { + return _builder.ToImmutable(); + } + + /// + /// Realizes the array and clears the collection. + /// + public ImmutableArray ToImmutableAndClear() + { + ImmutableArray result; + if (Count == 0) + { + result = ImmutableArray.Empty; + } + else if (_builder.Capacity == Count) + { + result = _builder.MoveToImmutable(); + } + else + { + result = ToImmutable(); + Clear(); + } + + return result; + } + + public int Count + { + get + { + return _builder.Count; + } + set + { + _builder.Count = value; + } + } + + public int Capacity + { + get + { + return _builder.Capacity; + } + + set + { + _builder.Capacity = value; + } + } + + public T this[int index] + { + get + { + return _builder[index]; + } + + set + { + _builder[index] = value; + } + } + + public bool IsReadOnly + => false; + + public bool IsEmpty + => Count == 0; + + /// + /// Write to slot . + /// Fills in unallocated slots preceding the , if any. + /// + public void SetItem(int index, T value) + { + while (index > _builder.Count) + { + _builder.Add(default!); + } + + if (index == _builder.Count) + { + _builder.Add(value); + } + else + { + _builder[index] = value; + } + } + + public void Add(T item) + { + _builder.Add(item); + } + + public void Insert(int index, T item) + { + _builder.Insert(index, item); + } + + public void EnsureCapacity(int capacity) + { + if (_builder.Capacity < capacity) + { + _builder.Capacity = capacity; + } + } + + public void Clear() + { + _builder.Clear(); + } + + public bool Contains(T item) + { + return _builder.Contains(item); + } + + public int IndexOf(T item) + { + return _builder.IndexOf(item); + } + + public int IndexOf(T item, IEqualityComparer equalityComparer) + { + return _builder.IndexOf(item, 0, _builder.Count, equalityComparer); + } + + public int IndexOf(T item, int startIndex, int count) + { + return _builder.IndexOf(item, startIndex, count); + } + + public int FindIndex(Predicate match) + => FindIndex(0, this.Count, match); + + public int FindIndex(int startIndex, Predicate match) + => FindIndex(startIndex, this.Count - startIndex, match); + + public int FindIndex(int startIndex, int count, Predicate match) + { + var endIndex = startIndex + count; + for (var i = startIndex; i < endIndex; i++) + { + if (match(_builder[i])) + { + return i; + } + } + + return -1; + } + + public int FindIndex(Func match, TArg arg) + => FindIndex(0, Count, match, arg); + + public int FindIndex(int startIndex, Func match, TArg arg) + => FindIndex(startIndex, Count - startIndex, match, arg); + + public int FindIndex(int startIndex, int count, Func match, TArg arg) + { + var endIndex = startIndex + count; + for (var i = startIndex; i < endIndex; i++) + { + if (match(_builder[i], arg)) + { + return i; + } + } + + return -1; + } + + public bool Remove(T element) + { + return _builder.Remove(element); + } + + public void RemoveAt(int index) + { + _builder.RemoveAt(index); + } + + public void RemoveRange(int index, int length) + { + _builder.RemoveRange(index, length); + } + + public void RemoveLast() + { + _builder.RemoveAt(_builder.Count - 1); + } + + public void RemoveAll(Predicate match) + { + _builder.RemoveAll(match); + } + + public void RemoveAll(Func match, TArg arg) + { + var i = 0; + for (var j = 0; j < _builder.Count; j++) + { + if (!match(_builder[j], arg)) + { + if (i != j) + { + _builder[i] = _builder[j]; + } + + i++; + } + } + + Clip(i); + } + + public void RemoveAll(Func match, TArg arg) + { + var i = 0; + for (var j = 0; j < _builder.Count; j++) + { + if (!match(_builder[j], i, arg)) + { + if (i != j) + { + _builder[i] = _builder[j]; + } + + i++; + } + } + + Clip(i); + } + + public void ReverseContents() + { + _builder.Reverse(); + } + + public void Sort() + { + _builder.Sort(); + } + + public void Sort(IComparer? comparer) + { + _builder.Sort(comparer); + } + + public void Sort(Comparison compare) + { + if (this.Count <= 1) + return; + + Sort(Comparer.Create(compare)); + } + + public void Sort(int startIndex, IComparer comparer) + { + _builder.Sort(startIndex, _builder.Count - startIndex, comparer); + } + + public T[] ToArray() + { + return _builder.ToArray(); + } + + public void CopyTo(T[] array, int start) + { + _builder.CopyTo(array, start); + } + + public T Last() + => _builder[_builder.Count - 1]; + + internal T? LastOrDefault() + => Count == 0 ? default : Last(); + + public T First() + { + return _builder[0]; + } + + public bool Any() + { + return _builder.Count > 0; + } + + /// + /// Realizes the array. + /// + public ImmutableArray ToImmutableOrNull() + { + if (Count == 0) + { + return default; + } + + return this.ToImmutable(); + } + + /// + /// Realizes the array, downcasting each element to a derived type. + /// + public ImmutableArray ToDowncastedImmutable() + where U : T + { + if (Count == 0) + { + return ImmutableArray.Empty; + } + + var tmp = ArrayBuilder.GetInstance(Count); + foreach (var i in this) + { + tmp.Add((U)i!); + } + + return tmp.ToImmutableAndFree(); + } + + public ImmutableArray ToDowncastedImmutableAndFree() where U : T + { + var result = ToDowncastedImmutable(); + this.Free(); + return result; + } + + /// + /// Realizes the array and disposes the builder in one operation. + /// + public ImmutableArray ToImmutableAndFree() + { + // This is mostly the same as 'MoveToImmutable', but avoids delegating to that method since 'Free' contains + // fast paths to avoid caling 'Clear' in some cases. + ImmutableArray result; + if (Count == 0) + { + result = ImmutableArray.Empty; + } + else if (_builder.Capacity == Count) + { + result = _builder.MoveToImmutable(); + } + else + { + result = ToImmutable(); + } + + this.Free(); + return result; + } + + public T[] ToArrayAndFree() + { + var result = this.ToArray(); + this.Free(); + return result; + } + + public void FreeAll(Func?> getNested) + { + foreach (var item in this) + { + getNested(item)?.FreeAll(getNested); + } + Free(); + } + + #region Poolable + + // To implement Poolable, you need two things: + // 1) Expose Freeing primitive. + public void Free() + { + var pool = _pool; + if (pool != null) + { + // According to the statistics of a C# compiler self-build, the most commonly used builder size is 0. (808003 uses). + // The distant second is the Count == 1 (455619), then 2 (106362) ... + // After about 50 (just 67) we have a long tail of infrequently used builder sizes. + // However we have builders with size up to 50K (just one such thing) + // + // We do not want to retain (potentially indefinitely) very large builders + // while the chance that we will need their size is diminishingly small. + // It makes sense to constrain the size to some "not too small" number. + // Overall perf does not seem to be very sensitive to this number, so I picked 128 as a limit. + if (_builder.Capacity < PooledArrayLengthLimitExclusive) + { + if (this.Count != 0) + { + this.Clear(); + } + + pool.Free(this); + return; + } + else + { + pool.ForgetTrackedObject(this); + } + } + } + + // 2) Expose the pool or the way to create a pool or the way to get an instance. + // for now we will expose both and figure which way works better + private static readonly ObjectPool> s_poolInstance = CreatePool(); + public static ArrayBuilder GetInstance() + { + var builder = s_poolInstance.Allocate(); + Debug.Assert(builder.Count == 0); + return builder; + } + + public static ArrayBuilder GetInstance(int capacity) + { + var builder = GetInstance(); + builder.EnsureCapacity(capacity); + return builder; + } + + public static ArrayBuilder GetInstance(int capacity, T fillWithValue) + { + var builder = GetInstance(); + builder.EnsureCapacity(capacity); + + for (var i = 0; i < capacity; i++) + { + builder.Add(fillWithValue); + } + + return builder; + } + + public static ObjectPool> CreatePool() + { + return CreatePool(128); // we rarely need more than 10 + } + + public static ObjectPool> CreatePool(int size) + { + ObjectPool>? pool = null; + pool = new ObjectPool>(() => new ArrayBuilder(pool!), size); + return pool; + } + + #endregion + + public Enumerator GetEnumerator() + { + return new Enumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _builder.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return _builder.GetEnumerator(); + } + + internal Dictionary> ToDictionary(Func keySelector, IEqualityComparer? comparer = null) + where K : notnull + { + if (this.Count == 1) + { + var dictionary1 = new Dictionary>(1, comparer); + var value = this[0]; + dictionary1.Add(keySelector(value), ImmutableArray.Create(value)); + return dictionary1; + } + + if (this.Count == 0) + { + return new Dictionary>(comparer); + } + + // bucketize + // prevent reallocation. it may not have 'count' entries, but it won't have more. + var accumulator = new Dictionary>(Count, comparer); + for (var i = 0; i < Count; i++) + { + var item = this[i]; + var key = keySelector(item); + if (!accumulator.TryGetValue(key, out var bucket)) + { + bucket = ArrayBuilder.GetInstance(); + accumulator.Add(key, bucket); + } + + bucket.Add(item); + } + + var dictionary = new Dictionary>(accumulator.Count, comparer); + + // freeze + foreach (var pair in accumulator) + { + dictionary.Add(pair.Key, pair.Value.ToImmutableAndFree()); + } + + return dictionary; + } + + public void AddRange(ArrayBuilder items) + { + _builder.AddRange(items._builder); + } + + public void AddRange(ArrayBuilder items, Func selector) + { + foreach (var item in items) + { + _builder.Add(selector(item)); + } + } + + public void AddRange(ArrayBuilder items) where U : T + { + _builder.AddRange(items._builder); + } + + public void AddRange(ArrayBuilder items, int start, int length) where U : T + { + Debug.Assert(start >= 0 && length >= 0); + Debug.Assert(start + length <= items.Count); + for (int i = start, end = start + length; i < end; i++) + { + Add(items[i]); + } + } + + public void AddRange(ImmutableArray items) + { + _builder.AddRange(items); + } + + public void AddRange(ImmutableArray items, int length) + { + _builder.AddRange(items, length); + } + + public void AddRange(ImmutableArray items, int start, int length) + { + Debug.Assert(start >= 0 && length >= 0); + Debug.Assert(start + length <= items.Length); + for (int i = start, end = start + length; i < end; i++) + { + Add(items[i]); + } + } + + public void AddRange(ImmutableArray items) where S : class, T + { + AddRange(ImmutableArray.CastUp(items)); + } + + public void AddRange(T[] items, int start, int length) + { + Debug.Assert(start >= 0 && length >= 0); + Debug.Assert(start + length <= items.Length); + for (int i = start, end = start + length; i < end; i++) + { + Add(items[i]); + } + } + + public void AddRange(IEnumerable items) + { + _builder.AddRange(items); + } + + public void AddRange(params T[] items) + { + _builder.AddRange(items); + } + + public void AddRange(T[] items, int length) + { + _builder.AddRange(items, length); + } + + public void Clip(int limit) + { + Debug.Assert(limit <= Count); + _builder.Count = limit; + } + + public void ZeroInit(int count) + { + _builder.Clear(); + _builder.Count = count; + } + + public void AddMany(T item, int count) + { + EnsureCapacity(Count + count); + + for (var i = 0; i < count; i++) + { + Add(item); + } + } + + public void RemoveDuplicates() + { + var set = PooledHashSet.GetInstance(); + + var j = 0; + for (var i = 0; i < Count; i++) + { + if (set.Add(this[i])) + { + this[j] = this[i]; + j++; + } + } + + Clip(j); + set.Free(); + } + + public void SortAndRemoveDuplicates(IComparer? comparer = null) + { + if (Count <= 1) + { + return; + } + + comparer ??= Comparer.Default; + + Sort(comparer); + + int j = 0; + for (int i = 1; i < Count; i++) + { + if (comparer.Compare(this[j], this[i]) < 0) + { + j++; + this[j] = this[i]; + } + } + + Clip(j + 1); + } + + public ImmutableArray SelectDistinct(Func selector) + { + var result = ArrayBuilder.GetInstance(Count); + var set = PooledHashSet.GetInstance(); + + foreach (var item in this) + { + var selected = selector(item); + if (set.Add(selected)) + { + result.Add(selected); + } + } + + set.Free(); + return result.ToImmutableAndFree(); + } + + public bool Any(Func predicate) + { + foreach (var item in this) + { + if (predicate(item)) + { + return true; + } + } + return false; + } + + public bool Any(Func predicate, A arg) + { + foreach (var item in this) + { + if (predicate(item, arg)) + { + return true; + } + } + return false; + } + + public bool All(Func predicate) + { + foreach (var item in this) + { + if (!predicate(item)) + { + return false; + } + } + return true; + } + + public bool All(Func predicate, A arg) + { + foreach (var item in this) + { + if (!predicate(item, arg)) + { + return false; + } + } + return true; + } + + /// + /// Maps an array builder to immutable array. + /// + /// + /// The mapping delegate + /// If the items's length is 0, this will return an empty immutable array + public ImmutableArray SelectAsArray(Func map) + { + switch (Count) + { + case 0: + return []; + + case 1: + return [map(this[0])]; + + case 2: + return [map(this[0]), map(this[1])]; + + case 3: + return [map(this[0]), map(this[1]), map(this[2])]; + + case 4: + return [map(this[0]), map(this[1]), map(this[2]), map(this[3])]; + + default: + var builder = ArrayBuilder.GetInstance(Count); + foreach (var item in this) + { + builder.Add(map(item)); + } + + return builder.ToImmutableAndFree(); + } + } + + /// + /// Maps an array builder to immutable array. + /// + /// + /// + /// The mapping delegate + /// The extra input used by mapping delegate + /// If the items's length is 0, this will return an empty immutable array. + public ImmutableArray SelectAsArray(Func map, TArg arg) + { + switch (Count) + { + case 0: + return []; + + case 1: + return [map(this[0], arg)]; + + case 2: + return [map(this[0], arg), map(this[1], arg)]; + + case 3: + return [map(this[0], arg), map(this[1], arg), map(this[2], arg)]; + + case 4: + return [map(this[0], arg), map(this[1], arg), map(this[2], arg), map(this[3], arg)]; + + default: + var builder = ArrayBuilder.GetInstance(Count); + foreach (var item in this) + { + builder.Add(map(item, arg)); + } + + return builder.ToImmutableAndFree(); + } + } + + /// + /// Maps an array builder to immutable array. + /// + /// + /// + /// The mapping delegate + /// The extra input used by mapping delegate + /// If the items's length is 0, this will return an empty immutable array. + public ImmutableArray SelectAsArrayWithIndex(Func map, TArg arg) + { + switch (Count) + { + case 0: + return []; + + case 1: + return [map(this[0], 0, arg)]; + + case 2: + return [map(this[0], 0, arg), map(this[1], 1, arg)]; + + case 3: + return [map(this[0], 0, arg), map(this[1], 1, arg), map(this[2], 2, arg)]; + + case 4: + return [map(this[0], 0, arg), map(this[1], 1, arg), map(this[2], 2, arg), map(this[3], 3, arg)]; + + default: + var builder = ArrayBuilder.GetInstance(Count); + foreach (var item in this) + { + builder.Add(map(item, builder.Count, arg)); + } + + return builder.ToImmutableAndFree(); + } + } + + // The following extension methods allow an ArrayBuilder to be used as a stack. + // Note that the order of an IEnumerable from a List is from bottom to top of stack. An IEnumerable + // from the framework Stack is from top to bottom. + public void Push(T e) + => Add(e); + + public T Pop() + { + var e = Peek(); + RemoveAt(Count - 1); + return e; + } + + public bool TryPop([MaybeNullWhen(false)] out T result) + { + if (Count > 0) + { + result = Pop(); + return true; + } + + result = default; + return false; + } + + public T Peek() + => this[Count - 1]; + +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + + private static readonly ObjectPool> s_keepLargeInstancesPool = CreatePool(); + + public static PooledDisposer> GetInstance(out ArrayBuilder instance) + => GetInstance(discardLargeInstances: true, out instance); + + public static PooledDisposer> GetInstance(int capacity, out ArrayBuilder instance) + { + instance = GetInstance(capacity); + return new PooledDisposer>(instance); + } + + public static PooledDisposer> GetInstance(int capacity, T fillWithValue, out ArrayBuilder instance) + { + instance = GetInstance(capacity, fillWithValue); + return new PooledDisposer>(instance); + } + + public static PooledDisposer> GetInstance(bool discardLargeInstances, out ArrayBuilder instance) + { + // If we're discarding large instances (the default behavior), then just use the normal pool. If we're not, use + // a specific pool so that *other* normal callers don't accidentally get it and discard it. + instance = discardLargeInstances ? GetInstance() : s_keepLargeInstancesPool.Allocate(); + return new PooledDisposer>(instance, discardLargeInstances); + } + + void IPooled.Free(bool discardLargeInstances) + { + // If we're discarding large instances, use the default behavior (which already does that). Otherwise, always + // clear and free the instance back to its originating pool. + if (discardLargeInstances) + { + Free(); + } + else + { + this.Clear(); + _pool?.Free(this); + } + } + +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ArrayBuilderExtensions.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ArrayBuilderExtensions.cs new file mode 100755 index 00000000000..602e7df7b68 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ArrayBuilderExtensions.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.PooledObjects; + +/// +/// methods that can't be defined on the type itself. +/// +internal static class ArrayBuilderExtensions +{ + public static ImmutableArray ToImmutableOrEmptyAndFree(this ArrayBuilder? builder) + => builder?.ToImmutableAndFree() ?? []; + + public static void AddIfNotNull(this ArrayBuilder builder, T? value) + where T : struct + { + if (value != null) + { + builder.Add(value.Value); + } + } + + public static void AddIfNotNull(this ArrayBuilder builder, T? value) + where T : class + { + if (value != null) + { + builder.Add(value); + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/IPooled.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/IPooled.cs new file mode 100755 index 00000000000..db9243fce97 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/IPooled.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +namespace Microsoft.CodeAnalysis.PooledObjects; + +internal interface IPooled +{ + void Free(bool discardLargeInstances); +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ObjectPool`1.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ObjectPool`1.cs new file mode 100755 index 00000000000..66152356069 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/ObjectPool`1.cs @@ -0,0 +1,294 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +// define TRACE_LEAKS to get additional diagnostics that can lead to the leak sources. note: it will +// make everything about 2-3x slower +// +// #define TRACE_LEAKS + +// define DETECT_LEAKS to detect possible leaks +// #if DEBUG +// #define DETECT_LEAKS //for now always enable DETECT_LEAKS in debug. +// #endif + +using System; +using System.Diagnostics; +using System.Threading; + +#if DETECT_LEAKS +using System.Runtime.CompilerServices; +#endif + +namespace Microsoft.CodeAnalysis.PooledObjects +{ + /// + /// Generic implementation of object pooling pattern with predefined pool size limit. The main + /// purpose is that limited number of frequently used objects can be kept in the pool for + /// further recycling. + /// + /// Notes: + /// 1) it is not the goal to keep all returned objects. Pool is not meant for storage. If there + /// is no space in the pool, extra returned objects will be dropped. + /// + /// 2) it is implied that if object was obtained from a pool, the caller will return it back in + /// a relatively short time. Keeping checked out objects for long durations is ok, but + /// reduces usefulness of pooling. Just new up your own. + /// + /// Not returning objects to the pool in not detrimental to the pool's work, but is a bad practice. + /// Rationale: + /// If there is no intent for reusing the object, do not use pool - just use "new". + /// + internal class ObjectPool where T : class + { + [DebuggerDisplay("{Value,nq}")] + private struct Element + { + internal T? Value; + } + + /// + /// Not using System.Func{T} because this file is linked into the (debugger) Formatter, + /// which does not have that type (since it compiles against .NET 2.0). + /// + internal delegate T Factory(); + + // Storage for the pool objects. The first item is stored in a dedicated field because we + // expect to be able to satisfy most requests from it. + private T? _firstItem; + private readonly Element[] _items; + + // factory is stored for the lifetime of the pool. We will call this only when pool needs to + // expand. compared to "new T()", Func gives more flexibility to implementers and faster + // than "new T()". + private readonly Factory _factory; + + public readonly bool TrimOnFree; + +#if DETECT_LEAKS + private static readonly ConditionalWeakTable leakTrackers = new ConditionalWeakTable(); + + private class LeakTracker : IDisposable + { + private volatile bool disposed; + +#if TRACE_LEAKS + internal volatile object Trace = null; +#endif + + public void Dispose() + { + disposed = true; + GC.SuppressFinalize(this); + } + + private string GetTrace() + { +#if TRACE_LEAKS + return Trace == null ? "" : Trace.ToString(); +#else + return "Leak tracing information is disabled. Define TRACE_LEAKS on ObjectPool`1.cs to get more info \n"; +#endif + } + + ~LeakTracker() + { + if (!this.disposed && !Environment.HasShutdownStarted) + { + var trace = GetTrace(); + + // If you are seeing this message it means that object has been allocated from the pool + // and has not been returned back. This is not critical, but turns pool into rather + // inefficient kind of "new". + Debug.WriteLine($"TRACEOBJECTPOOLLEAKS_BEGIN\nPool detected potential leaking of {typeof(T)}. \n Location of the leak: \n {GetTrace()} TRACEOBJECTPOOLLEAKS_END"); + } + } + } +#endif + + internal ObjectPool(Factory factory, bool trimOnFree = true) + : this(factory, Environment.ProcessorCount * 2, trimOnFree) + { + } + + internal ObjectPool(Factory factory, int size, bool trimOnFree = true) + { + Debug.Assert(size >= 1); + _factory = factory; + _items = new Element[size - 1]; + TrimOnFree = trimOnFree; + } + + internal ObjectPool(Func, T> factory, int size) + { + Debug.Assert(size >= 1); + _factory = () => factory(this); + _items = new Element[size - 1]; + } + + private T CreateInstance() + { + var inst = _factory(); + return inst; + } + + /// + /// Produces an instance. + /// + /// + /// Search strategy is a simple linear probing which is chosen for it cache-friendliness. + /// Note that Free will try to store recycled objects close to the start thus statistically + /// reducing how far we will typically search. + /// + internal T Allocate() + { + // PERF: Examine the first element. If that fails, AllocateSlow will look at the remaining elements. + // Note that the initial read is optimistically not synchronized. That is intentional. + // We will interlock only when we have a candidate. in a worst case we may miss some + // recently returned objects. Not a big deal. + var inst = _firstItem; + if (inst == null || inst != Interlocked.CompareExchange(ref _firstItem, null, inst)) + { + inst = AllocateSlow(); + } + +#if DETECT_LEAKS + var tracker = new LeakTracker(); + leakTrackers.Add(inst, tracker); + +#if TRACE_LEAKS + var frame = CaptureStackTrace(); + tracker.Trace = frame; +#endif +#endif + return inst; + } + + private T AllocateSlow() + { + var items = _items; + + for (var i = 0; i < items.Length; i++) + { + // Note that the initial read is optimistically not synchronized. That is intentional. + // We will interlock only when we have a candidate. in a worst case we may miss some + // recently returned objects. Not a big deal. + var inst = items[i].Value; + if (inst != null) + { + if (inst == Interlocked.CompareExchange(ref items[i].Value, null, inst)) + { + return inst; + } + } + } + + return CreateInstance(); + } + + /// + /// Returns objects to the pool. + /// + /// + /// Search strategy is a simple linear probing which is chosen for it cache-friendliness. + /// Note that Free will try to store recycled objects close to the start thus statistically + /// reducing how far we will typically search in Allocate. + /// + internal void Free(T obj) + { + Validate(obj); + ForgetTrackedObject(obj); + + if (_firstItem == null) + { + // Intentionally not using interlocked here. + // In a worst case scenario two objects may be stored into same slot. + // It is very unlikely to happen and will only mean that one of the objects will get collected. + _firstItem = obj; + } + else + { + FreeSlow(obj); + } + } + + private void FreeSlow(T obj) + { + var items = _items; + for (var i = 0; i < items.Length; i++) + { + if (items[i].Value == null) + { + // Intentionally not using interlocked here. + // In a worst case scenario two objects may be stored into same slot. + // It is very unlikely to happen and will only mean that one of the objects will get collected. + items[i].Value = obj; + break; + } + } + } + + /// + /// Removes an object from leak tracking. + /// + /// This is called when an object is returned to the pool. It may also be explicitly + /// called if an object allocated from the pool is intentionally not being returned + /// to the pool. This can be of use with pooled arrays if the consumer wants to + /// return a larger array to the pool than was originally allocated. + /// + [Conditional("DEBUG")] + internal void ForgetTrackedObject(T old, T? replacement = null) + { +#if DETECT_LEAKS + LeakTracker tracker; + if (leakTrackers.TryGetValue(old, out tracker)) + { + tracker.Dispose(); + leakTrackers.Remove(old); + } + else + { + var trace = CaptureStackTrace(); + Debug.WriteLine($"TRACEOBJECTPOOLLEAKS_BEGIN\nObject of type {typeof(T)} was freed, but was not from pool. \n Callstack: \n {trace} TRACEOBJECTPOOLLEAKS_END"); + } + + if (replacement != null) + { + tracker = new LeakTracker(); + leakTrackers.Add(replacement, tracker); + } +#endif + } + +#if DETECT_LEAKS + private static Lazy _stackTraceType = new Lazy(() => Type.GetType("System.Diagnostics.StackTrace")); + + private static object CaptureStackTrace() + { + return Activator.CreateInstance(_stackTraceType.Value); + } +#endif + + [Conditional("DEBUG")] + private void Validate(object obj) + { + Debug.Assert(obj != null, "freeing null?"); + + Debug.Assert(_firstItem != obj, "freeing twice?"); + + var items = _items; + for (var i = 0; i < items.Length; i++) + { + var value = items[i].Value; + if (value == null) + { + return; + } + + Debug.Assert(value != obj, "freeing twice?"); + } + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledDelegates.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledDelegates.cs new file mode 100755 index 00000000000..f4c62b81662 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledDelegates.cs @@ -0,0 +1,457 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.PooledObjects +{ + /// + /// Provides pooled delegate instances to help avoid closure allocations for delegates that require a state argument + /// with APIs that do not provide appropriate overloads with state arguments. + /// + internal static class PooledDelegates + { + private static class DefaultDelegatePool + where T : class, new() + { + public static readonly ObjectPool Instance = new(() => new T(), 20); + } + + private static Releaser GetPooledDelegate(TUnboundDelegate unboundDelegate, TArg argument, out TBoundDelegate boundDelegate) + where TPooled : AbstractDelegateWithBoundArgument, new() + where TUnboundDelegate : Delegate + where TBoundDelegate : Delegate + { + var obj = DefaultDelegatePool.Instance.Allocate(); + obj.Initialize(unboundDelegate, argument); + boundDelegate = obj.BoundDelegate; + + return new Releaser(obj); + } + + /// + /// Gets an delegate, which calls with the specified + /// . The resulting may be called any number of times + /// until the returned is disposed. + /// + /// + /// The following example shows the use of a capturing delegate for a callback action that requires an + /// argument: + /// + /// + /// int x = 3; + /// RunWithActionCallback(() => this.DoSomething(x)); + /// + /// + /// The following example shows the use of a pooled delegate to avoid capturing allocations for the same + /// callback action: + /// + /// + /// int x = 3; + /// using var _ = GetPooledAction(arg => arg.self.DoSomething(arg.x), (self: this, x), out Action action); + /// RunWithActionCallback(action); + /// + /// + /// The type of argument to pass to . + /// The unbound action delegate. + /// The argument to pass to the unbound action delegate. + /// A delegate which calls with the specified + /// . + /// A disposable which returns the object to the delegate pool. + public static Releaser GetPooledAction(Action unboundAction, TArg argument, out Action boundAction) + => GetPooledDelegate, TArg, Action, Action>(unboundAction, argument, out boundAction); + + /// + /// Gets an delegate, which calls with the specified + /// . The resulting may be called any number of times + /// until the returned is disposed. + /// + /// + /// The following example shows the use of a capturing delegate for a callback action that requires an + /// argument: + /// + /// + /// int x = 3; + /// RunWithActionCallback(a => this.DoSomething(a, x)); + /// + /// + /// The following example shows the use of a pooled delegate to avoid capturing allocations for the same + /// callback action: + /// + /// + /// int x = 3; + /// using var _ = GetPooledAction((a, arg) => arg.self.DoSomething(a, arg.x), (self: this, x), out Action<int> action); + /// RunWithActionCallback(action); + /// + /// + /// The type of the first parameter of the bound action. + /// The type of argument to pass to . + /// The unbound action delegate. + /// The argument to pass to the unbound action delegate. + /// A delegate which calls with the specified + /// . + /// A disposable which returns the object to the delegate pool. + public static Releaser GetPooledAction(Action unboundAction, TArg argument, out Action boundAction) + => GetPooledDelegate, TArg, Action, Action>(unboundAction, argument, out boundAction); + + /// + /// Gets an delegate, which calls with the specified + /// . The resulting may be called any number of times + /// until the returned is disposed. + /// + /// + /// The following example shows the use of a capturing delegate for a callback action that requires an + /// argument: + /// + /// + /// int x = 3; + /// RunWithActionCallback((a, b) => this.DoSomething(a, b, x)); + /// + /// + /// The following example shows the use of a pooled delegate to avoid capturing allocations for the same + /// callback action: + /// + /// + /// int x = 3; + /// using var _ = GetPooledAction((a, b, arg) => arg.self.DoSomething(a, b, arg.x), (self: this, x), out Action<int, int> action); + /// RunWithActionCallback(action); + /// + /// + /// The type of the first parameter of the bound action. + /// The type of the second parameter of the bound action. + /// The type of argument to pass to . + /// The unbound action delegate. + /// The argument to pass to the unbound action delegate. + /// A delegate which calls with the specified + /// . + /// A disposable which returns the object to the delegate pool. + public static Releaser GetPooledAction(Action unboundAction, TArg argument, out Action boundAction) + => GetPooledDelegate, TArg, Action, Action>(unboundAction, argument, out boundAction); + + /// + /// Gets an delegate, which calls with the specified + /// . The resulting may be called any number of times + /// until the returned is disposed. + /// + /// + /// The following example shows the use of a capturing delegate for a callback action that requires an + /// argument: + /// + /// + /// int x = 3; + /// RunWithActionCallback((a, b, c) => this.DoSomething(a, b, c, x)); + /// + /// + /// The following example shows the use of a pooled delegate to avoid capturing allocations for the same + /// callback action: + /// + /// + /// int x = 3; + /// using var _ = GetPooledAction((a, b, c, arg) => arg.self.DoSomething(a, b, c, arg.x), (self: this, x), out Action<int, int, int> action); + /// RunWithActionCallback(action); + /// + /// + /// The type of the first parameter of the bound action. + /// The type of the second parameter of the bound action. + /// The type of the third parameter of the bound action. + /// The type of argument to pass to . + /// The unbound action delegate. + /// The argument to pass to the unbound action delegate. + /// A delegate which calls with the specified + /// . + /// A disposable which returns the object to the delegate pool. + public static Releaser GetPooledAction(Action unboundAction, TArg argument, out Action boundAction) + => GetPooledDelegate, TArg, Action, Action>(unboundAction, argument, out boundAction); + + /// + /// Gets a delegate, which calls with the + /// specified . The resulting may be called any + /// number of times until the returned is disposed. + /// + /// + /// The following example shows the use of a capturing delegate for a predicate that requires an + /// argument: + /// + /// + /// int x = 3; + /// RunWithPredicate(() => this.IsSomething(x)); + /// + /// + /// The following example shows the use of a pooled delegate to avoid capturing allocations for the same + /// predicate: + /// + /// + /// int x = 3; + /// using var _ = GetPooledFunction(arg => arg.self.IsSomething(arg.x), (self: this, x), out Func<bool> predicate); + /// RunWithPredicate(predicate); + /// + /// + /// The type of argument to pass to . + /// The type of the return value of the function. + /// The unbound function delegate. + /// The argument to pass to the unbound function delegate. + /// A delegate which calls with the specified + /// . + /// A disposable which returns the object to the delegate pool. + public static Releaser GetPooledFunction(Func unboundFunction, TArg argument, out Func boundFunction) + => GetPooledDelegate, TArg, Func, Func>(unboundFunction, argument, out boundFunction); + + /// + /// Equivalent to , + /// except typed such that it can be used to create a pooled . + /// + public static Releaser GetPooledCreateValueCallback( + Func unboundFunction, TArg argument, + out ConditionalWeakTable.CreateValueCallback boundFunction) where TKey : class where TValue : class + + { + return GetPooledDelegate, TArg, Func, ConditionalWeakTable.CreateValueCallback>(unboundFunction, argument, out boundFunction); + } + /// + /// Gets a delegate, which calls with the + /// specified . The resulting may be called any + /// number of times until the returned is disposed. + /// + /// + /// The following example shows the use of a capturing delegate for a predicate that requires an + /// argument: + /// + /// + /// int x = 3; + /// RunWithPredicate(a => this.IsSomething(a, x)); + /// + /// + /// The following example shows the use of a pooled delegate to avoid capturing allocations for the same + /// predicate: + /// + /// + /// int x = 3; + /// using var _ = GetPooledFunction((a, arg) => arg.self.IsSomething(a, arg.x), (self: this, x), out Func<int, bool> predicate); + /// RunWithPredicate(predicate); + /// + /// + /// The type of the first parameter of the bound function. + /// The type of argument to pass to . + /// The type of the return value of the function. + /// The unbound function delegate. + /// The argument to pass to the unbound function delegate. + /// A delegate which calls with the specified + /// . + /// A disposable which returns the object to the delegate pool. + public static Releaser GetPooledFunction(Func unboundFunction, TArg argument, out Func boundFunction) + => GetPooledDelegate, TArg, Func, Func>(unboundFunction, argument, out boundFunction); + + /// + /// Gets a delegate, which calls with the + /// specified . The resulting may be called any + /// number of times until the returned is disposed. + /// + /// + /// The following example shows the use of a capturing delegate for a predicate that requires an + /// argument: + /// + /// + /// int x = 3; + /// RunWithPredicate((a, b) => this.IsSomething(a, b, x)); + /// + /// + /// The following example shows the use of a pooled delegate to avoid capturing allocations for the same + /// predicate: + /// + /// + /// int x = 3; + /// using var _ = GetPooledFunction((a, b, arg) => arg.self.IsSomething(a, b, arg.x), (self: this, x), out Func<int, int, bool> predicate); + /// RunWithPredicate(predicate); + /// + /// + /// The type of the first parameter of the bound function. + /// The type of the second parameter of the bound function. + /// The type of argument to pass to . + /// The type of the return value of the function. + /// The unbound function delegate. + /// The argument to pass to the unbound function delegate. + /// A delegate which calls with the specified + /// . + /// A disposable which returns the object to the delegate pool. + public static Releaser GetPooledFunction(Func unboundFunction, TArg argument, out Func boundFunction) + => GetPooledDelegate, TArg, Func, Func>(unboundFunction, argument, out boundFunction); + + /// + /// Gets a delegate, which calls with the + /// specified . The resulting may be called any + /// number of times until the returned is disposed. + /// + /// + /// The following example shows the use of a capturing delegate for a predicate that requires an + /// argument: + /// + /// + /// int x = 3; + /// RunWithPredicate((a, b, c) => this.IsSomething(a, b, c, x)); + /// + /// + /// The following example shows the use of a pooled delegate to avoid capturing allocations for the same + /// predicate: + /// + /// + /// int x = 3; + /// using var _ = GetPooledFunction((a, b, c, arg) => arg.self.IsSomething(a, b, c, arg.x), (self: this, x), out Func<int, int, int, bool> predicate); + /// RunWithPredicate(predicate); + /// + /// + /// The type of the first parameter of the bound function. + /// The type of the second parameter of the bound function. + /// The type of the third parameter of the bound function. + /// The type of argument to pass to . + /// The type of the return value of the function. + /// The unbound function delegate. + /// The argument to pass to the unbound function delegate. + /// A delegate which calls with the specified + /// . + /// A disposable which returns the object to the delegate pool. + public static Releaser GetPooledFunction(Func unboundFunction, TArg argument, out Func boundFunction) + => GetPooledDelegate, TArg, Func, Func>(unboundFunction, argument, out boundFunction); + + /// + /// A releaser for a pooled delegate. + /// + /// + /// This type is intended for use as the resource of a using statement. When used in this manner, + /// should not be called explicitly. + /// + /// If used without a using statement, calling is optional. If the call is + /// omitted, the object will not be returned to the pool. The behavior of this type if is + /// called multiple times is undefined. + /// + [NonCopyable] + public readonly struct Releaser : IDisposable + { + private readonly Poolable _pooledObject; + + internal Releaser(Poolable pooledObject) + { + _pooledObject = pooledObject; + } + + public void Dispose() => _pooledObject.ClearAndFree(); + } + + internal abstract class Poolable + { + public abstract void ClearAndFree(); + } + + private abstract class AbstractDelegateWithBoundArgument : Poolable + where TSelf : AbstractDelegateWithBoundArgument, new() + where TUnboundDelegate : Delegate + where TBoundDelegate : Delegate + { + protected AbstractDelegateWithBoundArgument() + { + BoundDelegate = Bind(); + + UnboundDelegate = null!; + Argument = default!; + } + + public TBoundDelegate BoundDelegate { get; } + + public TUnboundDelegate UnboundDelegate { get; private set; } + public TArg Argument { get; private set; } + + public void Initialize(TUnboundDelegate unboundDelegate, TArg argument) + { + UnboundDelegate = unboundDelegate; + Argument = argument; + } + + public sealed override void ClearAndFree() + { + Argument = default!; + UnboundDelegate = null!; + DefaultDelegatePool.Instance.Free((TSelf)this); + } + + protected abstract TBoundDelegate Bind(); + } + + private sealed class ActionWithBoundArgument + : AbstractDelegateWithBoundArgument, TArg, Action, Action> + { + protected override Action Bind() + => () => UnboundDelegate(Argument); + } + + private sealed class ActionWithBoundArgument + : AbstractDelegateWithBoundArgument, TArg, Action, Action> + { + protected override Action Bind() + => arg1 => UnboundDelegate(arg1, Argument); + } + + private sealed class ActionWithBoundArgument + : AbstractDelegateWithBoundArgument, TArg, Action, Action> + { + protected override Action Bind() + => (arg1, arg2) => UnboundDelegate(arg1, arg2, Argument); + } + + private sealed class ActionWithBoundArgument + : AbstractDelegateWithBoundArgument, TArg, Action, Action> + { + protected override Action Bind() + => (arg1, arg2, arg3) => UnboundDelegate(arg1, arg2, arg3, Argument); + } + + private sealed class FuncWithBoundArgument + : AbstractDelegateWithBoundArgument, TArg, Func, Func> + { + protected override Func Bind() + => () => UnboundDelegate(Argument); + } + + private sealed class CreateValueCallbackWithBoundArgument + : AbstractDelegateWithBoundArgument< + CreateValueCallbackWithBoundArgument, + TArg, + Func, + ConditionalWeakTable.CreateValueCallback> + where TKey : class + where TValue : class + { + protected override ConditionalWeakTable.CreateValueCallback Bind() + => key => UnboundDelegate(key, Argument); + } + + private sealed class FuncWithBoundArgument + : AbstractDelegateWithBoundArgument, TArg, Func, Func> + { + protected override Func Bind() + => arg1 => UnboundDelegate(arg1, Argument); + } + + private sealed class FuncWithBoundArgument + : AbstractDelegateWithBoundArgument, TArg, Func, Func> + { + protected override Func Bind() + => (arg1, arg2) => UnboundDelegate(arg1, arg2, Argument); + } + + private sealed class FuncWithBoundArgument + : AbstractDelegateWithBoundArgument, TArg, Func, Func> + { + protected override Func Bind() + => (arg1, arg2, arg3) => UnboundDelegate(arg1, arg2, arg3, Argument); + } + + [AttributeUsage(AttributeTargets.Struct)] + private sealed class NonCopyableAttribute : Attribute + { + } + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledDictionary.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledDictionary.cs new file mode 100755 index 00000000000..c62b029a2db --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledDictionary.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.PooledObjects +{ + // Dictionary that can be recycled via an object pool + // NOTE: these dictionaries always have the default comparer. + internal sealed partial class PooledDictionary : Dictionary +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + , IPooled +#endif + where K : notnull + { + private readonly ObjectPool> _pool; + + private PooledDictionary(ObjectPool> pool, IEqualityComparer keyComparer) + : base(keyComparer) + { + _pool = pool; + } + + public ImmutableDictionary ToImmutableDictionaryAndFree() + { + var result = this.ToImmutableDictionary(this.Comparer); + this.Free(); + return result; + } + + public ImmutableDictionary ToImmutableDictionary() => this.ToImmutableDictionary(this.Comparer); + + public void Free() + { + this.Clear(); + _pool?.Free(this); + } + + // global pool + private static readonly ObjectPool> s_poolInstance = CreatePool(EqualityComparer.Default); + + // if someone needs to create a pool; + public static ObjectPool> CreatePool(IEqualityComparer keyComparer) + { + ObjectPool>? pool = null; + pool = new ObjectPool>(() => new PooledDictionary(pool!, keyComparer), 128); + return pool; + } + + public static PooledDictionary GetInstance() + { + var instance = s_poolInstance.Allocate(); + Debug.Assert(instance.Count == 0); + return instance; + } + +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + public static PooledDisposer> GetInstance(out PooledDictionary instance) + { + instance = GetInstance(); + return new PooledDisposer>(instance); + } + + // Nothing special to do here. + void IPooled.Free(bool discardLargeInstance) + => this.Free(); +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledDisposer.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledDisposer.cs new file mode 100755 index 00000000000..416eb6fc717 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledDisposer.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER +using System; + +namespace Microsoft.CodeAnalysis.PooledObjects; + +internal readonly partial struct PooledDisposer( + TPoolable instance, + bool discardLargeInstances = true) : IDisposable + where TPoolable : class, IPooled +{ + void IDisposable.Dispose() + => instance?.Free(discardLargeInstances); +} +#endif diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledHashSet.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledHashSet.cs new file mode 100755 index 00000000000..95617c5ad40 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledHashSet.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.PooledObjects +{ + // HashSet that can be recycled via an object pool + // NOTE: these HashSets always have the default comparer. + internal sealed partial class PooledHashSet : HashSet +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + , IPooled +#endif + { + private readonly ObjectPool> _pool; + + private PooledHashSet(ObjectPool> pool, IEqualityComparer equalityComparer) : + base(equalityComparer) + { + _pool = pool; + } + + public void Free() + { + this.Clear(); + _pool?.Free(this); + } + + // global pool + private static readonly ObjectPool> s_poolInstance = CreatePool(EqualityComparer.Default); + + // if someone needs to create a pool; + public static ObjectPool> CreatePool(IEqualityComparer equalityComparer) + { + ObjectPool>? pool = null; + pool = new ObjectPool>(() => new PooledHashSet(pool!, equalityComparer), 128); + return pool; + } + + public static PooledHashSet GetInstance() + { + var instance = s_poolInstance.Allocate(); + Debug.Assert(instance.Count == 0); + return instance; + } + +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + public static PooledDisposer> GetInstance(out PooledHashSet instance) + { + instance = GetInstance(); + return new PooledDisposer>(instance); + } + + // Nothing special to do here. + void IPooled.Free(bool discardLargeInstance) + => this.Free(); +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledStringBuilder.cs b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledStringBuilder.cs new file mode 100755 index 00000000000..673f8ca8140 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/contentFiles/cs/netstandard2.0/PooledStringBuilder.cs @@ -0,0 +1,135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Diagnostics; +using System.Text; + +namespace Microsoft.CodeAnalysis.PooledObjects +{ + /// + /// The usage is: + /// var inst = PooledStringBuilder.GetInstance(); + /// var sb = inst.builder; + /// ... Do Stuff... + /// ... sb.ToString() ... + /// inst.Free(); + /// + internal sealed partial class PooledStringBuilder +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + : IPooled +#endif + { + public readonly StringBuilder Builder = new(); + private readonly ObjectPool _pool; + + private PooledStringBuilder(ObjectPool pool) + { + Debug.Assert(pool != null); + _pool = pool!; + } + + public int Length + { + get { return this.Builder.Length; } + } + + public void Free() + { + var builder = this.Builder; + + // do not store builders that are too large. + if (builder.Capacity <= 1024) + { + builder.Clear(); + _pool.Free(this); + } + else + { + _pool.ForgetTrackedObject(this); + } + } + + [System.Obsolete("Consider calling ToStringAndFree instead.")] + public new string ToString() + { + return this.Builder.ToString(); + } + + public string ToStringAndFree() + { + var result = this.Builder.ToString(); + this.Free(); + + return result; + } + + public string ToStringAndFree(int startIndex, int length) + { + var result = this.Builder.ToString(startIndex, length); + this.Free(); + + return result; + } + + // global pool + private static readonly ObjectPool s_poolInstance = CreatePool(); + + // if someone needs to create a private pool; + /// + /// If someone need to create a private pool + /// + /// The size of the pool. + public static ObjectPool CreatePool(int size = 32) + { + ObjectPool? pool = null; + pool = new ObjectPool(() => new PooledStringBuilder(pool!), size); + return pool; + } + + public static PooledStringBuilder GetInstance() + { + var builder = s_poolInstance.Allocate(); + Debug.Assert(builder.Builder.Length == 0); + return builder; + } + + public static implicit operator StringBuilder(PooledStringBuilder obj) + { + return obj.Builder; + } + +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + private static readonly ObjectPool s_keepLargeInstancesPool = CreatePool(); + + public static PooledDisposer GetInstance(out StringBuilder instance) + => GetInstance(discardLargeInstances: true, out instance); + + public static PooledDisposer GetInstance(bool discardLargeInstances, out StringBuilder instance) + { + // If we're discarding large instances (the default behavior), then just use the normal pool. If we're not, use + // a specific pool so that *other* normal callers don't accidentally get it and discard it. + var pooledInstance = discardLargeInstances ? GetInstance() : s_keepLargeInstancesPool.Allocate(); + instance = pooledInstance; + return new PooledDisposer(pooledInstance, discardLargeInstances); + } + + void IPooled.Free(bool discardLargeInstances) + { + // If we're discarding large instances, use the default behavior (which already does that). Otherwise, always + // clear and free the instance back to its originating pool. + if (discardLargeInstances) + { + Free(); + } + else + { + this.Builder.Clear(); + _pool.Free(this); + } + } +#endif + } +} diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/microsoft.codeanalysis.pooledobjects.5.0.0-1.25277.114.csproj b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/microsoft.codeanalysis.pooledobjects.5.0.0-1.25277.114.csproj new file mode 100644 index 00000000000..886a75c1590 --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/microsoft.codeanalysis.pooledobjects.5.0.0-1.25277.114.csproj @@ -0,0 +1,17 @@ + + + + netstandard2.0 + 5.0.0-1.25277.114 + Microsoft.CodeAnalysis.PooledObjects + + + + + + + + + + + diff --git a/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/microsoft.codeanalysis.pooledobjects.nuspec b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/microsoft.codeanalysis.pooledobjects.nuspec new file mode 100644 index 00000000000..824e6e9e5bb --- /dev/null +++ b/src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.pooledobjects/5.0.0-1.25277.114/microsoft.codeanalysis.pooledobjects.nuspec @@ -0,0 +1,47 @@ + + + + Microsoft.CodeAnalysis.PooledObjects + 5.0.0-1.25277.114 + Microsoft + true + MIT + https://licenses.nuget.org/MIT + https://github.com/dotnet/roslyn + Package containing sources of Microsoft .NET Compiler Platform ("Roslyn") pooled objects. + + + The source code included in this package is subject to arbitrary changes in future versions. + Updating a reference to this package to a newer version of the package may require changes in the referencing project. + No compatibility guarantees are provided. + + More details at https://aka.ms/roslyn-packages + This package was built from the source at https://github.com/dotnet/dotnet/commit/ddf39a1b4690fbe23aea79c78da67004a5c31094. + © Microsoft Corporation. All rights reserved. + Roslyn CodeAnalysis Compiler CSharp VB VisualBasic Parser Scanner Lexer Emit CodeGeneration Metadata IL Compilation Scripting Syntax Semantics + true + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/source-manifest.json b/src/source-manifest.json index d3d733969c8..bfbb343af61 100644 --- a/src/source-manifest.json +++ b/src/source-manifest.json @@ -7,10 +7,10 @@ "commitSha": "4e526204e83e615efe8eb5743be7fbccfa4e492a" }, { - "barId": 275017, + "barId": 275303, "path": "aspnetcore", "remoteUri": "https://github.com/dotnet/aspnetcore", - "commitSha": "f905bebf6206d90192c66e84993963f2f8a506c4" + "commitSha": "9d4270cd93259b2ad6740bd8bb8315615ce93c94" }, { "barId": 273742, @@ -19,10 +19,10 @@ "commitSha": "95da703c5b2c85bf4c81b92c1ea1994c7de4970f" }, { - "barId": 274651, + "barId": 275338, "path": "command-line-api", "remoteUri": "https://github.com/dotnet/command-line-api", - "commitSha": "12473cd29fac1b9070c71ed8f5a43cada6872905" + "commitSha": "dbc3781d3398b69cd9ffe24f60a7b77110bdadbf" }, { "barId": 274234, @@ -31,16 +31,16 @@ "commitSha": "227da60247996ce95c272cdb5941163c669224e8" }, { - "barId": 275020, + "barId": 275333, "path": "diagnostics", "remoteUri": "https://github.com/dotnet/diagnostics", - "commitSha": "c3c57bbd7ce6950087b2e99be7a1a1170cf94923" + "commitSha": "15863918a40fc31d0498ca5f1b8a5f7f7ada113a" }, { - "barId": 274910, + "barId": 275325, "path": "efcore", "remoteUri": "https://github.com/dotnet/efcore", - "commitSha": "fa310bbb8fb21987d6b0916faa01beacc104a3cf" + "commitSha": "bc5def338228c7ec5ab5d46f6e9042439270f438" }, { "barId": 274251, @@ -67,16 +67,16 @@ "commitSha": "772ee13d2bafaa1414d90dbfbd77e0941115ef19" }, { - "barId": 274804, + "barId": 275165, "path": "razor", "remoteUri": "https://github.com/dotnet/razor", - "commitSha": "ce330d020d1686e80f5ed4aec2e66f12c4f505b5" + "commitSha": "88d10f21004784390b5e220607bd4fa6ebfe1301" }, { - "barId": 274992, + "barId": 275167, "path": "roslyn", "remoteUri": "https://github.com/dotnet/roslyn", - "commitSha": "d3571ef089ef13c74ea786dce8ef615916a097cd" + "commitSha": "c1794aa58db74f27cd6bc7afc1b1d72b713f393b" }, { "barId": 273951, @@ -85,10 +85,10 @@ "commitSha": "714a51c57430dab50b67e5b468016288f5f7b0bd" }, { - "barId": 275054, + "barId": 275332, "path": "runtime", "remoteUri": "https://github.com/dotnet/runtime", - "commitSha": "9c0555e89d91149226cfade4a395e02b8d9401ff" + "commitSha": "6d7ba3656fa078fb17e68b4e31dc9fd9ff9868da" }, { "barId": 273704, @@ -103,10 +103,10 @@ "commitSha": "1414d33c86e760d6635a838a45da0308ff3d53c9" }, { - "barId": 275117, + "barId": 275454, "path": "source-build-reference-packages", "remoteUri": "https://github.com/dotnet/source-build-reference-packages", - "commitSha": "9f13ec67aeca9a84458549b440c1b0e33df71b44" + "commitSha": "e66cb9556591cff76527ba15386357bc2f463c7c" }, { "barId": 274866, @@ -121,16 +121,16 @@ "commitSha": "66c6797a1e9a9346d5f6de3f9edaecad6e4350d0" }, { - "barId": 274065, + "barId": 275177, "path": "templating", "remoteUri": "https://github.com/dotnet/templating", - "commitSha": "57150459685ad38272234d96c17036c2cd2f3b96" + "commitSha": "43d52c423e7ed37cf59a01629f9bace5c6bf6f96" }, { - "barId": 272429, + "barId": 275283, "path": "vstest", "remoteUri": "https://github.com/microsoft/vstest", - "commitSha": "cdcfb7f5c163d7b7a555b129522c3b868f73e92c" + "commitSha": "8b102963a8cce7809a6956fe0a6df5cb93b2447a" }, { "barId": 273947, @@ -139,16 +139,16 @@ "commitSha": "7890fbb7f086ae12b11ca85499b18f460c9090dd" }, { - "barId": 274987, + "barId": 275281, "path": "winforms", "remoteUri": "https://github.com/dotnet/winforms", - "commitSha": "d5b62a713f569a578805301a2bc77e7dfe60b36d" + "commitSha": "6dd129e422c9b14dc835e669688247386bef2f95" }, { - "barId": 274919, + "barId": 275192, "path": "wpf", "remoteUri": "https://github.com/dotnet/wpf", - "commitSha": "46685670c98a9e003ca98df637f68092d3b2cb65" + "commitSha": "900946a8e06533fd7ea8909d91b0c879a7c1f9be" }, { "barId": 274010, diff --git a/src/templating/eng/Version.Details.xml b/src/templating/eng/Version.Details.xml index 6149d98c1bc..0739db91bad 100644 --- a/src/templating/eng/Version.Details.xml +++ b/src/templating/eng/Version.Details.xml @@ -1,16 +1,16 @@ - + - + https://github.com/dotnet/dotnet - eaa19c281d34580a8168cff9ce1e7337da8bfe4f + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - eaa19c281d34580a8168cff9ce1e7337da8bfe4f + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 diff --git a/src/templating/eng/Versions.props b/src/templating/eng/Versions.props index 8899b047c4e..cfad649c188 100644 --- a/src/templating/eng/Versions.props +++ b/src/templating/eng/Versions.props @@ -15,7 +15,7 @@ 9.0.3 - 2.0.0-beta6.25351.106 + 2.0.0-beta7.25363.101 9.0.3 9.0.3 9.0.3 diff --git a/src/templating/global.json b/src/templating/global.json index eed21e61148..2a7fe81c5c9 100644 --- a/src/templating/global.json +++ b/src/templating/global.json @@ -1,8 +1,18 @@ { + "sdk": { + "version": "10.0.100-preview.7.25322.101", + "allowPrerelease": true, + "rollForward": "latestFeature", + "paths": [ + ".dotnet", + "$host$" + ], + "errorMessage": "The required .NET SDK wasn't found. Please run ./eng/common/dotnet.cmd/sh to install it." + }, "tools": { - "dotnet": "10.0.100-preview.6.25315.102" + "dotnet": "10.0.100-preview.7.25322.101" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25351.106" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25363.101" } } diff --git a/src/templating/tools/Microsoft.TemplateEngine.Authoring.CLI/Program.cs b/src/templating/tools/Microsoft.TemplateEngine.Authoring.CLI/Program.cs index 00a3597b35d..8656226e120 100644 --- a/src/templating/tools/Microsoft.TemplateEngine.Authoring.CLI/Program.cs +++ b/src/templating/tools/Microsoft.TemplateEngine.Authoring.CLI/Program.cs @@ -16,10 +16,7 @@ internal static Task Main(string[] args) rootCommand.Subcommands.Add(new VerifyCommand()); rootCommand.Subcommands.Add(new ValidateCommand()); - return rootCommand.Parse(args, new CommandLineConfiguration(rootCommand) - { - EnablePosixBundling = false, - }).InvokeAsync(); + return rootCommand.Parse(args, new() { EnablePosixBundling = false }).InvokeAsync(); } } } diff --git a/src/vstest/.github/dependabot.yml b/src/vstest/.github/dependabot.yml new file mode 100644 index 00000000000..a1ef8b6a84a --- /dev/null +++ b/src/vstest/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "dotnet-sdk" + directory: "/" + schedule: + interval: "weekly" + day: "wednesday" + ignore: + - dependency-name: "*" + update-types: + - "version-update:semver-major" + - "version-update:semver-minor" diff --git a/src/vstest/Directory.Build.props b/src/vstest/Directory.Build.props index 51ef037d2e2..f8aef037989 100644 --- a/src/vstest/Directory.Build.props +++ b/src/vstest/Directory.Build.props @@ -15,17 +15,6 @@ - - 17.10.0 - - $(TPVersionPrefix)-dev 15.0.0 @@ -147,6 +136,8 @@ MSTest $(TestRunnerAdditionalArguments) --filter "TestCategory!=Windows&TestCategory!=Windows-Review" + + false diff --git a/src/vstest/azure-pipelines.yml b/src/vstest/azure-pipelines.yml index 16723ccbc2f..541b35ce346 100644 --- a/src/vstest/azure-pipelines.yml +++ b/src/vstest/azure-pipelines.yml @@ -112,6 +112,7 @@ stages: -nobl -integrationTest -performanceTest + /bl:$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Test.binlog name: Test displayName: Test diff --git a/src/vstest/docs/contribute.md b/src/vstest/docs/contribute.md index 2a5100be9d0..05ba93c560e 100644 --- a/src/vstest/docs/contribute.md +++ b/src/vstest/docs/contribute.md @@ -147,7 +147,7 @@ default, `Debug` configuration is run. If you want to run a particular test. Eg: Test Name that contains Blame in Acceptance test ```shell -> test.cmd -p accept -f net451 -filter blame +> .\test.cmd -bl -c release /p:TestRunnerAdditionalArguments="'--filter Blame'" -Integration ``` ## Deployment diff --git a/src/vstest/dotnet.config b/src/vstest/dotnet.config new file mode 100644 index 00000000000..da0410e32d5 --- /dev/null +++ b/src/vstest/dotnet.config @@ -0,0 +1,2 @@ +[dotnet.test.runner] +name = "Microsoft.Testing.Platform" diff --git a/src/vstest/eng/Version.Details.xml b/src/vstest/eng/Version.Details.xml index 7a86e9ff834..185bd6fa6ec 100644 --- a/src/vstest/eng/Version.Details.xml +++ b/src/vstest/eng/Version.Details.xml @@ -2,9 +2,9 @@ - + https://dev.azure.com/devdiv/DevDiv/_git/vs-code-coverage - 414b8035705ca246a1b7331eab02a656b0dc3706 + b3c8a0e7de26919a4efd2a347133522dca5b8ee6 https://github.com/dotnet/dotnet @@ -27,9 +27,9 @@ - + https://github.com/dotnet/arcade - 0d52a8b262d35fa2fde84e398cb2e791b8454bd2 + 4e526204e83e615efe8eb5743be7fbccfa4e492a https://github.com/dotnet/symreader-converter diff --git a/src/vstest/eng/Versions.props b/src/vstest/eng/Versions.props index d00f73e8a71..62571e2c450 100644 --- a/src/vstest/eng/Versions.props +++ b/src/vstest/eng/Versions.props @@ -13,7 +13,7 @@ from appending +, which breaks DTAAgent. --> false - 17.15.0 + 18.0.0 preview @@ -51,13 +51,13 @@ 0.2.631904 6.0.2 6.0.0 - 17.12.0 - 17.14.3-preview.25164.1 + 18.0.0-beta.25364.2 + 17.15.0-preview.25354.5 - 17.13.35723.115 + 18.0.0-preview-1-10811-208 $(MicrosoftVisualStudioDiagnosticsUtilitiesVersion) 17.13.39960 17.13.24 @@ -69,8 +69,9 @@ 8.0.0 4.5.5 8.0.0 - 17.10.0-preview-2-34602-162 - 17.10.0-preview-2-34602-162 + + 18.0.0-preview-1-10811-208 + 18.0.0-preview-1-10811-208 17.12.35519.223 5.0.0 6.1.0 @@ -78,13 +79,14 @@ 8.1.0 + 1.7.2 4.16.1 17.9.0 - 3.4.3 - 3.4.3 + 3.9.3 + 3.9.3 1.0.3-preview 2.4.2 2.4.5 @@ -98,8 +100,8 @@ These versions need to be "statically" readable because we read this file as xml in our build and tests. --> - [3.4.3] - [3.4.3] + [3.9.3] + [3.9.3] [3.3.1] [2.2.10] [2.2.10] diff --git a/src/vstest/eng/common/CIBuild.cmd b/src/vstest/eng/common/CIBuild.cmd index 56c2f25ac22..ac1f72bf94e 100644 --- a/src/vstest/eng/common/CIBuild.cmd +++ b/src/vstest/eng/common/CIBuild.cmd @@ -1,2 +1,2 @@ @echo off -powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0Build.ps1""" -restore -build -test -sign -pack -publish -ci %*" \ No newline at end of file +powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0Build.ps1""" -restore -build -test -sign -pack -publish -ci %*" diff --git a/src/vstest/eng/common/build.ps1 b/src/vstest/eng/common/build.ps1 index 438f9920c43..8cfee107e7a 100644 --- a/src/vstest/eng/common/build.ps1 +++ b/src/vstest/eng/common/build.ps1 @@ -7,6 +7,7 @@ Param( [string] $msbuildEngine = $null, [bool] $warnAsError = $true, [bool] $nodeReuse = $true, + [switch] $buildCheck = $false, [switch][Alias('r')]$restore, [switch] $deployDeps, [switch][Alias('b')]$build, @@ -20,6 +21,7 @@ Param( [switch] $publish, [switch] $clean, [switch][Alias('pb')]$productBuild, + [switch]$fromVMR, [switch][Alias('bl')]$binaryLog, [switch][Alias('nobl')]$excludeCIBinarylog, [switch] $ci, @@ -71,6 +73,9 @@ function Print-Usage() { Write-Host " -msbuildEngine Msbuild engine to use to run build ('dotnet', 'vs', or unspecified)." Write-Host " -excludePrereleaseVS Set to exclude build engines in prerelease versions of Visual Studio" Write-Host " -nativeToolsOnMachine Sets the native tools on machine environment variable (indicating that the script should use native tools on machine)" + Write-Host " -nodeReuse Sets nodereuse msbuild parameter ('true' or 'false')" + Write-Host " -buildCheck Sets /check msbuild parameter" + Write-Host " -fromVMR Set when building from within the VMR" Write-Host "" Write-Host "Command line arguments not listed above are passed thru to msbuild." @@ -97,6 +102,7 @@ function Build { $bl = if ($binaryLog) { '/bl:' + (Join-Path $LogDir 'Build.binlog') } else { '' } $platformArg = if ($platform) { "/p:Platform=$platform" } else { '' } + $check = if ($buildCheck) { '/check' } else { '' } if ($projects) { # Re-assign properties to a new variable because PowerShell doesn't let us append properties directly for unclear reasons. @@ -113,6 +119,7 @@ function Build { MSBuild $toolsetBuildProj ` $bl ` $platformArg ` + $check ` /p:Configuration=$configuration ` /p:RepoRoot=$RepoRoot ` /p:Restore=$restore ` @@ -122,11 +129,13 @@ function Build { /p:Deploy=$deploy ` /p:Test=$test ` /p:Pack=$pack ` - /p:DotNetBuildRepo=$productBuild ` + /p:DotNetBuild=$productBuild ` + /p:DotNetBuildFromVMR=$fromVMR ` /p:IntegrationTest=$integrationTest ` /p:PerformanceTest=$performanceTest ` /p:Sign=$sign ` /p:Publish=$publish ` + /p:RestoreStaticGraphEnableBinaryLogger=$binaryLog ` @properties } diff --git a/src/vstest/eng/common/build.sh b/src/vstest/eng/common/build.sh index ac1ee8620cd..9767bb411a4 100755 --- a/src/vstest/eng/common/build.sh +++ b/src/vstest/eng/common/build.sh @@ -42,6 +42,8 @@ usage() echo " --prepareMachine Prepare machine for CI run, clean up processes after build" echo " --nodeReuse Sets nodereuse msbuild parameter ('true' or 'false')" echo " --warnAsError Sets warnaserror msbuild parameter ('true' or 'false')" + echo " --buildCheck Sets /check msbuild parameter" + echo " --fromVMR Set when building from within the VMR" echo "" echo "Command line arguments not listed above are passed thru to msbuild." echo "Arguments can also be passed in with a single hyphen." @@ -63,6 +65,7 @@ restore=false build=false source_build=false product_build=false +from_vmr=false rebuild=false test=false integration_test=false @@ -76,6 +79,7 @@ clean=false warn_as_error=true node_reuse=true +build_check=false binary_log=false exclude_ci_binary_log=false pipelines_log=false @@ -87,7 +91,7 @@ verbosity='minimal' runtime_source_feed='' runtime_source_feed_key='' -properties='' +properties=() while [[ $# > 0 ]]; do opt="$(echo "${1/#--/-}" | tr "[:upper:]" "[:lower:]")" case "$opt" in @@ -127,19 +131,22 @@ while [[ $# > 0 ]]; do -pack) pack=true ;; - -sourcebuild|-sb) + -sourcebuild|-source-build|-sb) build=true source_build=true product_build=true restore=true pack=true ;; - -productBuild|-pb) + -productbuild|-product-build|-pb) build=true product_build=true restore=true pack=true ;; + -fromvmr|-from-vmr) + from_vmr=true + ;; -test|-t) test=true ;; @@ -173,6 +180,9 @@ while [[ $# > 0 ]]; do node_reuse=$2 shift ;; + -buildcheck) + build_check=true + ;; -runtimesourcefeed) runtime_source_feed=$2 shift @@ -182,7 +192,7 @@ while [[ $# > 0 ]]; do shift ;; *) - properties="$properties $1" + properties+=("$1") ;; esac @@ -216,7 +226,7 @@ function Build { InitializeCustomToolset if [[ ! -z "$projects" ]]; then - properties="$properties /p:Projects=$projects" + properties+=("/p:Projects=$projects") fi local bl="" @@ -224,15 +234,21 @@ function Build { bl="/bl:\"$log_dir/Build.binlog\"" fi + local check="" + if [[ "$build_check" == true ]]; then + check="/check" + fi + MSBuild $_InitializeToolset \ $bl \ + $check \ /p:Configuration=$configuration \ /p:RepoRoot="$repo_root" \ /p:Restore=$restore \ /p:Build=$build \ - /p:DotNetBuildRepo=$product_build \ - /p:ArcadeBuildFromSource=$source_build \ + /p:DotNetBuild=$product_build \ /p:DotNetBuildSourceOnly=$source_build \ + /p:DotNetBuildFromVMR=$from_vmr \ /p:Rebuild=$rebuild \ /p:Test=$test \ /p:Pack=$pack \ @@ -240,7 +256,8 @@ function Build { /p:PerformanceTest=$performance_test \ /p:Sign=$sign \ /p:Publish=$publish \ - $properties + /p:RestoreStaticGraphEnableBinaryLogger=$binary_log \ + ${properties[@]+"${properties[@]}"} ExitWithExitCode 0 } diff --git a/src/vstest/eng/common/cibuild.sh b/src/vstest/eng/common/cibuild.sh index 1a02c0dec8f..66e3b0ac61c 100644 --- a/src/vstest/eng/common/cibuild.sh +++ b/src/vstest/eng/common/cibuild.sh @@ -13,4 +13,4 @@ while [[ -h $source ]]; do done scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" -. "$scriptroot/build.sh" --restore --build --test --pack --publish --ci $@ \ No newline at end of file +. "$scriptroot/build.sh" --restore --build --test --pack --publish --ci $@ diff --git a/src/vstest/eng/common/core-templates/job/job.yml b/src/vstest/eng/common/core-templates/job/job.yml index ba53ebfbd51..6badecba7bc 100644 --- a/src/vstest/eng/common/core-templates/job/job.yml +++ b/src/vstest/eng/common/core-templates/job/job.yml @@ -19,10 +19,10 @@ parameters: # publishing defaults artifacts: '' enableMicrobuild: false + enableMicrobuildForMacAndLinux: false enablePublishBuildArtifacts: false enablePublishBuildAssets: false enablePublishTestResults: false - enablePublishUsingPipelines: false enableBuildRetry: false mergeTestResults: false testRunTitle: '' @@ -73,9 +73,6 @@ jobs: - ${{ 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 @@ -127,18 +124,11 @@ jobs: - ${{ 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)' + - template: /eng/common/core-templates/steps/install-microbuild.yml + parameters: + enableMicrobuild: ${{ parameters.enableMicrobuild }} + enableMicrobuildForMacAndLinux: ${{ parameters.enableMicrobuildForMacAndLinux }} 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 @@ -154,27 +144,15 @@ jobs: - ${{ 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')) + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - template: /eng/common/core-templates/steps/cleanup-microbuild.yml + parameters: + enableMicrobuild: ${{ parameters.enableMicrobuild }} + enableMicrobuildForMacAndLinux: ${{ parameters.enableMicrobuildForMacAndLinux }} continueOnError: ${{ parameters.continueOnError }} - env: - TeamName: $(_TeamName) # Publish test results - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: diff --git a/src/vstest/eng/common/core-templates/job/onelocbuild.yml b/src/vstest/eng/common/core-templates/job/onelocbuild.yml index 00feec8ebbc..8034815f421 100644 --- a/src/vstest/eng/common/core-templates/job/onelocbuild.yml +++ b/src/vstest/eng/common/core-templates/job/onelocbuild.yml @@ -86,8 +86,7 @@ jobs: isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} ${{ if eq(parameters.CreatePr, true) }}: isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - isShouldReusePrSelected: ${{ parameters.ReusePr }} + isShouldReusePrSelected: ${{ parameters.ReusePr }} packageSourceAuth: patAuth patVariable: ${{ parameters.CeapexPat }} ${{ if eq(parameters.RepoType, 'gitHub') }}: @@ -118,4 +117,4 @@ jobs: pathToPublish: '$(Build.SourcesDirectory)/eng/Localize/' publishLocation: Container artifactName: Loc - condition: ${{ parameters.condition }} \ No newline at end of file + condition: ${{ parameters.condition }} diff --git a/src/vstest/eng/common/core-templates/job/publish-build-assets.yml b/src/vstest/eng/common/core-templates/job/publish-build-assets.yml index 3d3356e3196..d5303229c97 100644 --- a/src/vstest/eng/common/core-templates/job/publish-build-assets.yml +++ b/src/vstest/eng/common/core-templates/job/publish-build-assets.yml @@ -20,9 +20,6 @@ parameters: # 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 @@ -32,6 +29,15 @@ parameters: is1ESPipeline: '' + # Optional: 🌤️ or not the build has assets it wants to publish to BAR + isAssetlessBuild: false + + # Optional, publishing version + publishingVersion: 3 + + # Optional: A minimatch pattern for the asset manifests to publish to BAR + assetManifestsPattern: '*/manifests/**/*.xml' + jobs: - job: Asset_Registry_Publish @@ -75,15 +81,33 @@ jobs: - 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 }} + + - ${{ if eq(parameters.isAssetlessBuild, 'false') }}: + - ${{ if eq(parameters.publishingVersion, 3) }}: + - task: DownloadPipelineArtifact@2 + displayName: Download Asset Manifests + inputs: + artifactName: AssetManifests + targetPath: '$(Build.StagingDirectory)/AssetManifests' + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + - ${{ if eq(parameters.publishingVersion, 4) }}: + - task: DownloadPipelineArtifact@2 + displayName: Download V4 asset manifests + inputs: + itemPattern: '*/manifests/**/*.xml' + targetPath: '$(Build.StagingDirectory)/AllAssetManifests' + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + - task: CopyFiles@2 + displayName: Copy V4 asset manifests to AssetManifests + inputs: + SourceFolder: '$(Build.StagingDirectory)/AllAssetManifests' + Contents: ${{ parameters.assetManifestsPattern }} + TargetFolder: '$(Build.StagingDirectory)/AssetManifests' + flattenFolders: true + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} - task: NuGetAuthenticate@1 @@ -95,9 +119,9 @@ jobs: scriptLocation: scriptPath scriptPath: $(Build.SourcesDirectory)/eng/common/sdk-task.ps1 arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet - /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' + /p:ManifestsPath='$(Build.StagingDirectory)/AssetManifests' + /p:IsAssetlessBuild=${{ parameters.isAssetlessBuild }} /p:MaestroApiEndpoint=https://maestro.dot.net - /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} /p:OfficialBuildId=$(Build.BuildNumber) condition: ${{ parameters.condition }} continueOnError: ${{ parameters.continueOnError }} @@ -120,6 +144,17 @@ jobs: Copy-Item -Path $symbolExclusionfile -Destination "$(Build.StagingDirectory)/ReleaseConfigs" } + - ${{ if eq(parameters.publishingVersion, 4) }}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + targetPath: '$(Build.ArtifactStagingDirectory)/MergedManifest.xml' + artifactName: AssetManifests + displayName: 'Publish Merged Manifest' + retryCountOnTaskFailure: 10 # for any logs being locked + sbomEnabled: false # we don't need SBOM for logs + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} @@ -129,7 +164,7 @@ jobs: publishLocation: Container artifactName: ReleaseConfigs - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: + - ${{ if or(eq(parameters.publishAssetsImmediately, 'true'), eq(parameters.isAssetlessBuild, 'true')) }}: - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml parameters: BARBuildId: ${{ parameters.BARBuildId }} @@ -150,6 +185,7 @@ jobs: -WaitPublishingFinish true -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + -SkipAssetsPublishing '${{ parameters.isAssetlessBuild }}' - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - template: /eng/common/core-templates/steps/publish-logs.yml diff --git a/src/vstest/eng/common/core-templates/job/source-build.yml b/src/vstest/eng/common/core-templates/job/source-build.yml index d47f09d58fd..d805d5faeb9 100644 --- a/src/vstest/eng/common/core-templates/job/source-build.yml +++ b/src/vstest/eng/common/core-templates/job/source-build.yml @@ -12,9 +12,10 @@ parameters: # 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 + # portableBuild: 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. + # linux-x64), and compiling against distro-provided packages rather than portable ones. The + # default is portable mode. # skipPublishValidation: false # Disables publishing validation. By default, a check is performed to ensure no packages are # published by source-build. diff --git a/src/vstest/eng/common/core-templates/job/source-index-stage1.yml b/src/vstest/eng/common/core-templates/job/source-index-stage1.yml index 8b833332b3e..30530359a5d 100644 --- a/src/vstest/eng/common/core-templates/job/source-index-stage1.yml +++ b/src/vstest/eng/common/core-templates/job/source-index-stage1.yml @@ -1,8 +1,5 @@ parameters: runAsPublic: false - sourceIndexUploadPackageVersion: 2.0.0-20250425.2 - sourceIndexProcessBinlogPackageVersion: 1.0.1-20250425.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 @@ -16,12 +13,6 @@ jobs: 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 @@ -34,12 +25,10 @@ jobs: pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: name: $(DncEngPublicBuildPool) - image: 1es-windows-2022-open - os: windows + image: windows.vs2022.amd64.open ${{ if eq(variables['System.TeamProject'], 'internal') }}: name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows + image: windows.vs2022.amd64 steps: - ${{ if eq(parameters.is1ESPipeline, '') }}: @@ -47,35 +36,9 @@ jobs: - ${{ 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 + - template: /eng/common/core-templates/steps/source-index-stage1-publish.yml + parameters: + binLogPath: ${{ parameters.binLogPath }} \ No newline at end of file diff --git a/src/vstest/eng/common/core-templates/jobs/codeql-build.yml b/src/vstest/eng/common/core-templates/jobs/codeql-build.yml index f2144252cc6..693b00b3704 100644 --- a/src/vstest/eng/common/core-templates/jobs/codeql-build.yml +++ b/src/vstest/eng/common/core-templates/jobs/codeql-build.yml @@ -15,7 +15,6 @@ jobs: enablePublishBuildArtifacts: false enablePublishTestResults: false enablePublishBuildAssets: false - enablePublishUsingPipelines: false enableTelemetry: true variables: diff --git a/src/vstest/eng/common/core-templates/jobs/jobs.yml b/src/vstest/eng/common/core-templates/jobs/jobs.yml index ea69be4341c..bf35b78faa6 100644 --- a/src/vstest/eng/common/core-templates/jobs/jobs.yml +++ b/src/vstest/eng/common/core-templates/jobs/jobs.yml @@ -5,9 +5,6 @@ parameters: # 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 @@ -30,6 +27,9 @@ parameters: # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. publishAssetsImmediately: false + # Optional: 🌤️ or not the build has assets it wants to publish to BAR + isAssetlessBuild: 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: '' @@ -96,7 +96,7 @@ jobs: ${{ 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, '')) }}: + - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, ''), eq(parameters.isAssetlessBuild, true)) }}: - template: ../job/publish-build-assets.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} @@ -112,8 +112,8 @@ jobs: - Source_Build_Complete runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} + publishAssetsImmediately: ${{ or(parameters.publishAssetsImmediately, parameters.isAssetlessBuild) }} + isAssetlessBuild: ${{ parameters.isAssetlessBuild }} enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} diff --git a/src/vstest/eng/common/core-templates/jobs/source-build.yml b/src/vstest/eng/common/core-templates/jobs/source-build.yml index a10ccfbee6d..df24c948ba1 100644 --- a/src/vstest/eng/common/core-templates/jobs/source-build.yml +++ b/src/vstest/eng/common/core-templates/jobs/source-build.yml @@ -14,7 +14,7 @@ parameters: # 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' + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream-10-amd64' # 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, diff --git a/src/vstest/eng/common/core-templates/post-build/post-build.yml b/src/vstest/eng/common/core-templates/post-build/post-build.yml index a8c0bd3b921..a151fd811e3 100644 --- a/src/vstest/eng/common/core-templates/post-build/post-build.yml +++ b/src/vstest/eng/common/core-templates/post-build/post-build.yml @@ -60,6 +60,11 @@ parameters: artifactNames: '' downloadArtifacts: true + - name: isAssetlessBuild + type: boolean + displayName: Is Assetless Build + default: false + # 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 @@ -188,9 +193,6 @@ stages: 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 @@ -320,3 +322,4 @@ stages: -RequireDefaultChannels ${{ parameters.requireDefaultChannels }} -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + -SkipAssetsPublishing '${{ parameters.isAssetlessBuild }}' diff --git a/src/vstest/eng/common/core-templates/steps/cleanup-microbuild.yml b/src/vstest/eng/common/core-templates/steps/cleanup-microbuild.yml new file mode 100644 index 00000000000..c0fdcd3379d --- /dev/null +++ b/src/vstest/eng/common/core-templates/steps/cleanup-microbuild.yml @@ -0,0 +1,28 @@ +parameters: + # Enable cleanup tasks for MicroBuild + enableMicrobuild: false + # Enable cleanup tasks for MicroBuild on Mac and Linux + # Will be ignored if 'enableMicrobuild' is false or 'Agent.Os' is 'Windows_NT' + enableMicrobuildForMacAndLinux: false + continueOnError: false + +steps: + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - task: MicroBuildCleanup@1 + displayName: Execute Microbuild cleanup tasks + condition: and( + always(), + or( + and( + eq(variables['Agent.Os'], 'Windows_NT'), + in(variables['_SignType'], 'real', 'test') + ), + and( + ${{ eq(parameters.enableMicrobuildForMacAndLinux, true) }}, + ne(variables['Agent.Os'], 'Windows_NT'), + eq(variables['_SignType'], 'real') + ) + )) + continueOnError: ${{ parameters.continueOnError }} + env: + TeamName: $(_TeamName) diff --git a/src/vstest/eng/common/core-templates/steps/generate-sbom.yml b/src/vstest/eng/common/core-templates/steps/generate-sbom.yml index 56a09009482..44a9636cdff 100644 --- a/src/vstest/eng/common/core-templates/steps/generate-sbom.yml +++ b/src/vstest/eng/common/core-templates/steps/generate-sbom.yml @@ -5,7 +5,7 @@ # IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. parameters: - PackageVersion: 9.0.0 + PackageVersion: 10.0.0 BuildDropPath: '$(Build.SourcesDirectory)/artifacts' PackageName: '.NET' ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom diff --git a/src/vstest/eng/common/core-templates/steps/get-delegation-sas.yml b/src/vstest/eng/common/core-templates/steps/get-delegation-sas.yml index 9db5617ea7d..d2901470a7f 100644 --- a/src/vstest/eng/common/core-templates/steps/get-delegation-sas.yml +++ b/src/vstest/eng/common/core-templates/steps/get-delegation-sas.yml @@ -31,16 +31,7 @@ steps: # Calculate the expiration of the SAS token and convert to UTC $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") - # Temporarily work around a helix issue where SAS tokens with / in them will cause incorrect downloads - # of correlation payloads. https://github.com/dotnet/dnceng/issues/3484 - $sas = "" - do { - $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 - } - } while($sas.IndexOf('/') -ne -1) + $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." diff --git a/src/vstest/eng/common/core-templates/steps/install-microbuild.yml b/src/vstest/eng/common/core-templates/steps/install-microbuild.yml new file mode 100644 index 00000000000..f3064a7834e --- /dev/null +++ b/src/vstest/eng/common/core-templates/steps/install-microbuild.yml @@ -0,0 +1,54 @@ +parameters: + # Enable install tasks for MicroBuild + enableMicrobuild: false + # Enable install tasks for MicroBuild on Mac and Linux + # Will be ignored if 'enableMicrobuild' is false or 'Agent.Os' is 'Windows_NT' + enableMicrobuildForMacAndLinux: false + # Location of the MicroBuild output folder + microBuildOutputFolder: '$(Build.SourcesDirectory)' + continueOnError: false + +steps: + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - ${{ if eq(parameters.enableMicrobuildForMacAndLinux, 'true') }}: + # Needed to download the MicroBuild plugin nupkgs on Mac and Linux when nuget.exe is unavailable + - task: UseDotNet@2 + displayName: Install .NET 8.0 SDK for MicroBuild Plugin + inputs: + packageType: sdk + version: 8.0.x + installationPath: ${{ parameters.microBuildOutputFolder }}/.dotnet + workingDirectory: ${{ parameters.microBuildOutputFolder }} + condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) + + - task: MicroBuildSigningPlugin@4 + displayName: Install MicroBuild plugin + inputs: + signType: $(_SignType) + zipSources: false + feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json + ${{ if and(eq(parameters.enableMicrobuildForMacAndLinux, 'true'), ne(variables['Agent.Os'], 'Windows_NT')) }}: + azureSubscription: 'MicroBuild Signing Task (DevDiv)' + useEsrpCli: true + ${{ elseif eq(variables['System.TeamProject'], 'DevDiv') }}: + ConnectedPMEServiceName: 6cc74545-d7b9-4050-9dfa-ebefcc8961ea + ${{ else }}: + ConnectedPMEServiceName: 248d384a-b39b-46e3-8ad5-c2c210d5e7ca + env: + TeamName: $(_TeamName) + MicroBuildOutputFolderOverride: ${{ parameters.microBuildOutputFolder }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + continueOnError: ${{ parameters.continueOnError }} + condition: and( + succeeded(), + or( + and( + eq(variables['Agent.Os'], 'Windows_NT'), + in(variables['_SignType'], 'real', 'test') + ), + and( + ${{ eq(parameters.enableMicrobuildForMacAndLinux, true) }}, + ne(variables['Agent.Os'], 'Windows_NT'), + eq(variables['_SignType'], 'real') + ) + )) diff --git a/src/vstest/eng/common/core-templates/steps/publish-logs.yml b/src/vstest/eng/common/core-templates/steps/publish-logs.yml index 80788c52319..de24d0087c5 100644 --- a/src/vstest/eng/common/core-templates/steps/publish-logs.yml +++ b/src/vstest/eng/common/core-templates/steps/publish-logs.yml @@ -34,7 +34,9 @@ steps: '$(akams-client-id)' '$(microsoft-symbol-server-pat)' '$(symweb-symbol-server-pat)' + '$(dnceng-symbol-server-pat)' '$(dn-bot-all-orgs-build-rw-code-rw)' + '$(System.AccessToken)' ${{parameters.CustomSensitiveDataList}} continueOnError: true condition: always() @@ -45,6 +47,7 @@ steps: SourceFolder: '$(Build.SourcesDirectory)/PostBuildLogs' Contents: '**' TargetFolder: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + condition: always() - template: /eng/common/core-templates/steps/publish-build-artifacts.yml parameters: diff --git a/src/vstest/eng/common/core-templates/steps/source-build.yml b/src/vstest/eng/common/core-templates/steps/source-build.yml index 37133b55b75..acf16ed3496 100644 --- a/src/vstest/eng/common/core-templates/steps/source-build.yml +++ b/src/vstest/eng/common/core-templates/steps/source-build.yml @@ -19,25 +19,12 @@ steps: 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)' + internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://ci.dot.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://ci.dot.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' fi buildConfig=Release @@ -46,85 +33,33 @@ steps: 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 + portableBuildArgs= + if [ '${{ parameters.platform.portableBuild }}' != '' ]; then + portableBuildArgs='/p:PortableBuild=${{ parameters.platform.portableBuild }}' fi ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ --configuration $buildConfig \ - --restore --build --pack $publishArgs -bl \ + --restore --build --pack -bl \ + --source-build \ ${{ parameters.platform.buildArguments }} \ - $officialBuildArgs \ $internalRuntimeDownloadArgs \ - $internalRestoreArgs \ $targetRidArgs \ - $runtimeOsArgs \ - $baseOsArgs \ - /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ - /p:ArcadeBuildFromSource=true \ - /p:DotNetBuildSourceOnly=true \ - /p:DotNetBuildRepo=true \ - /p:AssetManifestFileName=$assetManifestFileName + $portableBuildArgs \ 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' + targetPath: artifacts/log/${{ coalesce(variables._BuildConfig, 'Release') }} 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/src/vstest/eng/common/core-templates/steps/source-index-stage1-publish.yml b/src/vstest/eng/common/core-templates/steps/source-index-stage1-publish.yml new file mode 100644 index 00000000000..c2917c1efc1 --- /dev/null +++ b/src/vstest/eng/common/core-templates/steps/source-index-stage1-publish.yml @@ -0,0 +1,35 @@ +parameters: + sourceIndexUploadPackageVersion: 2.0.0-20250425.2 + sourceIndexProcessBinlogPackageVersion: 1.0.1-20250515.1 + sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json + binlogPath: artifacts/log/Debug/Build.binlog + +steps: +- task: UseDotNet@2 + displayName: "Source Index: Use .NET 9 SDK" + inputs: + packageType: sdk + version: 9.0.x + installationPath: $(Agent.TempDirectory)/dotnet + workingDirectory: $(Agent.TempDirectory) + +- script: | + $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version ${{parameters.sourceIndexProcessBinlogPackageVersion}} --add-source ${{parameters.SourceIndexPackageSource}} --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version ${{parameters.sourceIndexUploadPackageVersion}} --add-source ${{parameters.SourceIndexPackageSource}} --tool-path $(Agent.TempDirectory)/.source-index/tools + displayName: "Source Index: Download netsourceindex 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: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i ${{parameters.BinlogPath}} -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output + displayName: "Source Index: Process Binlog into indexable sln" + +- ${{ if and(ne(parameters.runAsPublic, 'true'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - task: AzureCLI@2 + displayName: "Source Index: Upload Source Index stage1 artifacts to Azure" + 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/src/vstest/eng/common/cross/arm64/tizen/tizen.patch b/src/vstest/eng/common/cross/arm64/tizen/tizen.patch index af7c8be0590..2cebc547382 100644 --- a/src/vstest/eng/common/cross/arm64/tizen/tizen.patch +++ b/src/vstest/eng/common/cross/arm64/tizen/tizen.patch @@ -5,5 +5,5 @@ diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so Use the shared library, but some functions are only in the static library, so try that secondarily. */ OUTPUT_FORMAT(elf64-littleaarch64) --GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /lib/ld-linux-aarch64.so.1 ) ) +-GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-aarch64.so.1 ) ) +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux-aarch64.so.1 ) ) diff --git a/src/vstest/eng/common/cross/armel/armel.jessie.patch b/src/vstest/eng/common/cross/armel/armel.jessie.patch deleted file mode 100644 index 2d261561935..00000000000 --- a/src/vstest/eng/common/cross/armel/armel.jessie.patch +++ /dev/null @@ -1,43 +0,0 @@ -diff -u -r a/usr/include/urcu/uatomic/generic.h b/usr/include/urcu/uatomic/generic.h ---- a/usr/include/urcu/uatomic/generic.h 2014-10-22 15:00:58.000000000 -0700 -+++ b/usr/include/urcu/uatomic/generic.h 2020-10-30 21:38:28.550000000 -0700 -@@ -69,10 +69,10 @@ - #endif - #ifdef UATOMIC_HAS_ATOMIC_SHORT - case 2: -- return __sync_val_compare_and_swap_2(addr, old, _new); -+ return __sync_val_compare_and_swap_2((uint16_t*) addr, old, _new); - #endif - case 4: -- return __sync_val_compare_and_swap_4(addr, old, _new); -+ return __sync_val_compare_and_swap_4((uint32_t*) addr, old, _new); - #if (CAA_BITS_PER_LONG == 64) - case 8: - return __sync_val_compare_and_swap_8(addr, old, _new); -@@ -109,7 +109,7 @@ - return; - #endif - case 4: -- __sync_and_and_fetch_4(addr, val); -+ __sync_and_and_fetch_4((uint32_t*) addr, val); - return; - #if (CAA_BITS_PER_LONG == 64) - case 8: -@@ -148,7 +148,7 @@ - return; - #endif - case 4: -- __sync_or_and_fetch_4(addr, val); -+ __sync_or_and_fetch_4((uint32_t*) addr, val); - return; - #if (CAA_BITS_PER_LONG == 64) - case 8: -@@ -187,7 +187,7 @@ - return __sync_add_and_fetch_2(addr, val); - #endif - case 4: -- return __sync_add_and_fetch_4(addr, val); -+ return __sync_add_and_fetch_4((uint32_t*) addr, val); - #if (CAA_BITS_PER_LONG == 64) - case 8: - return __sync_add_and_fetch_8(addr, val); diff --git a/src/vstest/eng/common/cross/build-android-rootfs.sh b/src/vstest/eng/common/cross/build-android-rootfs.sh index 7e9ba2b75ed..fbd8d80848a 100644 --- a/src/vstest/eng/common/cross/build-android-rootfs.sh +++ b/src/vstest/eng/common/cross/build-android-rootfs.sh @@ -6,10 +6,11 @@ usage() { echo "Creates a toolchain and sysroot used for cross-compiling for Android." echo - echo "Usage: $0 [BuildArch] [ApiLevel]" + echo "Usage: $0 [BuildArch] [ApiLevel] [--ndk NDKVersion]" 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 "NDKVersion is the version of Android NDK. The default is r21. See https://developer.android.com/ndk/downloads/revision_history" 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" @@ -25,10 +26,15 @@ __BuildArch=arm64 __AndroidArch=aarch64 __AndroidToolchain=aarch64-linux-android -for i in "$@" - do - lowerI="$(echo $i | tr "[:upper:]" "[:lower:]")" - case $lowerI in +while :; do + if [[ "$#" -le 0 ]]; then + break + fi + + i=$1 + + lowerI="$(echo $i | tr "[:upper:]" "[:lower:]")" + case $lowerI in -?|-h|--help) usage exit 1 @@ -43,6 +49,10 @@ for i in "$@" __AndroidArch=arm __AndroidToolchain=arm-linux-androideabi ;; + --ndk) + shift + __NDK_Version=$1 + ;; *[0-9]) __ApiLevel=$i ;; @@ -50,8 +60,17 @@ for i in "$@" __UnprocessedBuildArgs="$__UnprocessedBuildArgs $i" ;; esac + shift done +if [[ "$__NDK_Version" == "r21" ]] || [[ "$__NDK_Version" == "r22" ]]; then + __NDK_File_Arch_Spec=-x86_64 + __SysRoot=sysroot +else + __NDK_File_Arch_Spec= + __SysRoot=toolchains/llvm/prebuilt/linux-x86_64/sysroot +fi + # Obtain the location of the bash script to figure out where the root of the repo is. __ScriptBaseDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" @@ -78,6 +97,7 @@ fi echo "Target API level: $__ApiLevel" echo "Target architecture: $__BuildArch" +echo "NDK version: $__NDK_Version" echo "NDK location: $__NDK_Dir" echo "Target Toolchain location: $__ToolchainDir" @@ -85,8 +105,8 @@ echo "Target Toolchain location: $__ToolchainDir" if [ ! -d $__NDK_Dir ]; then echo Downloading the NDK into $__NDK_Dir mkdir -p $__NDK_Dir - wget -q --progress=bar:force:noscroll --show-progress https://dl.google.com/android/repository/android-ndk-$__NDK_Version-linux-x86_64.zip -O $__CrossDir/android-ndk-$__NDK_Version-linux-x86_64.zip - unzip -q $__CrossDir/android-ndk-$__NDK_Version-linux-x86_64.zip -d $__CrossDir + wget -q --progress=bar:force:noscroll --show-progress https://dl.google.com/android/repository/android-ndk-$__NDK_Version-linux$__NDK_File_Arch_Spec.zip -O $__CrossDir/android-ndk-$__NDK_Version-linux.zip + unzip -q $__CrossDir/android-ndk-$__NDK_Version-linux.zip -d $__CrossDir fi if [ ! -d $__lldb_Dir ]; then @@ -116,16 +136,11 @@ for path in $(wget -qO- https://packages.termux.dev/termux-main-21/dists/stable/ fi done -cp -R "$__TmpDir/data/data/com.termux/files/usr/"* "$__ToolchainDir/sysroot/usr/" +cp -R "$__TmpDir/data/data/com.termux/files/usr/"* "$__ToolchainDir/$__SysRoot/usr/" # Generate platform file for build.sh script to assign to __DistroRid echo "Generating platform file..." -echo "RID=android.${__ApiLevel}-${__BuildArch}" > $__ToolchainDir/sysroot/android_platform - -echo "Now to build coreclr, libraries and installers; run:" -echo ROOTFS_DIR=\$\(realpath $__ToolchainDir/sysroot\) ./build.sh --cross --arch $__BuildArch \ - --subsetCategory coreclr -echo ROOTFS_DIR=\$\(realpath $__ToolchainDir/sysroot\) ./build.sh --cross --arch $__BuildArch \ - --subsetCategory libraries -echo ROOTFS_DIR=\$\(realpath $__ToolchainDir/sysroot\) ./build.sh --cross --arch $__BuildArch \ - --subsetCategory installer +echo "RID=android.${__ApiLevel}-${__BuildArch}" > $__ToolchainDir/$__SysRoot/android_platform + +echo "Now to build coreclr, libraries and host; run:" +echo ROOTFS_DIR=$(realpath $__ToolchainDir/$__SysRoot) ./build.sh clr+libs+host --cross --arch $__BuildArch diff --git a/src/vstest/eng/common/cross/build-rootfs.sh b/src/vstest/eng/common/cross/build-rootfs.sh index 4b5e8d7166b..8abfb71f727 100644 --- a/src/vstest/eng/common/cross/build-rootfs.sh +++ b/src/vstest/eng/common/cross/build-rootfs.sh @@ -5,7 +5,7 @@ set -e usage() { echo "Usage: $0 [BuildArch] [CodeName] [lldbx.y] [llvmx[.y]] [--skipunmount] --rootfsdir ]" - echo "BuildArch can be: arm(default), arm64, armel, armv6, ppc64le, riscv64, s390x, x64, x86" + echo "BuildArch can be: arm(default), arm64, armel, armv6, loongarch64, 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: freebsd13, freebsd14" @@ -15,6 +15,7 @@ usage() echo "llvmx[.y] - optional, LLVM version for LLVM related packages." echo "--skipunmount - optional, will skip the unmount of rootfs folder." echo "--skipsigcheck - optional, will skip package signature checks (allowing untrusted packages)." + echo "--skipemulation - optional, will skip qemu and debootstrap requirement when building environment for debian based systems." echo "--use-mirror - optional, use mirror URL to fetch resources, when available." echo "--jobs N - optional, restrict to N jobs." exit 1 @@ -52,28 +53,27 @@ __UbuntuPackages+=" symlinks" __UbuntuPackages+=" libicu-dev" __UbuntuPackages+=" liblttng-ust-dev" __UbuntuPackages+=" libunwind8-dev" -__UbuntuPackages+=" libnuma-dev" __AlpinePackages+=" gettext-dev" __AlpinePackages+=" icu-dev" __AlpinePackages+=" libunwind-dev" __AlpinePackages+=" lttng-ust-dev" __AlpinePackages+=" compiler-rt" -__AlpinePackages+=" numactl-dev" # runtime libraries' dependencies __UbuntuPackages+=" libcurl4-openssl-dev" __UbuntuPackages+=" libkrb5-dev" __UbuntuPackages+=" libssl-dev" __UbuntuPackages+=" zlib1g-dev" +__UbuntuPackages+=" libbrotli-dev" __AlpinePackages+=" curl-dev" __AlpinePackages+=" krb5-dev" __AlpinePackages+=" openssl-dev" __AlpinePackages+=" zlib-dev" -__FreeBSDBase="13.3-RELEASE" -__FreeBSDPkg="1.17.0" +__FreeBSDBase="13.4-RELEASE" +__FreeBSDPkg="1.21.3" __FreeBSDABI="13" __FreeBSDPackages="libunwind" __FreeBSDPackages+=" icu" @@ -91,18 +91,18 @@ __HaikuPackages="gcc_syslibs" __HaikuPackages+=" gcc_syslibs_devel" __HaikuPackages+=" gmp" __HaikuPackages+=" gmp_devel" -__HaikuPackages+=" icu66" -__HaikuPackages+=" icu66_devel" +__HaikuPackages+=" icu[0-9]+" +__HaikuPackages+=" icu[0-9]*_devel" __HaikuPackages+=" krb5" __HaikuPackages+=" krb5_devel" __HaikuPackages+=" libiconv" __HaikuPackages+=" libiconv_devel" -__HaikuPackages+=" llvm12_libunwind" -__HaikuPackages+=" llvm12_libunwind_devel" +__HaikuPackages+=" llvm[0-9]*_libunwind" +__HaikuPackages+=" llvm[0-9]*_libunwind_devel" __HaikuPackages+=" mpfr" __HaikuPackages+=" mpfr_devel" -__HaikuPackages+=" openssl" -__HaikuPackages+=" openssl_devel" +__HaikuPackages+=" openssl3" +__HaikuPackages+=" openssl3_devel" __HaikuPackages+=" zlib" __HaikuPackages+=" zlib_devel" @@ -128,10 +128,12 @@ __AlpineKeys=' 616adfeb:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq0BFD1D4lIxQcsqEpQzU\npNCYM3aP1V/fxxVdT4DWvSI53JHTwHQamKdMWtEXetWVbP5zSROniYKFXd/xrD9X\n0jiGHey3lEtylXRIPxe5s+wXoCmNLcJVnvTcDtwx/ne2NLHxp76lyc25At+6RgE6\nADjLVuoD7M4IFDkAsd8UQ8zM0Dww9SylIk/wgV3ZkifecvgUQRagrNUdUjR56EBZ\nraQrev4hhzOgwelT0kXCu3snbUuNY/lU53CoTzfBJ5UfEJ5pMw1ij6X0r5S9IVsy\nKLWH1hiO0NzU2c8ViUYCly4Fe9xMTFc6u2dy/dxf6FwERfGzETQxqZvSfrRX+GLj\n/QZAXiPg5178hT/m0Y3z5IGenIC/80Z9NCi+byF1WuJlzKjDcF/TU72zk0+PNM/H\nKuppf3JT4DyjiVzNC5YoWJT2QRMS9KLP5iKCSThwVceEEg5HfhQBRT9M6KIcFLSs\nmFjx9kNEEmc1E8hl5IR3+3Ry8G5/bTIIruz14jgeY9u5jhL8Vyyvo41jgt9sLHR1\n/J1TxKfkgksYev7PoX6/ZzJ1ksWKZY5NFoDXTNYUgzFUTOoEaOg3BAQKadb3Qbbq\nXIrxmPBdgrn9QI7NCgfnAY3Tb4EEjs3ON/BNyEhUENcXOH6I1NbcuBQ7g9P73kE4\nVORdoc8MdJ5eoKBpO8Ww8HECAwEAAQ== 616ae350:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyduVzi1mWm+lYo2Tqt/0\nXkCIWrDNP1QBMVPrE0/ZlU2bCGSoo2Z9FHQKz/mTyMRlhNqTfhJ5qU3U9XlyGOPJ\npiM+b91g26pnpXJ2Q2kOypSgOMOPA4cQ42PkHBEqhuzssfj9t7x47ppS94bboh46\nxLSDRff/NAbtwTpvhStV3URYkxFG++cKGGa5MPXBrxIp+iZf9GnuxVdST5PGiVGP\nODL/b69sPJQNbJHVquqUTOh5Ry8uuD2WZuXfKf7/C0jC/ie9m2+0CttNu9tMciGM\nEyKG1/Xhk5iIWO43m4SrrT2WkFlcZ1z2JSf9Pjm4C2+HovYpihwwdM/OdP8Xmsnr\nDzVB4YvQiW+IHBjStHVuyiZWc+JsgEPJzisNY0Wyc/kNyNtqVKpX6dRhMLanLmy+\nf53cCSI05KPQAcGj6tdL+D60uKDkt+FsDa0BTAobZ31OsFVid0vCXtsbplNhW1IF\nHwsGXBTVcfXg44RLyL8Lk/2dQxDHNHzAUslJXzPxaHBLmt++2COa2EI1iWlvtznk\nOk9WP8SOAIj+xdqoiHcC4j72BOVVgiITIJNHrbppZCq6qPR+fgXmXa+sDcGh30m6\n9Wpbr28kLMSHiENCWTdsFij+NQTd5S47H7XTROHnalYDuF1RpS+DpQidT5tUimaT\nJZDr++FjKrnnijbyNF8b98UCAwEAAQ== 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== +66ba20fe:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtfB12w4ZgqsXWZDfUAV/\n6Y4aHUKIu3q4SXrNZ7CXF9nXoAVYrS7NAxJdAodsY3vPCN0g5O8DFXR+390LdOuQ\n+HsGKCc1k5tX5ZXld37EZNTNSbR0k+NKhd9h6X3u6wqPOx7SIKxwAQR8qeeFq4pP\nrt9GAGlxtuYgzIIcKJPwE0dZlcBCg+GnptCUZXp/38BP1eYC+xTXSL6Muq1etYfg\nodXdb7Yl+2h1IHuOwo5rjgY5kpY7GcAs8AjGk3lDD/av60OTYccknH0NCVSmPoXK\nvrxDBOn0LQRNBLcAfnTKgHrzy0Q5h4TNkkyTgxkoQw5ObDk9nnabTxql732yy9BY\ns+hM9+dSFO1HKeVXreYSA2n1ndF18YAvAumzgyqzB7I4pMHXq1kC/8bONMJxwSkS\nYm6CoXKyavp7RqGMyeVpRC7tV+blkrrUml0BwNkxE+XnwDRB3xDV6hqgWe0XrifD\nYTfvd9ScZQP83ip0r4IKlq4GMv/R5shcCRJSkSZ6QSGshH40JYSoiwJf5FHbj9ND\n7do0UAqebWo4yNx63j/wb2ULorW3AClv0BCFSdPsIrCStiGdpgJDBR2P2NZOCob3\nG9uMj+wJD6JJg2nWqNJxkANXX37Qf8plgzssrhrgOvB0fjjS7GYhfkfmZTJ0wPOw\nA8+KzFseBh4UFGgue78KwgkCAwEAAQ== ' __Keyring= __KeyringFile="/usr/share/keyrings/ubuntu-archive-keyring.gpg" __SkipSigCheck=0 +__SkipEmulation=0 __UseMirror=0 __UnprocessedBuildArgs= @@ -162,9 +164,13 @@ while :; do armel) __BuildArch=armel __UbuntuArch=armel - __UbuntuRepo="http://ftp.debian.org/debian/" - __CodeName=jessie + __UbuntuRepo="http://archive.debian.org/debian/" + __CodeName=buster __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" + __LLDB_Package="liblldb-6.0-dev" + __UbuntuPackages="${__UbuntuPackages// libomp-dev/}" + __UbuntuPackages="${__UbuntuPackages// libomp5/}" + __UbuntuSuites= ;; armv6) __BuildArch=armv6 @@ -180,6 +186,18 @@ while :; do __Keyring="--keyring $__KeyringFile" fi ;; + loongarch64) + __BuildArch=loongarch64 + __AlpineArch=loongarch64 + __QEMUArch=loongarch64 + __UbuntuArch=loong64 + __UbuntuSuites=unreleased + __LLDB_Package="liblldb-19-dev" + + if [[ "$__CodeName" == "sid" ]]; then + __UbuntuRepo="http://ftp.ports.debian.org/debian-ports/" + fi + ;; riscv64) __BuildArch=riscv64 __AlpineArch=riscv64 @@ -264,44 +282,21 @@ while :; do ;; xenial) # Ubuntu 16.04 - if [[ "$__CodeName" != "jessie" ]]; then - __CodeName=xenial - fi - ;; - zesty) # Ubuntu 17.04 - if [[ "$__CodeName" != "jessie" ]]; then - __CodeName=zesty - fi + __CodeName=xenial ;; bionic) # Ubuntu 18.04 - if [[ "$__CodeName" != "jessie" ]]; then - __CodeName=bionic - fi + __CodeName=bionic ;; focal) # Ubuntu 20.04 - if [[ "$__CodeName" != "jessie" ]]; then - __CodeName=focal - fi + __CodeName=focal ;; jammy) # Ubuntu 22.04 - if [[ "$__CodeName" != "jessie" ]]; then - __CodeName=jammy - fi + __CodeName=jammy ;; 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/" + __CodeName=noble + if [[ -z "$__LLDB_Package" ]]; then + __LLDB_Package="liblldb-19-dev" fi ;; stretch) # Debian 9 @@ -319,7 +314,7 @@ while :; do __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then - __UbuntuRepo="http://ftp.debian.org/debian/" + __UbuntuRepo="http://archive.debian.org/debian/" fi ;; bullseye) # Debian 11 @@ -340,10 +335,28 @@ while :; do ;; sid) # Debian sid __CodeName=sid - __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" + __UbuntuSuites= - if [[ -z "$__UbuntuRepo" ]]; then - __UbuntuRepo="http://ftp.debian.org/debian/" + # Debian-Ports architectures need different values + case "$__UbuntuArch" in + amd64|arm64|armel|armhf|i386|mips64el|ppc64el|riscv64|s390x) + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" + + if [[ -z "$__UbuntuRepo" ]]; then + __UbuntuRepo="http://ftp.debian.org/debian/" + fi + ;; + *) + __KeyringFile="/usr/share/keyrings/debian-ports-archive-keyring.gpg" + + if [[ -z "$__UbuntuRepo" ]]; then + __UbuntuRepo="http://ftp.ports.debian.org/debian-ports/" + fi + ;; + esac + + if [[ -e "$__KeyringFile" ]]; then + __Keyring="--keyring $__KeyringFile" fi ;; tizen) @@ -370,7 +383,7 @@ while :; do ;; freebsd14) __CodeName=freebsd - __FreeBSDBase="14.0-RELEASE" + __FreeBSDBase="14.2-RELEASE" __FreeBSDABI="14" __SkipUnmount=1 ;; @@ -388,6 +401,9 @@ while :; do --skipsigcheck) __SkipSigCheck=1 ;; + --skipemulation) + __SkipEmulation=1 + ;; --rootfsdir|-rootfsdir) shift __RootfsDir="$1" @@ -420,16 +436,15 @@ case "$__AlpineVersion" in elif [[ "$__AlpineArch" == "x86" ]]; then __AlpineVersion=3.17 # minimum version that supports lldb-dev __AlpinePackages+=" llvm15-libs" - elif [[ "$__AlpineArch" == "riscv64" ]]; then + elif [[ "$__AlpineArch" == "riscv64" || "$__AlpineArch" == "loongarch64" ]]; then + __AlpineVersion=3.21 # minimum version that supports lldb-dev + __AlpinePackages+=" llvm19-libs" + elif [[ -n "$__AlpineMajorVersion" ]]; then + # use whichever alpine version is provided and select the latest toolchain libs __AlpineLlvmLibsLookup=1 - __AlpineVersion=edge # minimum version with APKINDEX.tar.gz (packages archive) else __AlpineVersion=3.13 # 3.13 to maximize compatibility __AlpinePackages+=" llvm10-libs" - - if [[ "$__AlpineArch" == "armv7" ]]; then - __AlpinePackages="${__AlpinePackages//numactl-dev/}" - fi fi esac @@ -439,15 +454,6 @@ if [[ "$__AlpineVersion" =~ 3\.1[345] ]]; then __AlpinePackages="${__AlpinePackages/compiler-rt/compiler-rt-static}" fi -if [[ "$__BuildArch" == "armel" ]]; then - __LLDB_Package="lldb-3.5-dev" -fi - -if [[ "$__CodeName" == "xenial" && "$__UbuntuArch" == "armhf" ]]; then - # libnuma-dev is not available on armhf for xenial - __UbuntuPackages="${__UbuntuPackages//libnuma-dev/}" -fi - __UbuntuPackages+=" ${__LLDB_Package:-}" if [[ -z "$__UbuntuRepo" ]]; then @@ -496,7 +502,7 @@ if [[ "$__CodeName" == "alpine" ]]; then arch="$(uname -m)" ensureDownloadTool - + if [[ "$__hasWget" == 1 ]]; then wget -P "$__ApkToolsDir" "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic/v$__ApkToolsVersion/$arch/apk.static" else @@ -512,11 +518,6 @@ if [[ "$__CodeName" == "alpine" ]]; then echo "$__ApkToolsSHA512SUM $__ApkToolsDir/apk.static" | sha512sum -c chmod +x "$__ApkToolsDir/apk.static" - if [[ -f "/usr/bin/qemu-$__QEMUArch-static" ]]; then - mkdir -p "$__RootfsDir"/usr/bin - cp -v "/usr/bin/qemu-$__QEMUArch-static" "$__RootfsDir/usr/bin" - fi - if [[ "$__AlpineVersion" == "edge" ]]; then version=edge else @@ -536,6 +537,10 @@ if [[ "$__CodeName" == "alpine" ]]; then __ApkSignatureArg="--keys-dir $__ApkKeysDir" fi + if [[ "$__SkipEmulation" == "1" ]]; then + __NoEmulationArg="--no-scripts" + fi + # initialize DB # shellcheck disable=SC2086 "$__ApkToolsDir/apk.static" \ @@ -557,7 +562,7 @@ if [[ "$__CodeName" == "alpine" ]]; then "$__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" \ + -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" $__NoEmulationArg \ add $__AlpinePackages rm -r "$__ApkToolsDir" @@ -573,7 +578,7 @@ elif [[ "$__CodeName" == "freebsd" ]]; then 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 + echo "FreeBSD: { url: \"pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly\", mirror_type: \"srv\", signature_type: \"fingerprints\", fingerprints: \"/usr/share/keys/pkg\", enabled: yes }" > "${__RootfsDir}"/etc/pkg/FreeBSD.conf mkdir -p "$__RootfsDir"/tmp # get and build package manager if [[ "$__hasWget" == 1 ]]; then @@ -681,7 +686,7 @@ elif [[ "$__CodeName" == "haiku" ]]; then ensureDownloadTool - echo "Downloading Haiku package tool" + echo "Downloading Haiku package tools" 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)" @@ -691,34 +696,42 @@ elif [[ "$__CodeName" == "haiku" ]]; then unzip -o "$__RootfsDir/tmp/download/hosttools.zip" -d "$__RootfsDir/tmp/bin" - DepotBaseUrl="https://depot.haiku-os.org/__api/v2/pkg/get-pkg" - HpkgBaseUrl="https://eu.hpkg.haiku-os.org/haiku/master/$__HaikuArch/current" + HaikuBaseUrl="https://eu.hpkg.haiku-os.org/haiku/master/$__HaikuArch/current" + HaikuPortsBaseUrl="https://eu.hpkg.haiku-os.org/haikuports/master/$__HaikuArch/current" + + echo "Downloading HaikuPorts package repository index..." + if [[ "$__hasWget" == 1 ]]; then + wget -P "$__RootfsDir/tmp/download" "$HaikuPortsBaseUrl/repo" + else + curl -SLO --create-dirs --output-dir "$__RootfsDir/tmp/download" "$HaikuPortsBaseUrl/repo" + fi - # Download Haiku packages echo "Downloading Haiku packages" read -ra array <<<"$__HaikuPackages" for package in "${array[@]}"; do 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 + hpkgFilename="$(LD_LIBRARY_PATH="$__RootfsDir/tmp/bin" "$__RootfsDir/tmp/bin/package_repo" list -f "$__RootfsDir/tmp/download/repo" | + grep -E "${package}-" | sort -V | tail -n 1 | xargs)" + if [ -z "$hpkgFilename" ]; then + >&2 echo "ERROR: package $package missing." + exit 1 + fi + echo "Resolved filename: $hpkgFilename..." + hpkgDownloadUrl="$HaikuPortsBaseUrl/packages/$hpkgFilename" 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..." 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" + hpkgVersion="$(wget -qO- "$HaikuBaseUrl" | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" + wget -P "$__RootfsDir/tmp/download" "$HaikuBaseUrl/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" + hpkgVersion="$(curl -sSL "$HaikuBaseUrl" | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" + curl -SLO --create-dirs --output-dir "$__RootfsDir/tmp/download" "$HaikuBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" fi done @@ -744,25 +757,67 @@ elif [[ "$__CodeName" == "haiku" ]]; then popd rm -rf "$__RootfsDir/tmp" elif [[ -n "$__CodeName" ]]; then + __Suites="$__CodeName $(for suite in $__UbuntuSuites; do echo -n "$__CodeName-$suite "; done)" + + if [[ "$__SkipEmulation" == "1" ]]; then + if [[ -z "$AR" ]]; then + if command -v ar &>/dev/null; then + AR="$(command -v ar)" + elif command -v llvm-ar &>/dev/null; then + AR="$(command -v llvm-ar)" + else + echo "Unable to find ar or llvm-ar on PATH, add them to PATH or set AR environment variable pointing to the available AR tool" + exit 1 + fi + fi + + PYTHON=${PYTHON_EXECUTABLE:-python3} + + # shellcheck disable=SC2086,SC2046 + echo running "$PYTHON" "$__CrossDir/install-debs.py" --arch "$__UbuntuArch" --mirror "$__UbuntuRepo" --rootfsdir "$__RootfsDir" --artool "$AR" \ + $(for suite in $__Suites; do echo -n "--suite $suite "; done) \ + $__UbuntuPackages + + # shellcheck disable=SC2086,SC2046 + "$PYTHON" "$__CrossDir/install-debs.py" --arch "$__UbuntuArch" --mirror "$__UbuntuRepo" --rootfsdir "$__RootfsDir" --artool "$AR" \ + $(for suite in $__Suites; do echo -n "--suite $suite "; done) \ + $__UbuntuPackages + exit 0 + fi + + __UpdateOptions= if [[ "$__SkipSigCheck" == "0" ]]; then __Keyring="$__Keyring --force-check-gpg" + else + __Keyring= + __UpdateOptions="--allow-unauthenticated --allow-insecure-repositories" fi # shellcheck disable=SC2086 echo running debootstrap "--variant=minbase" $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo" - debootstrap "--variant=minbase" $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo" + # shellcheck disable=SC2086 + if ! debootstrap "--variant=minbase" $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo"; then + echo "debootstrap failed! dumping debootstrap.log" + cat "$__RootfsDir/debootstrap/debootstrap.log" + exit 1 + fi + + rm -rf "$__RootfsDir"/etc/apt/*.{sources,list} "$__RootfsDir"/etc/apt/sources.list.d mkdir -p "$__RootfsDir/etc/apt/sources.list.d/" + + # shellcheck disable=SC2086 cat > "$__RootfsDir/etc/apt/sources.list.d/$__CodeName.sources" < token2) - (token1 < token2) + else: + return -1 if isinstance(token1, str) else 1 + + return len(tokens1) - len(tokens2) + +def compare_debian_versions(version1, version2): + """Compare two Debian package versions.""" + epoch1, upstream1, revision1 = parse_debian_version(version1) + epoch2, upstream2, revision2 = parse_debian_version(version2) + + if epoch1 != epoch2: + return epoch1 - epoch2 + + result = compare_upstream_version(upstream1, upstream2) + if result != 0: + return result + + return compare_upstream_version(revision1, revision2) + +def resolve_dependencies(packages, aliases, desired_packages): + """Recursively resolves dependencies for the desired packages.""" + resolved = [] + to_process = deque(desired_packages) + + while to_process: + current = to_process.popleft() + resolved_package = current if current in packages else aliases.get(current, [None])[0] + + if not resolved_package: + print(f"Error: Package '{current}' was not found in the available packages.") + sys.exit(1) + + if resolved_package not in resolved: + resolved.append(resolved_package) + + deps = packages.get(resolved_package, {}).get("Depends", "") + if deps: + deps = [dep.split(' ')[0] for dep in deps.split(', ') if dep] + for dep in deps: + if dep not in resolved and dep not in to_process and dep in packages: + to_process.append(dep) + + return resolved + +def parse_package_index(content): + """Parses the Packages.gz file and returns package information.""" + packages = {} + aliases = {} + entries = re.split(r'\n\n+', content) + + for entry in entries: + fields = dict(re.findall(r'^(\S+): (.+)$', entry, re.MULTILINE)) + if "Package" in fields: + package_name = fields["Package"] + version = fields.get("Version") + filename = fields.get("Filename") + depends = fields.get("Depends") + provides = fields.get("Provides", None) + + # Only update if package_name is not in packages or if the new version is higher + if package_name not in packages or compare_debian_versions(version, packages[package_name]["Version"]) > 0: + packages[package_name] = { + "Version": version, + "Filename": filename, + "Depends": depends + } + + # Update aliases if package provides any alternatives + if provides: + provides_list = [x.strip() for x in provides.split(",")] + for alias in provides_list: + # Strip version specifiers + alias_name = re.sub(r'\s*\(=.*\)', '', alias) + if alias_name not in aliases: + aliases[alias_name] = [] + if package_name not in aliases[alias_name]: + aliases[alias_name].append(package_name) + + return packages, aliases + +def install_packages(mirror, packages_info, aliases, tmp_dir, extract_dir, ar_tool, desired_packages): + """Downloads .deb files and extracts them.""" + resolved_packages = resolve_dependencies(packages_info, aliases, desired_packages) + print(f"Resolved packages (including dependencies): {resolved_packages}") + + packages_to_download = {} + + for pkg in resolved_packages: + if pkg in packages_info: + packages_to_download[pkg] = packages_info[pkg] + + if pkg in aliases: + for alias in aliases[pkg]: + if alias in packages_info: + packages_to_download[alias] = packages_info[alias] + + asyncio.run(download_deb_files_parallel(mirror, packages_to_download, tmp_dir)) + + package_to_deb_file_map = {} + for pkg in resolved_packages: + pkg_info = packages_info.get(pkg) + if pkg_info: + deb_filename = pkg_info.get("Filename") + if deb_filename: + deb_file_path = os.path.join(tmp_dir, os.path.basename(deb_filename)) + package_to_deb_file_map[pkg] = deb_file_path + + for pkg in reversed(resolved_packages): + deb_file = package_to_deb_file_map.get(pkg) + if deb_file and os.path.exists(deb_file): + extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool) + + print("All done!") + +def extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool): + """Extract .deb file contents""" + + os.makedirs(extract_dir, exist_ok=True) + + with tempfile.TemporaryDirectory(dir=tmp_dir) as tmp_subdir: + result = subprocess.run(f"{ar_tool} t {os.path.abspath(deb_file)}", cwd=tmp_subdir, check=True, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + tar_filename = None + for line in result.stdout.decode().splitlines(): + if line.startswith("data.tar"): + tar_filename = line.strip() + break + + if not tar_filename: + raise FileNotFoundError(f"Could not find 'data.tar.*' in {deb_file}.") + + tar_file_path = os.path.join(tmp_subdir, tar_filename) + print(f"Extracting {tar_filename} from {deb_file}..") + + subprocess.run(f"{ar_tool} p {os.path.abspath(deb_file)} {tar_filename} > {tar_file_path}", check=True, shell=True) + + file_extension = os.path.splitext(tar_file_path)[1].lower() + + if file_extension == ".xz": + mode = "r:xz" + elif file_extension == ".gz": + mode = "r:gz" + elif file_extension == ".zst": + # zstd is not supported by standard library yet + decompressed_tar_path = tar_file_path.replace(".zst", "") + with open(tar_file_path, "rb") as zst_file, open(decompressed_tar_path, "wb") as decompressed_file: + dctx = zstandard.ZstdDecompressor() + dctx.copy_stream(zst_file, decompressed_file) + + tar_file_path = decompressed_tar_path + mode = "r" + else: + raise ValueError(f"Unsupported compression format: {file_extension}") + + with tarfile.open(tar_file_path, mode) as tar: + tar.extractall(path=extract_dir, filter='fully_trusted') + +def finalize_setup(rootfsdir): + lib_dir = os.path.join(rootfsdir, 'lib') + usr_lib_dir = os.path.join(rootfsdir, 'usr', 'lib') + + if os.path.exists(lib_dir): + if os.path.islink(lib_dir): + os.remove(lib_dir) + else: + os.makedirs(usr_lib_dir, exist_ok=True) + + for item in os.listdir(lib_dir): + src = os.path.join(lib_dir, item) + dest = os.path.join(usr_lib_dir, item) + + if os.path.isdir(src): + shutil.copytree(src, dest, dirs_exist_ok=True) + else: + shutil.copy2(src, dest) + + shutil.rmtree(lib_dir) + + os.symlink(usr_lib_dir, lib_dir) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate rootfs for .NET runtime on Debian-like OS") + parser.add_argument("--distro", required=False, help="Distro name (e.g., debian, ubuntu, etc.)") + parser.add_argument("--arch", required=True, help="Architecture (e.g., amd64, loong64, etc.)") + parser.add_argument("--rootfsdir", required=True, help="Destination directory.") + parser.add_argument('--suite', required=True, action='append', help='Specify one or more repository suites to collect index data.') + parser.add_argument("--mirror", required=False, help="Mirror (e.g., http://ftp.debian.org/debian-ports etc.)") + parser.add_argument("--artool", required=False, default="ar", help="ar tool to extract debs (e.g., ar, llvm-ar etc.)") + parser.add_argument("packages", nargs="+", help="List of package names to be installed.") + + args = parser.parse_args() + + if args.mirror is None: + if args.distro == "ubuntu": + args.mirror = "http://archive.ubuntu.com/ubuntu" if args.arch in ["amd64", "i386"] else "http://ports.ubuntu.com/ubuntu-ports" + elif args.distro == "debian": + args.mirror = "http://ftp.debian.org/debian-ports" + else: + raise Exception("Unsupported distro") + + DESIRED_PACKAGES = args.packages + [ # base packages + "dpkg", + "busybox", + "libc-bin", + "base-files", + "base-passwd", + "debianutils" + ] + + print(f"Creating rootfs. rootfsdir: {args.rootfsdir}, distro: {args.distro}, arch: {args.arch}, suites: {args.suite}, mirror: {args.mirror}") + + package_index_content = asyncio.run(download_package_index_parallel(args.mirror, args.arch, args.suite)) + + packages_info, aliases = parse_package_index(package_index_content) + + with tempfile.TemporaryDirectory() as tmp_dir: + install_packages(args.mirror, packages_info, aliases, tmp_dir, args.rootfsdir, args.artool, DESIRED_PACKAGES) + + finalize_setup(args.rootfsdir) diff --git a/src/vstest/eng/common/cross/tizen-fetch.sh b/src/vstest/eng/common/cross/tizen-fetch.sh index 28936ceef3a..37c3a61f1de 100644 --- a/src/vstest/eng/common/cross/tizen-fetch.sh +++ b/src/vstest/eng/common/cross/tizen-fetch.sh @@ -156,13 +156,8 @@ fetch_tizen_pkgs() done } -if [ "$TIZEN_ARCH" == "riscv64" ]; then - BASE="Tizen-Base-RISCV" - UNIFIED="Tizen-Unified-RISCV" -else - BASE="Tizen-Base" - UNIFIED="Tizen-Unified" -fi +BASE="Tizen-Base" +UNIFIED="Tizen-Unified" Inform "Initialize ${TIZEN_ARCH} base" fetch_tizen_pkgs_init standard $BASE diff --git a/src/vstest/eng/common/cross/toolchain.cmake b/src/vstest/eng/common/cross/toolchain.cmake index 9a7ecfbd42c..0ff85cf0367 100644 --- a/src/vstest/eng/common/cross/toolchain.cmake +++ b/src/vstest/eng/common/cross/toolchain.cmake @@ -67,6 +67,13 @@ elseif(TARGET_ARCH_NAME STREQUAL "armv6") else() set(TOOLCHAIN "arm-linux-gnueabihf") endif() +elseif(TARGET_ARCH_NAME STREQUAL "loongarch64") + set(CMAKE_SYSTEM_PROCESSOR "loongarch64") + if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/loongarch64-alpine-linux-musl) + set(TOOLCHAIN "loongarch64-alpine-linux-musl") + else() + set(TOOLCHAIN "loongarch64-linux-gnu") + endif() elseif(TARGET_ARCH_NAME STREQUAL "ppc64le") set(CMAKE_SYSTEM_PROCESSOR ppc64le) if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/powerpc64le-alpine-linux-musl) @@ -118,7 +125,7 @@ elseif(TARGET_ARCH_NAME STREQUAL "x86") set(TIZEN_TOOLCHAIN "i586-tizen-linux-gnu") endif() else() - message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only arm, arm64, armel, armv6, ppc64le, riscv64, s390x, x64 and x86 are supported!") + message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only arm, arm64, armel, armv6, loongarch64, ppc64le, riscv64, s390x, x64 and x86 are supported!") endif() if(DEFINED ENV{TOOLCHAIN}) @@ -148,6 +155,25 @@ if(TIZEN) include_directories(SYSTEM ${TIZEN_TOOLCHAIN_PATH}/include/c++/${TIZEN_TOOLCHAIN}) endif() +function(locate_toolchain_exec exec var) + set(TOOLSET_PREFIX ${TOOLCHAIN}-) + string(TOUPPER ${exec} EXEC_UPPERCASE) + if(NOT "$ENV{CLR_${EXEC_UPPERCASE}}" STREQUAL "") + set(${var} "$ENV{CLR_${EXEC_UPPERCASE}}" PARENT_SCOPE) + return() + endif() + + find_program(EXEC_LOCATION_${exec} + NAMES + "${TOOLSET_PREFIX}${exec}${CLR_CMAKE_COMPILER_FILE_NAME_VERSION}" + "${TOOLSET_PREFIX}${exec}") + + if (EXEC_LOCATION_${exec} STREQUAL "EXEC_LOCATION_${exec}-NOTFOUND") + message(FATAL_ERROR "Unable to find toolchain executable. Name: ${exec}, Prefix: ${TOOLSET_PREFIX}.") + endif() + set(${var} ${EXEC_LOCATION_${exec}} PARENT_SCOPE) +endfunction() + if(ANDROID) if(TARGET_ARCH_NAME STREQUAL "arm") set(ANDROID_ABI armeabi-v7a) @@ -178,66 +204,24 @@ elseif(FREEBSD) set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fuse-ld=lld") elseif(ILLUMOS) set(CMAKE_SYSROOT "${CROSS_ROOTFS}") + set(CMAKE_SYSTEM_PREFIX_PATH "${CROSS_ROOTFS}") + set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} -lssp") + set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lssp") include_directories(SYSTEM ${CROSS_ROOTFS}/include) - set(TOOLSET_PREFIX ${TOOLCHAIN}-) - function(locate_toolchain_exec exec var) - string(TOUPPER ${exec} EXEC_UPPERCASE) - if(NOT "$ENV{CLR_${EXEC_UPPERCASE}}" STREQUAL "") - set(${var} "$ENV{CLR_${EXEC_UPPERCASE}}" PARENT_SCOPE) - return() - endif() - - find_program(EXEC_LOCATION_${exec} - NAMES - "${TOOLSET_PREFIX}${exec}${CLR_CMAKE_COMPILER_FILE_NAME_VERSION}" - "${TOOLSET_PREFIX}${exec}") - - if (EXEC_LOCATION_${exec} STREQUAL "EXEC_LOCATION_${exec}-NOTFOUND") - message(FATAL_ERROR "Unable to find toolchain executable. Name: ${exec}, Prefix: ${TOOLSET_PREFIX}.") - endif() - set(${var} ${EXEC_LOCATION_${exec}} PARENT_SCOPE) - endfunction() - - set(CMAKE_SYSTEM_PREFIX_PATH "${CROSS_ROOTFS}") - locate_toolchain_exec(gcc CMAKE_C_COMPILER) locate_toolchain_exec(g++ CMAKE_CXX_COMPILER) - - set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} -lssp") - set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lssp") elseif(HAIKU) set(CMAKE_SYSROOT "${CROSS_ROOTFS}") set(CMAKE_PROGRAM_PATH "${CMAKE_PROGRAM_PATH};${CROSS_ROOTFS}/cross-tools-x86_64/bin") - - set(TOOLSET_PREFIX ${TOOLCHAIN}-) - function(locate_toolchain_exec exec var) - string(TOUPPER ${exec} EXEC_UPPERCASE) - if(NOT "$ENV{CLR_${EXEC_UPPERCASE}}" STREQUAL "") - set(${var} "$ENV{CLR_${EXEC_UPPERCASE}}" PARENT_SCOPE) - return() - endif() - - find_program(EXEC_LOCATION_${exec} - NAMES - "${TOOLSET_PREFIX}${exec}${CLR_CMAKE_COMPILER_FILE_NAME_VERSION}" - "${TOOLSET_PREFIX}${exec}") - - if (EXEC_LOCATION_${exec} STREQUAL "EXEC_LOCATION_${exec}-NOTFOUND") - message(FATAL_ERROR "Unable to find toolchain executable. Name: ${exec}, Prefix: ${TOOLSET_PREFIX}.") - endif() - set(${var} ${EXEC_LOCATION_${exec}} PARENT_SCOPE) - endfunction() - set(CMAKE_SYSTEM_PREFIX_PATH "${CROSS_ROOTFS}") + set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} -lssp") + set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lssp") locate_toolchain_exec(gcc CMAKE_C_COMPILER) locate_toolchain_exec(g++ CMAKE_CXX_COMPILER) - set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} -lssp") - set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lssp") - # let CMake set up the correct search paths include(Platform/Haiku) else() @@ -307,7 +291,7 @@ endif() # Specify compile options -if((TARGET_ARCH_NAME MATCHES "^(arm|arm64|armel|armv6|ppc64le|riscv64|s390x|x64|x86)$" AND NOT ANDROID AND NOT FREEBSD) OR ILLUMOS OR HAIKU) +if((TARGET_ARCH_NAME MATCHES "^(arm|arm64|armel|armv6|loongarch64|ppc64le|riscv64|s390x|x64|x86)$" AND NOT ANDROID AND NOT FREEBSD) OR ILLUMOS OR HAIKU) set(CMAKE_C_COMPILER_TARGET ${TOOLCHAIN}) set(CMAKE_CXX_COMPILER_TARGET ${TOOLCHAIN}) set(CMAKE_ASM_COMPILER_TARGET ${TOOLCHAIN}) diff --git a/src/vstest/eng/common/darc-init.sh b/src/vstest/eng/common/darc-init.sh index 36dbd45e1ce..e889f439b8d 100644 --- a/src/vstest/eng/common/darc-init.sh +++ b/src/vstest/eng/common/darc-init.sh @@ -68,7 +68,7 @@ function InstallDarcCli { fi fi - local arcadeServicesSource="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" + local arcadeServicesSource="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" echo "Installing Darc CLI version $darcVersion..." echo "You may need to restart your command shell if this is the first dotnet tool you have installed." diff --git a/src/vstest/eng/common/dotnet.cmd b/src/vstest/eng/common/dotnet.cmd new file mode 100644 index 00000000000..527fa4bb38f --- /dev/null +++ b/src/vstest/eng/common/dotnet.cmd @@ -0,0 +1,7 @@ +@echo off + +:: This script is used to install the .NET SDK. +:: It will also invoke the SDK with any provided arguments. + +powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0dotnet.ps1""" %*" +exit /b %ErrorLevel% diff --git a/src/vstest/eng/common/dotnet.ps1 b/src/vstest/eng/common/dotnet.ps1 new file mode 100644 index 00000000000..45e5676c9eb --- /dev/null +++ b/src/vstest/eng/common/dotnet.ps1 @@ -0,0 +1,11 @@ +# This script is used to install the .NET SDK. +# It will also invoke the SDK with any provided arguments. + +. $PSScriptRoot\tools.ps1 +$dotnetRoot = InitializeDotNetCli -install:$true + +# Invoke acquired SDK with args if they are provided +if ($args.count -gt 0) { + $env:DOTNET_NOLOGO=1 + & "$dotnetRoot\dotnet.exe" $args +} diff --git a/src/vstest/eng/common/dotnet.sh b/src/vstest/eng/common/dotnet.sh new file mode 100644 index 00000000000..2ef68235675 --- /dev/null +++ b/src/vstest/eng/common/dotnet.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# This script is used to install the .NET SDK. +# It will also invoke the SDK with any provided arguments. + +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 )" + +source $scriptroot/tools.sh +InitializeDotNetCli true # install + +# Invoke acquired SDK with args if they are provided +if [[ $# > 0 ]]; then + __dotnetDir=${_InitializeDotNetCli} + dotnetPath=${__dotnetDir}/dotnet + ${dotnetPath} "$@" +fi diff --git a/src/vstest/eng/common/internal/NuGet.config b/src/vstest/eng/common/internal/NuGet.config index 19d3d311b16..f70261ed689 100644 --- a/src/vstest/eng/common/internal/NuGet.config +++ b/src/vstest/eng/common/internal/NuGet.config @@ -4,4 +4,7 @@ + + + diff --git a/src/vstest/eng/common/native/install-dependencies.sh b/src/vstest/eng/common/native/install-dependencies.sh new file mode 100644 index 00000000000..477a44f335b --- /dev/null +++ b/src/vstest/eng/common/native/install-dependencies.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +set -e + +# This is a simple script primarily used for CI to install necessary dependencies +# +# Usage: +# +# ./install-dependencies.sh + +os="$(echo "$1" | tr "[:upper:]" "[:lower:]")" + +if [ -z "$os" ]; then + . "$(dirname "$0")"/init-os-and-arch.sh +fi + +case "$os" in + linux) + if [ -e /etc/os-release ]; then + . /etc/os-release + fi + + if [ "$ID" = "debian" ] || [ "$ID_LIKE" = "debian" ]; then + apt update + + apt install -y build-essential gettext locales cmake llvm clang lld lldb liblldb-dev libunwind8-dev libicu-dev liblttng-ust-dev \ + libssl-dev libkrb5-dev pigz cpio + + localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 + elif [ "$ID" = "fedora" ] || [ "$ID" = "rhel" ] || [ "$ID" = "azurelinux" ]; then + pkg_mgr="$(command -v tdnf 2>/dev/null || command -v dnf)" + $pkg_mgr install -y cmake llvm lld lldb clang python curl libicu-devel openssl-devel krb5-devel lttng-ust-devel pigz cpio + elif [ "$ID" = "alpine" ]; then + apk add build-base cmake bash curl clang llvm-dev lld lldb krb5-dev lttng-ust-dev icu-dev openssl-dev pigz cpio + else + echo "Unsupported distro. distro: $ID" + exit 1 + fi + ;; + + osx|maccatalyst|ios|iossimulator|tvos|tvossimulator) + echo "Installed xcode version: $(xcode-select -p)" + + export HOMEBREW_NO_INSTALL_CLEANUP=1 + export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 + # Skip brew update for now, see https://github.com/actions/setup-python/issues/577 + # brew update --preinstall + brew bundle --no-upgrade --file=- < Msbuild engine to use to run build ('dotnet', 'vs', or unspecified)." + Write-Host " -excludeCIBinaryLog When running on CI, allow no binary log (short: -nobl)" Write-Host "" Write-Host "Command line arguments not listed above are passed thru to msbuild." } @@ -34,10 +36,11 @@ function Print-Usage() { function Build([string]$target) { $logSuffix = if ($target -eq 'Execute') { '' } else { ".$target" } $log = Join-Path $LogDir "$task$logSuffix.binlog" + $binaryLogArg = if ($binaryLog) { "/bl:$log" } else { "" } $outputPath = Join-Path $ToolsetDir "$task\" MSBuild $taskProject ` - /bl:$log ` + $binaryLogArg ` /t:$target ` /p:Configuration=$configuration ` /p:RepoRoot=$RepoRoot ` @@ -64,7 +67,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.12.0" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.13.0" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/src/vstest/eng/common/sdk-task.sh b/src/vstest/eng/common/sdk-task.sh new file mode 100644 index 00000000000..2f83adc0269 --- /dev/null +++ b/src/vstest/eng/common/sdk-task.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash + +show_usage() { + echo "Common settings:" + echo " --task Name of Arcade task (name of a project in SdkTasks directory of the Arcade SDK package)" + echo " --restore Restore dependencies" + echo " --verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]" + echo " --help Print help and exit" + echo "" + + echo "Advanced settings:" + echo " --excludeCIBinarylog Don't output binary log (short: -nobl)" + echo "" + echo "Command line arguments not listed above are passed thru to msbuild." +} + +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 )" + +Build() { + local target=$1 + local log_suffix="" + [[ "$target" != "Execute" ]] && log_suffix=".$target" + local log="$log_dir/$task$log_suffix.binlog" + local binaryLogArg="" + [[ $binary_log == true ]] && binaryLogArg="/bl:$log" + local output_path="$toolset_dir/$task/" + + MSBuild "$taskProject" \ + $binaryLogArg \ + /t:"$target" \ + /p:Configuration="$configuration" \ + /p:RepoRoot="$repo_root" \ + /p:BaseIntermediateOutputPath="$output_path" \ + /v:"$verbosity" \ + $properties +} + +binary_log=true +configuration="Debug" +verbosity="minimal" +exclude_ci_binary_log=false +restore=false +help=false +properties='' + +while (($# > 0)); do + lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" + case $lowerI in + --task) + task=$2 + shift 2 + ;; + --restore) + restore=true + shift 1 + ;; + --verbosity) + verbosity=$2 + shift 2 + ;; + --excludecibinarylog|--nobl) + binary_log=false + exclude_ci_binary_log=true + shift 1 + ;; + --help) + help=true + shift 1 + ;; + *) + properties="$properties $1" + shift 1 + ;; + esac +done + +ci=true +warnAsError=true + +if $help; then + show_usage + exit 0 +fi + +. "$scriptroot/tools.sh" +InitializeToolset + +if [[ -z "$task" ]]; then + Write-PipelineTelemetryError -Category 'Task' -Name 'MissingTask' -Message "Missing required parameter '-task '" + ExitWithExitCode 1 +fi + +taskProject=$(GetSdkTaskProject "$task") +if [[ ! -e "$taskProject" ]]; then + Write-PipelineTelemetryError -Category 'Task' -Name 'UnknownTask' -Message "Unknown task: $task" + ExitWithExitCode 1 +fi + +if $restore; then + Build "Restore" +fi + +Build "Execute" + + +ExitWithExitCode 0 diff --git a/src/vstest/eng/common/sdl/packages.config b/src/vstest/eng/common/sdl/packages.config index 4585cfd6bba..e5f543ea68c 100644 --- a/src/vstest/eng/common/sdl/packages.config +++ b/src/vstest/eng/common/sdl/packages.config @@ -1,4 +1,4 @@ - + diff --git a/src/vstest/eng/common/templates-official/job/job.yml b/src/vstest/eng/common/templates-official/job/job.yml index 817555505aa..a8a94328745 100644 --- a/src/vstest/eng/common/templates-official/job/job.yml +++ b/src/vstest/eng/common/templates-official/job/job.yml @@ -31,6 +31,7 @@ jobs: PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} condition: always() + retryCountOnTaskFailure: 10 # for any logs being locked continueOnError: true - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - output: pipelineArtifact @@ -39,6 +40,7 @@ jobs: displayName: 'Publish logs' continueOnError: true condition: always() + retryCountOnTaskFailure: 10 # for any logs being locked sbomEnabled: false # we don't need SBOM for logs - ${{ if eq(parameters.enablePublishBuildArtifacts, true) }}: @@ -46,7 +48,7 @@ jobs: displayName: Publish Logs PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' publishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)_Attempt$(System.JobAttempt)' ) }} continueOnError: true condition: always() sbomEnabled: false # we don't need SBOM for logs diff --git a/src/vstest/eng/common/templates-official/steps/publish-build-artifacts.yml b/src/vstest/eng/common/templates-official/steps/publish-build-artifacts.yml index 100a3fc9849..fcf6637b2eb 100644 --- a/src/vstest/eng/common/templates-official/steps/publish-build-artifacts.yml +++ b/src/vstest/eng/common/templates-official/steps/publish-build-artifacts.yml @@ -24,6 +24,10 @@ parameters: - name: is1ESPipeline type: boolean default: true + +- name: retryCountOnTaskFailure + type: string + default: 10 steps: - ${{ if ne(parameters.is1ESPipeline, true) }}: @@ -38,4 +42,5 @@ steps: PathtoPublish: ${{ parameters.pathToPublish }} ${{ if parameters.artifactName }}: ArtifactName: ${{ parameters.artifactName }} - + ${{ if parameters.retryCountOnTaskFailure }}: + retryCountOnTaskFailure: ${{ parameters.retryCountOnTaskFailure }} diff --git a/src/vstest/eng/common/templates-official/steps/source-index-stage1-publish.yml b/src/vstest/eng/common/templates-official/steps/source-index-stage1-publish.yml new file mode 100644 index 00000000000..9b8b80942b5 --- /dev/null +++ b/src/vstest/eng/common/templates-official/steps/source-index-stage1-publish.yml @@ -0,0 +1,7 @@ +steps: +- template: /eng/common/core-templates/steps/source-index-stage1-publish.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/src/vstest/eng/common/templates/job/job.yml b/src/vstest/eng/common/templates/job/job.yml index d1aeb92fcea..7cbf668c22b 100644 --- a/src/vstest/eng/common/templates/job/job.yml +++ b/src/vstest/eng/common/templates/job/job.yml @@ -46,6 +46,7 @@ jobs: artifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} continueOnError: true condition: always() + retryCountOnTaskFailure: 10 # for any logs being locked - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml parameters: @@ -56,6 +57,7 @@ jobs: displayName: 'Publish logs' continueOnError: true condition: always() + retryCountOnTaskFailure: 10 # for any logs being locked sbomEnabled: false # we don't need SBOM for logs - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: @@ -66,7 +68,7 @@ jobs: displayName: Publish Logs pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' publishLocation: Container - artifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + artifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)_Attempt$(System.JobAttempt)' ) }} continueOnError: true condition: always() diff --git a/src/vstest/eng/common/templates/steps/publish-build-artifacts.yml b/src/vstest/eng/common/templates/steps/publish-build-artifacts.yml index 6428a98dfef..605e602e94d 100644 --- a/src/vstest/eng/common/templates/steps/publish-build-artifacts.yml +++ b/src/vstest/eng/common/templates/steps/publish-build-artifacts.yml @@ -25,6 +25,10 @@ parameters: type: string default: 'Container' +- name: retryCountOnTaskFailure + type: string + default: 10 + steps: - ${{ if eq(parameters.is1ESPipeline, true) }}: - 'eng/common/templates cannot be referenced from a 1ES managed template': error @@ -37,4 +41,6 @@ steps: PublishLocation: ${{ parameters.publishLocation }} PathtoPublish: ${{ parameters.pathToPublish }} ${{ if parameters.artifactName }}: - ArtifactName: ${{ parameters.artifactName }} \ No newline at end of file + ArtifactName: ${{ parameters.artifactName }} + ${{ if parameters.retryCountOnTaskFailure }}: + retryCountOnTaskFailure: ${{ parameters.retryCountOnTaskFailure }} diff --git a/src/vstest/eng/common/templates/steps/source-index-stage1-publish.yml b/src/vstest/eng/common/templates/steps/source-index-stage1-publish.yml new file mode 100644 index 00000000000..182cec33a7b --- /dev/null +++ b/src/vstest/eng/common/templates/steps/source-index-stage1-publish.yml @@ -0,0 +1,7 @@ +steps: +- template: /eng/common/core-templates/steps/source-index-stage1-publish.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/src/vstest/eng/common/templates/steps/vmr-sync.yml b/src/vstest/eng/common/templates/steps/vmr-sync.yml new file mode 100644 index 00000000000..599afb6186b --- /dev/null +++ b/src/vstest/eng/common/templates/steps/vmr-sync.yml @@ -0,0 +1,207 @@ +### These steps synchronize new code from product repositories into the VMR (https://github.com/dotnet/dotnet). +### They initialize the darc CLI and pull the new updates. +### Changes are applied locally onto the already cloned VMR (located in $vmrPath). + +parameters: +- name: targetRef + displayName: Target revision in dotnet/ to synchronize + type: string + default: $(Build.SourceVersion) + +- name: vmrPath + displayName: Path where the dotnet/dotnet is checked out to + type: string + default: $(Agent.BuildDirectory)/vmr + +- name: additionalSyncs + displayName: Optional list of package names whose repo's source will also be synchronized in the local VMR, e.g. NuGet.Protocol + type: object + default: [] + +steps: +- checkout: vmr + displayName: Clone dotnet/dotnet + path: vmr + clean: true + +- checkout: self + displayName: Clone $(Build.Repository.Name) + path: repo + fetchDepth: 0 + +# This step is needed so that when we get a detached HEAD / shallow clone, +# we still pull the commit into the temporary repo clone to use it during the sync. +# Also unshallow the clone so that forwardflow command would work. +- script: | + git branch repo-head + git rev-parse HEAD + displayName: Label PR commit + workingDirectory: $(Agent.BuildDirectory)/repo + +- script: | + vmr_sha=$(grep -oP '(?<=Sha=")[^"]*' $(Agent.BuildDirectory)/repo/eng/Version.Details.xml) + echo "##vso[task.setvariable variable=vmr_sha]$vmr_sha" + displayName: Obtain the vmr sha from Version.Details.xml (Unix) + condition: ne(variables['Agent.OS'], 'Windows_NT') + workingDirectory: $(Agent.BuildDirectory)/repo + +- powershell: | + [xml]$xml = Get-Content -Path $(Agent.BuildDirectory)/repo/eng/Version.Details.xml + $vmr_sha = $xml.SelectSingleNode("//Source").Sha + Write-Output "##vso[task.setvariable variable=vmr_sha]$vmr_sha" + displayName: Obtain the vmr sha from Version.Details.xml (Windows) + condition: eq(variables['Agent.OS'], 'Windows_NT') + workingDirectory: $(Agent.BuildDirectory)/repo + +- script: | + git fetch --all + git checkout $(vmr_sha) + displayName: Checkout VMR at correct sha for repo flow + workingDirectory: ${{ parameters.vmrPath }} + +- script: | + git config --global user.name "dotnet-maestro[bot]" + git config --global user.email "dotnet-maestro[bot]@users.noreply.github.com" + displayName: Set git author to dotnet-maestro[bot] + workingDirectory: ${{ parameters.vmrPath }} + +- script: | + ./eng/common/vmr-sync.sh \ + --vmr ${{ parameters.vmrPath }} \ + --tmp $(Agent.TempDirectory) \ + --azdev-pat '$(dn-bot-all-orgs-code-r)' \ + --ci \ + --debug + + if [ "$?" -ne 0 ]; then + echo "##vso[task.logissue type=error]Failed to synchronize the VMR" + exit 1 + fi + displayName: Sync repo into VMR (Unix) + condition: ne(variables['Agent.OS'], 'Windows_NT') + workingDirectory: $(Agent.BuildDirectory)/repo + +- script: | + git config --global diff.astextplain.textconv echo + git config --system core.longpaths true + displayName: Configure Windows git (longpaths, astextplain) + condition: eq(variables['Agent.OS'], 'Windows_NT') + +- powershell: | + ./eng/common/vmr-sync.ps1 ` + -vmr ${{ parameters.vmrPath }} ` + -tmp $(Agent.TempDirectory) ` + -azdevPat '$(dn-bot-all-orgs-code-r)' ` + -ci ` + -debugOutput + + if ($LASTEXITCODE -ne 0) { + echo "##vso[task.logissue type=error]Failed to synchronize the VMR" + exit 1 + } + displayName: Sync repo into VMR (Windows) + condition: eq(variables['Agent.OS'], 'Windows_NT') + workingDirectory: $(Agent.BuildDirectory)/repo + +- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: + - task: CopyFiles@2 + displayName: Collect failed patches + condition: failed() + inputs: + SourceFolder: '$(Agent.TempDirectory)' + Contents: '*.patch' + TargetFolder: '$(Build.ArtifactStagingDirectory)/FailedPatches' + + - publish: '$(Build.ArtifactStagingDirectory)/FailedPatches' + artifact: $(System.JobDisplayName)_FailedPatches + displayName: Upload failed patches + condition: failed() + +- ${{ each assetName in parameters.additionalSyncs }}: + # The vmr-sync script ends up staging files in the local VMR so we have to commit those + - script: + git commit --allow-empty -am "Forward-flow $(Build.Repository.Name)" + displayName: Commit local VMR changes + workingDirectory: ${{ parameters.vmrPath }} + + - script: | + set -ex + + echo "Searching for details of asset ${{ assetName }}..." + + # Use darc to get dependencies information + dependencies=$(./.dotnet/dotnet darc get-dependencies --name '${{ assetName }}' --ci) + + # Extract repository URL and commit hash + repository=$(echo "$dependencies" | grep 'Repo:' | sed 's/Repo:[[:space:]]*//' | head -1) + + if [ -z "$repository" ]; then + echo "##vso[task.logissue type=error]Asset ${{ assetName }} not found in the dependency list" + exit 1 + fi + + commit=$(echo "$dependencies" | grep 'Commit:' | sed 's/Commit:[[:space:]]*//' | head -1) + + echo "Updating the VMR from $repository / $commit..." + cd .. + git clone $repository ${{ assetName }} + cd ${{ assetName }} + git checkout $commit + git branch "sync/$commit" + + ./eng/common/vmr-sync.sh \ + --vmr ${{ parameters.vmrPath }} \ + --tmp $(Agent.TempDirectory) \ + --azdev-pat '$(dn-bot-all-orgs-code-r)' \ + --ci \ + --debug + + if [ "$?" -ne 0 ]; then + echo "##vso[task.logissue type=error]Failed to synchronize the VMR" + exit 1 + fi + displayName: Sync ${{ assetName }} into (Unix) + condition: ne(variables['Agent.OS'], 'Windows_NT') + workingDirectory: $(Agent.BuildDirectory)/repo + + - powershell: | + $ErrorActionPreference = 'Stop' + + Write-Host "Searching for details of asset ${{ assetName }}..." + + $dependencies = .\.dotnet\dotnet darc get-dependencies --name '${{ assetName }}' --ci + + $repository = $dependencies | Select-String -Pattern 'Repo:\s+([^\s]+)' | Select-Object -First 1 + $repository -match 'Repo:\s+([^\s]+)' | Out-Null + $repository = $matches[1] + + if ($repository -eq $null) { + Write-Error "Asset ${{ assetName }} not found in the dependency list" + exit 1 + } + + $commit = $dependencies | Select-String -Pattern 'Commit:\s+([^\s]+)' | Select-Object -First 1 + $commit -match 'Commit:\s+([^\s]+)' | Out-Null + $commit = $matches[1] + + Write-Host "Updating the VMR from $repository / $commit..." + cd .. + git clone $repository ${{ assetName }} + cd ${{ assetName }} + git checkout $commit + git branch "sync/$commit" + + .\eng\common\vmr-sync.ps1 ` + -vmr ${{ parameters.vmrPath }} ` + -tmp $(Agent.TempDirectory) ` + -azdevPat '$(dn-bot-all-orgs-code-r)' ` + -ci ` + -debugOutput + + if ($LASTEXITCODE -ne 0) { + echo "##vso[task.logissue type=error]Failed to synchronize the VMR" + exit 1 + } + displayName: Sync ${{ assetName }} into (Windows) + condition: ne(variables['Agent.OS'], 'Windows_NT') + workingDirectory: $(Agent.BuildDirectory)/repo diff --git a/src/vstest/eng/common/templates/vmr-build-pr.yml b/src/vstest/eng/common/templates/vmr-build-pr.yml new file mode 100644 index 00000000000..ce3c29a62fa --- /dev/null +++ b/src/vstest/eng/common/templates/vmr-build-pr.yml @@ -0,0 +1,42 @@ +# This pipeline is used for running the VMR verification of the PR changes in repo-level PRs. +# +# It will run a full set of verification jobs defined in: +# https://github.com/dotnet/dotnet/blob/10060d128e3f470e77265f8490f5e4f72dae738e/eng/pipelines/templates/stages/vmr-build.yml#L27-L38 +# +# For repos that do not need to run the full set, you would do the following: +# +# 1. Copy this YML file to a repo-specific location, i.e. outside of eng/common. +# +# 2. Add `verifications` parameter to VMR template reference +# +# Examples: +# - For source-build stage 1 verification, add the following: +# verifications: [ "source-build-stage1" ] +# +# - For Windows only verifications, add the following: +# verifications: [ "unified-build-windows-x64", "unified-build-windows-x86" ] + +trigger: none +pr: none + +variables: +- template: /eng/common/templates/variables/pool-providers.yml@self + +- name: skipComponentGovernanceDetection # we run CG on internal builds only + value: true + +- name: Codeql.Enabled # we run CodeQL on internal builds only + value: false + +resources: + repositories: + - repository: vmr + type: github + name: dotnet/dotnet + endpoint: dotnet + +stages: +- template: /eng/pipelines/templates/stages/vmr-build.yml@vmr + parameters: + isBuiltFromVmr: false + scope: lite diff --git a/src/vstest/eng/common/tools.ps1 b/src/vstest/eng/common/tools.ps1 index 22b49e09d09..40f0aa86128 100644 --- a/src/vstest/eng/common/tools.ps1 +++ b/src/vstest/eng/common/tools.ps1 @@ -65,10 +65,8 @@ $ErrorActionPreference = 'Stop' # Base-64 encoded SAS token that has permission to storage container described by $runtimeSourceFeed [string]$runtimeSourceFeedKey = if (Test-Path variable:runtimeSourceFeedKey) { $runtimeSourceFeedKey } else { $null } -# True if the build is a product build -[bool]$productBuild = if (Test-Path variable:productBuild) { $productBuild } else { $false } - -[String[]]$properties = if (Test-Path variable:properties) { $properties } else { @() } +# True when the build is running within the VMR. +[bool]$fromVMR = if (Test-Path variable:fromVMR) { $fromVMR } else { $false } function Create-Directory ([string[]] $path) { New-Item -Path $path -Force -ItemType 'Directory' | Out-Null @@ -383,8 +381,8 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/Microsoft.DotNet.Arcade.MSBuild.Xcopy/versions/17.12.0 - $defaultXCopyMSBuildVersion = '17.12.0' + # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/Microsoft.DotNet.Arcade.MSBuild.Xcopy/versions/17.13.0 + $defaultXCopyMSBuildVersion = '17.13.0' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { @@ -604,14 +602,7 @@ function InitializeBuildTool() { } $dotnetPath = Join-Path $dotnetRoot (GetExecutableFileName 'dotnet') - # Use override if it exists - commonly set by source-build - if ($null -eq $env:_OverrideArcadeInitializeBuildToolFramework) { - $initializeBuildToolFramework="net9.0" - } else { - $initializeBuildToolFramework=$env:_OverrideArcadeInitializeBuildToolFramework - } - - $buildTool = @{ Path = $dotnetPath; Command = 'msbuild'; Tool = 'dotnet'; Framework = $initializeBuildToolFramework } + $buildTool = @{ Path = $dotnetPath; Command = 'msbuild'; Tool = 'dotnet'; Framework = 'net' } } elseif ($msbuildEngine -eq "vs") { try { $msbuildPath = InitializeVisualStudioMSBuild -install:$restore @@ -620,7 +611,7 @@ function InitializeBuildTool() { ExitWithExitCode 1 } - $buildTool = @{ Path = $msbuildPath; Command = ""; Tool = "vs"; Framework = "net472"; ExcludePrereleaseVS = $excludePrereleaseVS } + $buildTool = @{ Path = $msbuildPath; Command = ""; Tool = "vs"; Framework = "netframework"; ExcludePrereleaseVS = $excludePrereleaseVS } } else { Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unexpected value of -msbuildEngine: '$msbuildEngine'." ExitWithExitCode 1 @@ -653,7 +644,6 @@ function GetNuGetPackageCachePath() { $env:NUGET_PACKAGES = Join-Path $env:UserProfile '.nuget\packages\' } else { $env:NUGET_PACKAGES = Join-Path $RepoRoot '.packages\' - $env:RESTORENOHTTPCACHE = $true } } @@ -775,26 +765,13 @@ function MSBuild() { $toolsetBuildProject = InitializeToolset $basePath = Split-Path -parent $toolsetBuildProject - $possiblePaths = @( - # new scripts need to work with old packages, so we need to look for the old names/versions - (Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.ArcadeLogging.dll')), - (Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.Arcade.Sdk.dll')), - (Join-Path $basePath (Join-Path net7.0 'Microsoft.DotNet.ArcadeLogging.dll')), - (Join-Path $basePath (Join-Path net7.0 'Microsoft.DotNet.Arcade.Sdk.dll')), - (Join-Path $basePath (Join-Path net8.0 'Microsoft.DotNet.ArcadeLogging.dll')), - (Join-Path $basePath (Join-Path net8.0 'Microsoft.DotNet.Arcade.Sdk.dll')) - ) - $selectedPath = $null - foreach ($path in $possiblePaths) { - if (Test-Path $path -PathType Leaf) { - $selectedPath = $path - break - } - } + $selectedPath = Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.ArcadeLogging.dll') + if (-not $selectedPath) { - Write-PipelineTelemetryError -Category 'Build' -Message 'Unable to find arcade sdk logger assembly.' + Write-PipelineTelemetryError -Category 'Build' -Message "Unable to find arcade sdk logger assembly: $selectedPath" ExitWithExitCode 1 } + $args += "/logger:$selectedPath" } @@ -857,8 +834,8 @@ function MSBuild-Core() { } # When running on Azure Pipelines, override the returned exit code to avoid double logging. - # Skip this when the build is a child of the VMR orchestrator build. - if ($ci -and $env:SYSTEM_TEAMPROJECT -ne $null -and !$productBuild -and -not($properties -like "*DotNetBuildRepo=true*")) { + # Skip this when the build is a child of the VMR build. + if ($ci -and $env:SYSTEM_TEAMPROJECT -ne $null -and !$fromVMR) { 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/src/vstest/eng/common/tools.sh b/src/vstest/eng/common/tools.sh index 01b09b65796..3def02a638d 100644 --- a/src/vstest/eng/common/tools.sh +++ b/src/vstest/eng/common/tools.sh @@ -5,6 +5,9 @@ # CI mode - set to true on CI server for PR validation build or official build. ci=${ci:-false} +# Build mode +source_build=${source_build:-false} + # Set to true to use the pipelines logger which will enable Azure logging output. # https://github.com/Microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md # This flag is meant as a temporary opt-opt for the feature while validate it across @@ -58,7 +61,8 @@ use_installed_dotnet_cli=${use_installed_dotnet_cli:-true} dotnetInstallScriptVersion=${dotnetInstallScriptVersion:-'v1'} # True to use global NuGet cache instead of restoring packages to repository-local directory. -if [[ "$ci" == true ]]; then +# Keep in sync with NuGetPackageroot in Arcade SDK's RepositoryLayout.props. +if [[ "$ci" == true || "$source_build" == true ]]; then use_global_nuget_cache=${use_global_nuget_cache:-false} else use_global_nuget_cache=${use_global_nuget_cache:-true} @@ -68,8 +72,8 @@ fi runtime_source_feed=${runtime_source_feed:-''} runtime_source_feed_key=${runtime_source_feed_key:-''} -# True if the build is a product build -product_build=${product_build:-false} +# True when the build is running within the VMR. +from_vmr=${from_vmr:-false} # Resolve any symlinks in the given path. function ResolvePath { @@ -339,22 +343,14 @@ function InitializeBuildTool { # return values _InitializeBuildTool="$_InitializeDotNetCli/dotnet" _InitializeBuildToolCommand="msbuild" - # use override if it exists - commonly set by source-build - if [[ "${_OverrideArcadeInitializeBuildToolFramework:-x}" == "x" ]]; then - _InitializeBuildToolFramework="net9.0" - else - _InitializeBuildToolFramework="${_OverrideArcadeInitializeBuildToolFramework}" - fi } -# 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/" else export NUGET_PACKAGES="$repo_root/.packages/" - export RESTORENOHTTPCACHE=true fi fi @@ -451,25 +447,13 @@ function MSBuild { fi local toolset_dir="${_InitializeToolset%/*}" - # new scripts need to work with old packages, so we need to look for the old names/versions - local selectedPath= - local possiblePaths=() - possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.ArcadeLogging.dll" ) - possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/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 - break - fi - done + local selectedPath="$toolset_dir/net/Microsoft.DotNet.ArcadeLogging.dll" + if [[ -z "$selectedPath" ]]; then - Write-PipelineTelemetryError -category 'Build' "Unable to find arcade sdk logger assembly." + Write-PipelineTelemetryError -category 'Build' "Unable to find arcade sdk logger assembly: $selectedPath" ExitWithExitCode 1 fi + args+=( "-logger:$selectedPath" ) fi @@ -506,8 +490,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. - # 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 + # Skip this when the build is a child of the VMR build. + if [[ "$ci" == true && -n ${SYSTEM_TEAMPROJECT:-} && "$from_vmr" != 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 @@ -530,6 +514,13 @@ function GetDarc { fi "$eng_root/common/darc-init.sh" --toolpath "$darc_path" $version + darc_tool="$darc_path/darc" +} + +# Returns a full path to an Arcade SDK task project file. +function GetSdkTaskProject { + taskName=$1 + echo "$(dirname $_InitializeToolset)/SdkTasks/$taskName.proj" } ResolvePath "${BASH_SOURCE[0]}" diff --git a/src/vstest/eng/common/vmr-sync.ps1 b/src/vstest/eng/common/vmr-sync.ps1 new file mode 100644 index 00000000000..97302f3205b --- /dev/null +++ b/src/vstest/eng/common/vmr-sync.ps1 @@ -0,0 +1,138 @@ +<# +.SYNOPSIS + +This script is used for synchronizing the current repository into a local VMR. +It pulls the current repository's code into the specified VMR directory for local testing or +Source-Build validation. + +.DESCRIPTION + +The tooling used for synchronization will clone the VMR repository into a temporary folder if +it does not already exist. These clones can be reused in future synchronizations, so it is +recommended to dedicate a folder for this to speed up re-runs. + +.EXAMPLE + Synchronize current repository into a local VMR: + ./vmr-sync.ps1 -vmrDir "$HOME/repos/dotnet" -tmpDir "$HOME/repos/tmp" + +.PARAMETER tmpDir +Required. Path to the temporary folder where repositories will be cloned + +.PARAMETER vmrBranch +Optional. Branch of the 'dotnet/dotnet' repo to synchronize. The VMR will be checked out to this branch + +.PARAMETER azdevPat +Optional. Azure DevOps PAT to use for cloning private repositories. + +.PARAMETER vmrDir +Optional. Path to the dotnet/dotnet repository. When null, gets cloned to the temporary folder + +.PARAMETER debugOutput +Optional. Enables debug logging in the darc vmr command. + +.PARAMETER ci +Optional. Denotes that the script is running in a CI environment. +#> +param ( + [Parameter(Mandatory=$true, HelpMessage="Path to the temporary folder where repositories will be cloned")] + [string][Alias('t', 'tmp')]$tmpDir, + [string][Alias('b', 'branch')]$vmrBranch, + [string]$remote, + [string]$azdevPat, + [string][Alias('v', 'vmr')]$vmrDir, + [switch]$ci, + [switch]$debugOutput +) + +function Fail { + Write-Host "> $($args[0])" -ForegroundColor 'Red' +} + +function Highlight { + Write-Host "> $($args[0])" -ForegroundColor 'Cyan' +} + +$verbosity = 'verbose' +if ($debugOutput) { + $verbosity = 'debug' +} +# Validation + +if (-not $tmpDir) { + Fail "Missing -tmpDir argument. Please specify the path to the temporary folder where the repositories will be cloned" + exit 1 +} + +# Sanitize the input + +if (-not $vmrDir) { + $vmrDir = Join-Path $tmpDir 'dotnet' +} + +if (-not (Test-Path -Path $tmpDir -PathType Container)) { + New-Item -ItemType Directory -Path $tmpDir | Out-Null +} + +# Prepare the VMR + +if (-not (Test-Path -Path $vmrDir -PathType Container)) { + Highlight "Cloning 'dotnet/dotnet' into $vmrDir.." + git clone https://github.com/dotnet/dotnet $vmrDir + + if ($vmrBranch) { + git -C $vmrDir switch -c $vmrBranch + } +} +else { + if ((git -C $vmrDir diff --quiet) -eq $false) { + Fail "There are changes in the working tree of $vmrDir. Please commit or stash your changes" + exit 1 + } + + if ($vmrBranch) { + Highlight "Preparing $vmrDir" + git -C $vmrDir checkout $vmrBranch + git -C $vmrDir pull + } +} + +Set-StrictMode -Version Latest + +# Prepare darc + +Highlight 'Installing .NET, preparing the tooling..' +. .\eng\common\tools.ps1 +$dotnetRoot = InitializeDotNetCli -install:$true +$darc = Get-Darc +$dotnet = "$dotnetRoot\dotnet.exe" + +Highlight "Starting the synchronization of VMR.." + +# Synchronize the VMR +$darcArgs = ( + "vmr", "forwardflow", + "--tmp", $tmpDir, + "--$verbosity", + $vmrDir +) + +if ($ci) { + $darcArgs += ("--ci") +} + +if ($azdevPat) { + $darcArgs += ("--azdev-pat", $azdevPat) +} + +& "$darc" $darcArgs + +if ($LASTEXITCODE -eq 0) { + Highlight "Synchronization succeeded" +} +else { + Fail "Synchronization of repo to VMR failed!" + Fail "'$vmrDir' is left in its last state (re-run of this script will reset it)." + Fail "Please inspect the logs which contain path to the failing patch file (use -debugOutput to get all the details)." + Fail "Once you make changes to the conflicting VMR patch, commit it locally and re-run this script." + exit 1 +} diff --git a/src/vstest/eng/common/vmr-sync.sh b/src/vstest/eng/common/vmr-sync.sh new file mode 100644 index 00000000000..44239e331c0 --- /dev/null +++ b/src/vstest/eng/common/vmr-sync.sh @@ -0,0 +1,207 @@ +#!/bin/bash + +### This script is used for synchronizing the current repository into a local VMR. +### It pulls the current repository's code into the specified VMR directory for local testing or +### Source-Build validation. +### +### The tooling used for synchronization will clone the VMR repository into a temporary folder if +### it does not already exist. These clones can be reused in future synchronizations, so it is +### recommended to dedicate a folder for this to speed up re-runs. +### +### USAGE: +### Synchronize current repository into a local VMR: +### ./vmr-sync.sh --tmp "$HOME/repos/tmp" "$HOME/repos/dotnet" +### +### Options: +### -t, --tmp, --tmp-dir PATH +### Required. Path to the temporary folder where repositories will be cloned +### +### -b, --branch, --vmr-branch BRANCH_NAME +### Optional. Branch of the 'dotnet/dotnet' repo to synchronize. The VMR will be checked out to this branch +### +### --debug +### Optional. Turns on the most verbose logging for the VMR tooling +### +### --remote name:URI +### Optional. Additional remote to use during the synchronization +### This can be used to synchronize to a commit from a fork of the repository +### Example: 'runtime:https://github.com/yourfork/runtime' +### +### --azdev-pat +### Optional. Azure DevOps PAT to use for cloning private repositories. +### +### -v, --vmr, --vmr-dir PATH +### Optional. Path to the dotnet/dotnet repository. When null, gets cloned to the temporary folder + +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 )" + +function print_help () { + sed -n '/^### /,/^$/p' "$source" | cut -b 5- +} + +COLOR_RED=$(tput setaf 1 2>/dev/null || true) +COLOR_CYAN=$(tput setaf 6 2>/dev/null || true) +COLOR_CLEAR=$(tput sgr0 2>/dev/null || true) +COLOR_RESET=uniquesearchablestring +FAILURE_PREFIX='> ' + +function fail () { + echo "${COLOR_RED}$FAILURE_PREFIX${1//${COLOR_RESET}/${COLOR_RED}}${COLOR_CLEAR}" >&2 +} + +function highlight () { + echo "${COLOR_CYAN}$FAILURE_PREFIX${1//${COLOR_RESET}/${COLOR_CYAN}}${COLOR_CLEAR}" +} + +tmp_dir='' +vmr_dir='' +vmr_branch='' +additional_remotes='' +verbosity=verbose +azdev_pat='' +ci=false + +while [[ $# -gt 0 ]]; do + opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" + case "$opt" in + -t|--tmp|--tmp-dir) + tmp_dir=$2 + shift + ;; + -v|--vmr|--vmr-dir) + vmr_dir=$2 + shift + ;; + -b|--branch|--vmr-branch) + vmr_branch=$2 + shift + ;; + --remote) + additional_remotes="$additional_remotes $2" + shift + ;; + --azdev-pat) + azdev_pat=$2 + shift + ;; + --ci) + ci=true + ;; + -d|--debug) + verbosity=debug + ;; + -h|--help) + print_help + exit 0 + ;; + *) + fail "Invalid argument: $1" + print_help + exit 1 + ;; + esac + + shift +done + +# Validation + +if [[ -z "$tmp_dir" ]]; then + fail "Missing --tmp-dir argument. Please specify the path to the temporary folder where the repositories will be cloned" + exit 1 +fi + +# Sanitize the input + +if [[ -z "$vmr_dir" ]]; then + vmr_dir="$tmp_dir/dotnet" +fi + +if [[ ! -d "$tmp_dir" ]]; then + mkdir -p "$tmp_dir" +fi + +if [[ "$verbosity" == "debug" ]]; then + set -x +fi + +# Prepare the VMR + +if [[ ! -d "$vmr_dir" ]]; then + highlight "Cloning 'dotnet/dotnet' into $vmr_dir.." + git clone https://github.com/dotnet/dotnet "$vmr_dir" + + if [[ -n "$vmr_branch" ]]; then + git -C "$vmr_dir" switch -c "$vmr_branch" + fi +else + if ! git -C "$vmr_dir" diff --quiet; then + fail "There are changes in the working tree of $vmr_dir. Please commit or stash your changes" + exit 1 + fi + + if [[ -n "$vmr_branch" ]]; then + highlight "Preparing $vmr_dir" + git -C "$vmr_dir" checkout "$vmr_branch" + git -C "$vmr_dir" pull + fi +fi + +set -e + +# Prepare darc + +highlight 'Installing .NET, preparing the tooling..' +source "./eng/common/tools.sh" +InitializeDotNetCli true +GetDarc +dotnetDir=$( cd ./.dotnet/; pwd -P ) +dotnet=$dotnetDir/dotnet + +highlight "Starting the synchronization of VMR.." +set +e + +if [[ -n "$additional_remotes" ]]; then + additional_remotes="--additional-remotes $additional_remotes" +fi + +if [[ -n "$azdev_pat" ]]; then + azdev_pat="--azdev-pat $azdev_pat" +fi + +ci_arg='' +if [[ "$ci" == "true" ]]; then + ci_arg="--ci" +fi + +# Synchronize the VMR + +export DOTNET_ROOT="$dotnetDir" + +"$darc_tool" vmr forwardflow \ + --tmp "$tmp_dir" \ + $azdev_pat \ + --$verbosity \ + $ci_arg \ + $additional_remotes \ + "$vmr_dir" + +if [[ $? == 0 ]]; then + highlight "Synchronization succeeded" +else + fail "Synchronization of repo to VMR failed!" + fail "'$vmr_dir' is left in its last state (re-run of this script will reset it)." + fail "Please inspect the logs which contain path to the failing patch file (use --debug to get all the details)." + fail "Once you make changes to the conflicting VMR patch, commit it locally and re-run this script." + exit 1 +fi diff --git a/src/vstest/eng/verify-nupkgs.ps1 b/src/vstest/eng/verify-nupkgs.ps1 index f1595e100f2..1d571723de0 100644 --- a/src/vstest/eng/verify-nupkgs.ps1 +++ b/src/vstest/eng/verify-nupkgs.ps1 @@ -17,9 +17,9 @@ Add-Type -AssemblyName System.IO.Compression.FileSystem function Verify-Nuget-Packages { Write-Host "Starting Verify-Nuget-Packages." $expectedNumOfFiles = @{ - "Microsoft.CodeCoverage" = 59; + "Microsoft.CodeCoverage" = 75; "Microsoft.NET.Test.Sdk" = 25; - "Microsoft.TestPlatform" = 619; + "Microsoft.TestPlatform" = 601; "Microsoft.TestPlatform.Build" = 20; "Microsoft.TestPlatform.CLI" = 481; "Microsoft.TestPlatform.Extensions.TrxLogger" = 34; diff --git a/src/vstest/global.json b/src/vstest/global.json index ae9cab826fc..ed7ad0de933 100644 --- a/src/vstest/global.json +++ b/src/vstest/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.106", + "version": "10.0.100-preview.6.25315.102", "rollForward": "minor", "allowPrerelease": false, "architecture": "x64" @@ -13,7 +13,8 @@ "5.0.17", "6.0.32", "7.0.20", - "8.0.7" + "8.0.7", + "9.0.5" ], "dotnet/x86": [ "2.1.30", @@ -21,16 +22,17 @@ "5.0.17", "6.0.32", "7.0.20", - "8.0.7" + "8.0.7", + "9.0.5" ] }, "vs": { "version": "17.8.0" }, "vswhere": "2.2.7", - "dotnet": "9.0.106" + "dotnet": "10.0.100-preview.6.25315.102" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.25302.2" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25358.3" } } diff --git a/src/vstest/playground/TestPlatform.Playground/TestPlatform.Playground.csproj b/src/vstest/playground/TestPlatform.Playground/TestPlatform.Playground.csproj index 620c160e2db..7259dc0728d 100644 --- a/src/vstest/playground/TestPlatform.Playground/TestPlatform.Playground.csproj +++ b/src/vstest/playground/TestPlatform.Playground/TestPlatform.Playground.csproj @@ -4,6 +4,14 @@ None $(MSBuildWarningsAsMessages);MSB3276 + + false + + false @@ -12,8 +20,8 @@ - - + + @@ -56,8 +64,8 @@ - - + + diff --git a/src/vstest/src/Microsoft.TestPlatform.Common/ExternalAssemblyVersions.cs b/src/vstest/src/Microsoft.TestPlatform.Common/ExternalAssemblyVersions.cs index 7e831df12f2..f05cf8adc33 100644 --- a/src/vstest/src/Microsoft.TestPlatform.Common/ExternalAssemblyVersions.cs +++ b/src/vstest/src/Microsoft.TestPlatform.Common/ExternalAssemblyVersions.cs @@ -10,5 +10,5 @@ internal class ExternalAssemblyVersions /// Microsoft.QualityTools.Testing.Fakes.TestRunnerHarness package. /// The Package version can be found in "eng\Versions.props" /// - internal const string MicrosoftFakesAssemblyVersion = "17.0.0.0"; + internal const string MicrosoftFakesAssemblyVersion = "18.0.0.0"; } diff --git a/src/vstest/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs b/src/vstest/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs index a20519373bb..5845c7b3b32 100644 --- a/src/vstest/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs +++ b/src/vstest/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs @@ -513,23 +513,115 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo( // i.e. I've got only private install and no global installation, in this case apphost needs to use env var to locate runtime. if (testHostExeFound) { - string prefix = "VSTEST_WINAPPHOST_"; - string dotnetRootEnvName = $"{prefix}DOTNET_ROOT(x86)"; - var dotnetRoot = _environmentVariableHelper.GetEnvironmentVariable(dotnetRootEnvName); - if (dotnetRoot is null) + // This change needs to happen first on vstest side, and then on dotnet/sdk, so prefer this approach and fallback to the old one. + // VSTEST_DOTNET_ROOT v2 + string? dotnetRootPath = _environmentVariableHelper.GetEnvironmentVariable("VSTEST_DOTNET_ROOT_PATH"); + if (!StringUtils.IsNullOrWhiteSpace(dotnetRootPath)) { - dotnetRootEnvName = $"{prefix}DOTNET_ROOT"; - dotnetRoot = _environmentVariableHelper.GetEnvironmentVariable(dotnetRootEnvName); - } + // This is v2 of the environment variables that we are passing, we are in new dotnet sdk. So also grab the architecture. + string? dotnetRootArchitecture = _environmentVariableHelper.GetEnvironmentVariable("VSTEST_DOTNET_ROOT_ARCHITECTURE"); - if (dotnetRoot != null) - { - EqtTrace.Verbose($"DotnetTestHostmanager.LaunchTestHostAsync: Found '{dotnetRootEnvName}' in env variables, value '{dotnetRoot}', forwarding to '{dotnetRootEnvName.Replace(prefix, string.Empty)}'"); - startInfo.EnvironmentVariables.Add(dotnetRootEnvName.Replace(prefix, string.Empty), dotnetRoot); + if (StringUtils.IsNullOrWhiteSpace(dotnetRootArchitecture)) + { + throw new InvalidOperationException("'VSTEST_DOTNET_ROOT_PATH' and 'VSTEST_DOTNET_ROOT_ARCHITECTURE' must be both always set. If you are seeing this error, this is a bug in dotnet SDK that sets those variables."); + } + + EqtTrace.Verbose($"DotnetTestHostmanager.LaunchTestHostAsync: VSTEST_DOTNET_ROOT_PATH={dotnetRootPath}"); + EqtTrace.Verbose($"DotnetTestHostmanager.LaunchTestHostAsync: VSTEST_DOTNET_ROOT_ARCHITECTURE={dotnetRootArchitecture}"); + + // The parent process is passing to us the path in which the dotnet.exe is and is passing the architecture of the dotnet.exe, + // so if the child process (testhost) is the same architecture it can pick up that dotnet.exe location and run. This is to allow + // local installations of dotnet/sdk to work with testhost. + // + // There are 2 complications in this process: + // 1) There are differences between how .NET Apphosts are handling DOTNET_ROOT, versions pre-net6 are only looking at + // DOTNET_ROOT(x86) and then DOTNET_ROOT. This makes is really easy to set DOTNET_ROOT to point at x64 dotnet installation + // and have that picked up by x86 testhost and fail. + // Unfortunately vstest.console has to support both new (17.14+) testhosts that are built against net8, and old (pre 17.14) + // testhosts that are built using netcoreapp3.1 apphost, and so their approach to resolving DOTNET_ROOT differ. + // + // /!\ The apphost version does not align with the targeted framework (tfm), an older testhost is built against netcoreapp3.1 + // but can be used to run net8 tests. The only way to tell is the version of the testhost. + // + // netcoreapp3.1 hosts only support DOTNET_ROOT and DOTNET_ROOT(x86) env variables. + // net8 hosts, support also DOTNET_ROOT_ variables, which is what we should prefer to set the location of dotnet + // in a more architecture specific way. + // + // 2) The surrounding environment might already have the environment variables set, most likely by setting DOTNET_ROOT, which is + // a universal way of setting where the dotnet is, that works across all different architectures of the .NET apphost. + // By setting our (hopefully more specific variable) we might overwrite what user specified, and in case of DOTNET_ROOT it is probably + // preferable when we can set the DOTNET_ROOT_ variable. + var testhostDllPath = Path.ChangeExtension(startInfo.FileName, ".dll"); + // This file check is for unit tests, we expect the file to always be there. Otherwise testhost.exe would not be able to run. + var testhostVersionInfo = _fileHelper.Exists(testhostDllPath) ? FileVersionInfo.GetVersionInfo(testhostDllPath) : null; + if (testhostVersionInfo != null && testhostVersionInfo.ProductMajorPart >= 17 && testhostVersionInfo.ProductMinorPart >= 14) + { + // This is a new testhost that builds at least against net8 we should set the architecture specific DOTNET_ROOT_. + // + // We ship just testhost.exe and testhost.x86.exe if the architecture is different we won't find the testhost*.exe and + // won't reach this code, but let's write this in a generic way anyway, to avoid breaking if we add more variants of testhost*.exe. + var environmentVariableName = $"DOTNET_ROOT_{_architecture.ToString().ToUpperInvariant()}"; + + var existingDotnetRoot = _environmentVariableHelper.GetEnvironmentVariable(environmentVariableName); + if (!StringUtilities.IsNullOrWhiteSpace(existingDotnetRoot)) + { + // The variable is already set in the surrounding environment, don't set it, because we want to keep what user provided. + } + else + { + // Set the architecture specific variable to the environment of the process so it is picked up. + startInfo.EnvironmentVariables.Add(environmentVariableName, dotnetRootPath); + } + } + else + { + // This is an old testhost that built against netcoreapp3.1, it does not understand architecture specific DOTNET_ROOT_, we have to set it more carefully + // to avoid setting DOTNET_ROOT that points to x64 but is picked up by x86 host. + // + // Also avoid setting it if we are already getting it from the surrounding environment. + var architectureFromEnv = (Architecture)Enum.Parse(typeof(Architecture), dotnetRootArchitecture, ignoreCase: true); + if (architectureFromEnv == _architecture) + { + if (_architecture == Architecture.X86) + { + const string dotnetRootX86 = "DOTNET_ROOT(x86)"; + if (StringUtils.IsNullOrWhiteSpace(_environmentVariableHelper.GetEnvironmentVariable(dotnetRootX86))) + { + startInfo.EnvironmentVariables.Add(dotnetRootX86, dotnetRootPath); + } + } + else + { + const string dotnetRoot = "DOTNET_ROOT"; + if (StringUtils.IsNullOrWhiteSpace(_environmentVariableHelper.GetEnvironmentVariable(dotnetRoot))) + { + startInfo.EnvironmentVariables.Add(dotnetRoot, dotnetRootPath); + } + } + } + } } else { - EqtTrace.Verbose($"DotnetTestHostmanager.LaunchTestHostAsync: Prefix '{prefix}*' not found in env variables"); + // Fallback, can delete this once the change is in dotnet sdk. because they are always used together. + string prefix = "VSTEST_WINAPPHOST_"; + string dotnetRootEnvName = $"{prefix}DOTNET_ROOT(x86)"; + var dotnetRoot = _environmentVariableHelper.GetEnvironmentVariable(dotnetRootEnvName); + if (dotnetRoot is null) + { + dotnetRootEnvName = $"{prefix}DOTNET_ROOT"; + dotnetRoot = _environmentVariableHelper.GetEnvironmentVariable(dotnetRootEnvName); + } + + if (dotnetRoot != null) + { + EqtTrace.Verbose($"DotnetTestHostmanager.LaunchTestHostAsync: Found '{dotnetRootEnvName}' in env variables, value '{dotnetRoot}', forwarding to '{dotnetRootEnvName.Replace(prefix, string.Empty)}'"); + startInfo.EnvironmentVariables.Add(dotnetRootEnvName.Replace(prefix, string.Empty), dotnetRoot); + } + else + { + EqtTrace.Verbose($"DotnetTestHostmanager.LaunchTestHostAsync: Prefix '{prefix}*' not found in env variables"); + } } } diff --git a/src/vstest/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleRequestSender.cs b/src/vstest/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleRequestSender.cs index e72355cd5b2..4c623ed472d 100644 --- a/src/vstest/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleRequestSender.cs +++ b/src/vstest/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleRequestSender.cs @@ -1197,7 +1197,7 @@ private void SendMessageAndListenAndReportTestResults( EqtTrace.Error("Aborting Test Run Operation: {0}", exception); eventHandler.HandleLogMessage( TestMessageLevel.Error, - TranslationLayerResources.AbortedTestsRun); + TranslationLayerResources.AbortedTestsRun + " " + exception.ToString()); var completeArgs = new TestRunCompleteEventArgs( null, false, true, exception, null, null, TimeSpan.Zero); eventHandler.HandleTestRunComplete(completeArgs, null, null, null); @@ -1282,7 +1282,7 @@ private async Task SendMessageAndListenAndReportTestResultsAsync( EqtTrace.Error("Aborting Test Run Operation: {0}", exception); eventHandler.HandleLogMessage( TestMessageLevel.Error, - TranslationLayerResources.AbortedTestsRun); + TranslationLayerResources.AbortedTestsRun + " " + exception.ToString()); var completeArgs = new TestRunCompleteEventArgs( null, false, true, exception, null, null, TimeSpan.Zero); eventHandler.HandleTestRunComplete(completeArgs, null, null, null); diff --git a/src/vstest/src/package/Microsoft.CodeCoverage/Microsoft.CodeCoverage.csproj b/src/vstest/src/package/Microsoft.CodeCoverage/Microsoft.CodeCoverage.csproj index 64ed693b4ca..11f305b2150 100644 --- a/src/vstest/src/package/Microsoft.CodeCoverage/Microsoft.CodeCoverage.csproj +++ b/src/vstest/src/package/Microsoft.CodeCoverage/Microsoft.CodeCoverage.csproj @@ -1,4 +1,4 @@ - + - - - - - - - - - - - - - + diff --git a/src/vstest/src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.csproj b/src/vstest/src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.csproj index 46ebe5d69b1..194eac7e864 100644 --- a/src/vstest/src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.csproj +++ b/src/vstest/src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.csproj @@ -1,4 +1,4 @@ - + $(TestHostAllTargetFrameworks) @@ -25,12 +25,6 @@ This package contains the full set of binaries for the Visual Studio Test Platform (vstest). It provides a modern, cross platform testing engine that powers the testing on .NET Core as well. It integrates with popular test frameworks like MSTest(v1 and v2), xUnit and Nunit with support for extensibility. - - The package supports running Coded UI tests. - While running Coded UI tests, you must ensure that the package version matches the major version of Visual Studio used to build the test binaries. - For example, if your Coded UI test project was built using Visual Studio 2019 (version 16.x), you must use test platform version 16.x. - Coded UI test is deprecated (https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#test-tools) and - Visual Studio 2019 (Test Platform version 16.x) will be the last version with Coded UI test functionality. LICENSE_VS.txt @@ -83,8 +77,6 @@ --> - - @@ -102,7 +94,6 @@ - @@ -111,7 +102,6 @@ - @@ -127,8 +117,7 @@ - - + @@ -136,7 +125,6 @@ - @@ -152,7 +140,6 @@ - diff --git a/src/vstest/src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.nuspec b/src/vstest/src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.nuspec index a2e27146bc1..75cdafdd6bd 100644 --- a/src/vstest/src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.nuspec +++ b/src/vstest/src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.nuspec @@ -58,8 +58,6 @@ - - @@ -98,8 +96,6 @@ - - @@ -238,29 +234,6 @@ - - - - - - - - - - - - - - - - - - - - - - - @@ -426,7 +399,6 @@ - @@ -457,59 +429,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/src/vstest/src/package/Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI/Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI.csproj b/src/vstest/src/package/Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI/Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI.csproj index bf5410cb19e..428a98d2e7a 100644 --- a/src/vstest/src/package/Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI/Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI.csproj +++ b/src/vstest/src/package/Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI/Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI.csproj @@ -31,7 +31,6 @@ $(ArtifactsBinDir)Microsoft.TestPlatform.CLI\$(Configuration)\$(NetFrameworkMinimum)\ $(ArtifactsBinDir)Microsoft.TestPlatform\$(Configuration)\$(NetFrameworkRunnerTargetFramework)\ $(TestPlatformBinFolder)Microsoft.Internal.Dia\ - $(TestPlatformBinFolder)Microsoft.VisualStudio.CUIT\ $(TestPlatformBinFolder)Microsoft.CodeCoverage.IO\ $(TestPlatformBinFolder)Microsoft.VisualStudio.QualityTools\ $(TestPlatformBinFolder)Microsoft.Extensions.DependencyModel\ @@ -141,25 +140,6 @@ - - - - CUITPlugins - - - CUITPlugins - - - - - - - - - - - - diff --git a/src/vstest/src/testhost.x86/app.config b/src/vstest/src/testhost.x86/app.config index 80f1fde9297..b06017b279b 100644 --- a/src/vstest/src/testhost.x86/app.config +++ b/src/vstest/src/testhost.x86/app.config @@ -18,7 +18,7 @@ - + @@ -26,23 +26,23 @@ - + - + - + - + - + diff --git a/src/vstest/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs b/src/vstest/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs index f93857b671b..63f8d99c09c 100644 --- a/src/vstest/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs +++ b/src/vstest/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs @@ -1600,6 +1600,7 @@ internal static class KnownPlatformSourceFilter "Microsoft.Testing.Extensions.HangDump.resources.dll", "Microsoft.Testing.Extensions.HotReload.dll", "Microsoft.Testing.Extensions.HotReload.resources.dll", + "Microsoft.Testing.Extensions.MSBuild.dll", "Microsoft.Testing.Extensions.Retry.dll", "Microsoft.Testing.Extensions.Retry.resources.dll", "Microsoft.Testing.Extensions.Telemetry.dll", diff --git a/src/vstest/src/vstest.console/app.config b/src/vstest/src/vstest.console/app.config index bd074de580e..3f040b9d206 100644 --- a/src/vstest/src/vstest.console/app.config +++ b/src/vstest/src/vstest.console/app.config @@ -14,11 +14,11 @@ - + - + diff --git a/src/vstest/test/DataCollectors/Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests/Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests.csproj b/src/vstest/test/DataCollectors/Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests/Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests.csproj index d0bf3ef5c38..3d675a513fd 100644 --- a/src/vstest/test/DataCollectors/Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests/Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests.csproj +++ b/src/vstest/test/DataCollectors/Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests/Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests.csproj @@ -5,6 +5,7 @@ true false + Exe diff --git a/src/vstest/test/Directory.Build.props b/src/vstest/test/Directory.Build.props index 6f5b8d7bf3c..b93c6783d24 100644 --- a/src/vstest/test/Directory.Build.props +++ b/src/vstest/test/Directory.Build.props @@ -3,5 +3,16 @@ true + true + + true + + + + diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/.runsettings b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/.runsettings new file mode 100644 index 00000000000..823b5bb2d55 --- /dev/null +++ b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/.runsettings @@ -0,0 +1,5 @@ + + + true + + \ No newline at end of file diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Build.cs b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Build.cs index 8fab97215f8..8dd581b00ff 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Build.cs +++ b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Build.cs @@ -62,7 +62,17 @@ private static void CopyAndPatchDotnet() // e.g. artifacts\tmp\.dotnet\sdk\ var sdkDirectory = Path.Combine(patchedDotnetDir, "sdk"); // e.g. artifacts\tmp\.dotnet\sdk\8.0.100-preview.6.23330.14 - var dotnetSdkDirectory = Directory.GetDirectories(sdkDirectory).Single(); + var dotnetSdkDirectories = Directory.GetDirectories(sdkDirectory); + if (dotnetSdkDirectories.Length == 0) + { + throw new InvalidOperationException($"No .NET SDK directories found in '{sdkDirectory}'."); + } + if (dotnetSdkDirectories.Length > 1) + { + throw new InvalidOperationException($"More than 1 .NET SDK directories found in '{sdkDirectory}': {string.Join(", ", dotnetSdkDirectories)}."); + } + + var dotnetSdkDirectory = dotnetSdkDirectories.Single(); DirectoryUtils.CopyDirectory(Path.Combine(packagePath, "lib", "netstandard2.0"), dotnetSdkDirectory); DirectoryUtils.CopyDirectory(Path.Combine(packagePath, "runtimes", "any", "native"), dotnetSdkDirectory); } diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/CUITTest.cs b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/CUITTest.cs deleted file mode 100644 index 96f8da27c67..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/CUITTest.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using Microsoft.TestPlatform.TestUtilities; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Microsoft.TestPlatform.AcceptanceTests; - -[TestClass] -[TestCategory("Windows-Review")] -public class CuitTest : AcceptanceTestBase -{ - [TestMethod] - [TestCategory("Windows-Review")] - [NetFullTargetFrameworkDataSource] - public void CuitRunAllTests(RunnerInfo runnerInfo) - { - SetTestEnvironment(_testEnvironment, runnerInfo); - CuitRunAll(runnerInfo); - } - - private void CuitRunAll(RunnerInfo runnerInfo) - { - if (runnerInfo.IsNetRunner) - { - Assert.Inconclusive("CUIT tests are not supported with .NET Core runner."); - return; - } - - var assemblyAbsolutePath = _testEnvironment.GetTestAsset("CUITTestProject.dll", "net462"); - var arguments = PrepareArguments(assemblyAbsolutePath, string.Empty, string.Empty, FrameworkArgValue, resultsDirectory: TempDirectory.Path); - arguments += " -- RunConfiguration.TargetPlatform=x86"; - - InvokeVsTest(arguments); - ValidateSummaryStatus(1, 0, 0); - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestMSBuildOutputTests.cs b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestMSBuildOutputTests.cs index 3aca6e7e04f..995ee1e133b 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestMSBuildOutputTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestMSBuildOutputTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using System.IO; using Microsoft.TestPlatform.TestUtilities; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -24,7 +25,7 @@ public void MSBuildLoggerCanBeEnabledByBuildPropertyAndDoesNotEatSpecialChars(Ru var projectPath = GetIsolatedTestAsset("TerminalLoggerTestProject.csproj"); // Forcing terminal logger so we can see the output when it is redirected - InvokeDotnetTest($@"{projectPath} -tl:on -nodereuse:false /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}"); + InvokeDotnetTest($@"{projectPath} -tl:on -nodereuse:false /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}", workingDirectory: Path.GetDirectoryName(projectPath)); // The output: // Determining projects to restore... @@ -53,7 +54,7 @@ public void MSBuildLoggerCanBeDisabledByBuildProperty(RunnerInfo runnerInfo) SetTestEnvironment(_testEnvironment, runnerInfo); var projectPath = GetIsolatedTestAsset("TerminalLoggerTestProject.csproj"); - InvokeDotnetTest($@"{projectPath} -nodereuse:false /p:VsTestUseMSBuildOutput=false /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}"); + InvokeDotnetTest($@"{projectPath} -nodereuse:false /p:VsTestUseMSBuildOutput=false /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}", workingDirectory: Path.GetDirectoryName(projectPath)); // Check that we see the summary that is printed from the console logger, meaning the new output is disabled. StdOutputContains("Failed! - Failed: 1, Passed: 1, Skipped: 1, Total: 3, Duration:"); @@ -73,7 +74,7 @@ public void MSBuildLoggerCanBeDisabledByEnvironmentVariableProperty(RunnerInfo r SetTestEnvironment(_testEnvironment, runnerInfo); var projectPath = GetIsolatedTestAsset("TerminalLoggerTestProject.csproj"); - InvokeDotnetTest($@"{projectPath} -nodereuse:false /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}", environmentVariables: new Dictionary { ["MSBUILDENSURESTDOUTFORTASKPROCESSES"] = "1" }); + InvokeDotnetTest($@"{projectPath} -nodereuse:false /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}", environmentVariables: new Dictionary { ["MSBUILDENSURESTDOUTFORTASKPROCESSES"] = "1" }, workingDirectory: Path.GetDirectoryName(projectPath)); // Check that we see the summary that is printed from the console logger, meaning the new output is disabled. StdOutputContains("Failed! - Failed: 1, Passed: 1, Skipped: 1, Total: 3, Duration:"); diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestTests.cs b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestTests.cs index 0332671357d..86f0dd308cf 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestTests.cs @@ -26,7 +26,7 @@ public void RunDotnetTestWithCsproj(RunnerInfo runnerInfo) SetTestEnvironment(_testEnvironment, runnerInfo); var projectPath = GetIsolatedTestAsset("SimpleTestProject.csproj"); - InvokeDotnetTest($@"{projectPath} -p:VSTestUseMSBuildOutput=false --logger:""Console;Verbosity=normal"" /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}"); + InvokeDotnetTest($@"{projectPath} -p:VSTestUseMSBuildOutput=false --logger:""Console;Verbosity=normal"" /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}", workingDirectory: Path.GetDirectoryName(projectPath)); // ensure our dev version is used StdOutputContains(GetFinalVersion(IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion)); @@ -43,7 +43,7 @@ public void RunDotnetTestWithDll(RunnerInfo runnerInfo) SetTestEnvironment(_testEnvironment, runnerInfo); var assemblyPath = GetAssetFullPath("SimpleTestProject.dll"); - InvokeDotnetTest($@"{assemblyPath} --logger:""Console;Verbosity=normal"""); + InvokeDotnetTest($@"{assemblyPath} --logger:""Console;Verbosity=normal""", workingDirectory: Path.GetDirectoryName(assemblyPath)); // ensure our dev version is used StdOutputContains(GetFinalVersion(IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion)); @@ -60,7 +60,7 @@ public void RunDotnetTestWithCsprojPassInlineSettings(RunnerInfo runnerInfo) SetTestEnvironment(_testEnvironment, runnerInfo); var projectPath = GetIsolatedTestAsset("ParametrizedTestProject.csproj"); - InvokeDotnetTest($@"{projectPath} --logger:""Console;Verbosity=normal"" -p:VSTestUseMSBuildOutput=false /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion} -- TestRunParameters.Parameter(name =\""weburl\"", value=\""http://localhost//def\"")"); + InvokeDotnetTest($@"{projectPath} --logger:""Console;Verbosity=normal"" -p:VSTestUseMSBuildOutput=false /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion} -- TestRunParameters.Parameter(name =\""weburl\"", value=\""http://localhost//def\"")", workingDirectory: Path.GetDirectoryName(projectPath)); ValidateSummaryStatus(1, 0, 0); ExitCodeEquals(0); @@ -75,7 +75,7 @@ public void RunDotnetTestWithDllPassInlineSettings(RunnerInfo runnerInfo) SetTestEnvironment(_testEnvironment, runnerInfo); var assemblyPath = GetAssetFullPath("ParametrizedTestProject.dll"); - InvokeDotnetTest($@"{assemblyPath} --logger:""Console;Verbosity=normal"" -- TestRunParameters.Parameter(name=\""weburl\"", value=\""http://localhost//def\"")"); + InvokeDotnetTest($@"{assemblyPath} --logger:""Console;Verbosity=normal"" -- TestRunParameters.Parameter(name=\""weburl\"", value=\""http://localhost//def\"")", workingDirectory: Path.GetDirectoryName(assemblyPath)); ValidateSummaryStatus(1, 0, 0); ExitCodeEquals(0); @@ -93,7 +93,7 @@ public void RunDotnetTestWithNativeDll(RunnerInfo runnerInfo) string assemblyRelativePath = @"microsoft.testplatform.testasset.nativecpp\2.0.0\contentFiles\any\any\x64\Microsoft.TestPlatform.TestAsset.NativeCPP.dll"; var assemblyAbsolutePath = Path.Combine(_testEnvironment.PackageDirectory, assemblyRelativePath); - InvokeDotnetTest($@"{assemblyAbsolutePath} --logger:""Console;Verbosity=normal"" --diag:c:\temp\logscpp\"); + InvokeDotnetTest($@"{assemblyAbsolutePath} --logger:""Console;Verbosity=normal"" --diag:c:\temp\logscpp\", workingDirectory: Path.GetDirectoryName(assemblyAbsolutePath)); ValidateSummaryStatus(1, 1, 0); ExitCodeEquals(1); @@ -108,7 +108,7 @@ public void RunDotnetTestAndSeeOutputFromConsoleWriteLine(RunnerInfo runnerInfo) SetTestEnvironment(_testEnvironment, runnerInfo); var assemblyPath = GetAssetFullPath("OutputtingTestProject.dll"); - InvokeDotnetTest($@"{assemblyPath} --logger:""Console;Verbosity=normal"" "); + InvokeDotnetTest($@"{assemblyPath} --logger:""Console;Verbosity=normal"" ", workingDirectory: Path.GetDirectoryName(assemblyPath)); StdOutputContains("MY OUTPUT FROM TEST"); diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Microsoft.TestPlatform.Acceptance.IntegrationTests.csproj b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Microsoft.TestPlatform.Acceptance.IntegrationTests.csproj index c13550e38a4..b675da74546 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Microsoft.TestPlatform.Acceptance.IntegrationTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Microsoft.TestPlatform.Acceptance.IntegrationTests.csproj @@ -4,10 +4,11 @@ true true true + $(TestRunnerAdditionalArguments) --settings "$(MSBuildThisFileDirectory)\.runsettings" - Exe + Exe net9.0;net48 diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Program.cs deleted file mode 100644 index 360f5003ae1..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Program.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#pragma warning disable IDE1006 // Naming Styles -namespace testhost.UnitTests; -#pragma warning restore IDE1006 // Naming Styles - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/RunsettingsTests.cs b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/RunsettingsTests.cs index 3546759ab5b..4eec7dc7d02 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/RunsettingsTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/RunsettingsTests.cs @@ -307,6 +307,7 @@ public void LegacySettingsWithPlatform(RunnerInfo runnerInfo) } [TestMethod] + [Ignore("Ignore until we have new host available with CUIT removed.")] [TestCategory("Windows-Review")] [NetFullTargetFrameworkDataSourceAttribute(inIsolation: true, useCoreRunner: false)] public void LegacySettingsWithScripts(RunnerInfo runnerInfo) @@ -353,6 +354,7 @@ public void LegacySettingsWithScripts(RunnerInfo runnerInfo) } [TestMethod] + [Ignore("Ignore until we have new host available with CUIT removed.")] [TestCategory("Windows-Review")] [NetFullTargetFrameworkDataSourceAttribute(inIsolation: true, useCoreRunner: false)] public void LegacySettingsWithDeploymentItem(RunnerInfo runnerInfo) @@ -390,6 +392,7 @@ public void LegacySettingsWithDeploymentItem(RunnerInfo runnerInfo) } [TestMethod] + [Ignore("Ignore until we have new host available with CUIT removed.")] [TestCategory("Windows")] [NetFullTargetFrameworkDataSourceAttribute(inIsolation: true, useCoreRunner: false)] public void LegacySettingsTestTimeout(RunnerInfo runnerInfo) @@ -417,6 +420,7 @@ public void LegacySettingsTestTimeout(RunnerInfo runnerInfo) } [TestMethod] + [Ignore("Ignore until we have new host available with CUIT removed.")] [TestCategory("Windows-Review")] [NetFullTargetFrameworkDataSourceAttribute(inIsolation: true, useCoreRunner: false)] public void LegacySettingsAssemblyResolution(RunnerInfo runnerInfo) @@ -507,7 +511,7 @@ public void RunSettingsAreLoadedFromProject(RunnerInfo runnerInfo) var projectName = "ProjectFileRunSettingsTestProject.csproj"; var projectPath = GetIsolatedTestAsset(projectName); - InvokeDotnetTest($@"{projectPath} /p:VSTestUseMSBuildOutput=false --logger:""Console;Verbosity=normal"" /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}"); + InvokeDotnetTest($@"{projectPath} /p:VSTestUseMSBuildOutput=false --logger:""Console;Verbosity=normal"" /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}", workingDirectory: Path.GetDirectoryName(projectPath)); ValidateSummaryStatus(0, 1, 0); // make sure that we can revert the project settings back by providing a config from command line @@ -515,7 +519,7 @@ public void RunSettingsAreLoadedFromProject(RunnerInfo runnerInfo) // are honored by dotnet test, instead of just using the default, which would produce the same // result var settingsPath = GetProjectAssetFullPath(projectName, "inconclusive.runsettings"); - InvokeDotnetTest($@"{projectPath} --settings {settingsPath} /p:VSTestUseMSBuildOutput=false --logger:""Console;Verbosity=normal"" /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}"); + InvokeDotnetTest($@"{projectPath} --settings {settingsPath} /p:VSTestUseMSBuildOutput=false --logger:""Console;Verbosity=normal"" /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}", workingDirectory: Path.GetDirectoryName(projectPath)); ValidateSummaryStatus(0, 0, 1); } diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TestPlatformNugetPackageTests.cs b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TestPlatformNugetPackageTests.cs index 5f55b852eb3..712e00b6e86 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TestPlatformNugetPackageTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TestPlatformNugetPackageTests.cs @@ -22,6 +22,7 @@ public static void ClassInit(TestContext _) [TestMethod] [TestCategory("Windows-Review")] + [Ignore("Code Coverage is using 17.x.x dependency, will be solved in other PR. https://github.com/microsoft/vstest/issues/15223")] [NetFullTargetFrameworkDataSourceAttribute(useCoreRunner: false)] [NetCoreTargetFrameworkDataSourceAttribute(useCoreRunner: false)] public void RunMultipleTestAssembliesWithCodeCoverage(RunnerInfo runnerInfo) diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TranslationLayerTests/CustomTestHostTests.cs b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TranslationLayerTests/CustomTestHostTests.cs index 9996f086e0f..cdff53add3f 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TranslationLayerTests/CustomTestHostTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TranslationLayerTests/CustomTestHostTests.cs @@ -1,9 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; +using System.Text; using System.Threading; using FluentAssertions; @@ -140,7 +143,8 @@ public void RunTestsWithCustomTestHostLauncherUsesLaunchWhenGivenAnOutdatedITest [TestMethod] [TestCategory("Windows-Review")] [TestCategory("Feature")] - [RunnerCompatibilityDataSource(AfterFeature = Features.MULTI_TFM)] + // "Just row" used here because mstest does not cooperate with older versions of vstest.console correctly, so we test with just the latest version available.. + [RunnerCompatibilityDataSource(AfterFeature = Features.MULTI_TFM, JustRow = 0)] public void RunAllTestsWithMixedTFMsWillProvideAdditionalInformationToTheDebugger(RunnerInfo runnerInfo) { // Arrange @@ -158,6 +162,27 @@ public void RunAllTestsWithMixedTFMsWillProvideAdditionalInformationToTheDebugge vstestConsoleWrapper.RunTestsWithCustomTestHost(new[] { netFrameworkDll, netDll }, runsettingsXml, runEventHandler, testHostLauncher); // Assert + if (runEventHandler.Errors.Any()) + { + var tempPath = TempDirectory.Path; + var files = System.IO.Directory.GetFiles(tempPath, "*.txt").ToList(); + if (files.Count == 0) + { + throw new InvalidOperationException($"No error files found in {tempPath}. {string.Join("\n", Directory.GetFiles(tempPath))}"); + } + + var allText = new StringBuilder(); + foreach (var file in files) + { +#pragma warning disable CA1305 // Specify IFormatProvider + allText.AppendLine($"Error file: {file}"); + allText.AppendLine(File.ReadAllText(file)); + allText.AppendLine(); +#pragma warning restore CA1305 // Specify IFormatProvider + } + throw new InvalidOperationException($"Logs: {allText}"); + } + runEventHandler.Errors.Should().BeEmpty(); testHostLauncher.AttachDebuggerInfos.Should().HaveCount(2); var targetFrameworks = testHostLauncher.AttachDebuggerInfos.Select(i => i.TargetFramework).ToList(); diff --git a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TranslationLayerTests/RunTestsWithDifferentConfigurationTests.cs b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TranslationLayerTests/RunTestsWithDifferentConfigurationTests.cs index abf6f49b7b1..b7717d4fe50 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TranslationLayerTests/RunTestsWithDifferentConfigurationTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/TranslationLayerTests/RunTestsWithDifferentConfigurationTests.cs @@ -102,7 +102,7 @@ public void RunTestsWithRunSettingsWithParallel(RunnerInfo runnerInfo) [TestMethod] [TestCategory("Windows-Review")] [NetFullTargetFrameworkDataSource()] - public void RunTestsWithTestSettings(RunnerInfo runnerInfo) + public void RunTestsWithTestSettingsInTpv2(RunnerInfo runnerInfo) { SetTestEnvironment(_testEnvironment, runnerInfo); ExecuteNotSupportedRunnerFrameworkTests(runnerInfo.RunnerFramework, NetFramework, Message); @@ -130,6 +130,72 @@ public void RunTestsWithTestSettings(RunnerInfo runnerInfo) Assert.AreEqual(1, _runEventHandler.TestResults.Count(t => t.Outcome == TestOutcome.Skipped)); } + [TestMethod] + [TestCategory("Windows-Review")] + [NetFullTargetFrameworkDataSource()] + public void RunTestsWithTestSettingsInTpv0(RunnerInfo runnerInfo) + { + SetTestEnvironment(_testEnvironment, runnerInfo); + ExecuteNotSupportedRunnerFrameworkTests(runnerInfo.RunnerFramework, NetFramework, Message); + Setup(); + + var testSettingsXml = """ + + + This is a default test run configuration for a local test run. + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + + """; + + var testsettingsFile = Path.Combine(TempDirectory.Path, "tempsettings.testsettings"); + + File.WriteAllText(testsettingsFile, testSettingsXml, Encoding.UTF8); + + var source = GetAssetFullPath("MstestV1UnitTestProject.dll"); + + InvokeVsTestForExecution(source, null, runnerInfo.TargetFramework, runSettings: testsettingsFile, null); + + // Assert + // Ensure that we are actually running via TPv0 provider. + StringAssert.Contains(StdOutWithWhiteSpace, "The test execution was delegated to legacy TestPlatform runner"); + + ValidateSummaryStatus(2, 2, 1); + ExitCodeEquals(1); // failing tests + StdErrHasTestRunFailedMessageButNoOtherError(); + } + [TestMethod] [NetFullTargetFrameworkDataSource] [NetCoreTargetFrameworkDataSource] diff --git a/src/vstest/test/Microsoft.TestPlatform.AdapterUtilities.UnitTests/Microsoft.TestPlatform.AdapterUtilities.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.AdapterUtilities.UnitTests/Microsoft.TestPlatform.AdapterUtilities.UnitTests.csproj index 3a908e87bc5..6fc895e272d 100644 --- a/src/vstest/test/Microsoft.TestPlatform.AdapterUtilities.UnitTests/Microsoft.TestPlatform.AdapterUtilities.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.AdapterUtilities.UnitTests/Microsoft.TestPlatform.AdapterUtilities.UnitTests.csproj @@ -6,7 +6,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.AdapterUtilities.UnitTests true $(NoWarn);RS1024 diff --git a/src/vstest/test/Microsoft.TestPlatform.AdapterUtilities.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.AdapterUtilities.UnitTests/Program.cs deleted file mode 100644 index 873e849545f..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.AdapterUtilities.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.TestPlatform.AdapterUtilities.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.Build.UnitTests/Microsoft.TestPlatform.Build.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.Build.UnitTests/Microsoft.TestPlatform.Build.UnitTests.csproj index 93638126374..a1197a83088 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Build.UnitTests/Microsoft.TestPlatform.Build.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.Build.UnitTests/Microsoft.TestPlatform.Build.UnitTests.csproj @@ -7,7 +7,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.Build.UnitTests diff --git a/src/vstest/test/Microsoft.TestPlatform.Build.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.Build.UnitTests/Program.cs deleted file mode 100644 index ff1507b8ea2..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.Build.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.TestPlatform.Build.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.Client.UnitTests/Microsoft.TestPlatform.Client.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.Client.UnitTests/Microsoft.TestPlatform.Client.UnitTests.csproj index 5839ea296be..890481f9771 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Client.UnitTests/Microsoft.TestPlatform.Client.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.Client.UnitTests/Microsoft.TestPlatform.Client.UnitTests.csproj @@ -7,7 +7,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.Client.UnitTests diff --git a/src/vstest/test/Microsoft.TestPlatform.Client.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.Client.UnitTests/Program.cs deleted file mode 100644 index 2f6d8d1a576..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.Client.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.VisualStudio.TestPlatform.Client.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.Common.UnitTests/Microsoft.TestPlatform.Common.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.Common.UnitTests/Microsoft.TestPlatform.Common.UnitTests.csproj index 37e4ae7b0f1..85a71355922 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Common.UnitTests/Microsoft.TestPlatform.Common.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.Common.UnitTests/Microsoft.TestPlatform.Common.UnitTests.csproj @@ -7,7 +7,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.Common.UnitTests diff --git a/src/vstest/test/Microsoft.TestPlatform.Common.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.Common.UnitTests/Program.cs deleted file mode 100644 index a5c6522e979..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.Common.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.VisualStudio.TestPlatform.Common.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests.csproj index 0605d93fd51..2e7b9725573 100644 --- a/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests.csproj @@ -7,7 +7,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.CommunicationUtilities.PlatformTests diff --git a/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests/Program.cs deleted file mode 100644 index b8f2141385d..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.Platform.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.TestPlatform.CommunicationUtilities.PlatformTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj index 99354bbad17..5d883492d23 100644 --- a/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj @@ -7,7 +7,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.CommunicationUtilities.UnitTests diff --git a/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Program.cs deleted file mode 100644 index a4932304d9d..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.TestPlatform.CommunicationUtilities.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Helpers/DotnetHostHelperTest.cs b/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Helpers/DotnetHostHelperTest.cs index ea802a56daf..39ca505872b 100644 --- a/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Helpers/DotnetHostHelperTest.cs +++ b/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Helpers/DotnetHostHelperTest.cs @@ -298,6 +298,7 @@ public void GetDotnetPathByArchitecture_DefaultInstallation_Win( Assert.AreEqual(found ? dotnetMuxer : null, muxerPath); } +#pragma warning disable MSTEST0042 // duplicate data row - TODO: Look more into it [DataTestMethod] [DataRow(PlatformArchitecture.X64, PlatformArchitecture.X64, "/usr/local/share/dotnet", "", true, PlatformOperatingSystem.OSX)] [DataRow(PlatformArchitecture.X64, PlatformArchitecture.ARM64, "/usr/local/share/dotnet/x64", "", true, PlatformOperatingSystem.OSX)] @@ -316,6 +317,7 @@ public void GetDotnetPathByArchitecture_DefaultInstallation_Win( [DataRow(PlatformArchitecture.X64, PlatformArchitecture.ARM64, "/usr/share/dotnet/x64", "", false, PlatformOperatingSystem.Unix, DotnetMuxerResolutionStrategy.DefaultInstallationLocation)] [DataRow(PlatformArchitecture.ARM64, PlatformArchitecture.X64, "/usr/share/dotnet", "", false, PlatformOperatingSystem.Unix, DotnetMuxerResolutionStrategy.DefaultInstallationLocation)] [DataRow(PlatformArchitecture.X64, PlatformArchitecture.X64, "/usr/share/dotnet", "", false, PlatformOperatingSystem.Unix, DotnetMuxerResolutionStrategy.DefaultInstallationLocation)] +#pragma warning restore MSTEST0042 public void GetDotnetPathByArchitecture_DefaultInstallation_Unix( PlatformArchitecture targetArchitecture, PlatformArchitecture platformArchitecture, diff --git a/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Microsoft.TestPlatform.CoreUtilities.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Microsoft.TestPlatform.CoreUtilities.UnitTests.csproj index 0999799a025..c0f492aed2b 100644 --- a/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Microsoft.TestPlatform.CoreUtilities.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Microsoft.TestPlatform.CoreUtilities.UnitTests.csproj @@ -7,7 +7,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.CoreUtilities.UnitTests diff --git a/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Program.cs deleted file mode 100644 index f027d8d6ce7..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Program.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace TestPlatform.CoreUtilities.UnitTests; - -/// -/// Main entry point for the command line runner. -/// -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscovererEnumeratorTests.cs b/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscovererEnumeratorTests.cs index 3215c024a30..802f7de7bda 100644 --- a/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscovererEnumeratorTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscovererEnumeratorTests.cs @@ -758,6 +758,7 @@ public static void Reset() } [FileExtension(".dll")] + [FileExtension(".exe")] [DefaultExecutorUri("discoverer://manageddlldiscoverer")] [Category("managed")] private class ManagedDllTestDiscoverer : DllTestDiscoverer @@ -781,6 +782,7 @@ public static void Reset() } [FileExtension(".dll")] + [FileExtension(".exe")] [DefaultExecutorUri("discoverer://nativedlldiscoverer")] [Category("native")] private class NativeDllTestDiscoverer : DllTestDiscoverer @@ -833,7 +835,7 @@ private static bool ShouldTestDiscovered(IEnumerable sources) var shouldTestDiscovered = false; foreach (var source in sources) { - if (source.Equals("native.dll") || source.Equals("managed.dll") || source.EndsWith("CrossPlatEngine.UnitTests.dll")) + if (source.Equals("native.dll") || source.Equals("managed.dll") || source.EndsWith("CrossPlatEngine.UnitTests.dll") || source.EndsWith("CrossPlatEngine.UnitTests.exe")) { shouldTestDiscovered = true; break; diff --git a/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs b/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs index ba5b3dd7287..89a81acd471 100644 --- a/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs @@ -382,6 +382,7 @@ public void CallInvokeExecutor(LazyExtension Microsoft.TestPlatform.CrossPlatEngine.UnitTests net9.0;net48 - Exe + Exe diff --git a/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Program.cs deleted file mode 100644 index 79c3743c992..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests.csproj index 1fe46f071b4..81efd08aad3 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests.csproj @@ -20,7 +20,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests diff --git a/src/vstest/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/Program.cs deleted file mode 100644 index 6333b3f0bc2..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests.csproj index de607265a61..7708ce4b170 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests.csproj @@ -7,7 +7,7 @@ net9.0;net48 - Exe + Exe diff --git a/src/vstest/test/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests/Program.cs deleted file mode 100644 index 0df49b12a6f..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.TestPlatform.Extensions.HtmlLogger.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests.csproj index 469621d3599..3df4825d3ee 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests.csproj @@ -7,7 +7,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests diff --git a/src/vstest/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Program.cs deleted file mode 100644 index f3ba5448d24..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Microsoft.TestPlatform.ObjectModel.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Microsoft.TestPlatform.ObjectModel.UnitTests.csproj index 2f8a9682787..744ca8bb296 100644 --- a/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Microsoft.TestPlatform.ObjectModel.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Microsoft.TestPlatform.ObjectModel.UnitTests.csproj @@ -7,7 +7,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.ObjectModel.UnitTests diff --git a/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Program.cs deleted file mode 100644 index 3911cf3a230..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.TestPlatform.ObjectModel.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/RunSettings/RunConfigurationTests.cs b/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/RunSettings/RunConfigurationTests.cs index cc548cd386b..c88336c7373 100644 --- a/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/RunSettings/RunConfigurationTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.ObjectModel.UnitTests/RunSettings/RunConfigurationTests.cs @@ -119,23 +119,23 @@ public void SetTargetFrameworkVersionShouldSetTargetFramework() { var runConfiguration = new RunConfiguration(); runConfiguration.TargetFrameworkVersion = FrameworkVersion.Framework35; - Equals(Framework.FromString("Framework35")!.Name, runConfiguration.TargetFramework!.Name); + Assert.AreEqual(Framework.FromString("Framework35")!.Name, runConfiguration.TargetFramework!.Name); Assert.AreEqual(FrameworkVersion.Framework35, runConfiguration.TargetFrameworkVersion); runConfiguration.TargetFrameworkVersion = FrameworkVersion.Framework40; - Equals(Framework.FromString("Framework40")!.Name, runConfiguration.TargetFramework.Name); + Assert.AreEqual(Framework.FromString("Framework40")!.Name, runConfiguration.TargetFramework.Name); Assert.AreEqual(FrameworkVersion.Framework40, runConfiguration.TargetFrameworkVersion); runConfiguration.TargetFrameworkVersion = FrameworkVersion.Framework45; - Equals(Framework.FromString("Framework45")!.Name, runConfiguration.TargetFramework.Name); + Assert.AreEqual(Framework.FromString("Framework45")!.Name, runConfiguration.TargetFramework.Name); Assert.AreEqual(FrameworkVersion.Framework45, runConfiguration.TargetFrameworkVersion); runConfiguration.TargetFrameworkVersion = FrameworkVersion.FrameworkCore10; - Equals(Framework.FromString("FrameworkCore10")!.Name, runConfiguration.TargetFramework.Name); + Assert.AreEqual(Framework.FromString("FrameworkCore10")!.Name, runConfiguration.TargetFramework.Name); Assert.AreEqual(FrameworkVersion.FrameworkCore10, runConfiguration.TargetFrameworkVersion); runConfiguration.TargetFrameworkVersion = FrameworkVersion.FrameworkUap10; - Equals(Framework.FromString("FrameworkUap10")!.Name, runConfiguration.TargetFramework.Name); + Assert.AreEqual(Framework.FromString("FrameworkUap10")!.Name, runConfiguration.TargetFramework.Name); Assert.AreEqual(FrameworkVersion.FrameworkUap10, runConfiguration.TargetFrameworkVersion); } diff --git a/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs b/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs index 997d4741f09..2ee8d94b3a9 100644 --- a/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs +++ b/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs @@ -86,7 +86,6 @@ public DotnetTestHostManagerTests() _mockProcessHelper.Setup(ph => ph.GetCurrentProcessFileName()).Returns(DefaultDotnetPath); _mockProcessHelper.Setup(ph => ph.GetTestEngineDirectory()).Returns(DefaultDotnetPath); _mockProcessHelper.Setup(ph => ph.GetCurrentProcessArchitecture()).Returns(PlatformArchitecture.X64); - _mockEnvironmentVariable.Setup(ev => ev.GetEnvironmentVariable(It.IsAny())).Returns(Path.GetDirectoryName(DefaultDotnetPath)!); _mockFileHelper.Setup(ph => ph.Exists(_defaultTestHostPath)).Returns(true); _mockFileHelper.Setup(ph => ph.Exists(DefaultDotnetPath)).Returns(true); diff --git a/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Microsoft.TestPlatform.TestHostProvider.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Microsoft.TestPlatform.TestHostProvider.UnitTests.csproj index 4768c56dcba..09db15d7e8e 100644 --- a/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Microsoft.TestPlatform.TestHostProvider.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Microsoft.TestPlatform.TestHostProvider.UnitTests.csproj @@ -8,7 +8,7 @@ Microsoft.TestPlatform.TestHostProvider.UnitTests net9.0;net48 - Exe + Exe diff --git a/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Program.cs deleted file mode 100644 index 79c3743c992..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/Microsoft.TestPlatform.TestUtilities/IntegrationTestBase.cs b/src/vstest/test/Microsoft.TestPlatform.TestUtilities/IntegrationTestBase.cs index d1fe09ace23..2fab9fa01ce 100644 --- a/src/vstest/test/Microsoft.TestPlatform.TestUtilities/IntegrationTestBase.cs +++ b/src/vstest/test/Microsoft.TestPlatform.TestUtilities/IntegrationTestBase.cs @@ -46,7 +46,7 @@ public class IntegrationTestBase protected readonly IntegrationTestEnvironment _testEnvironment; private readonly string _msTestPre3_0AdapterRelativePath = @"mstest.testadapter\{0}\build\_common".Replace('\\', Path.DirectorySeparatorChar); - private readonly string _msTestAdapterRelativePath = @"mstest.testadapter\{0}\build\{1}".Replace('\\', Path.DirectorySeparatorChar); + private readonly string _msTestAdapterRelativePath = @"mstest.testadapter\{0}\buildTransitive\{1}".Replace('\\', Path.DirectorySeparatorChar); private readonly string _nUnitTestAdapterRelativePath = @"nunit3testadapter\{0}\build".Replace('\\', Path.DirectorySeparatorChar); private readonly string _xUnitTestAdapterRelativePath = @"xunit.runner.visualstudio\{0}\build\{1}".Replace('\\', Path.DirectorySeparatorChar); @@ -196,8 +196,17 @@ public void InvokeVsTest(string? arguments, Dictionary? environ /// /// Arguments provided to vstest.console.exe /// Environment variables to set to the started process. - public void InvokeDotnetTest(string arguments, Dictionary? environmentVariables = null) + /// + public void InvokeDotnetTest(string arguments, Dictionary? environmentVariables = null, string? workingDirectory = null) { + if (workingDirectory is not null && !File.Exists(Path.Combine(workingDirectory, "dotnet.config"))) + { + File.WriteAllText(Path.Combine(workingDirectory, "dotnet.config"), """ + [dotnet.test.runner] + name = "VSTest" + """); + } + var debugEnvironmentVariables = AddDebugEnvironmentVariables(environmentVariables); var vstestConsolePath = GetDotnetRunnerPath(); @@ -222,7 +231,7 @@ public void InvokeDotnetTest(string arguments, Dictionary? envi // https://github.com/dotnet/sdk/blob/main/src/Cli/dotnet/commands/dotnet-test/VSTestForwardingApp.cs#L30-L39 debugEnvironmentVariables["VSTEST_CONSOLE_PATH"] = vstestConsolePath; - IntegrationTestBase.ExecutePatchedDotnet("test", arguments, out _standardTestOutput, out _standardTestError, out _runnerExitCode, debugEnvironmentVariables); + IntegrationTestBase.ExecutePatchedDotnet("test", arguments, out _standardTestOutput, out _standardTestError, out _runnerExitCode, debugEnvironmentVariables, workingDirectory); FormatStandardOutCome(); } @@ -790,8 +799,9 @@ protected void ExecuteVsTestConsole(string? args, out string stdOut, out string /// /// /// Environment variables to set to the started process. + /// private static void ExecutePatchedDotnet(string command, string args, out string stdOut, out string stdError, out int exitCode, - Dictionary? environmentVariables = null) + Dictionary? environmentVariables = null, string? workingDirectory = null) { environmentVariables ??= new(); @@ -799,7 +809,7 @@ private static void ExecutePatchedDotnet(string command, string args, out string var executablePath = OSUtils.IsWindows ? @"dotnet.exe" : @"dotnet"; var patchedDotnetPath = Path.GetFullPath(Path.Combine(IntegrationTestEnvironment.RepoRootDirectory, "artifacts", "tmp", ".dotnet", executablePath)); - ExecuteApplication(patchedDotnetPath, string.Join(" ", command, args), out stdOut, out stdError, out exitCode, environmentVariables); + ExecuteApplication(patchedDotnetPath, string.Join(" ", command, args), out stdOut, out stdError, out exitCode, environmentVariables, workingDirectory); } protected static void ExecuteApplication(string path, string? args, out string stdOut, out string stdError, out int exitCode, @@ -855,6 +865,7 @@ protected static void ExecuteApplication(string path, string? args, out string s Console.WriteLine("IntegrationTestBase.Execute: Path = {0}", process.StartInfo.FileName); Console.WriteLine("IntegrationTestBase.Execute: Arguments = {0}", process.StartInfo.Arguments); + Console.WriteLine("IntegrationTestBase.Execute: WorkingDirectory = {0}", StringUtils.IsNullOrWhiteSpace(process.StartInfo.WorkingDirectory) ? $"(Current Directory) {Directory.GetCurrentDirectory()}" : process.StartInfo.WorkingDirectory); var stopwatch = new Stopwatch(); stopwatch.Start(); diff --git a/src/vstest/test/Microsoft.TestPlatform.Utilities.UnitTests/Microsoft.TestPlatform.Utilities.UnitTests.csproj b/src/vstest/test/Microsoft.TestPlatform.Utilities.UnitTests/Microsoft.TestPlatform.Utilities.UnitTests.csproj index 2247db2ab0f..86bbf395d82 100644 --- a/src/vstest/test/Microsoft.TestPlatform.Utilities.UnitTests/Microsoft.TestPlatform.Utilities.UnitTests.csproj +++ b/src/vstest/test/Microsoft.TestPlatform.Utilities.UnitTests/Microsoft.TestPlatform.Utilities.UnitTests.csproj @@ -8,7 +8,7 @@ net9.0;net48 - Exe + Exe Microsoft.TestPlatform.Utilities.UnitTests diff --git a/src/vstest/test/Microsoft.TestPlatform.Utilities.UnitTests/Program.cs b/src/vstest/test/Microsoft.TestPlatform.Utilities.UnitTests/Program.cs deleted file mode 100644 index 20f06189b89..00000000000 --- a/src/vstest/test/Microsoft.TestPlatform.Utilities.UnitTests/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.TestPlatform.Utilities.UnitTests; - -public static class Program -{ - public static void Main() - { - } -} diff --git a/src/vstest/test/SettingsMigrator.UnitTests/SettingsMigrator.UnitTests.csproj b/src/vstest/test/SettingsMigrator.UnitTests/SettingsMigrator.UnitTests.csproj index b2eb1760e9c..60915654882 100644 --- a/src/vstest/test/SettingsMigrator.UnitTests/SettingsMigrator.UnitTests.csproj +++ b/src/vstest/test/SettingsMigrator.UnitTests/SettingsMigrator.UnitTests.csproj @@ -4,6 +4,7 @@ true true false + Exe diff --git a/src/vstest/test/TestAssets/ArchitectureSwitch/global.json b/src/vstest/test/TestAssets/ArchitectureSwitch/global.json deleted file mode 100644 index c8c7401e654..00000000000 --- a/src/vstest/test/TestAssets/ArchitectureSwitch/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "version": "6.0.200-preview" - } -} \ No newline at end of file diff --git a/src/vstest/test/TestAssets/CUITTestProject/CUITTestProject.csproj b/src/vstest/test/TestAssets/CUITTestProject/CUITTestProject.csproj deleted file mode 100644 index 44dffdbef08..00000000000 --- a/src/vstest/test/TestAssets/CUITTestProject/CUITTestProject.csproj +++ /dev/null @@ -1,47 +0,0 @@ - - - - - true - true - - - - CUITTestProject - $(NetFrameworkMinimum) - Exe - - - - - ..\..\..\.packages\microsoft.visualstudio.cuit\$(TestPlatformExternalsVersion)\tools\net451\Microsoft.VisualStudio.QualityTools.CodedUITestFramework.dll - - - ..\..\..\.packages\microsoft.visualstudio.qualitytools\$(TestPlatformExternalsVersion)\tools\net451\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll - - - ..\..\..\.packages\microsoft.visualstudio.cuit\$(TestPlatformExternalsVersion)\tools\net451\Microsoft.VisualStudio.TestTools.UITest.Common.dll - - - ..\..\..\.packages\microsoft.visualstudio.cuit\$(TestPlatformExternalsVersion)\tools\net451\Microsoft.VisualStudio.TestTools.UITest.Extension.dll - - - ..\..\..\.packages\microsoft.visualstudio.cuit\$(TestPlatformExternalsVersion)\tools\net451\Microsoft.VisualStudio.TestTools.UITesting.dll - - - - - - - - $(TestPlatformExternalsVersion) - - - $(TestPlatformExternalsVersion) - - - - - - - diff --git a/src/vstest/test/TestAssets/CUITTestProject/CodedUITest1.cs b/src/vstest/test/TestAssets/CUITTestProject/CodedUITest1.cs deleted file mode 100644 index 808ac345d04..00000000000 --- a/src/vstest/test/TestAssets/CUITTestProject/CodedUITest1.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using Microsoft.VisualStudio.TestTools.UITesting; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace CodedUITestProject -{ - [CodedUITest] - public class CodedUITestProject - { - [TestMethod] - public void CodedUITestMethod1() - { - UITestControl.Desktop.DrawHighlight(); - } - } -} diff --git a/src/vstest/test/TestAssets/QualityToolsAssets/BingWebTest/BingWebTest.csproj b/src/vstest/test/TestAssets/QualityToolsAssets/BingWebTest/BingWebTest.csproj index e9c0056a3f4..248b264e3e2 100644 --- a/src/vstest/test/TestAssets/QualityToolsAssets/BingWebTest/BingWebTest.csproj +++ b/src/vstest/test/TestAssets/QualityToolsAssets/BingWebTest/BingWebTest.csproj @@ -17,7 +17,6 @@ 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False true @@ -54,24 +53,6 @@ PreserveNewest - - - - - False - - - False - - - False - - - False - - - - - + - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 3c34a3f0178f5a637d21c3f0ba5a4ee86ab8e976 diff --git a/src/winforms/eng/Versions.props b/src/winforms/eng/Versions.props index fb0e9816687..215d3204b77 100644 --- a/src/winforms/eng/Versions.props +++ b/src/winforms/eng/Versions.props @@ -10,30 +10,30 @@ $(MajorVersion).$(MinorVersion).$(PatchVersion) false release - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 5.0.0-preview.7.20320.5 - 10.0.0-preview.7.25360.101 + 10.0.0-preview.7.25364.102 6.1.0-preview.1.24511.1 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 10.0.0-preview.5.25227.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 + 10.0.0-preview.7.25364.102 @@ -46,16 +46,16 @@ - 10.0.0-beta.25360.101 - 10.0.0-beta.25360.101 - 10.0.0-beta.25360.101 + 10.0.0-beta.25364.102 + 10.0.0-beta.25364.102 + 10.0.0-beta.25364.102 17.4.0-preview-20220707-01 - - 3.0.0-pre.25 + + 3.0.0 3.1.0 3.0.6-alpha diff --git a/src/winforms/global.json b/src/winforms/global.json index 1b308b40e0c..a274e977be5 100644 --- a/src/winforms/global.json +++ b/src/winforms/global.json @@ -21,11 +21,11 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25360.101", - "Microsoft.DotNet.CMake.Sdk": "10.0.0-beta.25360.101", - "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25360.101", + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25364.102", + "Microsoft.DotNet.CMake.Sdk": "10.0.0-beta.25364.102", + "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25364.102", "FIX-85B6-MERGE-9C38-CONFLICT": "1.0.0", - "Microsoft.NET.Sdk.IL": "10.0.0-preview.7.25360.101" + "Microsoft.NET.Sdk.IL": "10.0.0-preview.7.25364.102" }, "native-tools": { "cmake": "latest" diff --git a/src/winforms/src/System.Windows.Forms/System/Windows/Forms/Controls/DataGridView/DataGridViewLinkCell.cs b/src/winforms/src/System.Windows.Forms/System/Windows/Forms/Controls/DataGridView/DataGridViewLinkCell.cs index a964cedc7ab..89195caa137 100644 --- a/src/winforms/src/System.Windows.Forms/System/Windows/Forms/Controls/DataGridView/DataGridViewLinkCell.cs +++ b/src/winforms/src/System.Windows.Forms/System/Windows/Forms/Controls/DataGridView/DataGridViewLinkCell.cs @@ -949,7 +949,7 @@ private Rectangle PaintPrivate( Font? getHoverFont = null; bool isActive = (LinkState & LinkState.Active) == LinkState.Active; - LinkUtilities.EnsureLinkFonts(cellStyle.Font!, LinkBehavior, ref getLinkFont, ref getHoverFont, isActive); + LinkUtilities.EnsureLinkFonts(cellStyle.Font!, LinkBehavior, ref getLinkFont, ref getHoverFont); using Font linkFont = getLinkFont; using Font hoverFont = getHoverFont; @@ -1028,6 +1028,18 @@ private Rectangle PaintPrivate( valBounds, linkColor, flags); + + // add a visiting effect. + if (isActive) + { + TextRenderer.DrawText( + g, + formattedValueStr, + LinkState == LinkState.Hover ? hoverFont : linkFont, + new Rectangle(valBounds.X + 1, valBounds.Y, valBounds.Width, valBounds.Height), + linkColor, + flags); + } } } else if (cellCurrent && diff --git a/src/winforms/src/System.Windows.Forms/System/Windows/Forms/Controls/Labels/LinkUtilities.cs b/src/winforms/src/System.Windows.Forms/System/Windows/Forms/Controls/Labels/LinkUtilities.cs index 6d1511a0e0c..259e485424b 100644 --- a/src/winforms/src/System.Windows.Forms/System/Windows/Forms/Controls/Labels/LinkUtilities.cs +++ b/src/winforms/src/System.Windows.Forms/System/Windows/Forms/Controls/Labels/LinkUtilities.cs @@ -163,8 +163,7 @@ public static void EnsureLinkFonts( Font baseFont, LinkBehavior link, [AllowNull] ref Font linkFont, - [AllowNull] ref Font hoverLinkFont, - bool isActive = false) + [AllowNull] ref Font hoverLinkFont) { if (linkFont is not null && hoverLinkFont is not null) { @@ -210,15 +209,6 @@ public static void EnsureLinkFonts( style &= ~FontStyle.Underline; } - if (isActive) - { - style |= FontStyle.Bold; - } - else - { - style &= ~FontStyle.Bold; - } - hoverLinkFont = new Font(f, style); linkFont = hoverLinkFont; } diff --git a/src/winforms/src/test/unit/System.Windows.Forms/System/Windows/Forms/LinkUtilitiesTests.cs b/src/winforms/src/test/unit/System.Windows.Forms/System/Windows/Forms/LinkUtilitiesTests.cs index 2cdd2cc65b9..3b7d8d098b6 100644 --- a/src/winforms/src/test/unit/System.Windows.Forms/System/Windows/Forms/LinkUtilitiesTests.cs +++ b/src/winforms/src/test/unit/System.Windows.Forms/System/Windows/Forms/LinkUtilitiesTests.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Drawing; @@ -44,21 +44,4 @@ public void LinkUtilities_EnsureLinkFonts_CreatesExpectedFonts(LinkBehavior beha linkFont.Should().BeOfType(); hoverLinkFont.Should().BeOfType(); } - - [WinFormsTheory] - [InlineData(LinkBehavior.AlwaysUnderline)] - [InlineData(LinkBehavior.HoverUnderline)] - [InlineData(LinkBehavior.NeverUnderline)] - public void LinkUtilities_EnsureLinkFonts_CreatesExpectedFonts_WithActive(LinkBehavior behavior) - { - using Font baseFont = new("Arial", 12); - Font? linkFont = null; - Font? hoverLinkFont = null; - - Action act = () => LinkUtilities.EnsureLinkFonts(baseFont, behavior, ref linkFont, ref hoverLinkFont, isActive: true); - - act.Should().NotThrow(); - linkFont.Should().BeOfType(); - hoverLinkFont.Should().BeOfType(); - } } diff --git a/src/winforms/src/test/unit/System.Windows.Forms/System/Windows/Forms/ListView.CheckedListViewItemCollectionTests.cs b/src/winforms/src/test/unit/System.Windows.Forms/System/Windows/Forms/ListView.CheckedListViewItemCollectionTests.cs index 443838bdb9b..1742a9e71eb 100644 --- a/src/winforms/src/test/unit/System.Windows.Forms/System/Windows/Forms/ListView.CheckedListViewItemCollectionTests.cs +++ b/src/winforms/src/test/unit/System.Windows.Forms/System/Windows/Forms/ListView.CheckedListViewItemCollectionTests.cs @@ -1,15 +1,419 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable +using System.Collections; namespace System.Windows.Forms.Tests; -public class ListView_CheckedListViewItemCollectionTests +public class ListView_CheckedListViewItemCollectionTests : IDisposable { + private readonly ListView _listView; + private readonly ListView.CheckedListViewItemCollection _collection; + + public ListView_CheckedListViewItemCollectionTests() + { + _listView = new ListView(); + _collection = new ListView.CheckedListViewItemCollection(_listView); + } + + public void Dispose() => _listView.Dispose(); + + [WinFormsFact] + public void CheckedListViewItemCollection_Ctor_OwnerIsNull_ThrowsArgumentNullException() => + Assert.Throws("owner", () => new ListView.CheckedListViewItemCollection(null!)); + + [WinFormsFact] + public void Count_ReturnsCheckedItemCount_WhenNotVirtualMode() + { + _listView.CheckBoxes = true; + _listView.Items.AddRange([ + new ListViewItem { Checked = true }, + new ListViewItem { Checked = false }, + new ListViewItem { Checked = true } + ]); + + _collection.Count.Should().Be(2); + } + + [WinFormsFact] + public void Count_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.CheckBoxes = true; + _listView.VirtualMode = true; + + Action act = () => { int _ = _collection.Count; }; + + act.Should().Throw(); + } + + [WinFormsFact] + public void Indexer_ReturnsCheckedItem_ByIndex() + { + _listView.CheckBoxes = true; + ListViewItem item1 = new() { Name = "a", Checked = false }; + ListViewItem item2 = new() { Name = "b", Checked = true }; + ListViewItem item3 = new() { Name = "c", Checked = true }; + _listView.Items.AddRange([item1, item2, item3]); + + _collection[0].Should().Be(item2); + _collection[1].Should().Be(item3); + } + + [WinFormsFact] + public void Indexer_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.CheckBoxes = true; + _listView.VirtualMode = true; + + Action act = () => { var _ = _collection[0]; }; + + act.Should().Throw(); + } + + [WinFormsFact] + public void IList_Indexer_Get_ReturnsCheckedItem() + { + _listView.CheckBoxes = true; + ListViewItem item1 = new() { Checked = false }; + ListViewItem item2 = new() { Checked = true }; + _listView.Items.AddRange([item1, item2]); + IList iList = _collection; + + iList[0].Should().Be(item2); + } + + [WinFormsFact] + public void IList_Indexer_Set_ThrowsNotSupportedException() + { + IList iList = _collection; + + Action act = () => iList[0] = new ListViewItem(); + + act.Should().Throw(); + } + + [WinFormsFact] + public void StringIndexer_ReturnsCheckedItem_ByKey() + { + _listView.CheckBoxes = true; + ListViewItem item1 = new() { Name = "foo", Checked = true }; + ListViewItem item2 = new() { Name = "bar", Checked = true }; + _listView.Items.AddRange([item1, item2]); + + _collection["foo"].Should().Be(item1); + _collection["bar"].Should().Be(item2); + } + + [WinFormsFact] + public void StringIndexer_ReturnsNull_ForNullOrEmptyKey() + { + _listView.CheckBoxes = true; + + _collection[null].Should().BeNull(); + _collection[string.Empty].Should().BeNull(); + } + + [WinFormsFact] + public void StringIndexer_ReturnsNull_IfKeyNotFound() + { + _listView.CheckBoxes = true; + ListViewItem item = new() { Name = "foo", Checked = true }; + _listView.Items.Add(item); + + _collection["bar"].Should().BeNull(); + } + + [WinFormsFact] + public void StringIndexer_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.CheckBoxes = true; + _listView.VirtualMode = true; + + Action act = () => { var _ = _collection["foo"]; }; + + act.Should().Throw(); + } + + [WinFormsFact] + public void ICollection_SyncRoot_ReturnsSelf() + { + ListView.CheckedListViewItemCollection syncRoot = (ListView.CheckedListViewItemCollection)((ICollection)_collection).SyncRoot; + + syncRoot.Should().BeSameAs(_collection); + } + + [WinFormsFact] + public void ICollection_IsSynchronized_IsFalse() + { + bool isSynchronized = ((ICollection)_collection).IsSynchronized; + + isSynchronized.Should().BeFalse(); + } + + [WinFormsFact] + public void IList_IsFixedSize_IsTrue() + { + bool isFixedSize = ((IList)_collection).IsFixedSize; + + isFixedSize.Should().BeTrue(); + } + + [WinFormsFact] + public void IsReadOnly_IsTrue() + { + _collection.IsReadOnly.Should().BeTrue(); + } + + [WinFormsTheory] + [InlineData(true, true, true)] // Checked and owned + [InlineData(false, true, false)] // Not checked but owned + [InlineData(true, false, false)] // Checked but not owned + public void Contains_ReturnsExpected_BasedOnCheckedAndOwnership(bool isChecked, bool isOwned, bool expected) + { + using ListView listView2 = new(); + _listView.CheckBoxes = true; + listView2.CheckBoxes = true; + + ListViewItem item = new() { Checked = isChecked }; + if (isOwned) + { + _listView.Items.Add(item); + } + else + { + listView2.Items.Add(item); + } + + _collection.Contains(item).Should().Be(expected); + } + + [WinFormsFact] + public void Contains_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.VirtualMode = true; + ListViewItem item = new(); + + Action act = () => _collection.Contains(item); + + act.Should().Throw(); + } + + [WinFormsFact] + public void IList_Contains_ReturnsTrue_IfListViewItemIsCheckedAndOwned() + { + _listView.CheckBoxes = true; + ListViewItem item = new() { Checked = true }; + _listView.Items.Add(item); + IList iList = _collection; + + iList.Contains(item).Should().BeTrue(); + } + + [WinFormsFact] + public void IList_Contains_ReturnsFalse_IfNotListViewItem() + { + IList iList = _collection; + + iList.Contains("not an item").Should().BeFalse(); + } + + [WinFormsFact] + public void IList_Contains_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.VirtualMode = true; + IList iList = _collection; + + Action act = () => iList.Contains(new ListViewItem()); + + act.Should().Throw(); + } + + [WinFormsTheory] + [InlineData("foo", true)] + [InlineData("bar", false)] + [InlineData(null, false)] + [InlineData("", false)] + public void ContainsKey_ReturnsExpected(string? key, bool expected) + { + _listView.CheckBoxes = true; + ListViewItem item = new() { Name = "foo", Checked = true }; + _listView.Items.Add(item); + + _collection.ContainsKey(key).Should().Be(expected); + } + + [WinFormsFact] + public void ContainsKey_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.VirtualMode = true; + + Action act = () => _collection.ContainsKey("foo"); + + act.Should().Throw(); + } + + [WinFormsFact] + public void IndexOf_ReturnsIndex_IfItemIsCheckedAndOwned() + { + _listView.CheckBoxes = true; + ListViewItem item1 = new() { Checked = true }; + ListViewItem item2 = new() { Checked = true }; + _listView.Items.AddRange([item1, item2]); + + _collection.IndexOf(item2).Should().Be(1); + } + + [WinFormsFact] + public void IndexOf_ReturnsMinusOne_IfItemIsNotChecked() + { + _listView.CheckBoxes = true; + ListViewItem item = new() { Checked = false }; + _listView.Items.Add(item); + + _collection.IndexOf(item).Should().Be(-1); + } + + [WinFormsFact] + public void IndexOf_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.VirtualMode = true; + + Action act = () => _collection.IndexOf(new ListViewItem()); + + act.Should().Throw(); + } + + [WinFormsFact] + public void IndexOfKey_ReturnsIndex_IfKeyExists() + { + _listView.CheckBoxes = true; + ListViewItem item1 = new() { Name = "foo", Checked = true }; + ListViewItem item2 = new() { Name = "bar", Checked = true }; + _listView.Items.AddRange([item1, item2]); + + _collection.IndexOfKey("bar").Should().Be(1); + } + + [WinFormsFact] + public void IndexOfKey_ReturnsMinusOne_IfKeyIsNullOrEmpty() + { + _listView.CheckBoxes = true; + + _collection.IndexOfKey(null).Should().Be(-1); + _collection.IndexOfKey(string.Empty).Should().Be(-1); + } + [WinFormsFact] - public void CheckedListViewItemCollection_Ctor_OwnerIsNull_ThrowsArgumentNullException() + public void IndexOfKey_ThrowsInvalidOperationException_WhenVirtualMode() { - Assert.Throws("owner", () => { new ListView.CheckedListViewItemCollection(null); }); + _listView.VirtualMode = true; + + Action act = () => _collection.IndexOfKey("foo"); + + act.Should().Throw(); + } + + [WinFormsFact] + public void IList_IndexOf_ReturnsIndex_IfListViewItemIsCheckedAndOwned() + { + _listView.CheckBoxes = true; + ListViewItem item1 = new() { Checked = true }; + ListViewItem item2 = new() { Checked = true }; + _listView.Items.AddRange([item1, item2]); + IList iList = _collection; + + iList.IndexOf(item2).Should().Be(1); + } + + [WinFormsFact] + public void IList_IndexOf_ReturnsMinusOne_IfNotListViewItem() + { + IList iList = _collection; + + iList.IndexOf("not an item").Should().Be(-1); + } + + [WinFormsFact] + public void IList_IndexOf_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.VirtualMode = true; + IList iList = _collection; + + Action act = () => iList.IndexOf(new ListViewItem()); + + act.Should().Throw(); + } + + [WinFormsTheory] + [InlineData("Add")] + [InlineData("Clear")] + [InlineData("Insert")] + [InlineData("Remove")] + [InlineData("RemoveAt")] + public void IList_Methods_ThrowNotSupportedException(string methodName) + { + IList iList = _collection; + + Action act = methodName switch + { + "Add" => () => iList.Add(new ListViewItem()), + "Clear" => iList.Clear, + "Insert" => () => iList.Insert(0, new ListViewItem()), + "Remove" => () => iList.Remove(new ListViewItem()), + "RemoveAt" => () => iList.RemoveAt(0), + _ => throw new ArgumentException($"Invalid method name: {methodName}", nameof(methodName)) + }; + + act.Should().Throw(); + } + + [WinFormsFact] + public void CopyTo_CopiesCheckedItems() + { + _listView.CheckBoxes = true; + ListViewItem item1 = new() { Checked = true }; + ListViewItem item2 = new() { Checked = false }; + ListViewItem item3 = new() { Checked = true }; + _listView.Items.AddRange([item1, item2, item3]); + ListViewItem[] array = new ListViewItem[2]; + + _collection.CopyTo(array, 0); + + array.Should().Equal(item1, item3); + } + + [WinFormsFact] + public void CopyTo_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.VirtualMode = true; + ListViewItem[] array = new ListViewItem[1]; + + Action act = () => _collection.CopyTo(array, 0); + + act.Should().Throw(); + } + + [WinFormsFact] + public void GetEnumerator_EnumeratesCheckedItems() + { + _listView.CheckBoxes = true; + ListViewItem item1 = new() { Checked = true }; + ListViewItem item2 = new() { Checked = false }; + ListViewItem item3 = new() { Checked = true }; + _listView.Items.AddRange([item1, item2, item3]); + + ListViewItem[] items = _collection.Cast().ToArray(); + + items.Should().Equal(item1, item3); + } + + [WinFormsFact] + public void GetEnumerator_ThrowsInvalidOperationException_WhenVirtualMode() + { + _listView.VirtualMode = true; + + Action act = () => _collection.GetEnumerator(); + + act.Should().Throw(); } } diff --git a/src/wpf/eng/Version.Details.xml b/src/wpf/eng/Version.Details.xml index 8b10c203b59..f77ebd9f51c 100644 --- a/src/wpf/eng/Version.Details.xml +++ b/src/wpf/eng/Version.Details.xml @@ -1,104 +1,104 @@ - + - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 https://dev.azure.com/dnceng/internal/_git/dotnet-wpf-int 8a6c1d81657ef04c040f598cafacf8f5a33abda2 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 - + https://github.com/dotnet/dotnet - 86117ef4343bab700dab871c416e55b22848cd52 + 0b032b9f942c1ae8de535a434c4f4a9206fd3339 diff --git a/src/wpf/eng/Versions.props b/src/wpf/eng/Versions.props index 4899b503af3..c9a4bc5c364 100644 --- a/src/wpf/eng/Versions.props +++ b/src/wpf/eng/Versions.props @@ -19,33 +19,33 @@ dotnet/winforms is handling versions for the analyzers. --> $(MajorVersion).$(MinorVersion).0.0 - 10.0.0-beta.25360.101 - 10.0.0-beta.25360.101 - 10.0.0-beta.25360.101 + 10.0.0-beta.25363.101 + 10.0.0-beta.25363.101 + 10.0.0-beta.25363.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 4.6.0-preview4.19176.11 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 - 10.0.0-preview.7.25360.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 + 10.0.0-preview.7.25363.101 @@ -59,7 +59,7 @@ 9.0.0-beta.24053.1 - 10.0.0-beta.25360.101 + 10.0.0-beta.25363.101 diff --git a/src/wpf/global.json b/src/wpf/global.json index 9f82df38341..b479d6ad314 100644 --- a/src/wpf/global.json +++ b/src/wpf/global.json @@ -24,8 +24,8 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25360.101", - "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25360.101", + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25363.101", + "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25363.101", "Microsoft.Build.NoTargets": "3.7.56" }, "native-tools": { diff --git a/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/Dark.xaml b/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/Dark.xaml index 9456e48eff1..b3e08b806ca 100644 --- a/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/Dark.xaml +++ b/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/Dark.xaml @@ -532,6 +532,7 @@ + diff --git a/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/HC.xaml b/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/HC.xaml index 316b43b5248..1bbc712e822 100644 --- a/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/HC.xaml +++ b/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/HC.xaml @@ -351,6 +351,7 @@ + diff --git a/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/Light.xaml b/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/Light.xaml index 5a8fe89c121..1952082bb4d 100644 --- a/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/Light.xaml +++ b/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Resources/Theme/Light.xaml @@ -548,6 +548,7 @@ + diff --git a/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Styles/DataGrid.xaml b/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Styles/DataGrid.xaml index edcc31d29d3..22aec44127d 100644 --- a/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Styles/DataGrid.xaml +++ b/src/wpf/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Fluent/Styles/DataGrid.xaml @@ -404,6 +404,7 @@